diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index ac6348e2ff1f133b3a6dddffaff5a75c3ea19d7b..cafd206e8d7e9d47698a67f9fa741a841ff2fa2b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -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"); - - return -EOPNOTSUPP; -} - -static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr) -{ - struct netdev_notifier_changeupper_info *info = ptr; + if (!netif_is_l3_master(upper_dev)) { + NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type"); + return -EOPNOTSUPP; + } - 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)) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 2ad29ae1c640789549abef36398a6bd5df323802..a60d2bbd3aa6e258e8787a98c1e194d32089e9ed 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -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, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 9ac4f3c003499afb7e0ad88b97232efb22964ba3..9dbb573d53eaf6f5913f4c6bfe96440929d17fcd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -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 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, 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), diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 6e704d807a78cec419771ee1a4eaea1ab5cf478d..37411b74c3e690056f61d93f9fa52e4e14763f59 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -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; diff --git a/tools/testing/selftests/net/forwarding/Makefile b/tools/testing/selftests/net/forwarding/Makefile index 0912f5ae7f6bee2c6299276360208a6bb6300670..b5181b5a8e29035fa4a65185946ddf3b4dec0ecd 100644 --- a/tools/testing/selftests/net/forwarding/Makefile +++ b/tools/testing/selftests/net/forwarding/Makefile @@ -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 \ diff --git a/tools/testing/selftests/net/forwarding/hw_stats_l3.sh b/tools/testing/selftests/net/forwarding/hw_stats_l3.sh index 1c11c4256d06ee046c5addf6d4f3267cf990266e..9c1f76e108af1bff443485d4235933a7bba9af90 100755 --- a/tools/testing/selftests/net/forwarding/hw_stats_l3.sh +++ b/tools/testing/selftests/net/forwarding/hw_stats_l3.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" diff --git a/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh b/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh new file mode 100755 index 0000000000000000000000000000000000000000..eb9ec4a68f84bccea52fbfb43b12434605581343 --- /dev/null +++ b/tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh @@ -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 diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh index 66681a2bcdd3ffb80e0491ac3b2f6f9a97a85130..37ae49d47853686505c5fd6cf5bdbe202e2f8c86 100755 --- a/tools/testing/selftests/net/forwarding/lib.sh +++ b/tools/testing/selftests/net/forwarding/lib.sh @@ -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