Skip to content

Commit 88be326

Browse files
committed
Merge branch 'dsa-tagger-helpers'
Vladimir Oltean says: ==================== DSA tagger helpers The goal of this series is to minimize the use of memmove and skb->data in the DSA tagging protocol drivers. Unfiltered access to this level of information is not very friendly to drive-by contributors, and sometimes is also not the easiest to review. For starters, I have converted the most common form of DSA tagging protocols: the DSA headers which are placed where the EtherType is. The helper functions introduced by this series are: - dsa_alloc_etype_header - dsa_strip_etype_header - dsa_etype_header_pos_rx - dsa_etype_header_pos_tx This series is just a resend as non-RFC of v1. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1a8e628 + a72808b commit 88be326

File tree

8 files changed

+119
-81
lines changed

8 files changed

+119
-81
lines changed

net/dsa/dsa_priv.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,84 @@ static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb)
452452
skb->offload_fwd_mark = !!(dp->bridge_dev);
453453
}
454454

455+
/* Helper for removing DSA header tags from packets in the RX path.
456+
* Must not be called before skb_pull(len).
457+
* skb->data
458+
* |
459+
* v
460+
* | | | | | | | | | | | | | | | | | | |
461+
* +-----------------------+-----------------------+---------------+-------+
462+
* | Destination MAC | Source MAC | DSA header | EType |
463+
* +-----------------------+-----------------------+---------------+-------+
464+
* | |
465+
* <----- len -----> <----- len ----->
466+
* |
467+
* >>>>>>> v
468+
* >>>>>>> | | | | | | | | | | | | | | |
469+
* >>>>>>> +-----------------------+-----------------------+-------+
470+
* >>>>>>> | Destination MAC | Source MAC | EType |
471+
* +-----------------------+-----------------------+-------+
472+
* ^
473+
* |
474+
* skb->data
475+
*/
476+
static inline void dsa_strip_etype_header(struct sk_buff *skb, int len)
477+
{
478+
memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - len, 2 * ETH_ALEN);
479+
}
480+
481+
/* Helper for creating space for DSA header tags in TX path packets.
482+
* Must not be called before skb_push(len).
483+
*
484+
* Before:
485+
*
486+
* <<<<<<< | | | | | | | | | | | | | | |
487+
* ^ <<<<<<< +-----------------------+-----------------------+-------+
488+
* | <<<<<<< | Destination MAC | Source MAC | EType |
489+
* | +-----------------------+-----------------------+-------+
490+
* <----- len ----->
491+
* |
492+
* |
493+
* skb->data
494+
*
495+
* After:
496+
*
497+
* | | | | | | | | | | | | | | | | | | |
498+
* +-----------------------+-----------------------+---------------+-------+
499+
* | Destination MAC | Source MAC | DSA header | EType |
500+
* +-----------------------+-----------------------+---------------+-------+
501+
* ^ | |
502+
* | <----- len ----->
503+
* skb->data
504+
*/
505+
static inline void dsa_alloc_etype_header(struct sk_buff *skb, int len)
506+
{
507+
memmove(skb->data, skb->data + len, 2 * ETH_ALEN);
508+
}
509+
510+
/* On RX, eth_type_trans() on the DSA master pulls ETH_HLEN bytes starting from
511+
* skb_mac_header(skb), which leaves skb->data pointing at the first byte after
512+
* what the DSA master perceives as the EtherType (the beginning of the L3
513+
* protocol). Since DSA EtherType header taggers treat the EtherType as part of
514+
* the DSA tag itself, and the EtherType is 2 bytes in length, the DSA header
515+
* is located 2 bytes behind skb->data. Note that EtherType in this context
516+
* means the first 2 bytes of the DSA header, not the encapsulated EtherType
517+
* that will become visible after the DSA header is stripped.
518+
*/
519+
static inline void *dsa_etype_header_pos_rx(struct sk_buff *skb)
520+
{
521+
return skb->data - 2;
522+
}
523+
524+
/* On TX, skb->data points to skb_mac_header(skb), which means that EtherType
525+
* header taggers start exactly where the EtherType is (the EtherType is
526+
* treated as part of the DSA header).
527+
*/
528+
static inline void *dsa_etype_header_pos_tx(struct sk_buff *skb)
529+
{
530+
return skb->data + 2 * ETH_ALEN;
531+
}
532+
455533
/* switch.c */
456534
int dsa_switch_register_notifier(struct dsa_switch *ds);
457535
void dsa_switch_unregister_notifier(struct dsa_switch *ds);

