mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-20 07:26:49 +07:00
Merge branch 'mlxsw-Add-layer-3-devlink-trap-support'
Ido Schimmel says: ==================== mlxsw: Add layer 3 devlink-trap support This patch set from Amit adds support in mlxsw for layer 3 traps that can report drops and exceptions via devlink-trap. In a similar fashion to the existing layer 2 traps, these traps can send packets to the CPU that were not routed as intended by the underlying device. The traps are divided between the two types detailed in devlink-trap documentation: drops and exceptions. Unlike drops, packets received via exception traps are also injected to the kernel's receive path, as they are required for the correct functioning of the control plane. For example, packets trapped due to TTL error must be injected to kernel's receive path for traceroute to work properly. Patch set overview: Patch #1 adds the layer 3 drop traps to devlink along with their documentation. Patch #2 adds support for layer 3 drop traps in mlxsw. Patches #3-#5 add selftests for layer 3 drop traps. Patch #6 adds the layer 3 exception traps to devlink along with their documentation. Patches #7-#9 gradually add support for layer 3 exception traps in mlxsw. Patches #10-#12 add selftests for layer 3 exception traps. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7b89c580fb
@ -162,6 +162,67 @@ be added to the following table:
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they could not be
|
||||
enqueued to a transmission queue which is full
|
||||
* - ``non_ip``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to
|
||||
undergo a layer 3 lookup, but are not IP or MPLS packets
|
||||
* - ``uc_dip_over_mc_dmac``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed and they have a unicast destination IP and a multicast destination
|
||||
MAC
|
||||
* - ``dip_is_loopback_address``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed and their destination IP is the loopback address (i.e., 127.0.0.0/8
|
||||
and ::1/128)
|
||||
* - ``sip_is_mc``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed and their source IP is multicast (i.e., 224.0.0.0/8 and ff::/8)
|
||||
* - ``sip_is_loopback_address``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed and their source IP is the loopback address (i.e., 127.0.0.0/8 and ::1/128)
|
||||
* - ``ip_header_corrupted``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed and their IP header is corrupted: wrong checksum, wrong IP version
|
||||
or too short Internet Header Length (IHL)
|
||||
* - ``ipv4_sip_is_limited_bc``
|
||||
- ``drop``
|
||||
- Traps packets that the device decided to drop because they need to be
|
||||
routed and their source IP is limited broadcast (i.e., 255.255.255.255/32)
|
||||
* - ``ipv6_mc_dip_reserved_scope``
|
||||
- ``drop``
|
||||
- Traps IPv6 packets that the device decided to drop because they need to
|
||||
be routed and their IPv6 multicast destination IP has a reserved scope
|
||||
(i.e., ffx0::/16)
|
||||
* - ``ipv6_mc_dip_interface_local_scope``
|
||||
- ``drop``
|
||||
- Traps IPv6 packets that the device decided to drop because they need to
|
||||
be routed and their IPv6 multicast destination IP has an interface-local scope
|
||||
(i.e., ffx1::/16)
|
||||
* - ``mtu_value_is_too_small``
|
||||
- ``exception``
|
||||
- Traps packets that should have been routed by the device, but were bigger
|
||||
than the MTU of the egress interface
|
||||
* - ``unresolved_neigh``
|
||||
- ``exception``
|
||||
- Traps packets that did not have a matching IP neighbour after routing
|
||||
* - ``mc_reverse_path_forwarding``
|
||||
- ``exception``
|
||||
- Traps multicast IP packets that failed reverse-path forwarding (RPF)
|
||||
check during multicast routing
|
||||
* - ``reject_route``
|
||||
- ``exception``
|
||||
- Traps packets that hit reject routes (i.e., "unreachable", "prohibit")
|
||||
* - ``ipv4_lpm_miss``
|
||||
- ``exception``
|
||||
- Traps unicast IPv4 packets that did not match any route
|
||||
* - ``ipv6_lpm_miss``
|
||||
- ``exception``
|
||||
- Traps unicast IPv6 packets that did not match any route
|
||||
|
||||
Driver-specific Packet Traps
|
||||
============================
|
||||
|
@ -5480,6 +5480,7 @@ enum mlxsw_reg_htgt_trap_group {
|
||||
enum mlxsw_reg_htgt_discard_trap_group {
|
||||
MLXSW_REG_HTGT_DISCARD_TRAP_GROUP_BASE = MLXSW_REG_HTGT_TRAP_GROUP_MAX,
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS,
|
||||
MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS,
|
||||
};
|
||||
|
||||
/* reg_htgt_trap_group
|
||||
|
@ -4512,8 +4512,6 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
|
||||
MLXSW_SP_RXL_NO_MARK(IPV6_MLDV2_LISTENER_REPORT, TRAP_TO_CPU, IPV6_MLD,
|
||||
false),
|
||||
/* L3 traps */
|
||||
MLXSW_SP_RXL_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false),
|
||||
MLXSW_SP_RXL_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false),
|
||||
MLXSW_SP_RXL_L3_MARK(LBERROR, MIRROR_TO_CPU, LBERROR, false),
|
||||
MLXSW_SP_RXL_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false),
|
||||
MLXSW_SP_RXL_MARK(IPV6_UNSPECIFIED_ADDRESS, TRAP_TO_CPU, ROUTER_EXP,
|
||||
@ -4540,8 +4538,6 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
|
||||
MLXSW_SP_RXL_MARK(L3_IPV6_REDIRECTION, TRAP_TO_CPU, IPV6_ND, false),
|
||||
MLXSW_SP_RXL_MARK(IPV6_MC_LINK_LOCAL_DEST, TRAP_TO_CPU, ROUTER_EXP,
|
||||
false),
|
||||
MLXSW_SP_RXL_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, HOST_MISS, false),
|
||||
MLXSW_SP_RXL_MARK(HOST_MISS_IPV6, TRAP_TO_CPU, HOST_MISS, false),
|
||||
MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, TRAP_TO_CPU, ROUTER_EXP, false),
|
||||
MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, TRAP_TO_CPU, ROUTER_EXP, false),
|
||||
MLXSW_SP_RXL_MARK(IPIP_DECAP_ERROR, TRAP_TO_CPU, ROUTER_EXP, false),
|
||||
@ -4556,7 +4552,6 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
|
||||
/* Multicast Router Traps */
|
||||
MLXSW_SP_RXL_MARK(IPV4_PIM, TRAP_TO_CPU, PIM, false),
|
||||
MLXSW_SP_RXL_MARK(IPV6_PIM, TRAP_TO_CPU, PIM, false),
|
||||
MLXSW_SP_RXL_MARK(RPF, TRAP_TO_CPU, RPF, false),
|
||||
MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false),
|
||||
MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false),
|
||||
/* NVE traps */
|
||||
|
@ -77,6 +77,7 @@ struct mlxsw_sp_router {
|
||||
struct notifier_block inet6addr_nb;
|
||||
const struct mlxsw_sp_rif_ops **rif_ops_arr;
|
||||
const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
|
||||
u32 adj_discard_index;
|
||||
};
|
||||
|
||||
struct mlxsw_sp_rif {
|
||||
@ -367,6 +368,7 @@ enum mlxsw_sp_fib_entry_type {
|
||||
MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
|
||||
MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
|
||||
MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE,
|
||||
MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE,
|
||||
|
||||
/* This is a special case of local delivery, where a packet should be
|
||||
* decapsulated on reception. Note that there is no corresponding ENCAP,
|
||||
@ -4196,15 +4198,31 @@ mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl,
|
||||
}
|
||||
}
|
||||
|
||||
static int mlxsw_sp_adj_discard_write(struct mlxsw_sp *mlxsw_sp, u16 rif_index)
|
||||
{
|
||||
u32 adj_discard_index = mlxsw_sp->router->adj_discard_index;
|
||||
enum mlxsw_reg_ratr_trap_action trap_action;
|
||||
char ratr_pl[MLXSW_REG_RATR_LEN];
|
||||
|
||||
trap_action = MLXSW_REG_RATR_TRAP_ACTION_DISCARD_ERRORS;
|
||||
mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
|
||||
MLXSW_REG_RATR_TYPE_ETHERNET, adj_discard_index,
|
||||
rif_index);
|
||||
mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
|
||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib_entry *fib_entry,
|
||||
enum mlxsw_reg_ralue_op op)
|
||||
{
|
||||
struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
|
||||
char ralue_pl[MLXSW_REG_RALUE_LEN];
|
||||
enum mlxsw_reg_ralue_trap_action trap_action;
|
||||
u16 trap_id = 0;
|
||||
u32 adjacency_index = 0;
|
||||
u16 ecmp_size = 0;
|
||||
int err;
|
||||
|
||||
/* In case the nexthop group adjacency index is valid, use it
|
||||
* with provided ECMP size. Otherwise, setup trap and pass
|
||||
@ -4214,6 +4232,15 @@ static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
|
||||
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
|
||||
adjacency_index = fib_entry->nh_group->adj_index;
|
||||
ecmp_size = fib_entry->nh_group->ecmp_size;
|
||||
} else if (!nh_group->adj_index_valid && nh_group->count &&
|
||||
nh_group->nh_rif) {
|
||||
err = mlxsw_sp_adj_discard_write(mlxsw_sp,
|
||||
nh_group->nh_rif->rif_index);
|
||||
if (err)
|
||||
return err;
|
||||
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
|
||||
adjacency_index = mlxsw_sp->router->adj_discard_index;
|
||||
ecmp_size = 1;
|
||||
} else {
|
||||
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
|
||||
trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
|
||||
@ -4273,6 +4300,23 @@ static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp,
|
||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_fib_entry_op_unreachable(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib_entry *fib_entry,
|
||||
enum mlxsw_reg_ralue_op op)
|
||||
{
|
||||
enum mlxsw_reg_ralue_trap_action trap_action;
|
||||
char ralue_pl[MLXSW_REG_RALUE_LEN];
|
||||
u16 trap_id;
|
||||
|
||||
trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
|
||||
trap_id = MLXSW_TRAP_ID_RTR_INGRESS1;
|
||||
|
||||
mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
|
||||
mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, 0);
|
||||
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_fib_entry *fib_entry,
|
||||
@ -4314,6 +4358,9 @@ static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
|
||||
return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
|
||||
case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
|
||||
return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op);
|
||||
case MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE:
|
||||
return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp, fib_entry,
|
||||
op);
|
||||
case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
|
||||
return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
|
||||
fib_entry, op);
|
||||
@ -4391,7 +4438,7 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
|
||||
* can do so with a lower priority than packets directed
|
||||
* at the host, so use action type local instead of trap.
|
||||
*/
|
||||
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
|
||||
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
|
||||
return 0;
|
||||
case RTN_UNICAST:
|
||||
if (mlxsw_sp_fi_is_gateway(mlxsw_sp, fi))
|
||||
@ -5351,7 +5398,7 @@ static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
|
||||
else if (rt->fib6_type == RTN_BLACKHOLE)
|
||||
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
|
||||
else if (rt->fib6_flags & RTF_REJECT)
|
||||
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
|
||||
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
|
||||
else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
|
||||
fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
|
||||
else
|
||||
@ -8123,6 +8170,11 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
|
||||
if (err)
|
||||
goto err_neigh_init;
|
||||
|
||||
err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
|
||||
&router->adj_discard_index);
|
||||
if (err)
|
||||
goto err_adj_discard_index_alloc;
|
||||
|
||||
mlxsw_sp->router->netevent_nb.notifier_call =
|
||||
mlxsw_sp_router_netevent_event;
|
||||
err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
|
||||
@ -8151,6 +8203,9 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
|
||||
err_mp_hash_init:
|
||||
unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
|
||||
err_register_netevent_notifier:
|
||||
mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
|
||||
router->adj_discard_index);
|
||||
err_adj_discard_index_alloc:
|
||||
mlxsw_sp_neigh_fini(mlxsw_sp);
|
||||
err_neigh_init:
|
||||
mlxsw_sp_vrs_fini(mlxsw_sp);
|
||||
@ -8182,6 +8237,8 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
|
||||
unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
|
||||
&mlxsw_sp->router->fib_nb);
|
||||
unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
|
||||
mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
|
||||
mlxsw_sp->router->adj_discard_index);
|
||||
mlxsw_sp_neigh_fini(mlxsw_sp);
|
||||
mlxsw_sp_vrs_fini(mlxsw_sp);
|
||||
mlxsw_sp_mr_fini(mlxsw_sp);
|
||||
|
@ -13,16 +13,27 @@
|
||||
|
||||
static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
|
||||
void *priv);
|
||||
static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
|
||||
void *trap_ctx);
|
||||
|
||||
#define MLXSW_SP_TRAP_DROP(_id, _group_id) \
|
||||
DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
|
||||
DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
|
||||
MLXSW_SP_TRAP_METADATA)
|
||||
|
||||
#define MLXSW_SP_TRAP_EXCEPTION(_id, _group_id) \
|
||||
DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
|
||||
DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
|
||||
MLXSW_SP_TRAP_METADATA)
|
||||
|
||||
#define MLXSW_SP_RXL_DISCARD(_id, _group_id) \
|
||||
MLXSW_RXL(mlxsw_sp_rx_drop_listener, DISCARD_##_id, SET_FW_DEFAULT, \
|
||||
false, SP_##_group_id, DISCARD)
|
||||
|
||||
#define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action) \
|
||||
MLXSW_RXL(mlxsw_sp_rx_exception_listener, _id, \
|
||||
_action, false, SP_##_group_id, DISCARD)
|
||||
|
||||
static struct devlink_trap mlxsw_sp_traps_arr[] = {
|
||||
MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS),
|
||||
@ -30,6 +41,23 @@ static struct devlink_trap mlxsw_sp_traps_arr[] = {
|
||||
MLXSW_SP_TRAP_DROP(INGRESS_STP_FILTER, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(EMPTY_TX_LIST, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(PORT_LOOPBACK_FILTER, L2_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(NON_IP_PACKET, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(UC_DIP_MC_DMAC, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(DIP_LB, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(SIP_MC, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(SIP_LB, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(CORRUPTED_IP_HDR, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(IPV4_SIP_BC, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_RESERVED_SCOPE, L3_DROPS),
|
||||
MLXSW_SP_TRAP_DROP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(MTU_ERROR, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(TTL_ERROR, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(RPF, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(REJECT_ROUTE, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(UNRESOLVED_NEIGH, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(IPV4_LPM_UNICAST_MISS, L3_DROPS),
|
||||
MLXSW_SP_TRAP_EXCEPTION(IPV6_LPM_UNICAST_MISS, L3_DROPS),
|
||||
};
|
||||
|
||||
static struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
|
||||
@ -40,6 +68,28 @@ static struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
|
||||
MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_UC, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_MC_NULL, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(LOOKUP_SWITCH_LB, L2_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ROUTER2, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_NON_IP_PACKET, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_UC_DIP_MC_DMAC, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_DIP_LB, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_MC, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_SIP_LB, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_CORRUPTED_IP_HDR, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(ING_ROUTER_IPV4_SIP_BC, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_RESERVED_SCOPE, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_DISCARD(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, L3_DISCARDS),
|
||||
MLXSW_SP_RXL_EXCEPTION(MTUERROR, ROUTER_EXP, TRAP_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(TTLERROR, ROUTER_EXP, TRAP_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(RPF, RPF, TRAP_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(RTR_INGRESS1, REMOTE_ROUTE, TRAP_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV4, HOST_MISS, TRAP_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(HOST_MISS_IPV6, HOST_MISS, TRAP_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER3, REMOTE_ROUTE,
|
||||
TRAP_EXCEPTION_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM4, ROUTER_EXP,
|
||||
TRAP_EXCEPTION_TO_CPU),
|
||||
MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6, ROUTER_EXP,
|
||||
TRAP_EXCEPTION_TO_CPU),
|
||||
};
|
||||
|
||||
/* Mapping between hardware trap and devlink trap. Multiple hardware traps can
|
||||
@ -54,6 +104,25 @@ static u16 mlxsw_sp_listener_devlink_map[] = {
|
||||
DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST,
|
||||
DEVLINK_TRAP_GENERIC_ID_EMPTY_TX_LIST,
|
||||
DEVLINK_TRAP_GENERIC_ID_PORT_LOOPBACK_FILTER,
|
||||
DEVLINK_TRAP_GENERIC_ID_BLACKHOLE_ROUTE,
|
||||
DEVLINK_TRAP_GENERIC_ID_NON_IP_PACKET,
|
||||
DEVLINK_TRAP_GENERIC_ID_UC_DIP_MC_DMAC,
|
||||
DEVLINK_TRAP_GENERIC_ID_DIP_LB,
|
||||
DEVLINK_TRAP_GENERIC_ID_SIP_MC,
|
||||
DEVLINK_TRAP_GENERIC_ID_SIP_LB,
|
||||
DEVLINK_TRAP_GENERIC_ID_CORRUPTED_IP_HDR,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV4_SIP_BC,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV6_MC_DIP_RESERVED_SCOPE,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
|
||||
DEVLINK_TRAP_GENERIC_ID_MTU_ERROR,
|
||||
DEVLINK_TRAP_GENERIC_ID_TTL_ERROR,
|
||||
DEVLINK_TRAP_GENERIC_ID_RPF,
|
||||
DEVLINK_TRAP_GENERIC_ID_REJECT_ROUTE,
|
||||
DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
|
||||
DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
|
||||
DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV4_LPM_UNICAST_MISS,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV6_LPM_UNICAST_MISS,
|
||||
};
|
||||
|
||||
static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
|
||||
@ -104,6 +173,30 @@ static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
|
||||
consume_skb(skb);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
|
||||
void *trap_ctx)
|
||||
{
|
||||
struct devlink_port *in_devlink_port;
|
||||
struct mlxsw_sp_port *mlxsw_sp_port;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
struct devlink *devlink;
|
||||
|
||||
mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
|
||||
mlxsw_sp_port = mlxsw_sp->ports[local_port];
|
||||
|
||||
if (mlxsw_sp_rx_listener(mlxsw_sp, skb, local_port, mlxsw_sp_port))
|
||||
return;
|
||||
|
||||
devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
in_devlink_port = mlxsw_core_port_devlink_port_get(mlxsw_sp->core,
|
||||
local_port);
|
||||
skb_push(skb, ETH_HLEN);
|
||||
devlink_trap_report(devlink, skb, trap_ctx, in_devlink_port);
|
||||
skb_pull(skb, ETH_HLEN);
|
||||
skb->offload_fwd_mark = 1;
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
|
||||
{
|
||||
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
|
||||
@ -211,6 +304,7 @@ mlxsw_sp_trap_group_policer_init(struct mlxsw_sp *mlxsw_sp,
|
||||
u32 rate;
|
||||
|
||||
switch (group->id) {
|
||||
case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS:/* fall through */
|
||||
case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS:
|
||||
policer_id = MLXSW_SP_DISCARD_POLICER_ID;
|
||||
ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
|
||||
@ -242,6 +336,12 @@ __mlxsw_sp_trap_group_init(struct mlxsw_sp *mlxsw_sp,
|
||||
priority = 0;
|
||||
tc = 1;
|
||||
break;
|
||||
case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS:
|
||||
group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS;
|
||||
policer_id = MLXSW_SP_DISCARD_POLICER_ID;
|
||||
priority = 0;
|
||||
tc = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ enum {
|
||||
MLXSW_TRAP_ID_IPV6_DHCP = 0x69,
|
||||
MLXSW_TRAP_ID_IPV6_ALL_ROUTERS_LINK = 0x6F,
|
||||
MLXSW_TRAP_ID_RTR_INGRESS0 = 0x70,
|
||||
MLXSW_TRAP_ID_RTR_INGRESS1 = 0x71,
|
||||
MLXSW_TRAP_ID_IPV6_PIM = 0x79,
|
||||
MLXSW_TRAP_ID_IPV6_VRRP = 0x7A,
|
||||
MLXSW_TRAP_ID_IPV4_BGP = 0x88,
|
||||
@ -66,6 +67,8 @@ enum {
|
||||
MLXSW_TRAP_ID_NVE_ENCAP_ARP = 0xBD,
|
||||
MLXSW_TRAP_ID_ROUTER_ALERT_IPV4 = 0xD6,
|
||||
MLXSW_TRAP_ID_ROUTER_ALERT_IPV6 = 0xD7,
|
||||
MLXSW_TRAP_ID_DISCARD_ROUTER2 = 0x130,
|
||||
MLXSW_TRAP_ID_DISCARD_ROUTER3 = 0x131,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_PACKET_SMAC_MC = 0x140,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_SWITCH_VTAG_ALLOW = 0x148,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_SWITCH_VLAN = 0x149,
|
||||
@ -73,6 +76,18 @@ enum {
|
||||
MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_UC = 0x150,
|
||||
MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_MC_NULL = 0x151,
|
||||
MLXSW_TRAP_ID_DISCARD_LOOKUP_SWITCH_LB = 0x152,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_NON_IP_PACKET = 0x160,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_UC_DIP_MC_DMAC = 0x161,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_DIP_LB = 0x162,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_SIP_MC = 0x163,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_SIP_LB = 0x165,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_CORRUPTED_IP_HDR = 0x167,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_SIP_BC = 0x16A,
|
||||
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_DIP_LOCAL_NET = 0x16B,
|
||||
MLXSW_TRAP_ID_DISCARD_ROUTER_LPM4 = 0x17B,
|
||||
MLXSW_TRAP_ID_DISCARD_ROUTER_LPM6 = 0x17C,
|
||||
MLXSW_TRAP_ID_DISCARD_IPV6_MC_DIP_RESERVED_SCOPE = 0x1B0,
|
||||
MLXSW_TRAP_ID_DISCARD_IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE = 0x1B1,
|
||||
MLXSW_TRAP_ID_ACL0 = 0x1C0,
|
||||
/* Multicast trap used for routes with trap action */
|
||||
MLXSW_TRAP_ID_ACL1 = 0x1C1,
|
||||
|
@ -569,6 +569,21 @@ enum devlink_trap_generic_id {
|
||||
DEVLINK_TRAP_GENERIC_ID_BLACKHOLE_ROUTE,
|
||||
DEVLINK_TRAP_GENERIC_ID_TTL_ERROR,
|
||||
DEVLINK_TRAP_GENERIC_ID_TAIL_DROP,
|
||||
DEVLINK_TRAP_GENERIC_ID_NON_IP_PACKET,
|
||||
DEVLINK_TRAP_GENERIC_ID_UC_DIP_MC_DMAC,
|
||||
DEVLINK_TRAP_GENERIC_ID_DIP_LB,
|
||||
DEVLINK_TRAP_GENERIC_ID_SIP_MC,
|
||||
DEVLINK_TRAP_GENERIC_ID_SIP_LB,
|
||||
DEVLINK_TRAP_GENERIC_ID_CORRUPTED_IP_HDR,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV4_SIP_BC,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV6_MC_DIP_RESERVED_SCOPE,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE,
|
||||
DEVLINK_TRAP_GENERIC_ID_MTU_ERROR,
|
||||
DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
|
||||
DEVLINK_TRAP_GENERIC_ID_RPF,
|
||||
DEVLINK_TRAP_GENERIC_ID_REJECT_ROUTE,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV4_LPM_UNICAST_MISS,
|
||||
DEVLINK_TRAP_GENERIC_ID_IPV6_LPM_UNICAST_MISS,
|
||||
|
||||
/* Add new generic trap IDs above */
|
||||
__DEVLINK_TRAP_GENERIC_ID_MAX,
|
||||
@ -607,6 +622,36 @@ enum devlink_trap_group_generic_id {
|
||||
"ttl_value_is_too_small"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_TAIL_DROP \
|
||||
"tail_drop"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_NON_IP_PACKET \
|
||||
"non_ip"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_UC_DIP_MC_DMAC \
|
||||
"uc_dip_over_mc_dmac"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_DIP_LB \
|
||||
"dip_is_loopback_address"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_SIP_MC \
|
||||
"sip_is_mc"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_SIP_LB \
|
||||
"sip_is_loopback_address"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_CORRUPTED_IP_HDR \
|
||||
"ip_header_corrupted"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_IPV4_SIP_BC \
|
||||
"ipv4_sip_is_limited_bc"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_IPV6_MC_DIP_RESERVED_SCOPE \
|
||||
"ipv6_mc_dip_reserved_scope"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE \
|
||||
"ipv6_mc_dip_interface_local_scope"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_MTU_ERROR \
|
||||
"mtu_value_is_too_small"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_UNRESOLVED_NEIGH \
|
||||
"unresolved_neigh"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_RPF \
|
||||
"mc_reverse_path_forwarding"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_REJECT_ROUTE \
|
||||
"reject_route"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_IPV4_LPM_UNICAST_MISS \
|
||||
"ipv4_lpm_miss"
|
||||
#define DEVLINK_TRAP_GENERIC_NAME_IPV6_LPM_UNICAST_MISS \
|
||||
"ipv6_lpm_miss"
|
||||
|
||||
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \
|
||||
"l2_drops"
|
||||
|
@ -7602,6 +7602,21 @@ static const struct devlink_trap devlink_trap_generic[] = {
|
||||
DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
|
||||
DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
|
||||
DEVLINK_TRAP(TAIL_DROP, DROP),
|
||||
DEVLINK_TRAP(NON_IP_PACKET, DROP),
|
||||
DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
|
||||
DEVLINK_TRAP(DIP_LB, DROP),
|
||||
DEVLINK_TRAP(SIP_MC, DROP),
|
||||
DEVLINK_TRAP(SIP_LB, DROP),
|
||||
DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
|
||||
DEVLINK_TRAP(IPV4_SIP_BC, DROP),
|
||||
DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
|
||||
DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
|
||||
DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
|
||||
DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
|
||||
DEVLINK_TRAP(RPF, EXCEPTION),
|
||||
DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
|
||||
DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
|
||||
DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
|
||||
};
|
||||
|
||||
#define DEVLINK_TRAP_GROUP(_id) \
|
||||
|
@ -92,46 +92,6 @@ cleanup()
|
||||
vrf_cleanup
|
||||
}
|
||||
|
||||
l2_drops_test()
|
||||
{
|
||||
local trap_name=$1; shift
|
||||
local group_name=$1; shift
|
||||
|
||||
# This is the common part of all the tests. It checks that stats are
|
||||
# initially idle, then non-idle after changing the trap action and
|
||||
# finally idle again. It also makes sure the packets are dropped and
|
||||
# never forwarded.
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle with initial drop action"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with initial drop action"
|
||||
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_fail $? "Trap stats idle after setting action to trap"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_fail $? "Trap group stats idle after setting action to trap"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle after setting action to drop"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle after setting action to drop"
|
||||
|
||||
tc_check_packets "dev $swp2 egress" 101 0
|
||||
check_err $? "Packets were not dropped"
|
||||
}
|
||||
|
||||
l2_drops_cleanup()
|
||||
{
|
||||
local mz_pid=$1; shift
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
source_mac_is_multicast_test()
|
||||
{
|
||||
local trap_name="source_mac_is_multicast"
|
||||
@ -147,11 +107,11 @@ source_mac_is_multicast_test()
|
||||
|
||||
RET=0
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
log_test "Source MAC is multicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
}
|
||||
|
||||
__vlan_tag_mismatch_test()
|
||||
@ -172,7 +132,7 @@ __vlan_tag_mismatch_test()
|
||||
$MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
# Add PVID and make sure packets are no longer dropped.
|
||||
bridge vlan add vid 1 dev $swp1 pvid untagged master
|
||||
@ -188,7 +148,7 @@ __vlan_tag_mismatch_test()
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
}
|
||||
|
||||
vlan_tag_mismatch_untagged_test()
|
||||
@ -233,7 +193,7 @@ ingress_vlan_filter_test()
|
||||
$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
# Add the VLAN on the bridge port and make sure packets are no longer
|
||||
# dropped.
|
||||
@ -252,7 +212,7 @@ ingress_vlan_filter_test()
|
||||
|
||||
log_test "Ingress VLAN filter"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
|
||||
bridge vlan del vid $vid dev $swp1 master
|
||||
bridge vlan del vid $vid dev $swp2 master
|
||||
@ -277,7 +237,7 @@ __ingress_stp_filter_test()
|
||||
$MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
# Change STP state to forwarding and make sure packets are no longer
|
||||
# dropped.
|
||||
@ -294,7 +254,7 @@ __ingress_stp_filter_test()
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
|
||||
bridge vlan del vid $vid dev $swp1 master
|
||||
bridge vlan del vid $vid dev $swp2 master
|
||||
@ -348,7 +308,7 @@ port_list_is_empty_uc_test()
|
||||
$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
# Allow packets to be flooded to one port.
|
||||
ip link set dev $swp2 type bridge_slave flood on
|
||||
@ -366,7 +326,7 @@ port_list_is_empty_uc_test()
|
||||
|
||||
log_test "Port list is empty - unicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
|
||||
ip link set dev $swp1 type bridge_slave flood on
|
||||
}
|
||||
@ -394,7 +354,7 @@ port_list_is_empty_mc_test()
|
||||
$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
# Allow packets to be flooded to one port.
|
||||
ip link set dev $swp2 type bridge_slave mcast_flood on
|
||||
@ -412,7 +372,7 @@ port_list_is_empty_mc_test()
|
||||
|
||||
log_test "Port list is empty - multicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
|
||||
ip link set dev $swp1 type bridge_slave mcast_flood on
|
||||
}
|
||||
@ -441,7 +401,7 @@ port_loopback_filter_uc_test()
|
||||
$MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
l2_drops_test $trap_name $group_name
|
||||
devlink_trap_drop_test $trap_name $group_name $swp2
|
||||
|
||||
# Allow packets to be flooded.
|
||||
ip link set dev $swp2 type bridge_slave flood on
|
||||
@ -459,7 +419,7 @@ port_loopback_filter_uc_test()
|
||||
|
||||
log_test "Port loopback filter - unicast"
|
||||
|
||||
l2_drops_cleanup $mz_pid
|
||||
devlink_trap_drop_cleanup $mz_pid $swp2 ip
|
||||
}
|
||||
|
||||
port_loopback_filter_test()
|
||||
|
563
tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh
Executable file
563
tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh
Executable file
@ -0,0 +1,563 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Test devlink-trap L3 drops functionality over mlxsw. Each registered L3 drop
|
||||
# packet trap is tested to make sure it is triggered under the right
|
||||
# conditions.
|
||||
|
||||
# +---------------------------------+
|
||||
# | H1 (vrf) |
|
||||
# | + $h1 |
|
||||
# | | 192.0.2.1/24 |
|
||||
# | | 2001:db8:1::1/64 |
|
||||
# | | |
|
||||
# | | default via 192.0.2.2 |
|
||||
# | | default via 2001:db8:1::2 |
|
||||
# +----|----------------------------+
|
||||
# |
|
||||
# +----|----------------------------------------------------------------------+
|
||||
# | SW | |
|
||||
# | + $rp1 |
|
||||
# | 192.0.2.2/24 |
|
||||
# | 2001:db8:1::2/64 |
|
||||
# | |
|
||||
# | 2001:db8:2::2/64 |
|
||||
# | 198.51.100.2/24 |
|
||||
# | + $rp2 |
|
||||
# | | |
|
||||
# +----|----------------------------------------------------------------------+
|
||||
# |
|
||||
# +----|----------------------------+
|
||||
# | | default via 198.51.100.2 |
|
||||
# | | default via 2001:db8:2::2 |
|
||||
# | | |
|
||||
# | | 2001:db8:2::1/64 |
|
||||
# | | 198.51.100.1/24 |
|
||||
# | + $h2 |
|
||||
# | H2 (vrf) |
|
||||
# +---------------------------------+
|
||||
|
||||
lib_dir=$(dirname $0)/../../../net/forwarding
|
||||
|
||||
ALL_TESTS="
|
||||
non_ip_test
|
||||
uc_dip_over_mc_dmac_test
|
||||
dip_is_loopback_test
|
||||
sip_is_mc_test
|
||||
sip_is_loopback_test
|
||||
ip_header_corrupted_test
|
||||
ipv4_sip_is_limited_bc_test
|
||||
ipv6_mc_dip_reserved_scope_test
|
||||
ipv6_mc_dip_interface_local_scope_test
|
||||
blackhole_route_test
|
||||
"
|
||||
|
||||
NUM_NETIFS=4
|
||||
source $lib_dir/lib.sh
|
||||
source $lib_dir/tc_common.sh
|
||||
source $lib_dir/devlink_lib.sh
|
||||
|
||||
h1_create()
|
||||
{
|
||||
simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
|
||||
|
||||
ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
|
||||
ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2
|
||||
}
|
||||
|
||||
h1_destroy()
|
||||
{
|
||||
ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2
|
||||
ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
|
||||
|
||||
simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
|
||||
}
|
||||
|
||||
h2_create()
|
||||
{
|
||||
simple_if_init $h2 $h2_ipv4/24 $h2_ipv6/64
|
||||
|
||||
ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
|
||||
ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2
|
||||
}
|
||||
|
||||
h2_destroy()
|
||||
{
|
||||
ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2
|
||||
ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
|
||||
|
||||
simple_if_fini $h2 $h2_ipv4/24 $h2_ipv6/64
|
||||
}
|
||||
|
||||
router_create()
|
||||
{
|
||||
ip link set dev $rp1 up
|
||||
ip link set dev $rp2 up
|
||||
|
||||
tc qdisc add dev $rp2 clsact
|
||||
|
||||
__addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
|
||||
__addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64
|
||||
}
|
||||
|
||||
router_destroy()
|
||||
{
|
||||
__addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64
|
||||
__addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
|
||||
|
||||
tc qdisc del dev $rp2 clsact
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
rp1=${NETIFS[p2]}
|
||||
|
||||
rp2=${NETIFS[p3]}
|
||||
h2=${NETIFS[p4]}
|
||||
|
||||
h1mac=$(mac_get $h1)
|
||||
rp1mac=$(mac_get $rp1)
|
||||
|
||||
h1_ipv4=192.0.2.1
|
||||
h2_ipv4=198.51.100.1
|
||||
h1_ipv6=2001:db8:1::1
|
||||
h2_ipv6=2001:db8:2::1
|
||||
|
||||
vrf_prepare
|
||||
forwarding_enable
|
||||
|
||||
h1_create
|
||||
h2_create
|
||||
|
||||
router_create
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
||||
router_destroy
|
||||
|
||||
h2_destroy
|
||||
h1_destroy
|
||||
|
||||
forwarding_restore
|
||||
vrf_cleanup
|
||||
}
|
||||
|
||||
ping_check()
|
||||
{
|
||||
trap_name=$1; shift
|
||||
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
ping_do $h1 $h2_ipv4
|
||||
check_err $? "Packets that should not be trapped were trapped"
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
}
|
||||
|
||||
non_ip_test()
|
||||
{
|
||||
local trap_name="non_ip"
|
||||
local group_name="l3_drops"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_ip $h2_ipv4 action drop
|
||||
|
||||
# Generate non-IP packets to the router
|
||||
$MZ $h1 -c 0 -p 100 -d 1msec -B $h2_ipv4 -q "$rp1mac $h1mac \
|
||||
00:00 de:ad:be:ef" &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "Non IP"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
|
||||
}
|
||||
|
||||
__uc_dip_over_mc_dmac_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local proto=$1; shift
|
||||
local dip=$1; shift
|
||||
local flags=${1:-""}; shift
|
||||
local trap_name="uc_dip_over_mc_dmac"
|
||||
local group_name="l3_drops"
|
||||
local dmac=01:02:03:04:05:06
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
|
||||
flower ip_proto udp src_port 54321 dst_port 12345 action drop
|
||||
|
||||
# Generate IP packets with a unicast IP and a multicast destination MAC
|
||||
$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $dmac \
|
||||
-B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "Unicast destination IP over multicast destination MAC: $desc"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
|
||||
}
|
||||
|
||||
uc_dip_over_mc_dmac_test()
|
||||
{
|
||||
__uc_dip_over_mc_dmac_test "IPv4" "ip" $h2_ipv4
|
||||
__uc_dip_over_mc_dmac_test "IPv6" "ipv6" $h2_ipv6 "-6"
|
||||
}
|
||||
|
||||
__sip_is_loopback_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local proto=$1; shift
|
||||
local sip=$1; shift
|
||||
local dip=$1; shift
|
||||
local flags=${1:-""}; shift
|
||||
local trap_name="sip_is_loopback_address"
|
||||
local group_name="l3_drops"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
|
||||
flower src_ip $sip action drop
|
||||
|
||||
# Generate packets with loopback source IP
|
||||
$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip \
|
||||
-b $rp1mac -B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "Source IP is loopback address: $desc"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
|
||||
}
|
||||
|
||||
sip_is_loopback_test()
|
||||
{
|
||||
__sip_is_loopback_test "IPv4" "ip" "127.0.0.0/8" $h2_ipv4
|
||||
__sip_is_loopback_test "IPv6" "ipv6" "::1" $h2_ipv6 "-6"
|
||||
}
|
||||
|
||||
__dip_is_loopback_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local proto=$1; shift
|
||||
local dip=$1; shift
|
||||
local flags=${1:-""}; shift
|
||||
local trap_name="dip_is_loopback_address"
|
||||
local group_name="l3_drops"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
|
||||
flower dst_ip $dip action drop
|
||||
|
||||
# Generate packets with loopback destination IP
|
||||
$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \
|
||||
-B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "Destination IP is loopback address: $desc"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
|
||||
}
|
||||
|
||||
dip_is_loopback_test()
|
||||
{
|
||||
__dip_is_loopback_test "IPv4" "ip" "127.0.0.0/8"
|
||||
__dip_is_loopback_test "IPv6" "ipv6" "::1" "-6"
|
||||
}
|
||||
|
||||
__sip_is_mc_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local proto=$1; shift
|
||||
local sip=$1; shift
|
||||
local dip=$1; shift
|
||||
local flags=${1:-""}; shift
|
||||
local trap_name="sip_is_mc"
|
||||
local group_name="l3_drops"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
|
||||
flower src_ip $sip action drop
|
||||
|
||||
# Generate packets with multicast source IP
|
||||
$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip \
|
||||
-b $rp1mac -B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "Source IP is multicast: $desc"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
|
||||
}
|
||||
|
||||
sip_is_mc_test()
|
||||
{
|
||||
__sip_is_mc_test "IPv4" "ip" "239.1.1.1" $h2_ipv4
|
||||
__sip_is_mc_test "IPv6" "ipv6" "FF02::2" $h2_ipv6 "-6"
|
||||
}
|
||||
|
||||
ipv4_sip_is_limited_bc_test()
|
||||
{
|
||||
local trap_name="ipv4_sip_is_limited_bc"
|
||||
local group_name="l3_drops"
|
||||
local sip=255.255.255.255
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
|
||||
flower src_ip $sip action drop
|
||||
|
||||
# Generate packets with limited broadcast source IP
|
||||
$MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip -b $rp1mac \
|
||||
-B $h2_ipv4 -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "IPv4 source IP is limited broadcast"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
|
||||
}
|
||||
|
||||
ipv4_payload_get()
|
||||
{
|
||||
local ipver=$1; shift
|
||||
local ihl=$1; shift
|
||||
local checksum=$1; shift
|
||||
|
||||
p=$(:
|
||||
)"08:00:"$( : ETH type
|
||||
)"$ipver"$( : IP version
|
||||
)"$ihl:"$( : IHL
|
||||
)"00:"$( : IP TOS
|
||||
)"00:F4:"$( : IP total length
|
||||
)"00:00:"$( : IP identification
|
||||
)"20:00:"$( : IP flags + frag off
|
||||
)"30:"$( : IP TTL
|
||||
)"01:"$( : IP proto
|
||||
)"$checksum:"$( : IP header csum
|
||||
)"$h1_ipv4:"$( : IP saddr
|
||||
)"$h2_ipv4:"$( : IP daddr
|
||||
)
|
||||
echo $p
|
||||
}
|
||||
|
||||
__ipv4_header_corrupted_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local ipver=$1; shift
|
||||
local ihl=$1; shift
|
||||
local checksum=$1; shift
|
||||
local trap_name="ip_header_corrupted"
|
||||
local group_name="l3_drops"
|
||||
local payload
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_ip $h2_ipv4 action drop
|
||||
|
||||
payload=$(ipv4_payload_get $ipver $ihl $checksum)
|
||||
|
||||
# Generate packets with corrupted IP header
|
||||
$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "IP header corrupted: $desc: IPv4"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
|
||||
}
|
||||
|
||||
ipv6_payload_get()
|
||||
{
|
||||
local ipver=$1; shift
|
||||
|
||||
p=$(:
|
||||
)"86:DD:"$( : ETH type
|
||||
)"$ipver"$( : IP version
|
||||
)"0:0:"$( : Traffic class
|
||||
)"0:00:00:"$( : Flow label
|
||||
)"00:00:"$( : Payload length
|
||||
)"01:"$( : Next header
|
||||
)"04:"$( : Hop limit
|
||||
)"$h1_ipv6:"$( : IP saddr
|
||||
)"$h2_ipv6:"$( : IP daddr
|
||||
)
|
||||
echo $p
|
||||
}
|
||||
|
||||
__ipv6_header_corrupted_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local ipver=$1; shift
|
||||
local trap_name="ip_header_corrupted"
|
||||
local group_name="l3_drops"
|
||||
local payload
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
|
||||
flower dst_ip $h2_ipv4 action drop
|
||||
|
||||
payload=$(ipv6_payload_get $ipver)
|
||||
|
||||
# Generate packets with corrupted IP header
|
||||
$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "IP header corrupted: $desc: IPv6"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
|
||||
}
|
||||
|
||||
ip_header_corrupted_test()
|
||||
{
|
||||
# Each test uses one wrong value. The three values below are correct.
|
||||
local ipv="4"
|
||||
local ihl="5"
|
||||
local checksum="00:F4"
|
||||
|
||||
__ipv4_header_corrupted_test "wrong IP version" 5 $ihl $checksum
|
||||
__ipv4_header_corrupted_test "wrong IHL" $ipv 4 $checksum
|
||||
__ipv4_header_corrupted_test "wrong checksum" $ipv $ihl "00:00"
|
||||
__ipv6_header_corrupted_test "wrong IP version" 5
|
||||
}
|
||||
|
||||
ipv6_mc_dip_reserved_scope_test()
|
||||
{
|
||||
local trap_name="ipv6_mc_dip_reserved_scope"
|
||||
local group_name="l3_drops"
|
||||
local dip=FF00::
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \
|
||||
flower dst_ip $dip action drop
|
||||
|
||||
# Generate packets with reserved scope destination IP
|
||||
$MZ $h1 -6 -t udp "sp=54321,dp=12345" -c 0 -p 100 -b \
|
||||
"33:33:00:00:00:00" -B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "IPv6 multicast destination IP reserved scope"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6"
|
||||
}
|
||||
|
||||
ipv6_mc_dip_interface_local_scope_test()
|
||||
{
|
||||
local trap_name="ipv6_mc_dip_interface_local_scope"
|
||||
local group_name="l3_drops"
|
||||
local dip=FF01::
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \
|
||||
flower dst_ip $dip action drop
|
||||
|
||||
# Generate packets with interface local scope destination IP
|
||||
$MZ $h1 -6 -t udp "sp=54321,dp=12345" -c 0 -p 100 -b \
|
||||
"33:33:00:00:00:00" -B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
|
||||
log_test "IPv6 multicast destination IP interface-local scope"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6"
|
||||
}
|
||||
|
||||
__blackhole_route_test()
|
||||
{
|
||||
local flags=$1; shift
|
||||
local subnet=$1; shift
|
||||
local proto=$1; shift
|
||||
local dip=$1; shift
|
||||
local ip_proto=${1:-"icmp"}; shift
|
||||
local trap_name="blackhole_route"
|
||||
local group_name="l3_drops"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
|
||||
ip -$flags route add blackhole $subnet
|
||||
tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
|
||||
flower skip_hw dst_ip $dip ip_proto $ip_proto action drop
|
||||
|
||||
# Generate packets to the blackhole route
|
||||
$MZ $h1 -$flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \
|
||||
-B $dip -d 1msec -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_drop_test $trap_name $group_name $rp2
|
||||
log_test "Blackhole route: IPv$flags"
|
||||
|
||||
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
|
||||
ip -$flags route del blackhole $subnet
|
||||
}
|
||||
|
||||
blackhole_route_test()
|
||||
{
|
||||
__blackhole_route_test "4" "198.51.100.0/30" "ip" $h2_ipv4
|
||||
__blackhole_route_test "6" "2001:db8:2::/120" "ipv6" $h2_ipv6 "icmpv6"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
557
tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh
Executable file
557
tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh
Executable file
@ -0,0 +1,557 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Test devlink-trap L3 exceptions functionality over mlxsw.
|
||||
# Check all exception traps to make sure they are triggered under the right
|
||||
# conditions.
|
||||
|
||||
# +---------------------------------+
|
||||
# | H1 (vrf) |
|
||||
# | + $h1 |
|
||||
# | | 192.0.2.1/24 |
|
||||
# | | 2001:db8:1::1/64 |
|
||||
# | | |
|
||||
# | | default via 192.0.2.2 |
|
||||
# | | default via 2001:db8:1::2 |
|
||||
# +----|----------------------------+
|
||||
# |
|
||||
# +----|----------------------------------------------------------------------+
|
||||
# | SW | |
|
||||
# | + $rp1 |
|
||||
# | 192.0.2.2/24 |
|
||||
# | 2001:db8:1::2/64 |
|
||||
# | |
|
||||
# | 2001:db8:2::2/64 |
|
||||
# | 198.51.100.2/24 |
|
||||
# | + $rp2 |
|
||||
# | | |
|
||||
# +----|----------------------------------------------------------------------+
|
||||
# |
|
||||
# +----|----------------------------+
|
||||
# | | default via 198.51.100.2 |
|
||||
# | | default via 2001:db8:2::2 |
|
||||
# | | |
|
||||
# | | 2001:db8:2::1/64 |
|
||||
# | | 198.51.100.1/24 |
|
||||
# | + $h2 |
|
||||
# | H2 (vrf) |
|
||||
# +---------------------------------+
|
||||
|
||||
lib_dir=$(dirname $0)/../../../net/forwarding
|
||||
|
||||
ALL_TESTS="
|
||||
mtu_value_is_too_small_test
|
||||
ttl_value_is_too_small_test
|
||||
mc_reverse_path_forwarding_test
|
||||
reject_route_test
|
||||
unresolved_neigh_test
|
||||
ipv4_lpm_miss_test
|
||||
ipv6_lpm_miss_test
|
||||
"
|
||||
|
||||
NUM_NETIFS=4
|
||||
source $lib_dir/lib.sh
|
||||
source $lib_dir/tc_common.sh
|
||||
source $lib_dir/devlink_lib.sh
|
||||
|
||||
require_command $MCD
|
||||
require_command $MC_CLI
|
||||
table_name=selftests
|
||||
|
||||
h1_create()
|
||||
{
|
||||
simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
|
||||
|
||||
ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
|
||||
ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2
|
||||
|
||||
tc qdisc add dev $h1 clsact
|
||||
}
|
||||
|
||||
h1_destroy()
|
||||
{
|
||||
tc qdisc del dev $h1 clsact
|
||||
|
||||
ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2
|
||||
ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
|
||||
|
||||
simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
|
||||
}
|
||||
|
||||
h2_create()
|
||||
{
|
||||
simple_if_init $h2 198.51.100.1/24 2001:db8:2::1/64
|
||||
|
||||
ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
|
||||
ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2
|
||||
}
|
||||
|
||||
h2_destroy()
|
||||
{
|
||||
ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2
|
||||
ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
|
||||
|
||||
simple_if_fini $h2 198.51.100.1/24 2001:db8:2::1/64
|
||||
}
|
||||
|
||||
router_create()
|
||||
{
|
||||
ip link set dev $rp1 up
|
||||
ip link set dev $rp2 up
|
||||
|
||||
tc qdisc add dev $rp2 clsact
|
||||
|
||||
__addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
|
||||
__addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64
|
||||
}
|
||||
|
||||
router_destroy()
|
||||
{
|
||||
__addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64
|
||||
__addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
|
||||
|
||||
tc qdisc del dev $rp2 clsact
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
rp1=${NETIFS[p2]}
|
||||
|
||||
rp2=${NETIFS[p3]}
|
||||
h2=${NETIFS[p4]}
|
||||
|
||||
rp1mac=$(mac_get $rp1)
|
||||
|
||||
start_mcd
|
||||
|
||||
vrf_prepare
|
||||
forwarding_enable
|
||||
|
||||
h1_create
|
||||
h2_create
|
||||
|
||||
router_create
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
pre_cleanup
|
||||
|
||||
router_destroy
|
||||
|
||||
h2_destroy
|
||||
h1_destroy
|
||||
|
||||
forwarding_restore
|
||||
vrf_cleanup
|
||||
|
||||
kill_mcd
|
||||
}
|
||||
|
||||
ping_check()
|
||||
{
|
||||
ping_do $h1 198.51.100.1
|
||||
check_err $? "Packets that should not be trapped were trapped"
|
||||
}
|
||||
|
||||
trap_action_check()
|
||||
{
|
||||
local trap_name=$1; shift
|
||||
local expected_action=$1; shift
|
||||
|
||||
action=$(devlink_trap_action_get $trap_name)
|
||||
if [ "$action" != $expected_action ]; then
|
||||
check_err 1 "Trap $trap_name has wrong action: $action"
|
||||
fi
|
||||
}
|
||||
|
||||
mtu_value_is_too_small_test()
|
||||
{
|
||||
local trap_name="mtu_value_is_too_small"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
# type - Destination Unreachable
|
||||
# code - Fragmentation Needed and Don't Fragment was Set
|
||||
tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \
|
||||
flower skip_hw ip_proto icmp type 3 code 4 action pass
|
||||
|
||||
mtu_set $rp2 1300
|
||||
|
||||
# Generate IP packets bigger than router's MTU with don't fragment
|
||||
# flag on.
|
||||
$MZ $h1 -t udp "sp=54321,dp=12345,df" -p 1400 -c 0 -d 1msec -b $rp1mac \
|
||||
-B 198.51.100.1 -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_exception_test $trap_name $group_name
|
||||
|
||||
tc_check_packets_hitting "dev $h1 ingress" 101
|
||||
check_err $? "Packets were not received to h1"
|
||||
|
||||
log_test "MTU value is too small"
|
||||
|
||||
mtu_restore $rp2
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
__ttl_value_is_too_small_test()
|
||||
{
|
||||
local ttl_val=$1; shift
|
||||
local trap_name="ttl_value_is_too_small"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
# type - Time Exceeded
|
||||
# code - Time to Live exceeded in Transit
|
||||
tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \
|
||||
flower skip_hw ip_proto icmp type 11 code 0 action pass
|
||||
|
||||
# Generate IP packets with small TTL
|
||||
$MZ $h1 -t udp "ttl=$ttl_val,sp=54321,dp=12345" -c 0 -d 1msec \
|
||||
-b $rp1mac -B 198.51.100.1 -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_exception_test $trap_name $group_name
|
||||
|
||||
tc_check_packets_hitting "dev $h1 ingress" 101
|
||||
check_err $? "Packets were not received to h1"
|
||||
|
||||
log_test "TTL value is too small: TTL=$ttl_val"
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
ttl_value_is_too_small_test()
|
||||
{
|
||||
__ttl_value_is_too_small_test 0
|
||||
__ttl_value_is_too_small_test 1
|
||||
}
|
||||
|
||||
start_mcd()
|
||||
{
|
||||
SMCROUTEDIR="$(mktemp -d)"
|
||||
for ((i = 1; i <= $NUM_NETIFS; ++i)); do
|
||||
echo "phyint ${NETIFS[p$i]} enable" >> \
|
||||
$SMCROUTEDIR/$table_name.conf
|
||||
done
|
||||
|
||||
$MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \
|
||||
-P $SMCROUTEDIR/$table_name.pid
|
||||
}
|
||||
|
||||
kill_mcd()
|
||||
{
|
||||
pkill $MCD
|
||||
rm -rf $SMCROUTEDIR
|
||||
}
|
||||
|
||||
__mc_reverse_path_forwarding_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local src_ip=$1; shift
|
||||
local dst_ip=$1; shift
|
||||
local dst_mac=$1; shift
|
||||
local proto=$1; shift
|
||||
local flags=${1:-""}; shift
|
||||
local trap_name="mc_reverse_path_forwarding"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
|
||||
flower dst_ip $dst_ip ip_proto udp action drop
|
||||
|
||||
$MC_CLI -I $table_name add $rp1 $src_ip $dst_ip $rp2
|
||||
|
||||
# Generate packets to multicast address.
|
||||
$MZ $h2 $flags -t udp "sp=54321,dp=12345" -c 0 -p 128 \
|
||||
-a 00:11:22:33:44:55 -b $dst_mac \
|
||||
-A $src_ip -B $dst_ip -q &
|
||||
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_exception_test $trap_name $group_name
|
||||
|
||||
tc_check_packets "dev $rp2 egress" 101 0
|
||||
check_err $? "Packets were not dropped"
|
||||
|
||||
log_test "Multicast reverse path forwarding: $desc"
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
tc filter del dev $rp2 egress protocol $proto pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
mc_reverse_path_forwarding_test()
|
||||
{
|
||||
__mc_reverse_path_forwarding_test "IPv4" "192.0.2.1" "225.1.2.3" \
|
||||
"01:00:5e:01:02:03" "ip"
|
||||
__mc_reverse_path_forwarding_test "IPv6" "2001:db8:1::1" "ff0e::3" \
|
||||
"33:33:00:00:00:03" "ipv6" "-6"
|
||||
}
|
||||
|
||||
__reject_route_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local dst_ip=$1; shift
|
||||
local proto=$1; shift
|
||||
local ip_proto=$1; shift
|
||||
local type=$1; shift
|
||||
local code=$1; shift
|
||||
local unreachable=$1; shift
|
||||
local flags=${1:-""}; shift
|
||||
local trap_name="reject_route"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
tc filter add dev $h1 ingress protocol $proto pref 1 handle 101 flower \
|
||||
skip_hw ip_proto $ip_proto type $type code $code action pass
|
||||
|
||||
ip route add unreachable $unreachable
|
||||
|
||||
# Generate pacekts to h2. The destination IP is unreachable.
|
||||
$MZ $flags $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \
|
||||
-B $dst_ip -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_exception_test $trap_name $group_name
|
||||
|
||||
tc_check_packets_hitting "dev $h1 ingress" 101
|
||||
check_err $? "ICMP packet was not received to h1"
|
||||
|
||||
log_test "Reject route: $desc"
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
ip route del unreachable $unreachable
|
||||
tc filter del dev $h1 ingress protocol $proto pref 1 handle 101 flower
|
||||
}
|
||||
|
||||
reject_route_test()
|
||||
{
|
||||
# type - Destination Unreachable
|
||||
# code - Host Unreachable
|
||||
__reject_route_test "IPv4" 198.51.100.1 "ip" "icmp" 3 1 \
|
||||
"198.51.100.0/26"
|
||||
# type - Destination Unreachable
|
||||
# code - No Route
|
||||
__reject_route_test "IPv6" 2001:db8:2::1 "ipv6" "icmpv6" 1 0 \
|
||||
"2001:db8:2::0/66" "-6"
|
||||
}
|
||||
|
||||
__host_miss_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local dip=$1; shift
|
||||
local trap_name="unresolved_neigh"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
ip neigh flush dev $rp2
|
||||
|
||||
t0_packets=$(devlink_trap_rx_packets_get $trap_name)
|
||||
|
||||
# Generate packets to h2 (will incur a unresolved neighbor).
|
||||
# The ping should pass and devlink counters should be increased.
|
||||
ping_do $h1 $dip
|
||||
check_err $? "ping failed: $desc"
|
||||
|
||||
t1_packets=$(devlink_trap_rx_packets_get $trap_name)
|
||||
|
||||
if [[ $t0_packets -eq $t1_packets ]]; then
|
||||
check_err 1 "Trap counter did not increase"
|
||||
fi
|
||||
|
||||
log_test "Unresolved neigh: host miss: $desc"
|
||||
}
|
||||
|
||||
__invalid_nexthop_test()
|
||||
{
|
||||
local desc=$1; shift
|
||||
local dip=$1; shift
|
||||
local extra_add=$1; shift
|
||||
local subnet=$1; shift
|
||||
local via_add=$1; shift
|
||||
local trap_name="unresolved_neigh"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
ip address add $extra_add/$subnet dev $h2
|
||||
|
||||
# Check that correct route does not trigger unresolved_neigh
|
||||
ip $flags route add $dip via $extra_add dev $rp2
|
||||
|
||||
# Generate packets in order to discover all neighbours.
|
||||
# Without it, counters of unresolved_neigh will be increased
|
||||
# during neighbours discovery and the check below will fail
|
||||
# for a wrong reason
|
||||
ping_do $h1 $dip
|
||||
|
||||
t0_packets=$(devlink_trap_rx_packets_get $trap_name)
|
||||
ping_do $h1 $dip
|
||||
t1_packets=$(devlink_trap_rx_packets_get $trap_name)
|
||||
|
||||
if [[ $t0_packets -ne $t1_packets ]]; then
|
||||
check_err 1 "Trap counter increased when it should not"
|
||||
fi
|
||||
|
||||
ip $flags route del $dip via $extra_add dev $rp2
|
||||
|
||||
# Check that route to nexthop that does not exist trigger
|
||||
# unresolved_neigh
|
||||
ip $flags route add $dip via $via_add dev $h2
|
||||
|
||||
t0_packets=$(devlink_trap_rx_packets_get $trap_name)
|
||||
ping_do $h1 $dip
|
||||
t1_packets=$(devlink_trap_rx_packets_get $trap_name)
|
||||
|
||||
if [[ $t0_packets -eq $t1_packets ]]; then
|
||||
check_err 1 "Trap counter did not increase"
|
||||
fi
|
||||
|
||||
ip $flags route del $dip via $via_add dev $h2
|
||||
ip address del $extra_add/$subnet dev $h2
|
||||
log_test "Unresolved neigh: nexthop does not exist: $desc"
|
||||
}
|
||||
|
||||
unresolved_neigh_test()
|
||||
{
|
||||
__host_miss_test "IPv4" 198.51.100.1
|
||||
__host_miss_test "IPv6" 2001:db8:2::1
|
||||
__invalid_nexthop_test "IPv4" 198.51.100.1 198.51.100.3 24 198.51.100.4
|
||||
__invalid_nexthop_test "IPv6" 2001:db8:2::1 2001:db8:2::3 64 \
|
||||
2001:db8:2::4
|
||||
}
|
||||
|
||||
vrf_without_routes_create()
|
||||
{
|
||||
# VRF creating makes the links to be down and then up again.
|
||||
# By default, IPv6 address is not saved after link becomes down.
|
||||
# Save IPv6 address using sysctl configuration.
|
||||
sysctl_set net.ipv6.conf.$rp1.keep_addr_on_down 1
|
||||
sysctl_set net.ipv6.conf.$rp2.keep_addr_on_down 1
|
||||
|
||||
ip link add dev vrf1 type vrf table 101
|
||||
ip link set dev $rp1 master vrf1
|
||||
ip link set dev $rp2 master vrf1
|
||||
ip link set dev vrf1 up
|
||||
|
||||
# Wait for rp1 and rp2 to be up
|
||||
setup_wait
|
||||
}
|
||||
|
||||
vrf_without_routes_destroy()
|
||||
{
|
||||
ip link set dev $rp1 nomaster
|
||||
ip link set dev $rp2 nomaster
|
||||
ip link del dev vrf1
|
||||
|
||||
sysctl_restore net.ipv6.conf.$rp2.keep_addr_on_down
|
||||
sysctl_restore net.ipv6.conf.$rp1.keep_addr_on_down
|
||||
|
||||
# Wait for interfaces to be up
|
||||
setup_wait
|
||||
}
|
||||
|
||||
ipv4_lpm_miss_test()
|
||||
{
|
||||
local trap_name="ipv4_lpm_miss"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
# Create a VRF without a default route
|
||||
vrf_without_routes_create
|
||||
|
||||
# Generate packets through a VRF without a matching route.
|
||||
$MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \
|
||||
-B 203.0.113.1 -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_exception_test $trap_name $group_name
|
||||
|
||||
log_test "LPM miss: IPv4"
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
vrf_without_routes_destroy
|
||||
}
|
||||
|
||||
ipv6_lpm_miss_test()
|
||||
{
|
||||
local trap_name="ipv6_lpm_miss"
|
||||
local group_name="l3_drops"
|
||||
local expected_action="trap"
|
||||
local mz_pid
|
||||
|
||||
RET=0
|
||||
|
||||
ping_check $trap_name
|
||||
trap_action_check $trap_name $expected_action
|
||||
|
||||
# Create a VRF without a default route
|
||||
vrf_without_routes_create
|
||||
|
||||
# Generate packets through a VRF without a matching route.
|
||||
$MZ -6 $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \
|
||||
-B 2001:db8::1 -q &
|
||||
mz_pid=$!
|
||||
|
||||
devlink_trap_exception_test $trap_name $group_name
|
||||
|
||||
log_test "LPM miss: IPv6"
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
vrf_without_routes_destroy
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
setup_prepare
|
||||
setup_wait
|
||||
|
||||
tests_run
|
||||
|
||||
exit $EXIT_STATUS
|
@ -355,3 +355,58 @@ devlink_trap_group_stats_idle_test()
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
devlink_trap_exception_test()
|
||||
{
|
||||
local trap_name=$1; shift
|
||||
local group_name=$1; shift
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_fail $? "Trap stats idle when packets should have been trapped"
|
||||
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_fail $? "Trap group idle when packets should have been trapped"
|
||||
}
|
||||
|
||||
devlink_trap_drop_test()
|
||||
{
|
||||
local trap_name=$1; shift
|
||||
local group_name=$1; shift
|
||||
local dev=$1; shift
|
||||
|
||||
# This is the common part of all the tests. It checks that stats are
|
||||
# initially idle, then non-idle after changing the trap action and
|
||||
# finally idle again. It also makes sure the packets are dropped and
|
||||
# never forwarded.
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle with initial drop action"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle with initial drop action"
|
||||
|
||||
|
||||
devlink_trap_action_set $trap_name "trap"
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_fail $? "Trap stats idle after setting action to trap"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_fail $? "Trap group stats idle after setting action to trap"
|
||||
|
||||
devlink_trap_action_set $trap_name "drop"
|
||||
|
||||
devlink_trap_stats_idle_test $trap_name
|
||||
check_err $? "Trap stats not idle after setting action to drop"
|
||||
devlink_trap_group_stats_idle_test $group_name
|
||||
check_err $? "Trap group stats not idle after setting action to drop"
|
||||
|
||||
tc_check_packets "dev $dev egress" 101 0
|
||||
check_err $? "Packets were not dropped"
|
||||
}
|
||||
|
||||
devlink_trap_drop_cleanup()
|
||||
{
|
||||
local mz_pid=$1; shift
|
||||
local dev=$1; shift
|
||||
local proto=$1; shift
|
||||
|
||||
kill $mz_pid && wait $mz_pid &> /dev/null
|
||||
tc filter del dev $dev egress protocol $proto pref 1 handle 101 flower
|
||||
}
|
||||
|
@ -14,3 +14,14 @@ tc_check_packets()
|
||||
select(.options.actions[0].stats.packets == $count)" \
|
||||
&> /dev/null
|
||||
}
|
||||
|
||||
tc_check_packets_hitting()
|
||||
{
|
||||
local id=$1
|
||||
local handle=$2
|
||||
|
||||
cmd_jq "tc -j -s filter show $id" \
|
||||
".[] | select(.options.handle == $handle) | \
|
||||
select(.options.actions[0].stats.packets > 0)" \
|
||||
&> /dev/null
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user