cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tag_mtk.c (2612B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Mediatek DSA Tag support
      4 * Copyright (C) 2017 Landen Chao <landen.chao@mediatek.com>
      5 *		      Sean Wang <sean.wang@mediatek.com>
      6 */
      7
      8#include <linux/etherdevice.h>
      9#include <linux/if_vlan.h>
     10
     11#include "dsa_priv.h"
     12
     13#define MTK_HDR_LEN		4
     14#define MTK_HDR_XMIT_UNTAGGED		0
     15#define MTK_HDR_XMIT_TAGGED_TPID_8100	1
     16#define MTK_HDR_XMIT_TAGGED_TPID_88A8	2
     17#define MTK_HDR_RECV_SOURCE_PORT_MASK	GENMASK(2, 0)
     18#define MTK_HDR_XMIT_DP_BIT_MASK	GENMASK(5, 0)
     19#define MTK_HDR_XMIT_SA_DIS		BIT(6)
     20
     21static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
     22				    struct net_device *dev)
     23{
     24	struct dsa_port *dp = dsa_slave_to_port(dev);
     25	u8 xmit_tpid;
     26	u8 *mtk_tag;
     27
     28	/* Build the special tag after the MAC Source Address. If VLAN header
     29	 * is present, it's required that VLAN header and special tag is
     30	 * being combined. Only in this way we can allow the switch can parse
     31	 * the both special and VLAN tag at the same time and then look up VLAN
     32	 * table with VID.
     33	 */
     34	switch (skb->protocol) {
     35	case htons(ETH_P_8021Q):
     36		xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_8100;
     37		break;
     38	case htons(ETH_P_8021AD):
     39		xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_88A8;
     40		break;
     41	default:
     42		xmit_tpid = MTK_HDR_XMIT_UNTAGGED;
     43		skb_push(skb, MTK_HDR_LEN);
     44		dsa_alloc_etype_header(skb, MTK_HDR_LEN);
     45	}
     46
     47	mtk_tag = dsa_etype_header_pos_tx(skb);
     48
     49	/* Mark tag attribute on special tag insertion to notify hardware
     50	 * whether that's a combined special tag with 802.1Q header.
     51	 */
     52	mtk_tag[0] = xmit_tpid;
     53	mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
     54
     55	/* Tag control information is kept for 802.1Q */
     56	if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) {
     57		mtk_tag[2] = 0;
     58		mtk_tag[3] = 0;
     59	}
     60
     61	return skb;
     62}
     63
     64static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
     65{
     66	u16 hdr;
     67	int port;
     68	__be16 *phdr;
     69
     70	if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
     71		return NULL;
     72
     73	phdr = dsa_etype_header_pos_rx(skb);
     74	hdr = ntohs(*phdr);
     75
     76	/* Remove MTK tag and recalculate checksum. */
     77	skb_pull_rcsum(skb, MTK_HDR_LEN);
     78
     79	dsa_strip_etype_header(skb, MTK_HDR_LEN);
     80
     81	/* Get source port information */
     82	port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
     83
     84	skb->dev = dsa_master_find_slave(dev, 0, port);
     85	if (!skb->dev)
     86		return NULL;
     87
     88	dsa_default_offload_fwd_mark(skb);
     89
     90	return skb;
     91}
     92
     93static const struct dsa_device_ops mtk_netdev_ops = {
     94	.name		= "mtk",
     95	.proto		= DSA_TAG_PROTO_MTK,
     96	.xmit		= mtk_tag_xmit,
     97	.rcv		= mtk_tag_rcv,
     98	.needed_headroom = MTK_HDR_LEN,
     99};
    100
    101MODULE_LICENSE("GPL");
    102MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_MTK);
    103
    104module_dsa_tag_driver(mtk_netdev_ops);