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_lan9303.c (3564B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2017 Pengutronix, Juergen Borleis <jbe@pengutronix.de>
      4 */
      5#include <linux/dsa/lan9303.h>
      6#include <linux/etherdevice.h>
      7#include <linux/list.h>
      8#include <linux/slab.h>
      9
     10#include "dsa_priv.h"
     11
     12/* To define the outgoing port and to discover the incoming port a regular
     13 * VLAN tag is used by the LAN9303. But its VID meaning is 'special':
     14 *
     15 *       Dest MAC       Src MAC        TAG    Type
     16 * ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 | 1 2 |...
     17 *                                |<------->|
     18 * TAG:
     19 *    |<------------->|
     20 *    |  1  2 | 3  4  |
     21 *      TPID    VID
     22 *     0x8100
     23 *
     24 * VID bit 3 indicates a request for an ALR lookup.
     25 *
     26 * If VID bit 3 is zero, then bits 0 and 1 specify the destination port
     27 * (0, 1, 2) or broadcast (3) or the source port (1, 2).
     28 *
     29 * VID bit 4 is used to specify if the STP port state should be overridden.
     30 * Required when no forwarding between the external ports should happen.
     31 */
     32
     33#define LAN9303_TAG_LEN 4
     34# define LAN9303_TAG_TX_USE_ALR BIT(3)
     35# define LAN9303_TAG_TX_STP_OVERRIDE BIT(4)
     36# define LAN9303_TAG_RX_IGMP BIT(3)
     37# define LAN9303_TAG_RX_STP BIT(4)
     38# define LAN9303_TAG_RX_TRAPPED_TO_CPU (LAN9303_TAG_RX_IGMP | \
     39					LAN9303_TAG_RX_STP)
     40
     41/* Decide whether to transmit using ALR lookup, or transmit directly to
     42 * port using tag. ALR learning is performed only when using ALR lookup.
     43 * If the two external ports are bridged and the frame is unicast,
     44 * then use ALR lookup to allow ALR learning on CPU port.
     45 * Otherwise transmit directly to port with STP state override.
     46 * See also: lan9303_separate_ports() and lan9303.pdf 6.4.10.1
     47 */
     48static int lan9303_xmit_use_arl(struct dsa_port *dp, u8 *dest_addr)
     49{
     50	struct lan9303 *chip = dp->ds->priv;
     51
     52	return chip->is_bridged && !is_multicast_ether_addr(dest_addr);
     53}
     54
     55static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
     56{
     57	struct dsa_port *dp = dsa_slave_to_port(dev);
     58	__be16 *lan9303_tag;
     59	u16 tag;
     60
     61	/* provide 'LAN9303_TAG_LEN' bytes additional space */
     62	skb_push(skb, LAN9303_TAG_LEN);
     63
     64	/* make room between MACs and Ether-Type */
     65	dsa_alloc_etype_header(skb, LAN9303_TAG_LEN);
     66
     67	lan9303_tag = dsa_etype_header_pos_tx(skb);
     68
     69	tag = lan9303_xmit_use_arl(dp, skb->data) ?
     70		LAN9303_TAG_TX_USE_ALR :
     71		dp->index | LAN9303_TAG_TX_STP_OVERRIDE;
     72	lan9303_tag[0] = htons(ETH_P_8021Q);
     73	lan9303_tag[1] = htons(tag);
     74
     75	return skb;
     76}
     77
     78static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
     79{
     80	u16 lan9303_tag1;
     81	unsigned int source_port;
     82
     83	if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
     84		dev_warn_ratelimited(&dev->dev,
     85				     "Dropping packet, cannot pull\n");
     86		return NULL;
     87	}
     88
     89	if (skb_vlan_tag_present(skb)) {
     90		lan9303_tag1 = skb_vlan_tag_get(skb);
     91		__vlan_hwaccel_clear_tag(skb);
     92	} else {
     93		skb_push_rcsum(skb, ETH_HLEN);
     94		__skb_vlan_pop(skb, &lan9303_tag1);
     95		skb_pull_rcsum(skb, ETH_HLEN);
     96	}
     97
     98	source_port = lan9303_tag1 & 0x3;
     99
    100	skb->dev = dsa_master_find_slave(dev, 0, source_port);
    101	if (!skb->dev) {
    102		dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
    103		return NULL;
    104	}
    105
    106	if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU))
    107		dsa_default_offload_fwd_mark(skb);
    108
    109	return skb;
    110}
    111
    112static const struct dsa_device_ops lan9303_netdev_ops = {
    113	.name = "lan9303",
    114	.proto	= DSA_TAG_PROTO_LAN9303,
    115	.xmit = lan9303_xmit,
    116	.rcv = lan9303_rcv,
    117	.needed_headroom = LAN9303_TAG_LEN,
    118};
    119
    120MODULE_LICENSE("GPL");
    121MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_LAN9303);
    122
    123module_dsa_tag_driver(lan9303_netdev_ops);