Commit 99724c18 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

mlxsw: spectrum: Introduce support for router interfaces

Up until now we only supported bridged interfaces. Packets ingressing
through the switch ports were either classified to FIDs (in the case of
the VLAN-aware bridge) or vFIDs (in the case of VLAN-unaware bridges).
The packets were then forwarded according to the FDB. Routing was done
entirely in slowpath, by splitting the vFID range in two and using the
lower 0.5K vFIDs as dummy bridges that simply flooded all incoming
traffic to the CPU.

Instead, allow packets to be routed in the device by creating router
interfaces (RIFs) that will direct them to the router block.
Specifically, the RIFs introduced here are Sub-port RIFs used for VLAN
devices and port netdevs. Packets ingressing from the {Port / LAG ID, VID}
with which the RIF was programmed with will be assigned to a special
kind of FIDs called rFIDs and from there directed to the router.

Create a RIF whenever the first IPv4 address was programmed on a VLAN /
LAG / port netdev. Destroy it upon removal of the last IPv4 address.
Receive these notifications by registering for the 'inetaddr'
notification chain. A non-zero (10) priority is used for the
notification block, so that RIFs will be created before routes are
offloaded via FIB code.

Note that another trigger for RIF destruction are CHANGEUPPER
notifications causing the underlying FID's reference count to go down to
zero. This can happen, for example, when a VLAN netdev with an IP address
is put under bridge. While this configuration doesn't make sense it does
cause the device and the kernel to get out of sync when the netdev is
unbridged. We intend to address this in the future, hopefully in current
cycle.

Finally, Remove the lower 0.5K vFIDs, as they are deprecated by the RIFs,
which will trap packets according to their DIP.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6e095fd4
...@@ -50,9 +50,10 @@ ...@@ -50,9 +50,10 @@
#include "core.h" #include "core.h"
#define MLXSW_SP_VFID_BASE VLAN_N_VID #define MLXSW_SP_VFID_BASE VLAN_N_VID
#define MLXSW_SP_VFID_PORT_MAX 512 /* Non-bridged VLAN interfaces */ #define MLXSW_SP_VFID_MAX 6656 /* Bridged VLAN interfaces */
#define MLXSW_SP_VFID_BR_MAX 6144 /* Bridged VLAN interfaces */
#define MLXSW_SP_VFID_MAX (MLXSW_SP_VFID_PORT_MAX + MLXSW_SP_VFID_BR_MAX) #define MLXSW_SP_RFID_BASE 15360
#define MLXSW_SP_RIF_MAX 800
#define MLXSW_SP_LAG_MAX 64 #define MLXSW_SP_LAG_MAX 64
#define MLXSW_SP_PORT_PER_LAG_MAX 16 #define MLXSW_SP_PORT_PER_LAG_MAX 16
...@@ -81,8 +82,6 @@ ...@@ -81,8 +82,6 @@
#define MLXSW_SP_CELL_FACTOR 2 /* 2 * cell_size / (IPG + cell_size + 1) */ #define MLXSW_SP_CELL_FACTOR 2 /* 2 * cell_size / (IPG + cell_size + 1) */
#define MLXSW_SP_RIF_MAX 800
static inline u16 mlxsw_sp_pfc_delay_get(int mtu, u16 delay) static inline u16 mlxsw_sp_pfc_delay_get(int mtu, u16 delay)
{ {
delay = MLXSW_SP_BYTES_TO_CELLS(DIV_ROUND_UP(delay, BITS_PER_BYTE)); delay = MLXSW_SP_BYTES_TO_CELLS(DIV_ROUND_UP(delay, BITS_PER_BYTE));
...@@ -101,12 +100,13 @@ struct mlxsw_sp_fid { ...@@ -101,12 +100,13 @@ struct mlxsw_sp_fid {
struct list_head list; struct list_head list;
unsigned int ref_count; unsigned int ref_count;
struct net_device *dev; struct net_device *dev;
struct mlxsw_sp_rif *r;
u16 fid; u16 fid;
u16 vid;
}; };
struct mlxsw_sp_rif { struct mlxsw_sp_rif {
struct net_device *dev; struct net_device *dev;
unsigned int ref_count;
struct mlxsw_sp_fid *f; struct mlxsw_sp_fid *f;
unsigned char addr[ETH_ALEN]; unsigned char addr[ETH_ALEN];
int mtu; int mtu;
...@@ -133,7 +133,17 @@ static inline u16 mlxsw_sp_fid_to_vfid(u16 fid) ...@@ -133,7 +133,17 @@ static inline u16 mlxsw_sp_fid_to_vfid(u16 fid)
static inline bool mlxsw_sp_fid_is_vfid(u16 fid) static inline bool mlxsw_sp_fid_is_vfid(u16 fid)
{ {
return fid >= MLXSW_SP_VFID_BASE; return fid >= MLXSW_SP_VFID_BASE && fid < MLXSW_SP_RFID_BASE;
}
static inline bool mlxsw_sp_fid_is_rfid(u16 fid)
{
return fid >= MLXSW_SP_RFID_BASE;
}
static inline u16 mlxsw_sp_rif_sp_to_fid(u16 rif)
{
return MLXSW_SP_RFID_BASE + rif;
} }
struct mlxsw_sp_sb_pr { struct mlxsw_sp_sb_pr {
...@@ -207,11 +217,7 @@ struct mlxsw_sp_router { ...@@ -207,11 +217,7 @@ struct mlxsw_sp_router {
struct mlxsw_sp { struct mlxsw_sp {
struct { struct {
struct list_head list; struct list_head list;
DECLARE_BITMAP(mapped, MLXSW_SP_VFID_PORT_MAX); DECLARE_BITMAP(mapped, MLXSW_SP_VFID_MAX);
} port_vfids;
struct {
struct list_head list;
DECLARE_BITMAP(mapped, MLXSW_SP_VFID_BR_MAX);
} br_vfids; } br_vfids;
struct { struct {
struct list_head list; struct list_head list;
......
...@@ -166,11 +166,6 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -166,11 +166,6 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state); return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state);
} }
static bool mlxsw_sp_vfid_is_vport_br(u16 vfid)
{
return vfid >= MLXSW_SP_VFID_PORT_MAX;
}
static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 idx_begin, u16 idx_end, bool set, u16 idx_begin, u16 idx_end, bool set,
bool only_uc) bool only_uc)
...@@ -182,15 +177,10 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -182,15 +177,10 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
char *sftr_pl; char *sftr_pl;
int err; int err;
if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) { if (mlxsw_sp_port_is_vport(mlxsw_sp_port))
table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID; table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID;
if (mlxsw_sp_vfid_is_vport_br(idx_begin))
local_port = mlxsw_sp_port->local_port;
else else
local_port = MLXSW_PORT_CPU_PORT;
} else {
table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST; table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST;
}
sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL);
if (!sftr_pl) if (!sftr_pl)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment