if (learning_sync) {
info.addr = mac;
info.vid = vid;
- notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
+ notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
call_switchdev_notifiers(notifier_type, dev, &info.info);
}
}
rtnl_lock();
if (learned && removing)
- call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
+ call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
lw->ofdpa_port->dev, &info.info);
else if (learned && !removing)
- call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
+ call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
lw->ofdpa_port->dev, &info.info);
rtnl_unlock();
};
enum switchdev_notifier_type {
- SWITCHDEV_FDB_ADD = 1,
- SWITCHDEV_FDB_DEL,
+ SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
+ SWITCHDEV_FDB_DEL_TO_BRIDGE,
+ SWITCHDEV_FDB_ADD_TO_DEVICE,
+ SWITCHDEV_FDB_DEL_TO_DEVICE,
};
struct switchdev_notifier_info {
br = p->br;
switch (event) {
- case SWITCHDEV_FDB_ADD:
+ case SWITCHDEV_FDB_ADD_TO_BRIDGE:
fdb_info = ptr;
err = br_fdb_external_learn_add(br, p, fdb_info->addr,
fdb_info->vid);
if (err)
err = notifier_from_errno(err);
break;
- case SWITCHDEV_FDB_DEL:
+ case SWITCHDEV_FDB_DEL_TO_BRIDGE:
fdb_info = ptr;
err = br_fdb_external_learn_del(br, p, fdb_info->addr,
fdb_info->vid);
struct sk_buff *skb;
int err = -ENOBUFS;
+ br_switchdev_fdb_notify(fdb, type);
+
skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
int br_switchdev_set_port_flag(struct net_bridge_port *p,
unsigned long flags,
unsigned long mask);
+void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb,
+ int type);
#else
static inline int nbp_switchdev_mark_set(struct net_bridge_port *p)
{
{
return 0;
}
+
+static inline void
+br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
+{
+}
#endif /* CONFIG_NET_SWITCHDEV */
#endif
return 0;
}
+
+static void
+br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
+ u16 vid, struct net_device *dev)
+{
+ struct switchdev_notifier_fdb_info info;
+ unsigned long notifier_type;
+
+ info.addr = mac;
+ info.vid = vid;
+ notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
+ call_switchdev_notifiers(notifier_type, dev, &info.info);
+}
+
+void
+br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
+{
+ if (!fdb->added_by_user)
+ return;
+
+ switch (type) {
+ case RTM_DELNEIGH:
+ br_switchdev_fdb_call_notifiers(false, fdb->addr.addr,
+ fdb->vlan_id,
+ fdb->dst->dev);
+ break;
+ case RTM_NEWNEIGH:
+ br_switchdev_fdb_call_notifiers(true, fdb->addr.addr,
+ fdb->vlan_id,
+ fdb->dst->dev);
+ break;
+ }
+}