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

net: switchdev: Add a helper to replay objects on a bridge port

When a front panel joins a bridge via another netdevice (typically a LAG),
the driver needs to learn about the objects configured on the bridge port.
When the bridge port is offloaded by the driver for the first time, this
can be achieved by passing a notifier to switchdev_bridge_port_offload().
The notifier is then invoked for the individual objects (such as VLANs)
configured on the bridge, and can look for the interesting ones.

Calling switchdev_bridge_port_offload() when the second port joins the
bridge lower is unnecessary, but the replay is still needed. To that end,
add a new function, switchdev_bridge_port_replay(), which does only the
replay part of the _offload() function in exactly the same way as that
function.

Cc: Jiri Pirko <jiri@resnulli.us>
Cc: Ivan Vecera <ivecera@redhat.com>
Cc: Roopa Prabhu <roopa@nvidia.com>
Cc: Nikolay Aleksandrov <razor@blackwall.org>
Cc: bridge@lists.linux-foundation.org
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Petr Machata and committed by
David S. Miller
f2e2857b 989280d6

+64
+6
include/net/switchdev.h
··· 231 231 232 232 SWITCHDEV_BRPORT_OFFLOADED, 233 233 SWITCHDEV_BRPORT_UNOFFLOADED, 234 + SWITCHDEV_BRPORT_REPLAY, 234 235 }; 235 236 236 237 struct switchdev_notifier_info { ··· 300 299 const void *ctx, 301 300 struct notifier_block *atomic_nb, 302 301 struct notifier_block *blocking_nb); 302 + int switchdev_bridge_port_replay(struct net_device *brport_dev, 303 + struct net_device *dev, const void *ctx, 304 + struct notifier_block *atomic_nb, 305 + struct notifier_block *blocking_nb, 306 + struct netlink_ext_ack *extack); 303 307 304 308 void switchdev_deferred_process(void); 305 309 int switchdev_port_attr_set(struct net_device *dev,
+8
net/bridge/br.c
··· 234 234 br_switchdev_port_unoffload(p, b->ctx, b->atomic_nb, 235 235 b->blocking_nb); 236 236 break; 237 + case SWITCHDEV_BRPORT_REPLAY: 238 + brport_info = ptr; 239 + b = &brport_info->brport; 240 + 241 + err = br_switchdev_port_replay(p, b->dev, b->ctx, b->atomic_nb, 242 + b->blocking_nb, extack); 243 + err = notifier_from_errno(err); 244 + break; 237 245 } 238 246 239 247 out:
+16
net/bridge/br_private.h
··· 2118 2118 struct notifier_block *atomic_nb, 2119 2119 struct notifier_block *blocking_nb); 2120 2120 2121 + int br_switchdev_port_replay(struct net_bridge_port *p, 2122 + struct net_device *dev, const void *ctx, 2123 + struct notifier_block *atomic_nb, 2124 + struct notifier_block *blocking_nb, 2125 + struct netlink_ext_ack *extack); 2126 + 2121 2127 bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb); 2122 2128 2123 2129 void br_switchdev_frame_set_offload_fwd_mark(struct sk_buff *skb); ··· 2172 2166 struct notifier_block *atomic_nb, 2173 2167 struct notifier_block *blocking_nb) 2174 2168 { 2169 + } 2170 + 2171 + static inline int 2172 + br_switchdev_port_replay(struct net_bridge_port *p, 2173 + struct net_device *dev, const void *ctx, 2174 + struct notifier_block *atomic_nb, 2175 + struct notifier_block *blocking_nb, 2176 + struct netlink_ext_ack *extack) 2177 + { 2178 + return -EOPNOTSUPP; 2175 2179 } 2176 2180 2177 2181 static inline bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb)
+9
net/bridge/br_switchdev.c
··· 829 829 830 830 nbp_switchdev_del(p); 831 831 } 832 + 833 + int br_switchdev_port_replay(struct net_bridge_port *p, 834 + struct net_device *dev, const void *ctx, 835 + struct notifier_block *atomic_nb, 836 + struct notifier_block *blocking_nb, 837 + struct netlink_ext_ack *extack) 838 + { 839 + return nbp_switchdev_sync_objs(p, ctx, atomic_nb, blocking_nb, extack); 840 + }
+25
net/switchdev/switchdev.c
··· 862 862 NULL); 863 863 } 864 864 EXPORT_SYMBOL_GPL(switchdev_bridge_port_unoffload); 865 + 866 + int switchdev_bridge_port_replay(struct net_device *brport_dev, 867 + struct net_device *dev, const void *ctx, 868 + struct notifier_block *atomic_nb, 869 + struct notifier_block *blocking_nb, 870 + struct netlink_ext_ack *extack) 871 + { 872 + struct switchdev_notifier_brport_info brport_info = { 873 + .brport = { 874 + .dev = dev, 875 + .ctx = ctx, 876 + .atomic_nb = atomic_nb, 877 + .blocking_nb = blocking_nb, 878 + }, 879 + }; 880 + int err; 881 + 882 + ASSERT_RTNL(); 883 + 884 + err = call_switchdev_blocking_notifiers(SWITCHDEV_BRPORT_REPLAY, 885 + brport_dev, &brport_info.info, 886 + extack); 887 + return notifier_to_errno(err); 888 + } 889 + EXPORT_SYMBOL_GPL(switchdev_bridge_port_replay);