net/dsa/tag_brcm.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
9999
skb_push(skb, BRCM_TAG_LEN);
100100

101101
if (offset)
102-
memmove(skb->data, skb->data + BRCM_TAG_LEN, offset);
102+
dsa_alloc_etype_header(skb, BRCM_TAG_LEN);
103103

104104
brcm_tag = skb->data + offset;
105105

@@ -190,10 +190,7 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev)
190190
if (!nskb)
191191
return nskb;
192192

193-
/* Move the Ethernet DA and SA */
194-
memmove(nskb->data - ETH_HLEN,
195-
nskb->data - ETH_HLEN - BRCM_TAG_LEN,
196-
2 * ETH_ALEN);
193+
dsa_strip_etype_header(skb, BRCM_TAG_LEN);
197194

198195
return nskb;
199196
}
@@ -231,7 +228,7 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
231228

232229
skb_push(skb, BRCM_LEG_TAG_LEN);
233230

234-
memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN);
231+
dsa_alloc_etype_header(skb, BRCM_LEG_TAG_LEN);
235232

236233
brcm_tag = skb->data + 2 * ETH_ALEN;
237234

@@ -257,7 +254,7 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
257254
if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID)))
258255
return NULL;
259256

260-
brcm_tag = skb->data - 2;
257+
brcm_tag = dsa_etype_header_pos_rx(skb);
261258

262259
source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
263260

@@ -270,10 +267,7 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
270267

271268
dsa_default_offload_fwd_mark(skb);
272269

273-
/* Move the Ethernet DA and SA */
274-
memmove(skb->data - ETH_HLEN,
275-
skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN,
276-
2 * ETH_ALEN);
270+
dsa_strip_etype_header(skb, BRCM_LEG_TAG_LEN);
277271

278272
return skb;
279273
}

