Skip to content

Commit f444ef5

Browse files
committed
Merge branch 'dsa-lan9303-IGMP-handling'
Egil Hjelmeland says: ==================== net: dsa: lan9303: IGMP handling Set up the HW switch to trap IGMP packets to CPU port. And make sure skb->offload_fwd_mark is cleared for incoming IGMP packets. skb->offload_fwd_mark calculation is a candidate for consolidation into the DSA core. The calculation can probably be more polished when done at a point where DSA has updated skb. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 940c9c4 + 4672cd3 commit f444ef5

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

drivers/net/dsa/lan9303-core.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@
153153
# define LAN9303_SWE_VLAN_UNTAG_PORT0 BIT(12)
154154
#define LAN9303_SWE_VLAN_CMD_STS 0x1810
155155
#define LAN9303_SWE_GLB_INGRESS_CFG 0x1840
156+
# define LAN9303_SWE_GLB_INGR_IGMP_TRAP BIT(7)
157+
# define LAN9303_SWE_GLB_INGR_IGMP_PORT(p) BIT(10 + p)
156158
#define LAN9303_SWE_PORT_STATE 0x1843
157159
# define LAN9303_SWE_PORT_STATE_FORWARDING_PORT2 (0)
158160
# define LAN9303_SWE_PORT_STATE_LEARNING_PORT2 BIT(5)
@@ -450,6 +452,21 @@ static int lan9303_read_switch_reg(struct lan9303 *chip, u16 regnum, u32 *val)
450452
return ret;
451453
}
452454

455+
static int lan9303_write_switch_reg_mask(struct lan9303 *chip, u16 regnum,
456+
u32 val, u32 mask)
457+
{
458+
int ret;
459+
u32 reg;
460+
461+
ret = lan9303_read_switch_reg(chip, regnum, &reg);
462+
if (ret)
463+
return ret;
464+
465+
reg = (reg & ~mask) | val;
466+
467+
return lan9303_write_switch_reg(chip, regnum, reg);
468+
}
469+
453470
static int lan9303_write_switch_port(struct lan9303 *chip, int port,
454471
u16 regnum, u32 val)
455472
{
@@ -905,6 +922,15 @@ static int lan9303_setup(struct dsa_switch *ds)
905922
if (ret)
906923
dev_err(chip->dev, "failed to re-enable switching %d\n", ret);
907924

925+
/* Trap IGMP to port 0 */
926+
ret = lan9303_write_switch_reg_mask(chip, LAN9303_SWE_GLB_INGRESS_CFG,
927+
LAN9303_SWE_GLB_INGR_IGMP_TRAP |
928+
LAN9303_SWE_GLB_INGR_IGMP_PORT(0),
929+
LAN9303_SWE_GLB_INGR_IGMP_PORT(1) |
930+
LAN9303_SWE_GLB_INGR_IGMP_PORT(2));
931+
if (ret)
932+
dev_err(chip->dev, "failed to setup IGMP trap %d\n", ret);
933+
908934
return 0;
909935
}
910936

net/dsa/tag_lan9303.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
9292
{
9393
u16 *lan9303_tag;
9494
unsigned int source_port;
95+
u16 ether_type_nw;
96+
u8 ip_protocol;
9597

9698
if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
9799
dev_warn_ratelimited(&dev->dev,
@@ -129,6 +131,17 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
129131
skb->offload_fwd_mark = !ether_addr_equal(skb->data - ETH_HLEN,
130132
eth_stp_addr);
131133

134+
/* We also need IGMP packets to have skb->offload_fwd_mark = 0.
135+
* Solving this for all conceivable situations would add more cost to
136+
* every packet. Instead we handle just the common case:
137+
* No VLAN tag + Ethernet II framing.
138+
* Test least probable term first.
139+
*/
140+
ether_type_nw = lan9303_tag[2];
141+
ip_protocol = *(skb->data + 9);
142+
if (ip_protocol == IPPROTO_IGMP && ether_type_nw == htons(ETH_P_IP))
143+
skb->offload_fwd_mark = 0;
144+
132145
return skb;
133146
}
134147

0 commit comments

Comments
 (0)