History

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.

Petr Machata committed 3 years ago

Commit f2e28571 parent 989280d5 files · +64 −0Browse files

Unified · Split

5 files
  1. include/net/switchdev.h +6 −0
  2. net/bridge/br.c +8 −0
  3. net/bridge/br_private.h +16 −0
  4. net/bridge/br_switchdev.c +9 −0
  5. net/switchdev/switchdev.c +25 −0
include/net/switchdev.h+6−0
@@ -231,6 +231,7 @@ enum switchdev_notifier_type { · 230 unmodified lines
231231
232232 SWITCHDEV_BRPORT_OFFLOADED,
233233 SWITCHDEV_BRPORT_UNOFFLOADED,
234+ SWITCHDEV_BRPORT_REPLAY,
234235 };
235236
236237 struct switchdev_notifier_info {
@@ -299,6 +300,11 @@ void switchdev_bridge_port_unoffload(struct net_device *brport_dev, · 62 unmodified lines
299300 const void *ctx,
300301 struct notifier_block *atomic_nb,
301302 struct notifier_block *blocking_nb);
303+int switchdev_bridge_port_replay(struct net_device *brport_dev,
304+ struct net_device *dev, const void *ctx,
305+ struct notifier_block *atomic_nb,
306+ struct notifier_block *blocking_nb,
307+ struct netlink_ext_ack *extack);
302308
303309 void switchdev_deferred_process(void);
304310 int switchdev_port_attr_set(struct net_device *dev,
net/bridge/br.c+8−0
@@ -234,6 +234,14 @@ static int br_switchdev_blocking_event(struct notifier_block *nb, · 233 unmodified lines
234234 br_switchdev_port_unoffload(p, b->ctx, b->atomic_nb,
235235 b->blocking_nb);
236236 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;
237245 }
238246
239247 out:
net/bridge/br_private.h+16−0
@@ -2118,6 +2118,12 @@ void br_switchdev_port_unoffload(struct net_bridge_port *p, const void *ctx, · 2117 unmodified lines
21182118 struct notifier_block *atomic_nb,
21192119 struct notifier_block *blocking_nb);
21202120
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+
21212127 bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb);
21222128
21232129 void br_switchdev_frame_set_offload_fwd_mark(struct sk_buff *skb);
@@ -2168,6 +2174,16 @@ br_switchdev_port_unoffload(struct net_bridge_port *p, const void *ctx, · 44 unmodified lines
21682174 {
21692175 }
21702176
2177+static inline int
2178+br_switchdev_port_replay(struct net_bridge_port *p,
2179+ struct net_device *dev, const void *ctx,
2180+ struct notifier_block *atomic_nb,
2181+ struct notifier_block *blocking_nb,
2182+ struct netlink_ext_ack *extack)
2183+{
2184+ return -EOPNOTSUPP;
2185+}
2186+
21712187 static inline bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb)
21722188 {
21732189 return false;
net/bridge/br_switchdev.c+9−0
@@ -829,3 +829,12 @@ void br_switchdev_port_unoffload(struct net_bridge_port *p, const void *ctx, · 828 unmodified lines
829829
830830 nbp_switchdev_del(p);
831831 }
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+}
net/switchdev/switchdev.c+25−0
@@ -862,3 +862,28 @@ void switchdev_bridge_port_unoffload(struct net_device *brport_dev, · 861 unmodified lines
862862 NULL);
863863 }
864864 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);