diff options
author | Ido Schimmel <idosch@mellanox.com> | 2016-08-24 05:18:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-24 12:39:03 -0400 |
commit | f888f58795b640442165e60a6fa93e8e623d01a5 (patch) | |
tree | c3cf1d4eeecd2b51a682a50c6674177b71122096 | |
parent | d7226c7a4dd19929d6df4ae04698da2fcf6f875a (diff) |
mlxsw: spectrum: Add missing flood to router port
In case we have a layer 3 interface on top of a bridge (VLAN / FID RIF),
then we should flood the following packet types to the router:
* Broadcast: If DIP is the broadcast address of the interface, then we
need to be able to get it to CPU by trapping it following route lookup.
* Reserved IP multicast (224.0.0.X): Some control packets (e.g. OSPF)
use this range and are trapped in the router block.
Fixes: 99f44bb3527b ("mlxsw: spectrum: Enable L3 interfaces on top of bridge devices")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/port.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 43 |
2 files changed, 43 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/port.h b/drivers/net/ethernet/mellanox/mlxsw/port.h index f33b997f2b61..af371a82c35b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/port.h +++ b/drivers/net/ethernet/mellanox/mlxsw/port.h | |||
@@ -56,6 +56,7 @@ | |||
56 | #define MLXSW_PORT_PHY_BITS_MASK (MLXSW_PORT_MAX_PHY_PORTS - 1) | 56 | #define MLXSW_PORT_PHY_BITS_MASK (MLXSW_PORT_MAX_PHY_PORTS - 1) |
57 | 57 | ||
58 | #define MLXSW_PORT_CPU_PORT 0x0 | 58 | #define MLXSW_PORT_CPU_PORT 0x0 |
59 | #define MLXSW_PORT_ROUTER_PORT (MLXSW_PORT_MAX_PHY_PORTS + 2) | ||
59 | 60 | ||
60 | #define MLXSW_PORT_DONT_CARE (MLXSW_PORT_MAX_PORTS) | 61 | #define MLXSW_PORT_DONT_CARE (MLXSW_PORT_MAX_PORTS) |
61 | 62 | ||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 1f8168906811..7291f2c4b0c7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c | |||
@@ -3324,6 +3324,39 @@ static struct mlxsw_sp_fid *mlxsw_sp_bridge_fid_get(struct mlxsw_sp *mlxsw_sp, | |||
3324 | return mlxsw_sp_fid_find(mlxsw_sp, fid); | 3324 | return mlxsw_sp_fid_find(mlxsw_sp, fid); |
3325 | } | 3325 | } |
3326 | 3326 | ||
3327 | static enum mlxsw_flood_table_type mlxsw_sp_flood_table_type_get(u16 fid) | ||
3328 | { | ||
3329 | return mlxsw_sp_fid_is_vfid(fid) ? MLXSW_REG_SFGC_TABLE_TYPE_FID : | ||
3330 | MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST; | ||
3331 | } | ||
3332 | |||
3333 | static u16 mlxsw_sp_flood_table_index_get(u16 fid) | ||
3334 | { | ||
3335 | return mlxsw_sp_fid_is_vfid(fid) ? mlxsw_sp_fid_to_vfid(fid) : fid; | ||
3336 | } | ||
3337 | |||
3338 | static int mlxsw_sp_router_port_flood_set(struct mlxsw_sp *mlxsw_sp, u16 fid, | ||
3339 | bool set) | ||
3340 | { | ||
3341 | enum mlxsw_flood_table_type table_type; | ||
3342 | char *sftr_pl; | ||
3343 | u16 index; | ||
3344 | int err; | ||
3345 | |||
3346 | sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); | ||
3347 | if (!sftr_pl) | ||
3348 | return -ENOMEM; | ||
3349 | |||
3350 | table_type = mlxsw_sp_flood_table_type_get(fid); | ||
3351 | index = mlxsw_sp_flood_table_index_get(fid); | ||
3352 | mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, index, table_type, | ||
3353 | 1, MLXSW_PORT_ROUTER_PORT, set); | ||
3354 | err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); | ||
3355 | |||
3356 | kfree(sftr_pl); | ||
3357 | return err; | ||
3358 | } | ||
3359 | |||
3327 | static enum mlxsw_reg_ritr_if_type mlxsw_sp_rif_type_get(u16 fid) | 3360 | static enum mlxsw_reg_ritr_if_type mlxsw_sp_rif_type_get(u16 fid) |
3328 | { | 3361 | { |
3329 | if (mlxsw_sp_fid_is_vfid(fid)) | 3362 | if (mlxsw_sp_fid_is_vfid(fid)) |
@@ -3360,10 +3393,14 @@ static int mlxsw_sp_rif_bridge_create(struct mlxsw_sp *mlxsw_sp, | |||
3360 | if (rif == MLXSW_SP_RIF_MAX) | 3393 | if (rif == MLXSW_SP_RIF_MAX) |
3361 | return -ERANGE; | 3394 | return -ERANGE; |
3362 | 3395 | ||
3363 | err = mlxsw_sp_rif_bridge_op(mlxsw_sp, l3_dev, f->fid, rif, true); | 3396 | err = mlxsw_sp_router_port_flood_set(mlxsw_sp, f->fid, true); |
3364 | if (err) | 3397 | if (err) |
3365 | return err; | 3398 | return err; |
3366 | 3399 | ||
3400 | err = mlxsw_sp_rif_bridge_op(mlxsw_sp, l3_dev, f->fid, rif, true); | ||
3401 | if (err) | ||
3402 | goto err_rif_bridge_op; | ||
3403 | |||
3367 | err = mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, true); | 3404 | err = mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, true); |
3368 | if (err) | 3405 | if (err) |
3369 | goto err_rif_fdb_op; | 3406 | goto err_rif_fdb_op; |
@@ -3385,6 +3422,8 @@ err_rif_alloc: | |||
3385 | mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, false); | 3422 | mlxsw_sp_rif_fdb_op(mlxsw_sp, l3_dev->dev_addr, f->fid, false); |
3386 | err_rif_fdb_op: | 3423 | err_rif_fdb_op: |
3387 | mlxsw_sp_rif_bridge_op(mlxsw_sp, l3_dev, f->fid, rif, false); | 3424 | mlxsw_sp_rif_bridge_op(mlxsw_sp, l3_dev, f->fid, rif, false); |
3425 | err_rif_bridge_op: | ||
3426 | mlxsw_sp_router_port_flood_set(mlxsw_sp, f->fid, false); | ||
3388 | return err; | 3427 | return err; |
3389 | } | 3428 | } |
3390 | 3429 | ||
@@ -3404,6 +3443,8 @@ void mlxsw_sp_rif_bridge_destroy(struct mlxsw_sp *mlxsw_sp, | |||
3404 | 3443 | ||
3405 | mlxsw_sp_rif_bridge_op(mlxsw_sp, l3_dev, f->fid, rif, false); | 3444 | mlxsw_sp_rif_bridge_op(mlxsw_sp, l3_dev, f->fid, rif, false); |
3406 | 3445 | ||
3446 | mlxsw_sp_router_port_flood_set(mlxsw_sp, f->fid, false); | ||
3447 | |||
3407 | netdev_dbg(l3_dev, "RIF=%d destroyed\n", rif); | 3448 | netdev_dbg(l3_dev, "RIF=%d destroyed\n", rif); |
3408 | } | 3449 | } |
3409 | 3450 | ||