net/dsa/tag_dsa.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
166166
if (skb->protocol == htons(ETH_P_8021Q)) {
167167
if (extra) {
168168
skb_push(skb, extra);
169-
memmove(skb->data, skb->data + extra, 2 * ETH_ALEN);
169+
dsa_alloc_etype_header(skb, extra);
170170
}
171171

172172
/* Construct tagged DSA tag from 802.1Q tag. */
173-
dsa_header = skb->data + 2 * ETH_ALEN + extra;
173+
dsa_header = dsa_etype_header_pos_tx(skb) + extra;
174174
dsa_header[0] = (cmd << 6) | 0x20 | tag_dev;
175175
dsa_header[1] = tag_port << 3;
176176

@@ -181,10 +181,10 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
181181
}
182182
} else {
183183
skb_push(skb, DSA_HLEN + extra);
184-
memmove(skb->data, skb->data + DSA_HLEN + extra, 2 * ETH_ALEN);
184+
dsa_alloc_etype_header(skb, DSA_HLEN + extra);
185185

186186
/* Construct untagged DSA tag. */
187-
dsa_header = skb->data + 2 * ETH_ALEN + extra;
187+
dsa_header = dsa_etype_header_pos_tx(skb) + extra;
188188

189189
dsa_header[0] = (cmd << 6) | tag_dev;
190190
dsa_header[1] = tag_port << 3;
@@ -205,7 +205,7 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
205205
u8 *dsa_header;
206206

207207
/* The ethertype field is part of the DSA header. */
208-
dsa_header = skb->data - 2;
208+
dsa_header = dsa_etype_header_pos_rx(skb);
209209

210210
cmd = dsa_header[0] >> 6;
211211
switch (cmd) {
@@ -312,14 +312,10 @@ static struct sk_buff *dsa_rcv_ll(struct sk_buff *skb, struct net_device *dev,
312312
memcpy(dsa_header, new_header, DSA_HLEN);
313313

314314
if (extra)
315-
memmove(skb->data - ETH_HLEN,
316-
skb->data - ETH_HLEN - extra,
317-
2 * ETH_ALEN);
315+
dsa_strip_etype_header(skb, extra);
318316
} else {
319317
skb_pull_rcsum(skb, DSA_HLEN);
320-
memmove(skb->data - ETH_HLEN,
321-
skb->data - ETH_HLEN - DSA_HLEN - extra,
322-
2 * ETH_ALEN);
318+
dsa_strip_etype_header(skb, DSA_HLEN + extra);
323319
}
324320

325321
return skb;
@@ -364,7 +360,7 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
364360
if (!skb)
365361
return NULL;
366362

367-
edsa_header = skb->data + 2 * ETH_ALEN;
363+
edsa_header = dsa_etype_header_pos_tx(skb);
368364
edsa_header[0] = (ETH_P_EDSA >> 8) & 0xff;
369365
edsa_header[1] = ETH_P_EDSA & 0xff;
370366
edsa_header[2] = 0x00;

net/dsa/tag_lan9303.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev)
6262
skb_push(skb, LAN9303_TAG_LEN);
6363

6464
/* make room between MACs and Ether-Type */
65-
memmove(skb->data, skb->data + LAN9303_TAG_LEN, 2 * ETH_ALEN);
65+
dsa_alloc_etype_header(skb, LAN9303_TAG_LEN);
66+
67+
lan9303_tag = dsa_etype_header_pos_tx(skb);
6668

67-
lan9303_tag = (__be16 *)(skb->data + 2 * ETH_ALEN);
6869
tag = lan9303_xmit_use_arl(dp, skb->data) ?
6970
LAN9303_TAG_TX_USE_ALR :
7071
dp->index | LAN9303_TAG_TX_STP_OVERRIDE;
@@ -86,13 +87,7 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
8687
return NULL;
8788
}
8889

89-
/* '->data' points into the middle of our special VLAN tag information:
90-
*
91-
* ~ MAC src | 0x81 | 0x00 | 0xyy | 0xzz | ether type
92-
* ^
93-
* ->data
94-
*/
95-
lan9303_tag = (__be16 *)(skb->data - 2);
90+
lan9303_tag = dsa_etype_header_pos_rx(skb);
9691

9792
if (lan9303_tag[0] != htons(ETH_P_8021Q)) {
9893
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid VLAN marker\n");
@@ -112,8 +107,9 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev)
112107
* and the current ethertype field.
113108
*/
114109
skb_pull_rcsum(skb, 2 + 2);
115-
memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
116-
2 * ETH_ALEN);
110+
111+
dsa_strip_etype_header(skb, LAN9303_TAG_LEN);
112+
117113
if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU))
118114
dsa_default_offload_fwd_mark(skb);
119115

net/dsa/tag_mtk.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
4141
default:
4242
xmit_tpid = MTK_HDR_XMIT_UNTAGGED;
4343
skb_push(skb, MTK_HDR_LEN);
44-
memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
44+
dsa_alloc_etype_header(skb, MTK_HDR_LEN);
4545
}
4646

47-
mtk_tag = skb->data + 2 * ETH_ALEN;
47+
mtk_tag = dsa_etype_header_pos_tx(skb);
4848

4949
/* Mark tag attribute on special tag insertion to notify hardware
5050
* whether that's a combined special tag with 802.1Q header.
@@ -70,19 +70,13 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev)
7070
if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
7171
return NULL;
7272

73-
/* The MTK header is added by the switch between src addr
74-
* and ethertype at this point, skb->data points to 2 bytes
75-
* after src addr so header should be 2 bytes right before.
76-
*/
77-
phdr = (__be16 *)(skb->data - 2);
73+
phdr = dsa_etype_header_pos_rx(skb);
7874
hdr = ntohs(*phdr);
7975

