Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: bridge: add per-port group_fwd_mask with less restrictions

We need to be able to transparently forward most link-local frames via
tunnels (e.g. vxlan, qinq). Currently the bridge's group_fwd_mask has a
mask which restricts the forwarding of STP and LACP, but we need to be able
to forward these over tunnels and control that forwarding on a per-port
basis thus add a new per-port group_fwd_mask option which only disallows
mac pause frames to be forwarded (they're always dropped anyway).
The patch does not change the current default situation - all of the others
are still restricted unless configured for forwarding.
We have successfully tested this patch with LACP and STP forwarding over
VxLAN and qinq tunnels.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Nikolay Aleksandrov and committed by
David S. Miller
5af48b59 de9c8a6a

+42 -2
+1
include/uapi/linux/if_link.h
··· 325 325 IFLA_BRPORT_MCAST_TO_UCAST, 326 326 IFLA_BRPORT_VLAN_TUNNEL, 327 327 IFLA_BRPORT_BCAST_FLOOD, 328 + IFLA_BRPORT_GROUP_FWD_MASK, 328 329 __IFLA_BRPORT_MAX 329 330 }; 330 331 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
+1
net/bridge/br_input.c
··· 289 289 * 290 290 * Others reserved for future standardization 291 291 */ 292 + fwd_mask |= p->group_fwd_mask; 292 293 switch (dest[5]) { 293 294 case 0x00: /* Bridge Group Address */ 294 295 /* If STP is turned off,
+13 -1
net/bridge/br_netlink.c
··· 152 152 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 153 153 + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MULTICAST_ROUTER */ 154 154 #endif 155 + + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_GROUP_FWD_MASK */ 155 156 + 0; 156 157 } 157 158 ··· 209 208 p->topology_change_ack) || 210 209 nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) || 211 210 nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags & 212 - BR_VLAN_TUNNEL))) 211 + BR_VLAN_TUNNEL)) || 212 + nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask)) 213 213 return -EMSGSIZE; 214 214 215 215 timerval = br_timer_value(&p->message_age_timer); ··· 639 637 [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 }, 640 638 [IFLA_BRPORT_MCAST_FLOOD] = { .type = NLA_U8 }, 641 639 [IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 }, 640 + [IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NLA_U16 }, 642 641 }; 643 642 644 643 /* Change the state of the port and notify spanning tree */ ··· 776 773 return err; 777 774 } 778 775 #endif 776 + 777 + if (tb[IFLA_BRPORT_GROUP_FWD_MASK]) { 778 + u16 fwd_mask = nla_get_u16(tb[IFLA_BRPORT_GROUP_FWD_MASK]); 779 + 780 + if (fwd_mask & BR_GROUPFWD_MACPAUSE) 781 + return -EINVAL; 782 + p->group_fwd_mask = fwd_mask; 783 + } 784 + 779 785 br_port_flags_change(p, old_flags ^ p->flags); 780 786 return 0; 781 787 }
+9 -1
net/bridge/br_private.h
··· 36 36 /* Control of forwarding link local multicast */ 37 37 #define BR_GROUPFWD_DEFAULT 0 38 38 /* Don't allow forwarding of control protocols like STP, MAC PAUSE and LACP */ 39 - #define BR_GROUPFWD_RESTRICTED 0x0007u 39 + enum { 40 + BR_GROUPFWD_STP = BIT(0), 41 + BR_GROUPFWD_MACPAUSE = BIT(1), 42 + BR_GROUPFWD_LACP = BIT(2), 43 + }; 44 + 45 + #define BR_GROUPFWD_RESTRICTED (BR_GROUPFWD_STP | BR_GROUPFWD_MACPAUSE | \ 46 + BR_GROUPFWD_LACP) 40 47 /* The Nearest Customer Bridge Group Address, 01-80-C2-00-00-[00,0B,0C,0D,0F] */ 41 48 #define BR_GROUPFWD_8021AD 0xB801u 42 49 ··· 275 268 #ifdef CONFIG_NET_SWITCHDEV 276 269 int offload_fwd_mark; 277 270 #endif 271 + u16 group_fwd_mask; 278 272 }; 279 273 280 274 #define br_auto_port(p) ((p)->flags & BR_AUTO_MASK)
+18
net/bridge/br_sysfs_if.c
··· 165 165 } 166 166 static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); 167 167 168 + static ssize_t show_group_fwd_mask(struct net_bridge_port *p, char *buf) 169 + { 170 + return sprintf(buf, "%#x\n", p->group_fwd_mask); 171 + } 172 + 173 + static int store_group_fwd_mask(struct net_bridge_port *p, 174 + unsigned long v) 175 + { 176 + if (v & BR_GROUPFWD_MACPAUSE) 177 + return -EINVAL; 178 + p->group_fwd_mask = v; 179 + 180 + return 0; 181 + } 182 + static BRPORT_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask, 183 + store_group_fwd_mask); 184 + 168 185 BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); 169 186 BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); 170 187 BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); ··· 240 223 &brport_attr_proxyarp_wifi, 241 224 &brport_attr_multicast_flood, 242 225 &brport_attr_broadcast_flood, 226 + &brport_attr_group_fwd_mask, 243 227 NULL 244 228 }; 245 229