Skip to content

Commit

Permalink
mlxsw: spectrum_router: Optimize processing of VRRP MACs
Browse files Browse the repository at this point in the history
Hosts using a VRRP router send their packets with a destination MAC of
the VRRP router which is of the following form [1]:

IPv4 - 00-00-5E-00-01-{VRID}
IPv6 - 00-00-5E-00-02-{VRID}

Where VRID is the ID of the virtual router. Such packets are directed to
the router block in the ASIC by an FDB entry that was added in the
previous patch.

However, in certain cases it is possible to skip this FDB lookup and
send such packets directly to the router. This is accomplished by adding
these special MAC addresses to the RIF cache. If the cache is hit, the
packet will skip the L2 lookup and ingress the router with the RIF
specified in the cache entry.

1. https://tools.ietf.org/html/rfc5798#section-7.3

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ido Schimmel authored and David S. Miller committed Jul 14, 2018
1 parent 11566d3 commit c3a4954
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
14 changes: 14 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -4353,6 +4353,20 @@ MLXSW_ITEM32(reg, ritr, if_swid, 0x08, 24, 8);
*/
MLXSW_ITEM_BUF(reg, ritr, if_mac, 0x12, 6);

/* reg_ritr_if_vrrp_id_ipv6
* VRRP ID for IPv6
* Note: Reserved for RIF types other than VLAN, FID and Sub-port.
* Access: RW
*/
MLXSW_ITEM32(reg, ritr, if_vrrp_id_ipv6, 0x1C, 8, 8);

/* reg_ritr_if_vrrp_id_ipv4
* VRRP ID for IPv4
* Note: Reserved for RIF types other than VLAN, FID and Sub-port.
* Access: RW
*/
MLXSW_ITEM32(reg, ritr, if_vrrp_id_ipv4, 0x1C, 0, 8);

/* VLAN Interface */

/* reg_ritr_vlan_if_vid
Expand Down
52 changes: 52 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
Original file line number Diff line number Diff line change
Expand Up @@ -6449,6 +6449,46 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
return 0;
}

static bool mlxsw_sp_rif_macvlan_is_vrrp4(const u8 *mac)
{
u8 vrrp4[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x01, 0x00 };
u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };

return ether_addr_equal_masked(mac, vrrp4, mask);
}

static bool mlxsw_sp_rif_macvlan_is_vrrp6(const u8 *mac)
{
u8 vrrp6[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x02, 0x00 };
u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };

return ether_addr_equal_masked(mac, vrrp6, mask);
}

static int mlxsw_sp_rif_vrrp_op(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
const u8 *mac, bool adding)
{
char ritr_pl[MLXSW_REG_RITR_LEN];
u8 vrrp_id = adding ? mac[5] : 0;
int err;

if (!mlxsw_sp_rif_macvlan_is_vrrp4(mac) &&
!mlxsw_sp_rif_macvlan_is_vrrp6(mac))
return 0;

mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
if (err)
return err;

if (mlxsw_sp_rif_macvlan_is_vrrp4(mac))
mlxsw_reg_ritr_if_vrrp_id_ipv4_set(ritr_pl, vrrp_id);
else
mlxsw_reg_ritr_if_vrrp_id_ipv6_set(ritr_pl, vrrp_id);

return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
}

static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp,
const struct net_device *macvlan_dev,
struct netlink_ext_ack *extack)
Expand All @@ -6468,13 +6508,23 @@ static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp,
if (err)
return err;

err = mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index,
macvlan_dev->dev_addr, true);
if (err)
goto err_rif_vrrp_add;

/* Make sure the bridge driver does not have this MAC pointing at
* some other port.
*/
if (rif->ops->fdb_del)
rif->ops->fdb_del(rif, macvlan_dev->dev_addr);

return 0;

err_rif_vrrp_add:
mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
return err;
}

void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
Expand All @@ -6489,6 +6539,8 @@ void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
*/
if (!rif)
return;
mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index, macvlan_dev->dev_addr,
false);
mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
mlxsw_sp_fid_index(rif->fid), false);
}
Expand Down

0 comments on commit c3a4954

Please sign in to comment.