Skip to content

Commit 3dc80af

Browse files
vladimirolteandavem330
authored andcommitted
net: dsa: introduce a separate cross-chip notifier type for host FDBs
DSA treats some bridge FDB entries by trapping them to the CPU port. Currently, the only class of such entries are FDB addresses learnt by the software bridge on a foreign interface. However there are many more to be added: - FDB entries with the is_local flag (for termination) added by the bridge on the user ports (typically containing the MAC address of the bridge port) - FDB entries pointing towards the bridge net device (for termination). Typically these contain the MAC address of the bridge net device. - Static FDB entries installed on a foreign interface that is in the same bridge with a DSA user port. The reason why a separate cross-chip notifier for host FDBs is justified compared to normal FDBs is the same as in the case of host MDBs: the cross-chip notifier matching function in switch.c should avoid installing these entries on routing ports that route towards the targeted switch, but not towards the CPU. This is required in order to have proper support for H-like multi-chip topologies. Signed-off-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 161ca59 commit 3dc80af

File tree

4 files changed

+90
-5
lines changed

4 files changed

+90
-5
lines changed

net/dsa/dsa_priv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ enum {
2020
DSA_NOTIFIER_BRIDGE_LEAVE,
2121
DSA_NOTIFIER_FDB_ADD,
2222
DSA_NOTIFIER_FDB_DEL,
23+
DSA_NOTIFIER_HOST_FDB_ADD,
24+
DSA_NOTIFIER_HOST_FDB_DEL,
2325
DSA_NOTIFIER_HSR_JOIN,
2426
DSA_NOTIFIER_HSR_LEAVE,
2527
DSA_NOTIFIER_LAG_CHANGE,
@@ -121,6 +123,7 @@ struct dsa_switchdev_event_work {
121123
*/
122124
unsigned char addr[ETH_ALEN];
123125
u16 vid;
126+
bool host_addr;
124127
};
125128

126129
/* DSA_NOTIFIER_HSR_* */
@@ -211,6 +214,10 @@ int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
211214
u16 vid);
212215
int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
213216
u16 vid);
217+
int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr,
218+
u16 vid);
219+
int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr,
220+
u16 vid);
214221
int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data);
215222
int dsa_port_mdb_add(const struct dsa_port *dp,
216223
const struct switchdev_obj_port_mdb *mdb);

net/dsa/port.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,32 @@ int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
646646
return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
647647
}
648648

