Skip to content

Commit 0064b86

Browse files
vladimirolteankuba-moo
authored andcommitted
net: dsa: tag_sja1105: absorb entire sja1105_vlan_rcv() into dsa_8021q_rcv()
tag_sja1105 has a wrapper over dsa_8021q_rcv(): sja1105_vlan_rcv(), which determines whether the packet came from a bridge with vlan_filtering=1 (the case resolved via dsa_find_designated_bridge_port_by_vid()), or if it contains a tag_8021q header. Looking at a new tagger implementation for vsc73xx, based also on tag_8021q, it is becoming clear that the logic is needed there as well. So instead of forcing each tagger to wrap around dsa_8021q_rcv(), let's merge the logic into the core. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Tested-by: Vladimir Oltean <olteanv@gmail.com> Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com> Link: https://patch.msgid.link/20240713211620.1125910-5-paweldembicki@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent dcfe767 commit 0064b86

4 files changed

Lines changed: 34 additions & 36 deletions

File tree

net/dsa/tag_8021q.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -507,27 +507,48 @@ EXPORT_SYMBOL_GPL(dsa_tag_8021q_find_port_by_vbid);
507507
* @vbid: pointer to storage for imprecise bridge ID. Must be pre-initialized
508508
* with -1. If a positive value is returned, the source_port and switch_id
509509
* are invalid.
510+
* @vid: pointer to storage for original VID, in case tag_8021q decoding failed.
511+
*
512+
* If the packet has a tag_8021q header, decode it and set @source_port,
513+
* @switch_id and @vbid, and strip the header. Otherwise set @vid and keep the
514+
* header in the hwaccel area of the packet.
510515
*/
511516
void dsa_8021q_rcv(struct sk_buff *skb, int *source_port, int *switch_id,
512-
int *vbid)
517+
int *vbid, int *vid)
513518
{
514519
int tmp_source_port, tmp_switch_id, tmp_vbid;
515-
u16 vid, tci;
520+
__be16 vlan_proto;
521+
u16 tmp_vid, tci;
516522

517523
if (skb_vlan_tag_present(skb)) {
524+
vlan_proto = skb->vlan_proto;
518525
tci = skb_vlan_tag_get(skb);
519526
__vlan_hwaccel_clear_tag(skb);
520527
} else {
528+
struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
529+
530+
vlan_proto = hdr->h_vlan_proto;
521531
skb_push_rcsum(skb, ETH_HLEN);
522532
__skb_vlan_pop(skb, &tci);
523533
skb_pull_rcsum(skb, ETH_HLEN);
524534
}
525535

526-
vid = tci & VLAN_VID_MASK;
536+
tmp_vid = tci & VLAN_VID_MASK;
537+
if (!vid_is_dsa_8021q(tmp_vid)) {
538+
/* Not a tag_8021q frame, so return the VID to the
539+
* caller for further processing, and put the tag back
540+
*/
541+
if (vid)
542+
*vid = tmp_vid;
543+
544+
__vlan_hwaccel_put_tag(skb, vlan_proto, tci);
545+
546+
return;
547+
}
527548

528-
tmp_source_port = dsa_8021q_rx_source_port(vid);
529-
tmp_switch_id = dsa_8021q_rx_switch_id(vid);
530-
tmp_vbid = dsa_tag_8021q_rx_vbid(vid);
549+
tmp_source_port = dsa_8021q_rx_source_port(tmp_vid);
550+
tmp_switch_id = dsa_8021q_rx_switch_id(tmp_vid);
551+
tmp_vbid = dsa_tag_8021q_rx_vbid(tmp_vid);
531552

532553
/* Precise source port information is unknown when receiving from a
533554
* VLAN-unaware bridging domain, and tmp_source_port and tmp_switch_id
@@ -546,5 +567,6 @@ void dsa_8021q_rcv(struct sk_buff *skb, int *source_port, int *switch_id,
546567
*vbid = tmp_vbid;
547568

548569
skb->priority = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
570+
return;
549571
}
550572
EXPORT_SYMBOL_GPL(dsa_8021q_rcv);

net/dsa/tag_8021q.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct sk_buff *dsa_8021q_xmit(struct sk_buff *skb, struct net_device *netdev,
1414
u16 tpid, u16 tci);
1515

1616
void dsa_8021q_rcv(struct sk_buff *skb, int *source_port, int *switch_id,
17-
int *vbid);
17+
int *vbid, int *vid);
1818

1919
struct net_device *dsa_tag_8021q_find_port_by_vbid(struct net_device *conduit,
2020
int vbid);

net/dsa/tag_ocelot_8021q.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
8181
{
8282
int src_port, switch_id;
8383

84-
dsa_8021q_rcv(skb, &src_port, &switch_id, NULL);
84+
dsa_8021q_rcv(skb, &src_port, &switch_id, NULL, NULL);
8585

8686
skb->dev = dsa_conduit_find_user(netdev, switch_id, src_port);
8787
if (!skb->dev)

net/dsa/tag_sja1105.c

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -472,37 +472,14 @@ static bool sja1110_skb_has_inband_control_extension(const struct sk_buff *skb)
472472
return ntohs(eth_hdr(skb)->h_proto) == ETH_P_SJA1110;
473473
}
474474

475-
/* If the VLAN in the packet is a tag_8021q one, set @source_port and
476-
* @switch_id and strip the header. Otherwise set @vid and keep it in the
477-
* packet.
478-
*/
479-
static void sja1105_vlan_rcv(struct sk_buff *skb, int *source_port,
480-
int *switch_id, int *vbid, u16 *vid)
481-
{
482-
struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
483-
u16 vlan_tci;
484-
485-
if (skb_vlan_tag_present(skb))
486-
vlan_tci = skb_vlan_tag_get(skb);
487-
else
488-
vlan_tci = ntohs(hdr->h_vlan_TCI);
489-
490-
if (vid_is_dsa_8021q(vlan_tci & VLAN_VID_MASK))
491-
return dsa_8021q_rcv(skb, source_port, switch_id, vbid);
492-
493-
/* Try our best with imprecise RX */
494-
*vid = vlan_tci & VLAN_VID_MASK;
495-
}
496-
497475
static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
498476
struct net_device *netdev)
499477
{
500-
int source_port = -1, switch_id = -1, vbid = -1;
478+
int source_port = -1, switch_id = -1, vbid = -1, vid = -1;
501479
struct sja1105_meta meta = {0};
502480
struct ethhdr *hdr;
503481
bool is_link_local;
504482
bool is_meta;
505-
u16 vid;
506483

507484
hdr = eth_hdr(skb);
508485
is_link_local = sja1105_is_link_local(skb);
@@ -525,7 +502,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
525502
* a tag_8021q VLAN which we have to strip
526503
*/
527504
if (sja1105_skb_has_tag_8021q(skb))
528-
sja1105_vlan_rcv(skb, &source_port, &switch_id, &vbid, &vid);
505+
dsa_8021q_rcv(skb, &source_port, &switch_id, &vbid, &vid);
529506
else if (source_port == -1 && switch_id == -1)
530507
/* Packets with no source information have no chance of
531508
* getting accepted, drop them straight away.
@@ -660,9 +637,8 @@ static struct sk_buff *sja1110_rcv_inband_control_extension(struct sk_buff *skb,
660637
static struct sk_buff *sja1110_rcv(struct sk_buff *skb,
661638
struct net_device *netdev)
662639
{
663-
int source_port = -1, switch_id = -1, vbid = -1;
640+
int source_port = -1, switch_id = -1, vbid = -1, vid = -1;
664641
bool host_only = false;
665-
u16 vid = 0;
666642

667643
if (sja1110_skb_has_inband_control_extension(skb)) {
668644
skb = sja1110_rcv_inband_control_extension(skb, &source_port,
@@ -674,7 +650,7 @@ static struct sk_buff *sja1110_rcv(struct sk_buff *skb,
674650

675651
/* Packets with in-band control extensions might still have RX VLANs */
676652
if (likely(sja1105_skb_has_tag_8021q(skb)))
677-
sja1105_vlan_rcv(skb, &source_port, &switch_id, &vbid, &vid);
653+
dsa_8021q_rcv(skb, &source_port, &switch_id, &vbid, &vid);
678654

679655
if (vbid >= 1)
680656
skb->dev = dsa_tag_8021q_find_port_by_vbid(netdev, vbid);

0 commit comments

Comments
 (0)