8076
/* Remove MTK tag and recalculate checksum. */
8177
skb_pull_rcsum(skb, MTK_HDR_LEN);
8278

83-
memmove(skb->data - ETH_HLEN,
84-
skb->data - ETH_HLEN - MTK_HDR_LEN,
85-
2 * ETH_ALEN);
79+
dsa_strip_etype_header(skb, MTK_HDR_LEN);
8680

8781
/* Get source port information */
8882
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);

net/dsa/tag_qca.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
3636

3737
skb_push(skb, QCA_HDR_LEN);
3838

39-
memmove(skb->data, skb->data + QCA_HDR_LEN, 2 * ETH_ALEN);
40-
phdr = (__be16 *)(skb->data + 2 * ETH_ALEN);
39+
dsa_alloc_etype_header(skb, QCA_HDR_LEN);
40+
phdr = dsa_etype_header_pos_tx(skb);
4141

4242
/* Set the version field, and set destination port information */
4343
hdr = QCA_HDR_VERSION << QCA_HDR_XMIT_VERSION_S |
@@ -58,11 +58,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
5858
if (unlikely(!pskb_may_pull(skb, QCA_HDR_LEN)))
5959
return NULL;
6060

61-
/* The QCA header is added by the switch between src addr and Ethertype
62-
* At this point, skb->data points to ethertype so header should be
63-
* right before
64-
*/
65-
phdr = (__be16 *)(skb->data - 2);
61+
phdr = dsa_etype_header_pos_rx(skb);
6662
hdr = ntohs(*phdr);
6763

6864
/* Make sure the version is correct */
@@ -72,8 +68,7 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev)
7268

7369
/* Remove QCA tag and recalculate checksum */
7470
skb_pull_rcsum(skb, QCA_HDR_LEN);
75-
memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - QCA_HDR_LEN,
76-
ETH_HLEN - QCA_HDR_LEN);
71+
dsa_strip_etype_header(skb, QCA_HDR_LEN);
7772

7873
/* Get source port information */
7974
port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK);

net/dsa/tag_rtl4_a.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
4747
dp->index);
4848
skb_push(skb, RTL4_A_HDR_LEN);
4949

50-
memmove(skb->data, skb->data + RTL4_A_HDR_LEN, 2 * ETH_ALEN);
51-
tag = skb->data + 2 * ETH_ALEN;
50+
dsa_alloc_etype_header(skb, RTL4_A_HDR_LEN);
51+
tag = dsa_etype_header_pos_tx(skb);
5252

5353
/* Set Ethertype */
5454
p = (__be16 *)tag;
@@ -76,12 +76,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
7676
if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))
7777
return NULL;
7878

79-
/* The RTL4 header has its own custom Ethertype 0x8899 and that
80-
* starts right at the beginning of the packet, after the src
81-
* ethernet addr. Apparently skb->data always points 2 bytes in,
82-
* behind the Ethertype.
83-
*/
84-
tag = skb->data - 2;
79+
tag = dsa_etype_header_pos_rx(skb);
8580
p = (__be16 *)tag;
8681
etype = ntohs(*p);
8782
if (etype != RTL4_A_ETHERTYPE) {
@@ -108,10 +103,7 @@ static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
108103
/* Remove RTL4 tag and recalculate checksum */
109104
skb_pull_rcsum(skb, RTL4_A_HDR_LEN);
110105

111-
/* Move ethernet DA and SA in front of the data */
112-
memmove(skb->data - ETH_HLEN,
113-
skb->data - ETH_HLEN - RTL4_A_HDR_LEN,
114-
2 * ETH_ALEN);
106+
dsa_strip_etype_header(skb, RTL4_A_HDR_LEN);
115107

116108
dsa_default_offload_fwd_mark(skb);
117109

0 commit comments

Comments
 (0)