Skip to content

Commit 6b26b51

Browse files
Arkadi Sharshevskydavem330
authored andcommitted
net: bridge: Add support for notifying devices about FDB add/del
Currently the bridge doesn't notify the underlying devices about new FDBs learned. The FDB sync is placed on the switchdev notifier chain because devices may potentially learn FDB that are not directly related to their ports, for example: 1. Mixed SW/HW bridge - FDBs that point to the ASICs external devices should be offloaded as CPU traps in order to perform forwarding in slow path. 2. EVPN - Externally learned FDBs for the vtep device. Notification is sent only about static FDB add/del. This is done due to fact that currently this is the only scenario supported by switch drivers. Signed-off-by: Arkadi Sharshevsky <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Reviewed-by: Nikolay Aleksandrov <[email protected]> Reviewed-by: Ivan Vecera <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ff5cf10 commit 6b26b51

File tree

7 files changed

+51
-7
lines changed

7 files changed

+51
-7
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1867,7 +1867,7 @@ static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
18671867
if (learning_sync) {
18681868
info.addr = mac;
18691869
info.vid = vid;
1870-
notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
1870+
notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
18711871
call_switchdev_notifiers(notifier_type, dev, &info.info);
18721872
}
18731873
}

drivers/net/ethernet/rocker/rocker_ofdpa.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,10 +1939,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
19391939

19401940
rtnl_lock();
19411941
if (learned && removing)
1942-
call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
1942+
call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
19431943
lw->ofdpa_port->dev, &info.info);
19441944
else if (learned && !removing)
1945-
call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
1945+
call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
19461946
lw->ofdpa_port->dev, &info.info);
19471947
rtnl_unlock();
19481948

include/net/switchdev.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,10 @@ struct switchdev_ops {
155155
};
156156

157157
enum switchdev_notifier_type {
158-
SWITCHDEV_FDB_ADD = 1,
159-
SWITCHDEV_FDB_DEL,
158+
SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
159+
SWITCHDEV_FDB_DEL_TO_BRIDGE,
160+
SWITCHDEV_FDB_ADD_TO_DEVICE,
161+
SWITCHDEV_FDB_DEL_TO_DEVICE,
160162
};
161163

162164
struct switchdev_notifier_info {

net/bridge/br.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,14 @@ static int br_switchdev_event(struct notifier_block *unused,
138138
br = p->br;
139139

140140
switch (event) {
141-
case SWITCHDEV_FDB_ADD:
141+
case SWITCHDEV_FDB_ADD_TO_BRIDGE:
142142
fdb_info = ptr;
143143
err = br_fdb_external_learn_add(br, p, fdb_info->addr,
144144
fdb_info->vid);
145145
if (err)
146146
err = notifier_from_errno(err);
147147
break;
148-
case SWITCHDEV_FDB_DEL:
148+
case SWITCHDEV_FDB_DEL_TO_BRIDGE:
149149
fdb_info = ptr;
150150
err = br_fdb_external_learn_del(br, p, fdb_info->addr,
151151
fdb_info->vid);

net/bridge/br_fdb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ static void fdb_notify(struct net_bridge *br,
690690
struct sk_buff *skb;
691691
int err = -ENOBUFS;
692692

693+
br_switchdev_fdb_notify(fdb, type);
694+
693695
skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
694696
if (skb == NULL)
695697
goto errout;

net/bridge/br_private.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,8 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
10851085
int br_switchdev_set_port_flag(struct net_bridge_port *p,
10861086
unsigned long flags,
10871087
unsigned long mask);
1088+
void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb,
1089+
int type);
10881090
#else
10891091
static inline int nbp_switchdev_mark_set(struct net_bridge_port *p)
10901092
{
@@ -1108,6 +1110,11 @@ static inline int br_switchdev_set_port_flag(struct net_bridge_port *p,
11081110
{
11091111
return 0;
11101112
}
1113+
1114+
static inline void
1115+
br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
1116+
{
1117+
}
11111118
#endif /* CONFIG_NET_SWITCHDEV */
11121119

11131120
#endif

net/bridge/br_switchdev.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,36 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
9898

9999
return 0;
100100
}
101+
102+
static void
103+
br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
104+
u16 vid, struct net_device *dev)
105+
{
106+
struct switchdev_notifier_fdb_info info;
107+
unsigned long notifier_type;
108+
109+
info.addr = mac;
110+
info.vid = vid;
111+
notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
112+
call_switchdev_notifiers(notifier_type, dev, &info.info);
113+
}
114+
115+
void
116+
br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
117+
{
118+
if (!fdb->added_by_user)
119+
return;
120+
121+
switch (type) {
122+
case RTM_DELNEIGH:
123+
br_switchdev_fdb_call_notifiers(false, fdb->addr.addr,
124+
fdb->vlan_id,
125+
fdb->dst->dev);
126+
break;
127+
case RTM_NEWNEIGH:
128+
br_switchdev_fdb_call_notifiers(true, fdb->addr.addr,
129+
fdb->vlan_id,
130+
fdb->dst->dev);
131+
break;
132+
}
133+
}

0 commit comments

Comments
 (0)