649+
int dsa_port_host_fdb_add(struct dsa_port *dp, const unsigned char *addr,
650+
u16 vid)
651+
{
652+
struct dsa_notifier_fdb_info info = {
653+
.sw_index = dp->ds->index,
654+
.port = dp->index,
655+
.addr = addr,
656+
.vid = vid,
657+
};
658+
659+
return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_ADD, &info);
660+
}
661+
662+
int dsa_port_host_fdb_del(struct dsa_port *dp, const unsigned char *addr,
663+
u16 vid)
664+
{
665+
struct dsa_notifier_fdb_info info = {
666+
.sw_index = dp->ds->index,
667+
.port = dp->index,
668+
.addr = addr,
669+
.vid = vid,
670+
};
671+
672+
return dsa_port_notify(dp, DSA_NOTIFIER_HOST_FDB_DEL, &info);
673+
}
674+
649675
int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data)
650676
{
651677
struct dsa_switch *ds = dp->ds;

net/dsa/slave.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,8 +2315,12 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
23152315
rtnl_lock();
23162316
switch (switchdev_work->event) {
23172317
case SWITCHDEV_FDB_ADD_TO_DEVICE:
2318-
err = dsa_port_fdb_add(dp, switchdev_work->addr,
2319-
switchdev_work->vid);
2318+
if (switchdev_work->host_addr)
2319+
err = dsa_port_host_fdb_add(dp, switchdev_work->addr,
2320+
switchdev_work->vid);
2321+
else
2322+
err = dsa_port_fdb_add(dp, switchdev_work->addr,
2323+
switchdev_work->vid);
23202324
if (err) {
23212325
dev_err(ds->dev,
23222326
"port %d failed to add %pM vid %d to fdb: %d\n",
@@ -2328,8 +2332,12 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work)
23282332
break;
23292333

23302334
case SWITCHDEV_FDB_DEL_TO_DEVICE:
2331-
err = dsa_port_fdb_del(dp, switchdev_work->addr,
2332-
switchdev_work->vid);
2335+
if (switchdev_work->host_addr)
2336+
err = dsa_port_host_fdb_del(dp, switchdev_work->addr,
2337+
switchdev_work->vid);
2338+
else
2339+
err = dsa_port_fdb_del(dp, switchdev_work->addr,
2340+
switchdev_work->vid);
23332341
if (err) {
23342342
dev_err(ds->dev,
23352343
"port %d failed to delete %pM vid %d from fdb: %d\n",
@@ -2375,6 +2383,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
23752383
struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
23762384
const struct switchdev_notifier_fdb_info *fdb_info;
23772385
struct dsa_switchdev_event_work *switchdev_work;
2386+
bool host_addr = false;
23782387
struct dsa_port *dp;
23792388
int err;
23802389

@@ -2412,7 +2421,8 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
24122421
if (!p)
24132422
return NOTIFY_DONE;
24142423

2415-
dp = p->dp->cpu_dp;
2424+
dp = p->dp;
2425+
host_addr = true;
24162426

24172427
if (!dp->ds->assisted_learning_on_cpu_port)
24182428
return NOTIFY_DONE;
@@ -2442,6 +2452,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
24422452
ether_addr_copy(switchdev_work->addr,
24432453
fdb_info->addr);
24442454
switchdev_work->vid = fdb_info->vid;
2455+
switchdev_work->host_addr = host_addr;
24452456

24462457
/* Hold a reference on the slave for dsa_fdb_offload_notify */
24472458
if (dsa_is_user_port(dp->ds, dp->index))

net/dsa/switch.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,41 @@ static int dsa_switch_do_mdb_del(struct dsa_switch *ds, int port,
253253
return 0;
254254
}
255255

256+
static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
257+
struct dsa_notifier_fdb_info *info)
258+
{
259+
int err = 0;
260+
int port;
261+
262+
if (!ds->ops->port_fdb_add)
263+
return -EOPNOTSUPP;
264+
265+
for (port = 0; port < ds->num_ports; port++) {
266+
if (dsa_switch_host_address_match(ds, port, info->sw_index,
267+
info->port)) {
268+
err = ds->ops->port_fdb_add(ds, port, info->addr,
269+
info->vid);
270+
if (err)
271+
break;
272+
}
273+
}
274+
275+
return err;
276+
}
277+
278+
static int dsa_switch_host_fdb_del(struct dsa_switch *ds,
279+
struct dsa_notifier_fdb_info *info)
280+
{
281+
if (!ds->ops->port_fdb_del)
282+
return -EOPNOTSUPP;
283+
284+
if (ds->index == info->sw_index)
285+
return ds->ops->port_fdb_del(ds, info->port, info->addr,
286+
info->vid);
287+
288+
return 0;
289+
}
290+
256291
static int dsa_switch_fdb_add(struct dsa_switch *ds,
257292
struct dsa_notifier_fdb_info *info)
258293
{
@@ -560,6 +595,12 @@ static int dsa_switch_event(struct notifier_block *nb,
560595
case DSA_NOTIFIER_FDB_DEL:
561596
err = dsa_switch_fdb_del(ds, info);
562597
break;
598+
case DSA_NOTIFIER_HOST_FDB_ADD:
599+
err = dsa_switch_host_fdb_add(ds, info);
600+
break;
601+
case DSA_NOTIFIER_HOST_FDB_DEL:
602+
err = dsa_switch_host_fdb_del(ds, info);
603+
break;
563604
case DSA_NOTIFIER_HSR_JOIN:
564605
err = dsa_switch_hsr_join(ds, info);
565606
break;

0 commit comments

Comments
 (0)