Blame view
net/dsa/tag_dsa.c
3.73 KB
dfedd3b62 dsa: Add SPDX hea... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
cf85d08fd dsa: add support ... |
2 3 |
/* * net/dsa/tag_dsa.c - (Non-ethertype) DSA tagging |
e84665c9c dsa: add switch c... |
4 |
* Copyright (c) 2008-2009 Marvell Semiconductor |
cf85d08fd dsa: add support ... |
5 6 7 8 |
*/ #include <linux/etherdevice.h> #include <linux/list.h> |
5a0e3ad6a include cleanup: ... |
9 |
#include <linux/slab.h> |
ea5dd34be net: dsa: include... |
10 |
|
cf85d08fd dsa: add support ... |
11 12 13 |
#include "dsa_priv.h" #define DSA_HLEN 4 |
4ed70ce9f net: dsa: Refacto... |
14 |
static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev) |
cf85d08fd dsa: add support ... |
15 |
{ |
d945097bb net: dsa: add sla... |
16 |
struct dsa_port *dp = dsa_slave_to_port(dev); |
cf85d08fd dsa: add support ... |
17 |
u8 *dsa_header; |
cf85d08fd dsa: add support ... |
18 19 20 21 22 23 24 |
/* * Convert the outermost 802.1q tag to a DSA tag for tagged * packets, or insert a DSA tag between the addresses and * the ethertype field for untagged packets. */ if (skb->protocol == htons(ETH_P_8021Q)) { if (skb_cow_head(skb, 0) < 0) |
fe47d5630 net: dsa: factor ... |
25 |
return NULL; |
cf85d08fd dsa: add support ... |
26 27 28 29 30 |
/* * Construct tagged FROM_CPU DSA tag from 802.1q tag. */ dsa_header = skb->data + 2 * ETH_ALEN; |
d945097bb net: dsa: add sla... |
31 32 |
dsa_header[0] = 0x60 | dp->ds->index; dsa_header[1] = dp->index << 3; |
cf85d08fd dsa: add support ... |
33 34 35 36 37 38 39 40 41 42 |
/* * Move CFI field from byte 2 to byte 1. */ if (dsa_header[2] & 0x10) { dsa_header[1] |= 0x01; dsa_header[2] &= ~0x10; } } else { if (skb_cow_head(skb, DSA_HLEN) < 0) |
fe47d5630 net: dsa: factor ... |
43 |
return NULL; |
cf85d08fd dsa: add support ... |
44 45 46 47 48 49 50 51 |
skb_push(skb, DSA_HLEN); memmove(skb->data, skb->data + DSA_HLEN, 2 * ETH_ALEN); /* * Construct untagged FROM_CPU DSA tag. */ dsa_header = skb->data + 2 * ETH_ALEN; |
d945097bb net: dsa: add sla... |
52 53 |
dsa_header[0] = 0x40 | dp->ds->index; dsa_header[1] = dp->index << 3; |
cf85d08fd dsa: add support ... |
54 55 56 |
dsa_header[2] = 0x00; dsa_header[3] = 0x00; } |
4ed70ce9f net: dsa: Refacto... |
57 |
return skb; |
cf85d08fd dsa: add support ... |
58 |
} |
a86d8becc net: dsa: Factor ... |
59 |
static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev, |
89e49506b dsa: remove unuse... |
60 |
struct packet_type *pt) |
cf85d08fd dsa: add support ... |
61 |
{ |
cf85d08fd dsa: add support ... |
62 |
u8 *dsa_header; |
e84665c9c dsa: add switch c... |
63 |
int source_device; |
cf85d08fd dsa: add support ... |
64 |
int source_port; |
cf85d08fd dsa: add support ... |
65 |
if (unlikely(!pskb_may_pull(skb, DSA_HLEN))) |
547097958 net: dsa: remove ... |
66 |
return NULL; |
cf85d08fd dsa: add support ... |
67 68 69 70 71 72 73 |
/* * The ethertype field is part of the DSA header. */ dsa_header = skb->data - 2; /* |
e84665c9c dsa: add switch c... |
74 |
* Check that frame type is either TO_CPU or FORWARD. |
cf85d08fd dsa: add support ... |
75 |
*/ |
e84665c9c dsa: add switch c... |
76 |
if ((dsa_header[0] & 0xc0) != 0x00 && (dsa_header[0] & 0xc0) != 0xc0) |
547097958 net: dsa: remove ... |
77 |
return NULL; |
cf85d08fd dsa: add support ... |
78 79 |
/* |
e84665c9c dsa: add switch c... |
80 |
* Determine source device and port. |
cf85d08fd dsa: add support ... |
81 |
*/ |
e84665c9c dsa: add switch c... |
82 |
source_device = dsa_header[0] & 0x1f; |
cf85d08fd dsa: add support ... |
83 |
source_port = (dsa_header[1] >> 3) & 0x1f; |
e84665c9c dsa: add switch c... |
84 |
|
2231c43b5 net: dsa: rename ... |
85 |
skb->dev = dsa_master_find_slave(dev, source_device, source_port); |
3775b1b7f net: dsa: add mas... |
86 |
if (!skb->dev) |
547097958 net: dsa: remove ... |
87 |
return NULL; |
cf85d08fd dsa: add support ... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
/* * Convert the DSA header to an 802.1q header if the 'tagged' * bit in the DSA header is set. If the 'tagged' bit is clear, * delete the DSA header entirely. */ if (dsa_header[0] & 0x20) { u8 new_header[4]; /* * Insert 802.1q ethertype and copy the VLAN-related * fields, but clear the bit that will hold CFI (since * DSA uses that bit location for another purpose). */ new_header[0] = (ETH_P_8021Q >> 8) & 0xff; new_header[1] = ETH_P_8021Q & 0xff; new_header[2] = dsa_header[2] & ~0x10; new_header[3] = dsa_header[3]; /* * Move CFI bit from its place in the DSA header to * its 802.1q-designated place. */ if (dsa_header[1] & 0x01) new_header[2] |= 0x10; /* * Update packet checksum if skb is CHECKSUM_COMPLETE. */ if (skb->ip_summed == CHECKSUM_COMPLETE) { __wsum c = skb->csum; c = csum_add(c, csum_partial(new_header + 2, 2, 0)); c = csum_sub(c, csum_partial(dsa_header + 2, 2, 0)); skb->csum = c; } memcpy(dsa_header, new_header, DSA_HLEN); } else { /* * Remove DSA tag and update checksum. */ skb_pull_rcsum(skb, DSA_HLEN); memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - DSA_HLEN, 2 * ETH_ALEN); } |
13edbdb6e net: dsa: {e}dsa:... |
134 |
skb->offload_fwd_mark = 1; |
a86d8becc net: dsa: Factor ... |
135 |
return skb; |
cf85d08fd dsa: add support ... |
136 |
} |
57fd96783 net: dsa: Impleme... |
137 138 139 140 141 142 143 |
static int dsa_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto, int *offset) { *offset = 4; *proto = ((__be16 *)skb->data)[1]; return 0; } |
f81a43e8d dsa: Cleanup unne... |
144 |
static const struct dsa_device_ops dsa_netdev_ops = { |
875138f81 dsa: Move tagger ... |
145 |
.name = "dsa", |
056eed2fb dsa: Add TAG prot... |
146 |
.proto = DSA_TAG_PROTO_DSA, |
3e8a72d1d net: dsa: reduce ... |
147 148 |
.xmit = dsa_xmit, .rcv = dsa_rcv, |
57fd96783 net: dsa: Impleme... |
149 |
.flow_dissect = dsa_tag_flow_dissect, |
a5dd30877 net: dsa: Add ove... |
150 |
.overhead = DSA_HLEN, |
cf85d08fd dsa: add support ... |
151 |
}; |
0b42f0336 dsa: Add MODULE_A... |
152 |
|
f18bba50d dsa: Add MODULE_L... |
153 |
MODULE_LICENSE("GPL"); |
0b42f0336 dsa: Add MODULE_A... |
154 |
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_DSA); |
d3b8c0498 dsa: Add boilerpl... |
155 156 |
module_dsa_tag_driver(dsa_netdev_ops); |