Merge branch 'mlxsw-dedicated-router-notification-block'
Ido Schimmel says: ==================== mlxsw: A dedicated notifier block for router code Petr says: Currently all netdevice events are handled in the centralized notifier handler maintained by spectrum.c. Since a number of events are involving router code, spectrum.c needs to dispatch them to spectrum_router.c. The spectrum module therefore needs to know more about the router code than it should have, and there is are several API points through which the two modules communicate. In this patchset, move bulk of the router-related event handling to the router code. Some of the knowledge has to stay: spectrum.c cannot veto events that the router supports, and vice versa. But beyond that, the two can ignore each other's details, which leads to more focused and simpler code. As a side effect, this fixes L3 HW stats support on tunnel netdevices. The patch set progresses as follows: - In patch #1, change spectrum code to not bounce L3 enslavement, which the router code supports. - In patch #2, add a new do-nothing notifier block to the router code. - In patches #3-#6, move router-specific event handling to the router module. In patch #7, clean up a comment. - In patch #8, use the advantage that all router event handling is in the router code and clean up taking router lock. - mlxsw supports L3 HW stats on tunnels as of this patchset. Patches #9 and #10 therefore add a selftest for L3 HW stats support on tunnels. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
eb60020411
|
@ -3122,9 +3122,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
|
|||
}
|
||||
}
|
||||
|
||||
/* Initialize netdevice notifier after router and SPAN is initialized,
|
||||
* so that the event handler can use router structures and call SPAN
|
||||
* respin.
|
||||
/* Initialize netdevice notifier after SPAN is initialized, so that the
|
||||
* event handler can call SPAN respin.
|
||||
*/
|
||||
mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event;
|
||||
err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
|
||||
|
@ -4525,7 +4524,8 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
|
|||
!netif_is_lag_master(upper_dev) &&
|
||||
!netif_is_bridge_master(upper_dev) &&
|
||||
!netif_is_ovs_master(upper_dev) &&
|
||||
!netif_is_macvlan(upper_dev)) {
|
||||
!netif_is_macvlan(upper_dev) &&
|
||||
!netif_is_l3_master(upper_dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -4724,7 +4724,8 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
|
|||
case NETDEV_PRECHANGEUPPER:
|
||||
upper_dev = info->upper_dev;
|
||||
if (!netif_is_bridge_master(upper_dev) &&
|
||||
!netif_is_macvlan(upper_dev)) {
|
||||
!netif_is_macvlan(upper_dev) &&
|
||||
!netif_is_l3_master(upper_dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -4763,9 +4764,6 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
|
|||
} else if (netif_is_macvlan(upper_dev)) {
|
||||
if (!info->linking)
|
||||
mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
WARN_ON(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -4813,7 +4811,8 @@ static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev,
|
|||
switch (event) {
|
||||
case NETDEV_PRECHANGEUPPER:
|
||||
upper_dev = info->upper_dev;
|
||||
if (!netif_is_macvlan(upper_dev)) {
|
||||
if (!netif_is_macvlan(upper_dev) &&
|
||||
!netif_is_l3_master(upper_dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -4874,7 +4873,9 @@ static int mlxsw_sp_netdevice_bridge_event(struct net_device *br_dev,
|
|||
switch (event) {
|
||||
case NETDEV_PRECHANGEUPPER:
|
||||
upper_dev = info->upper_dev;
|
||||
if (!is_vlan_dev(upper_dev) && !netif_is_macvlan(upper_dev)) {
|
||||
if (!is_vlan_dev(upper_dev) &&
|
||||
!netif_is_macvlan(upper_dev) &&
|
||||
!netif_is_l3_master(upper_dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -4918,25 +4919,20 @@ static int mlxsw_sp_netdevice_macvlan_event(struct net_device *macvlan_dev,
|
|||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(macvlan_dev);
|
||||
struct netdev_notifier_changeupper_info *info = ptr;
|
||||
struct netlink_ext_ack *extack;
|
||||
struct net_device *upper_dev;
|
||||
|
||||
if (!mlxsw_sp || event != NETDEV_PRECHANGEUPPER)
|
||||
return 0;
|
||||
|
||||
extack = netdev_notifier_info_to_extack(&info->info);
|
||||
upper_dev = info->upper_dev;
|
||||
|
||||
/* VRF enslavement is handled in mlxsw_sp_netdevice_vrf_event() */
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
|
||||
if (!netif_is_l3_master(upper_dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
|
||||
{
|
||||
struct netdev_notifier_changeupper_info *info = ptr;
|
||||
|
||||
if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
|
||||
return false;
|
||||
return netif_is_l3_master(info->upper_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_netdevice_vxlan_event(struct mlxsw_sp *mlxsw_sp,
|
||||
|
@ -5007,22 +5003,6 @@ static int mlxsw_sp_netdevice_vxlan_event(struct mlxsw_sp *mlxsw_sp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_netdevice_event_is_router(unsigned long event)
|
||||
{
|
||||
switch (event) {
|
||||
case NETDEV_PRE_CHANGEADDR:
|
||||
case NETDEV_CHANGEADDR:
|
||||
case NETDEV_CHANGEMTU:
|
||||
case NETDEV_OFFLOAD_XSTATS_ENABLE:
|
||||
case NETDEV_OFFLOAD_XSTATS_DISABLE:
|
||||
case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
|
||||
case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
|
@ -5041,16 +5021,6 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
|
|||
|
||||
if (netif_is_vxlan(dev))
|
||||
err = mlxsw_sp_netdevice_vxlan_event(mlxsw_sp, dev, event, ptr);
|
||||
if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
|
||||
err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
|
||||
event, ptr);
|
||||
else if (mlxsw_sp_netdev_is_ipip_ul(mlxsw_sp, dev))
|
||||
err = mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, dev,
|
||||
event, ptr);
|
||||
else if (mlxsw_sp_netdevice_event_is_router(event))
|
||||
err = mlxsw_sp_netdevice_router_port_event(dev, event, ptr);
|
||||
else if (mlxsw_sp_is_vrf_event(event, ptr))
|
||||
err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
|
||||
else if (mlxsw_sp_port_dev_check(dev))
|
||||
err = mlxsw_sp_netdevice_port_event(dev, dev, event, ptr);
|
||||
else if (netif_is_lag_master(dev))
|
||||
|
|
|
@ -718,29 +718,12 @@ union mlxsw_sp_l3addr {
|
|||
int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
|
||||
struct netlink_ext_ack *extack);
|
||||
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp);
|
||||
int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
|
||||
unsigned long event, void *ptr);
|
||||
void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *macvlan_dev);
|
||||
int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr);
|
||||
int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr);
|
||||
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
|
||||
struct netdev_notifier_changeupper_info *info);
|
||||
bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *dev);
|
||||
bool mlxsw_sp_netdev_is_ipip_ul(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *dev);
|
||||
int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *l3_dev,
|
||||
unsigned long event,
|
||||
struct netdev_notifier_info *info);
|
||||
int
|
||||
mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *l3_dev,
|
||||
unsigned long event,
|
||||
struct netdev_notifier_info *info);
|
||||
int
|
||||
mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
|
||||
struct net_device *l3_dev,
|
||||
|
|
|
@ -1530,8 +1530,8 @@ static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *dev)
|
||||
static bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *dev)
|
||||
{
|
||||
return mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
|
||||
}
|
||||
|
@ -1575,16 +1575,10 @@ mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp *mlxsw_sp,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool mlxsw_sp_netdev_is_ipip_ul(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *dev)
|
||||
static bool mlxsw_sp_netdev_is_ipip_ul(struct mlxsw_sp *mlxsw_sp,
|
||||
const struct net_device *dev)
|
||||
{
|
||||
bool is_ipip_ul;
|
||||
|
||||
mutex_lock(&mlxsw_sp->router->lock);
|
||||
is_ipip_ul = mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp, dev, NULL);
|
||||
mutex_unlock(&mlxsw_sp->router->lock);
|
||||
|
||||
return is_ipip_ul;
|
||||
return mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp, dev, NULL);
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp *mlxsw_sp,
|
||||
|
@ -1960,16 +1954,15 @@ static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp *mlxsw_sp,
|
|||
}
|
||||
}
|
||||
|
||||
int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *ol_dev,
|
||||
unsigned long event,
|
||||
struct netdev_notifier_info *info)
|
||||
static int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *ol_dev,
|
||||
unsigned long event,
|
||||
struct netdev_notifier_info *info)
|
||||
{
|
||||
struct netdev_notifier_changeupper_info *chup;
|
||||
struct netlink_ext_ack *extack;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&mlxsw_sp->router->lock);
|
||||
switch (event) {
|
||||
case NETDEV_REGISTER:
|
||||
err = mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp, ol_dev);
|
||||
|
@ -2000,7 +1993,6 @@ int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
|
|||
err = mlxsw_sp_netdevice_ipip_ol_update_mtu(mlxsw_sp, ol_dev);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&mlxsw_sp->router->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2038,16 +2030,15 @@ __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *ul_dev,
|
||||
unsigned long event,
|
||||
struct netdev_notifier_info *info)
|
||||
{
|
||||
struct mlxsw_sp_ipip_entry *ipip_entry = NULL;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
mutex_lock(&mlxsw_sp->router->lock);
|
||||
while ((ipip_entry = mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp,
|
||||
ul_dev,
|
||||
ipip_entry))) {
|
||||
|
@ -2060,7 +2051,7 @@ mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
|
|||
if (err) {
|
||||
mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp,
|
||||
ul_dev);
|
||||
break;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (demote_this) {
|
||||
|
@ -2077,9 +2068,8 @@ mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
|
|||
ipip_entry = prev;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mlxsw_sp->router->lock);
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
|
||||
|
@ -9378,6 +9368,19 @@ static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
|
|||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
|
||||
{
|
||||
switch (event) {
|
||||
case NETDEV_OFFLOAD_XSTATS_ENABLE:
|
||||
case NETDEV_OFFLOAD_XSTATS_DISABLE:
|
||||
case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
|
||||
case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_router_port_offload_xstats_cmd(struct mlxsw_sp_rif *rif,
|
||||
unsigned long event,
|
||||
|
@ -9407,45 +9410,60 @@ mlxsw_sp_router_port_offload_xstats_cmd(struct mlxsw_sp_rif *rif,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
|
||||
unsigned long event, void *ptr)
|
||||
static int
|
||||
mlxsw_sp_netdevice_offload_xstats_cmd(struct mlxsw_sp *mlxsw_sp,
|
||||
struct net_device *dev,
|
||||
unsigned long event,
|
||||
struct netdev_notifier_offload_xstats_info *info)
|
||||
{
|
||||
struct mlxsw_sp_rif *rif;
|
||||
|
||||
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
|
||||
if (!rif)
|
||||
return 0;
|
||||
|
||||
return mlxsw_sp_router_port_offload_xstats_cmd(rif, event, info);
|
||||
}
|
||||
|
||||
static bool mlxsw_sp_is_router_event(unsigned long event)
|
||||
{
|
||||
switch (event) {
|
||||
case NETDEV_PRE_CHANGEADDR:
|
||||
case NETDEV_CHANGEADDR:
|
||||
case NETDEV_CHANGEMTU:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr);
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
struct mlxsw_sp_rif *rif;
|
||||
int err = 0;
|
||||
|
||||
mlxsw_sp = mlxsw_sp_lower_get(dev);
|
||||
if (!mlxsw_sp)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&mlxsw_sp->router->lock);
|
||||
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
|
||||
if (!rif)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_CHANGEMTU:
|
||||
case NETDEV_CHANGEADDR:
|
||||
err = mlxsw_sp_router_port_change_event(mlxsw_sp, rif, extack);
|
||||
break;
|
||||
return mlxsw_sp_router_port_change_event(mlxsw_sp, rif, extack);
|
||||
case NETDEV_PRE_CHANGEADDR:
|
||||
err = mlxsw_sp_router_port_pre_changeaddr_event(rif, ptr);
|
||||
break;
|
||||
case NETDEV_OFFLOAD_XSTATS_ENABLE:
|
||||
case NETDEV_OFFLOAD_XSTATS_DISABLE:
|
||||
case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
|
||||
case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
|
||||
err = mlxsw_sp_router_port_offload_xstats_cmd(rif, event, ptr);
|
||||
break;
|
||||
return mlxsw_sp_router_port_pre_changeaddr_event(rif, ptr);
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&mlxsw_sp->router->lock);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
|
||||
|
@ -9476,8 +9494,18 @@ static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
|
|||
__mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, NULL);
|
||||
}
|
||||
|
||||
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
|
||||
struct netdev_notifier_changeupper_info *info)
|
||||
static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
|
||||
{
|
||||
struct netdev_notifier_changeupper_info *info = ptr;
|
||||
|
||||
if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
|
||||
return false;
|
||||
return netif_is_l3_master(info->upper_dev);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
|
||||
struct netdev_notifier_changeupper_info *info)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
|
||||
int err = 0;
|
||||
|
@ -9488,7 +9516,6 @@ int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
|
|||
if (!mlxsw_sp || netif_is_macvlan(l3_dev))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&mlxsw_sp->router->lock);
|
||||
switch (event) {
|
||||
case NETDEV_PRECHANGEUPPER:
|
||||
break;
|
||||
|
@ -9503,11 +9530,42 @@ int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
|
|||
}
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&mlxsw_sp->router->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct mlxsw_sp_router *router;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
int err = 0;
|
||||
|
||||
router = container_of(nb, struct mlxsw_sp_router, netdevice_nb);
|
||||
mlxsw_sp = router->mlxsw_sp;
|
||||
|
||||
mutex_lock(&mlxsw_sp->router->lock);
|
||||
|
||||
if (mlxsw_sp_is_offload_xstats_event(event))
|
||||
err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
|
||||
event, ptr);
|
||||
else if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
|
||||
err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
|
||||
event, ptr);
|
||||
else if (mlxsw_sp_netdev_is_ipip_ul(mlxsw_sp, dev))
|
||||
err = mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, dev,
|
||||
event, ptr);
|
||||
else if (mlxsw_sp_is_router_event(event))
|
||||
err = mlxsw_sp_netdevice_router_port_event(dev, event, ptr);
|
||||
else if (mlxsw_sp_is_vrf_event(event, ptr))
|
||||
err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
|
||||
|
||||
mutex_unlock(&mlxsw_sp->router->lock);
|
||||
|
||||
return notifier_from_errno(err);
|
||||
}
|
||||
|
||||
static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev,
|
||||
struct netdev_nested_priv *priv)
|
||||
{
|
||||
|
@ -10692,8 +10750,18 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
|
|||
if (err)
|
||||
goto err_register_fib_notifier;
|
||||
|
||||
mlxsw_sp->router->netdevice_nb.notifier_call =
|
||||
mlxsw_sp_router_netdevice_event;
|
||||
err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
|
||||
&mlxsw_sp->router->netdevice_nb);
|
||||
if (err)
|
||||
goto err_register_netdev_notifier;
|
||||
|
||||
return 0;
|
||||
|
||||
err_register_netdev_notifier:
|
||||
unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
|
||||
&mlxsw_sp->router->fib_nb);
|
||||
err_register_fib_notifier:
|
||||
unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
|
||||
&mlxsw_sp->router->nexthop_nb);
|
||||
|
@ -10741,6 +10809,8 @@ err_router_ops_init:
|
|||
|
||||
void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
|
||||
&mlxsw_sp->router->netdevice_nb);
|
||||
unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
|
||||
&mlxsw_sp->router->fib_nb);
|
||||
unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
|
||||
|
|
|
@ -67,6 +67,7 @@ struct mlxsw_sp_router {
|
|||
struct notifier_block netevent_nb;
|
||||
struct notifier_block inetaddr_nb;
|
||||
struct notifier_block inet6addr_nb;
|
||||
struct notifier_block netdevice_nb;
|
||||
const struct mlxsw_sp_rif_ops **rif_ops_arr;
|
||||
const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
|
||||
struct mlxsw_sp_router_nve_decap nve_decap_config;
|
||||
|
|
|
@ -20,6 +20,7 @@ TEST_PROGS = bridge_igmp.sh \
|
|||
gre_multipath_nh.sh \
|
||||
gre_multipath.sh \
|
||||
hw_stats_l3.sh \
|
||||
hw_stats_l3_gre.sh \
|
||||
ip6_forward_instats_vrf.sh \
|
||||
ip6gre_custom_multipath_hash.sh \
|
||||
ip6gre_flat_key.sh \
|
||||
|
|
|
@ -162,14 +162,6 @@ ping_ipv6()
|
|||
ping_test $h1.200 2001:db8:2::1 " IPv6"
|
||||
}
|
||||
|
||||
get_l3_stat()
|
||||
{
|
||||
local selector=$1; shift
|
||||
|
||||
ip -j stats show dev $rp1.200 group offload subgroup l3_stats |
|
||||
jq '.[0].stats64.'$selector
|
||||
}
|
||||
|
||||
send_packets_rx_ipv4()
|
||||
{
|
||||
# Send 21 packets instead of 20, because the first one might trap and go
|
||||
|
@ -208,11 +200,11 @@ ___test_stats()
|
|||
local a
|
||||
local b
|
||||
|
||||
a=$(get_l3_stat ${dir}.packets)
|
||||
a=$(hw_stats_get l3_stats $rp1.200 ${dir} packets)
|
||||
send_packets_${dir}_${prot}
|
||||
"$@"
|
||||
b=$(busywait "$TC_HIT_TIMEOUT" until_counter_is ">= $a + 20" \
|
||||
get_l3_stat ${dir}.packets)
|
||||
hw_stats_get l3_stats $rp1.200 ${dir} packets)
|
||||
check_err $? "Traffic not reflected in the counter: $a -> $b"
|
||||
}
|
||||
|
||||
|
@ -281,11 +273,11 @@ __test_stats_report()
|
|||
|
||||
RET=0
|
||||
|
||||
a=$(get_l3_stat ${dir}.packets)
|
||||
a=$(hw_stats_get l3_stats $rp1.200 ${dir} packets)
|
||||
send_packets_${dir}_${prot}
|
||||
ip address flush dev $rp1.200
|
||||
b=$(busywait "$TC_HIT_TIMEOUT" until_counter_is ">= $a + 20" \
|
||||
get_l3_stat ${dir}.packets)
|
||||
hw_stats_get l3_stats $rp1.200 ${dir} packets)
|
||||
check_err $? "Traffic not reflected in the counter: $a -> $b"
|
||||
log_test "Test ${dir} packets: stats pushed on loss of L3"
|
||||
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# Test L3 stats on IP-in-IP GRE tunnel without key.
|
||||
|
||||
# This test uses flat topology for IP tunneling tests. See ipip_lib.sh for more
|
||||
# details.
|
||||
|
||||
ALL_TESTS="
|
||||
ping_ipv4
|
||||
test_stats_rx
|
||||
test_stats_tx
|
||||
"
|
||||
NUM_NETIFS=6
|
||||
source lib.sh
|
||||
source ipip_lib.sh
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
ol1=${NETIFS[p2]}
|
||||
|
||||
ul1=${NETIFS[p3]}
|
||||
ul2=${NETIFS[p4]}
|
||||
|
||||
ol2=${NETIFS[p5]}
|
||||
h2=${NETIFS[p6]}
|
||||
|
||||
ol1mac=$(mac_get $ol1)
|
||||
|
||||
forwarding_enable
|
||||
vrf_prepare
|
||||
h1_create
|
||||
h2_create
|
||||
sw1_flat_create gre $ol1 $ul1
|
||||
sw2_flat_create gre $ol2 $ul2
|
||||
ip stats set dev g1a l3_stats on
|
||||
ip stats set dev g2a l3_stats on
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
||||
ip stats set dev g1a l3_stats off
|
||||
ip stats set dev g2a l3_stats off
|
||||
|
||||
sw2_flat_destroy $ol2 $ul2
|
||||
sw1_flat_destroy $ol1 $ul1
|
||||
h2_destroy
|
||||
h1_destroy
|
||||
|
||||
vrf_cleanup
|
||||
forwarding_restore
|
||||
}
|
||||
|
||||
ping_ipv4()
|
||||
{
|
||||
RET=0
|
||||
|
||||
ping_test $h1 192.0.2.18 " gre flat"
|
||||
}
|
||||
|
||||
send_packets_ipv4()
|
||||
{
|
||||
# Send 21 packets instead of 20, because the first one might trap and go
|
||||
# through the SW datapath, which might not bump the HW counter.
|
||||
$MZ $h1 -c 21 -d 20msec -p 100 \
|
||||
-a own -b $ol1mac -A 192.0.2.1 -B 192.0.2.18 \
|
||||
-q -t udp sp=54321,dp=12345
|
||||
}
|
||||
|
||||
test_stats()
|
||||
{
|
||||
local dev=$1; shift
|
||||
local dir=$1; shift
|
||||
|
||||
local a
|
||||
local b
|
||||
|
||||
RET=0
|
||||
|
||||
a=$(hw_stats_get l3_stats $dev $dir packets)
|
||||
send_packets_ipv4
|
||||
b=$(busywait "$TC_HIT_TIMEOUT" until_counter_is ">= $a + 20" \
|
||||
hw_stats_get l3_stats $dev $dir packets)
|
||||
check_err $? "Traffic not reflected in the counter: $a -> $b"
|
||||
|
||||
log_test "Test $dir packets: $prot"
|
||||
}
|
||||
|
||||
test_stats_tx()
|
||||
{
|
||||
test_stats g1a tx
|
||||
}
|
||||
|
||||
test_stats_rx()
|
||||
{
|
||||
test_stats g2a rx
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
|
@ -828,6 +828,17 @@ ipv6_stats_get()
|
|||
cat /proc/net/dev_snmp6/$dev | grep "^$stat" | cut -f2
|
||||
}
|
||||
|
||||
hw_stats_get()
|
||||
{
|
||||
local suite=$1; shift
|
||||
local if_name=$1; shift
|
||||
local dir=$1; shift
|
||||
local stat=$1; shift
|
||||
|
||||
ip -j stats show dev $if_name group offload subgroup $suite |
|
||||
jq ".[0].stats64.$dir.$stat"
|
||||
}
|
||||
|
||||
humanize()
|
||||
{
|
||||
local speed=$1; shift
|
||||
|
|
Loading…
Reference in New Issue