Skip to content

Commit 0293038

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum: Add support for flood control
Add or remove a bridged port from the flooding domain of unknown unicast packets according to user configuration. Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1b3433a commit 0293038

File tree

3 files changed

+78
-37
lines changed

3 files changed

+78
-37
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port)
12271227
mlxsw_sp_port->local_port = local_port;
12281228
mlxsw_sp_port->learning = 1;
12291229
mlxsw_sp_port->learning_sync = 1;
1230+
mlxsw_sp_port->uc_flood = 1;
12301231
mlxsw_sp_port->pvid = 1;
12311232

12321233
mlxsw_sp_port->pcpu_stats =

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ struct mlxsw_sp_port {
8686
u8 stp_state;
8787
u8 learning:1,
8888
learning_sync:1,
89+
uc_flood:1,
8990
bridged:1;
9091
u16 pvid;
9192
/* 802.1Q bridge VLANs */

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

Lines changed: 76 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev,
6666
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
6767
attr->u.brport_flags =
6868
(mlxsw_sp_port->learning ? BR_LEARNING : 0) |
69-
(mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0);
69+
(mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0) |
70+
(mlxsw_sp_port->uc_flood ? BR_FLOOD : 0);
7071
break;
7172
default:
7273
return -EOPNOTSUPP;
@@ -123,15 +124,89 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
123124
return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state);
124125
}
125126

127+
static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
128+
u16 fid_begin, u16 fid_end, bool set,
129+
bool only_uc)
130+
{
131+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
132+
u16 range = fid_end - fid_begin + 1;
133+
char *sftr_pl;
134+
int err;
135+
136+
sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
137+
if (!sftr_pl)
138+
return -ENOMEM;
139+
140+
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin,
141+
MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
142+
mlxsw_sp_port->local_port, set);
143+
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
144+
if (err)
145+
goto buffer_out;
146+
147+
/* Flooding control allows one to decide whether a given port will
148+
* flood unicast traffic for which there is no FDB entry.
149+
*/
150+
if (only_uc)
151+
goto buffer_out;
152+
153+
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin,
154+
MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
155+
mlxsw_sp_port->local_port, set);
156+
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
157+
158+
buffer_out:
159+
kfree(sftr_pl);
160+
return err;
161+
}
162+
163+
static int mlxsw_sp_port_uc_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
164+
bool set)
165+
{
166+
struct net_device *dev = mlxsw_sp_port->dev;
167+
u16 vid, last_visited_vid;
168+
int err;
169+
170+
for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
171+
err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, set,
172+
true);
173+
if (err) {
174+
last_visited_vid = vid;
175+
goto err_port_flood_set;
176+
}
177+
}
178+
179+
return 0;
180+
181+
err_port_flood_set:
182+
for_each_set_bit(vid, mlxsw_sp_port->active_vlans, last_visited_vid)
183+
__mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, !set, true);
184+
netdev_err(dev, "Failed to configure unicast flooding\n");
185+
return err;
186+
}
187+
126188
static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
127189
struct switchdev_trans *trans,
128190
unsigned long brport_flags)
129191
{
192+
unsigned long uc_flood = mlxsw_sp_port->uc_flood ? BR_FLOOD : 0;
193+
bool set;
194+
int err;
195+
130196
if (switchdev_trans_ph_prepare(trans))
131197
return 0;
132198

199+
if ((uc_flood ^ brport_flags) & BR_FLOOD) {
200+
set = mlxsw_sp_port->uc_flood ? false : true;
201+
err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port, set);
202+
if (err)
203+
return err;
204+
}
205+
206+
mlxsw_sp_port->uc_flood = brport_flags & BR_FLOOD ? 1 : 0;
133207
mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0;
134208
mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0;
209+
135210
return 0;
136211
}
137212

@@ -247,42 +322,6 @@ static int mlxsw_sp_port_fid_unmap(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid)
247322
return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, fid, fid);
248323
}
249324

250-
static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
251-
u16 fid_begin, u16 fid_end, bool set,
252-
bool only_uc)
253-
{
254-
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
255-
u16 range = fid_end - fid_begin + 1;
256-
char *sftr_pl;
257-
int err;
258-
259-
sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
260-
if (!sftr_pl)
261-
return -ENOMEM;
262-
263-
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin,
264-
MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
265-
mlxsw_sp_port->local_port, set);
266-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
267-
if (err)
268-
goto buffer_out;
269-
270-
/* Flooding control allows one to decide whether a given port will
271-
* flood unicast traffic for which there is no FDB entry.
272-
*/
273-
if (only_uc)
274-
goto buffer_out;
275-
276-
mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin,
277-
MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range,
278-
mlxsw_sp_port->local_port, set);
279-
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl);
280-
281-
buffer_out:
282-
kfree(sftr_pl);
283-
return err;
284-
}
285-
286325
static int mlxsw_sp_port_add_vids(struct net_device *dev, u16 vid_begin,
287326
u16 vid_end)
288327
{

0 commit comments

Comments
 (0)