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_ksz.c (5697B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * net/dsa/tag_ksz.c - Microchip KSZ Switch tag format handling
      4 * Copyright (c) 2017 Microchip Technology
      5 */
      6
      7#include <linux/etherdevice.h>
      8#include <linux/list.h>
      9#include <net/dsa.h>
     10#include "dsa_priv.h"
     11
     12/* Typically only one byte is used for tail tag. */
     13#define KSZ_EGRESS_TAG_LEN		1
     14#define KSZ_INGRESS_TAG_LEN		1
     15
     16static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
     17				      struct net_device *dev,
     18				      unsigned int port, unsigned int len)
     19{
     20	skb->dev = dsa_master_find_slave(dev, 0, port);
     21	if (!skb->dev)
     22		return NULL;
     23
     24	pskb_trim_rcsum(skb, skb->len - len);
     25
     26	dsa_default_offload_fwd_mark(skb);
     27
     28	return skb;
     29}
     30
     31/*
     32 * For Ingress (Host -> KSZ8795), 1 byte is added before FCS.
     33 * ---------------------------------------------------------------------------
     34 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag(1byte)|FCS(4bytes)
     35 * ---------------------------------------------------------------------------
     36 * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
     37 *
     38 * For Egress (KSZ8795 -> Host), 1 byte is added before FCS.
     39 * ---------------------------------------------------------------------------
     40 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
     41 * ---------------------------------------------------------------------------
     42 * tag0 : zero-based value represents port
     43 *	  (eg, 0x00=port1, 0x02=port3, 0x06=port7)
     44 */
     45
     46#define KSZ8795_TAIL_TAG_OVERRIDE	BIT(6)
     47#define KSZ8795_TAIL_TAG_LOOKUP		BIT(7)
     48
     49static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
     50{
     51	struct dsa_port *dp = dsa_slave_to_port(dev);
     52	u8 *tag;
     53	u8 *addr;
     54
     55	if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
     56		return NULL;
     57
     58	/* Tag encoding */
     59	tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
     60	addr = skb_mac_header(skb);
     61
     62	*tag = 1 << dp->index;
     63	if (is_link_local_ether_addr(addr))
     64		*tag |= KSZ8795_TAIL_TAG_OVERRIDE;
     65
     66	return skb;
     67}
     68
     69static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev)
     70{
     71	u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
     72
     73	return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
     74}
     75
     76static const struct dsa_device_ops ksz8795_netdev_ops = {
     77	.name	= "ksz8795",
     78	.proto	= DSA_TAG_PROTO_KSZ8795,
     79	.xmit	= ksz8795_xmit,
     80	.rcv	= ksz8795_rcv,
     81	.needed_tailroom = KSZ_INGRESS_TAG_LEN,
     82};
     83
     84DSA_TAG_DRIVER(ksz8795_netdev_ops);
     85MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
     86
     87/*
     88 * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
     89 * ---------------------------------------------------------------------------
     90 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
     91 * ---------------------------------------------------------------------------
     92 * tag0 : Prioritization (not used now)
     93 * tag1 : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
     94 *
     95 * For Egress (KSZ9477 -> Host), 1 byte is added before FCS.
     96 * ---------------------------------------------------------------------------
     97 * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
     98 * ---------------------------------------------------------------------------
     99 * tag0 : zero-based value represents port
    100 *	  (eg, 0x00=port1, 0x02=port3, 0x06=port7)
    101 */
    102
    103#define KSZ9477_INGRESS_TAG_LEN		2
    104#define KSZ9477_PTP_TAG_LEN		4
    105#define KSZ9477_PTP_TAG_INDICATION	0x80
    106
    107#define KSZ9477_TAIL_TAG_OVERRIDE	BIT(9)
    108#define KSZ9477_TAIL_TAG_LOOKUP		BIT(10)
    109
    110static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
    111				    struct net_device *dev)
    112{
    113	struct dsa_port *dp = dsa_slave_to_port(dev);
    114	__be16 *tag;
    115	u8 *addr;
    116	u16 val;
    117
    118	if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
    119		return NULL;
    120
    121	/* Tag encoding */
    122	tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN);
    123	addr = skb_mac_header(skb);
    124
    125	val = BIT(dp->index);
    126
    127	if (is_link_local_ether_addr(addr))
    128		val |= KSZ9477_TAIL_TAG_OVERRIDE;
    129
    130	*tag = cpu_to_be16(val);
    131
    132	return skb;
    133}
    134
    135static struct sk_buff *ksz9477_rcv(struct sk_buff *skb, struct net_device *dev)
    136{
    137	/* Tag decoding */
    138	u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
    139	unsigned int port = tag[0] & 7;
    140	unsigned int len = KSZ_EGRESS_TAG_LEN;
    141
    142	/* Extra 4-bytes PTP timestamp */
    143	if (tag[0] & KSZ9477_PTP_TAG_INDICATION)
    144		len += KSZ9477_PTP_TAG_LEN;
    145
    146	return ksz_common_rcv(skb, dev, port, len);
    147}
    148
    149static const struct dsa_device_ops ksz9477_netdev_ops = {
    150	.name	= "ksz9477",
    151	.proto	= DSA_TAG_PROTO_KSZ9477,
    152	.xmit	= ksz9477_xmit,
    153	.rcv	= ksz9477_rcv,
    154	.needed_tailroom = KSZ9477_INGRESS_TAG_LEN,
    155};
    156
    157DSA_TAG_DRIVER(ksz9477_netdev_ops);
    158MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9477);
    159
    160#define KSZ9893_TAIL_TAG_OVERRIDE	BIT(5)
    161#define KSZ9893_TAIL_TAG_LOOKUP		BIT(6)
    162
    163static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
    164				    struct net_device *dev)
    165{
    166	struct dsa_port *dp = dsa_slave_to_port(dev);
    167	u8 *addr;
    168	u8 *tag;
    169
    170	if (skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_help(skb))
    171		return NULL;
    172
    173	/* Tag encoding */
    174	tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
    175	addr = skb_mac_header(skb);
    176
    177	*tag = BIT(dp->index);
    178
    179	if (is_link_local_ether_addr(addr))
    180		*tag |= KSZ9893_TAIL_TAG_OVERRIDE;
    181
    182	return skb;
    183}
    184
    185static const struct dsa_device_ops ksz9893_netdev_ops = {
    186	.name	= "ksz9893",
    187	.proto	= DSA_TAG_PROTO_KSZ9893,
    188	.xmit	= ksz9893_xmit,
    189	.rcv	= ksz9477_rcv,
    190	.needed_tailroom = KSZ_INGRESS_TAG_LEN,
    191};
    192
    193DSA_TAG_DRIVER(ksz9893_netdev_ops);
    194MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
    195
    196static struct dsa_tag_driver *dsa_tag_driver_array[] = {
    197	&DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
    198	&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
    199	&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
    200};
    201
    202module_dsa_tag_drivers(dsa_tag_driver_array);
    203
    204MODULE_LICENSE("GPL");