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
231 231
232 SWITCHDEV_BRPORT_OFFLOADED,232 SWITCHDEV_BRPORT_OFFLOADED,
233 SWITCHDEV_BRPORT_UNOFFLOADED,233 SWITCHDEV_BRPORT_UNOFFLOADED,
234 SWITCHDEV_BRPORT_REPLAY,
234};235};
235 236
236struct switchdev_notifier_info {237struct switchdev_notifier_info {
@@ -299,6 +300,11 @@ void switchdev_bridge_port_unoffload(struct net_device *brport_dev, · 62 unmodified lines
299 const void *ctx,300 const void *ctx,
300 struct notifier_block *atomic_nb,301 struct notifier_block *atomic_nb,
301 struct notifier_block *blocking_nb);302 struct notifier_block *blocking_nb);
303int 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);
302 308
303void switchdev_deferred_process(void);309void switchdev_deferred_process(void);
304int switchdev_port_attr_set(struct net_device *dev,310int 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
234 br_switchdev_port_unoffload(p, b->ctx, b->atomic_nb,234 br_switchdev_port_unoffload(p, b->ctx, b->atomic_nb,
235 b->blocking_nb);235 b->blocking_nb);
236 break;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
239out:247out:
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
2118 struct notifier_block *atomic_nb,2118 struct notifier_block *atomic_nb,
2119 struct notifier_block *blocking_nb);2119 struct notifier_block *blocking_nb);
2120 2120
2121int 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
2121bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb);2127bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb);
2122 2128
2123void br_switchdev_frame_set_offload_fwd_mark(struct sk_buff *skb);2129void 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
2168{2174{
2169}2175}
2170 2176
2177static inline int
2178br_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
2171static inline bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb)2187static inline bool br_switchdev_frame_uses_tx_fwd_offload(struct sk_buff *skb)
2172{2188{
2173 return false;2189 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
829 829
830 nbp_switchdev_del(p);830 nbp_switchdev_del(p);
831}831}
832
833int 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
862 NULL);862 NULL);
863}863}
864EXPORT_SYMBOL_GPL(switchdev_bridge_port_unoffload);864EXPORT_SYMBOL_GPL(switchdev_bridge_port_unoffload);
865
866int 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}
889EXPORT_SYMBOL_GPL(switchdev_bridge_port_replay);