Commit 27cf31dc authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-Introduce-ACL-traps'

Jiri Pirko says:

====================
mlxsw: Introduce ACL traps

This patchset allows to track packets that are dropped in HW by ACL.

Unlike the existing mlxsw traps, ACL traps are "source traps".
That means the action is not controlled by HPKT register but directly
in ACL TRAP action. When devlink user changes action from drop to trap
and vice versa, it would be needed to go over all instances of ACL TRAP
action and do change. That does not scale. Instead, resolve this
by introducing "dummy" group with "thin" policer. The purpose of
this policer is to drop as many packets as possible. The ones
that pass through are going to be dropped in devlink code - patch #6
takes care of that.

First four patches are preparation for introduction of ACL traps in mlxsw
so it possible to easily change from drop to trap for source traps
as well - by changing group to "dummy" and back.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3b0b4252 e3294d2b
......@@ -238,6 +238,12 @@ be added to the following table:
- ``drop``
- Traps NVE packets that the device decided to drop because their overlay
source MAC is multicast
* - ``ingress_flow_action_drop``
- ``drop``
- Traps packets dropped during processing of ingress flow action drop
* - ``egress_flow_action_drop``
- ``drop``
- Traps packets dropped during processing of egress flow action drop
Driver-specific Packet Traps
============================
......@@ -277,6 +283,9 @@ narrow. The description of these groups must be added to the following table:
* - ``tunnel_drops``
- Contains packet traps for packets that were dropped by the device during
tunnel encapsulation / decapsulation
* - ``acl_drops``
- Contains packet traps for packets that were dropped by the device during
ACL processing
Testing
=======
......
......@@ -142,6 +142,7 @@ struct mlxsw_rx_listener_item {
struct list_head list;
struct mlxsw_rx_listener rxl;
void *priv;
bool enabled;
};
struct mlxsw_event_listener_item {
......@@ -1470,7 +1471,7 @@ __find_rx_listener_item(struct mlxsw_core *mlxsw_core,
int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
const struct mlxsw_rx_listener *rxl,
void *priv)
void *priv, bool enabled)
{
struct mlxsw_rx_listener_item *rxl_item;
......@@ -1482,6 +1483,7 @@ int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
return -ENOMEM;
rxl_item->rxl = *rxl;
rxl_item->priv = priv;
rxl_item->enabled = enabled;
list_add_rcu(&rxl_item->list, &mlxsw_core->rx_listener_list);
return 0;
......@@ -1502,6 +1504,19 @@ void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_rx_listener_unregister);
static void
mlxsw_core_rx_listener_state_set(struct mlxsw_core *mlxsw_core,
const struct mlxsw_rx_listener *rxl,
bool enabled)
{
struct mlxsw_rx_listener_item *rxl_item;
rxl_item = __find_rx_listener_item(mlxsw_core, rxl);
if (WARN_ON(!rxl_item))
return;
rxl_item->enabled = enabled;
}
static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port,
void *priv)
{
......@@ -1563,7 +1578,7 @@ int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core,
el_item->el = *el;
el_item->priv = priv;
err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item);
err = mlxsw_core_rx_listener_register(mlxsw_core, &rxl, el_item, true);
if (err)
goto err_rx_listener_register;
......@@ -1601,16 +1616,18 @@ EXPORT_SYMBOL(mlxsw_core_event_listener_unregister);
static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener,
void *priv)
void *priv, bool enabled)
{
if (listener->is_event)
if (listener->is_event) {
WARN_ON(!enabled);
return mlxsw_core_event_listener_register(mlxsw_core,
&listener->event_listener,
priv);
else
} else {
return mlxsw_core_rx_listener_register(mlxsw_core,
&listener->rx_listener,
priv);
priv, enabled);
}
}
static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
......@@ -1628,15 +1645,22 @@ static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener, void *priv)
{
enum mlxsw_reg_htgt_trap_group trap_group;
enum mlxsw_reg_hpkt_action action;
char hpkt_pl[MLXSW_REG_HPKT_LEN];
int err;
err = mlxsw_core_listener_register(mlxsw_core, listener, priv);
err = mlxsw_core_listener_register(mlxsw_core, listener, priv,
listener->enabled_on_register);
if (err)
return err;
mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id,
listener->trap_group, listener->is_ctrl);
action = listener->enabled_on_register ? listener->en_action :
listener->dis_action;
trap_group = listener->enabled_on_register ? listener->en_trap_group :
listener->dis_trap_group;
mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id,
trap_group, listener->is_ctrl);
err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
if (err)
goto err_trap_set;
......@@ -1656,8 +1680,8 @@ void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
char hpkt_pl[MLXSW_REG_HPKT_LEN];
if (!listener->is_event) {
mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action,
listener->trap_id, listener->trap_group,
mlxsw_reg_hpkt_pack(hpkt_pl, listener->dis_action,
listener->trap_id, listener->dis_trap_group,
listener->is_ctrl);
mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
}
......@@ -1666,17 +1690,33 @@ void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
}
EXPORT_SYMBOL(mlxsw_core_trap_unregister);
int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener,
enum mlxsw_reg_hpkt_action action)
int mlxsw_core_trap_state_set(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener,
bool enabled)
{
enum mlxsw_reg_htgt_trap_group trap_group;
enum mlxsw_reg_hpkt_action action;
char hpkt_pl[MLXSW_REG_HPKT_LEN];
int err;
/* Not supported for event listener */
if (WARN_ON(listener->is_event))
return -EINVAL;
action = enabled ? listener->en_action : listener->dis_action;
trap_group = enabled ? listener->en_trap_group :
listener->dis_trap_group;
mlxsw_reg_hpkt_pack(hpkt_pl, action, listener->trap_id,
listener->trap_group, listener->is_ctrl);
return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
trap_group, listener->is_ctrl);
err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
if (err)
return err;
mlxsw_core_rx_listener_state_set(mlxsw_core, &listener->rx_listener,
enabled);
return 0;
}
EXPORT_SYMBOL(mlxsw_core_trap_action_set);
EXPORT_SYMBOL(mlxsw_core_trap_state_set);
static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
{
......@@ -1934,7 +1974,8 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
if ((rxl->local_port == MLXSW_PORT_DONT_CARE ||
rxl->local_port == local_port) &&
rxl->trap_id == rx_info->trap_id) {
found = true;
if (rxl_item->enabled)
found = true;
break;
}
}
......
......@@ -76,45 +76,62 @@ struct mlxsw_listener {
struct mlxsw_rx_listener rx_listener;
struct mlxsw_event_listener event_listener;
};
enum mlxsw_reg_hpkt_action action;
enum mlxsw_reg_hpkt_action unreg_action;
u8 trap_group;
enum mlxsw_reg_hpkt_action en_action; /* Action when enabled */
enum mlxsw_reg_hpkt_action dis_action; /* Action when disabled */
u8 en_trap_group; /* Trap group when enabled */
u8 dis_trap_group; /* Trap group when disabled */
u8 is_ctrl:1, /* should go via control buffer or not */
is_event:1;
is_event:1,
enabled_on_register:1; /* Trap should be enabled when listener
* is registered.
*/
};
#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _trap_group, \
_unreg_action) \
{ \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
.rx_listener = \
{ \
.func = _func, \
.local_port = MLXSW_PORT_DONT_CARE, \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
}, \
.action = MLXSW_REG_HPKT_ACTION_##_action, \
.unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action, \
.trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \
.is_ctrl = _is_ctrl, \
#define __MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \
_dis_action, _enabled_on_register, _dis_trap_group) \
{ \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
.rx_listener = \
{ \
.func = _func, \
.local_port = MLXSW_PORT_DONT_CARE, \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
}, \
.en_action = MLXSW_REG_HPKT_ACTION_##_en_action, \
.dis_action = MLXSW_REG_HPKT_ACTION_##_dis_action, \
.en_trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_en_trap_group, \
.dis_trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_dis_trap_group, \
.is_ctrl = _is_ctrl, \
.enabled_on_register = _enabled_on_register, \
}
#define MLXSW_EVENTL(_func, _trap_id, _trap_group) \
{ \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
.event_listener = \
{ \
.func = _func, \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
}, \
.action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \
.trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \
.is_event = true, \
#define MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _trap_group, \
_dis_action) \
__MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _trap_group, \
_dis_action, true, _trap_group)
#define MLXSW_RXL_DIS(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \
_dis_action, _dis_trap_group) \
__MLXSW_RXL(_func, _trap_id, _en_action, _is_ctrl, _en_trap_group, \
_dis_action, false, _dis_trap_group)
#define MLXSW_EVENTL(_func, _trap_id, _trap_group) \
{ \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
.event_listener = \
{ \
.func = _func, \
.trap_id = MLXSW_TRAP_ID_##_trap_id, \
}, \
.en_action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, \
.en_trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group, \
.is_event = true, \
.enabled_on_register = true, \
}
int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
const struct mlxsw_rx_listener *rxl,
void *priv);
void *priv, bool enabled);
void mlxsw_core_rx_listener_unregister(struct mlxsw_core *mlxsw_core,
const struct mlxsw_rx_listener *rxl);
......@@ -130,9 +147,9 @@ int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener,
void *priv);
int mlxsw_core_trap_action_set(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener,
enum mlxsw_reg_hpkt_action action);
int mlxsw_core_trap_state_set(struct mlxsw_core *mlxsw_core,
const struct mlxsw_listener *listener,
bool enabled);
typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload,
size_t payload_len, unsigned long cb_priv);
......
......@@ -813,15 +813,17 @@ mlxsw_afa_trap_mirror_pack(char *payload, bool mirror_enable,
mlxsw_afa_trap_mirror_agent_set(payload, mirror_agent);
}
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block)
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress)
{
char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_TRAP_CODE,
MLXSW_AFA_TRAP_SIZE);
if (IS_ERR(act))
return PTR_ERR(act);
mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_NOP,
MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD, 0);
mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL);
return 0;
}
EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
......
......@@ -42,7 +42,7 @@ int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity);
int mlxsw_afa_block_continue(struct mlxsw_afa_block *block);
int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
int mlxsw_afa_block_terminate(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress);
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
u16 trap_id);
......
......@@ -5526,9 +5526,11 @@ 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_DUMMY,
MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS,
};
/* reg_htgt_trap_group
......
......@@ -645,6 +645,7 @@ struct mlxsw_sp_acl_rule_info {
struct mlxsw_afk_element_values values;
struct mlxsw_afa_block *act_block;
u8 action_created:1,
ingress_bind_blocker:1,
egress_bind_blocker:1;
unsigned int counter_index;
};
......@@ -664,7 +665,10 @@ struct mlxsw_sp_acl_block {
struct mlxsw_sp *mlxsw_sp;
unsigned int rule_count;
unsigned int disable_count;
unsigned int ingress_blocker_rule_count;
unsigned int egress_blocker_rule_count;
unsigned int ingress_binding_count;
unsigned int egress_binding_count;
struct net *net;
};
......@@ -688,6 +692,8 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress);
bool mlxsw_sp_acl_block_is_egress_bound(const struct mlxsw_sp_acl_block *block);
bool mlxsw_sp_acl_block_is_ingress_bound(const struct mlxsw_sp_acl_block *block);
bool mlxsw_sp_acl_block_is_mixed_bound(const struct mlxsw_sp_acl_block *block);
struct mlxsw_sp_acl_ruleset *
mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_block *block, u32 chain_index,
......@@ -719,7 +725,8 @@ int mlxsw_sp_acl_rulei_act_continue(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
u16 group_id);
int mlxsw_sp_acl_rulei_act_terminate(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
bool ingress);
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
......
......@@ -124,13 +124,17 @@ bool mlxsw_sp_acl_block_disabled(const struct mlxsw_sp_acl_block *block)
bool mlxsw_sp_acl_block_is_egress_bound(const struct mlxsw_sp_acl_block *block)
{
struct mlxsw_sp_acl_block_binding *binding;
return block->egress_binding_count;
}
list_for_each_entry(binding, &block->binding_list, list) {
if (!binding->ingress)
return true;
}
return false;
bool mlxsw_sp_acl_block_is_ingress_bound(const struct mlxsw_sp_acl_block *block)
{
return block->ingress_binding_count;
}
bool mlxsw_sp_acl_block_is_mixed_bound(const struct mlxsw_sp_acl_block *block)
{
return block->ingress_binding_count && block->egress_binding_count;
}
static bool
......@@ -252,6 +256,11 @@ int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress)))
return -EEXIST;
if (ingress && block->ingress_blocker_rule_count) {
NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to ingress because it contains unsupported rules");
return -EOPNOTSUPP;
}
if (!ingress && block->egress_blocker_rule_count) {
NL_SET_ERR_MSG_MOD(extack, "Block cannot be bound to egress because it contains unsupported rules");
return -EOPNOTSUPP;
......@@ -269,6 +278,10 @@ int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp,
goto err_ruleset_bind;
}
if (ingress)
block->ingress_binding_count++;
else
block->egress_binding_count++;
list_add(&binding->list, &block->binding_list);
return 0;
......@@ -290,6 +303,11 @@ int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp,
list_del(&binding->list);
if (ingress)
block->ingress_binding_count--;
else
block->egress_binding_count--;
if (mlxsw_sp_acl_ruleset_block_bound(block))
mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding);
......@@ -517,9 +535,10 @@ int mlxsw_sp_acl_rulei_act_terminate(struct mlxsw_sp_acl_rule_info *rulei)
return mlxsw_afa_block_terminate(rulei->act_block);
}
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei)
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
bool ingress)
{
return mlxsw_afa_block_append_drop(rulei->act_block);
return mlxsw_afa_block_append_drop(rulei->act_block, ingress);
}
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei)
......@@ -709,6 +728,7 @@ int mlxsw_sp_acl_rule_add(struct mlxsw_sp *mlxsw_sp,
list_add_tail(&rule->list, &mlxsw_sp->acl->rules);
mutex_unlock(&mlxsw_sp->acl->rules_lock);
block->rule_count++;
block->ingress_blocker_rule_count += rule->rulei->ingress_bind_blocker;
block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker;
return 0;
......@@ -728,6 +748,7 @@ void mlxsw_sp_acl_rule_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_block *block = ruleset->ht_key.block;
block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker;
block->ingress_blocker_rule_count -= rule->rulei->ingress_bind_blocker;
ruleset->ht_key.block->rule_count--;
mutex_lock(&mlxsw_sp->acl->rules_lock);
list_del(&rule->list);
......
......@@ -41,12 +41,29 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
return err;
}
break;
case FLOW_ACTION_DROP:
err = mlxsw_sp_acl_rulei_act_drop(rulei);
case FLOW_ACTION_DROP: {
bool ingress;
if (mlxsw_sp_acl_block_is_mixed_bound(block)) {
NL_SET_ERR_MSG_MOD(extack, "Drop action is not supported when block is bound to ingress and egress");
return -EOPNOTSUPP;
}
ingress = mlxsw_sp_acl_block_is_ingress_bound(block);
err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Cannot append drop action");
return err;
}
/* Forbid block with this rulei to be bound
* to ingress/egress in future. Ingress rule is
* a blocker for egress and vice versa.
*/
if (ingress)
rulei->egress_bind_blocker = 1;
else
rulei->ingress_bind_blocker = 1;
}
break;
case FLOW_ACTION_TRAP:
err = mlxsw_sp_acl_rulei_act_trap(rulei);
......
......@@ -118,12 +118,18 @@ static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
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)
MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, DISCARD_##_id, \
TRAP_EXCEPTION_TO_CPU, false, SP_##_group_id, \
SET_FW_DEFAULT, SP_##_group_id)
#define MLXSW_SP_RXL_ACL_DISCARD(_id, _en_group_id, _dis_group_id) \
MLXSW_RXL_DIS(mlxsw_sp_rx_drop_listener, DISCARD_##_id, \
TRAP_EXCEPTION_TO_CPU, false, SP_##_en_group_id, \
SET_FW_DEFAULT, SP_##_dis_group_id)
#define MLXSW_SP_RXL_EXCEPTION(_id, _group_id, _action) \
MLXSW_RXL(mlxsw_sp_rx_exception_listener, _id, \
_action, false, SP_##_group_id, DISCARD)
_action, false, SP_##_group_id, SET_FW_DEFAULT)
static const struct devlink_trap mlxsw_sp_traps_arr[] = {
MLXSW_SP_TRAP_DROP(SMAC_MC, L2_DROPS),
......@@ -154,6 +160,8 @@ static const struct devlink_trap mlxsw_sp_traps_arr[] = {
MLXSW_SP_TRAP_DROP(NON_ROUTABLE, L3_DROPS),
MLXSW_SP_TRAP_EXCEPTION(DECAP_ERROR, TUNNEL_DROPS),
MLXSW_SP_TRAP_DROP(OVERLAY_SMAC_MC, TUNNEL_DROPS),
MLXSW_SP_TRAP_DROP(INGRESS_FLOW_ACTION_DROP, ACL_DROPS),
MLXSW_SP_TRAP_DROP(EGRESS_FLOW_ACTION_DROP, ACL_DROPS),
};
static const struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
......@@ -195,6 +203,8 @@ static const struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
MLXSW_SP_RXL_EXCEPTION(DISCARD_DEC_PKT, TUNNEL_DISCARDS,
TRAP_EXCEPTION_TO_CPU),
MLXSW_SP_RXL_DISCARD(OVERLAY_SMAC_MC, TUNNEL_DISCARDS),
MLXSW_SP_RXL_ACL_DISCARD(INGRESS_ACL, ACL_DISCARDS, DUMMY),
MLXSW_SP_RXL_ACL_DISCARD(EGRESS_ACL, ACL_DISCARDS, DUMMY),
};
/* Mapping between hardware trap and devlink trap. Multiple hardware traps can
......@@ -235,19 +245,41 @@ static const u16 mlxsw_sp_listener_devlink_map[] = {
DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
DEVLINK_TRAP_GENERIC_ID_OVERLAY_SMAC_MC,
DEVLINK_TRAP_GENERIC_ID_INGRESS_FLOW_ACTION_DROP,
DEVLINK_TRAP_GENERIC_ID_EGRESS_FLOW_ACTION_DROP,
};
#define MLXSW_SP_DISCARD_POLICER_ID (MLXSW_REG_HTGT_TRAP_GROUP_MAX + 1)
#define MLXSW_SP_THIN_POLICER_ID (MLXSW_SP_DISCARD_POLICER_ID + 1)
static int mlxsw_sp_trap_cpu_policers_set(struct mlxsw_sp *mlxsw_sp)
{
char qpcr_pl[MLXSW_REG_QPCR_LEN];
int err;
mlxsw_reg_qpcr_pack(qpcr_pl, MLXSW_SP_DISCARD_POLICER_ID,
MLXSW_REG_QPCR_IR_UNITS_M, false, 10 * 1024, 7);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
if (err)
return err;
/* The purpose of "thin" policer is to drop as many packets
* as possible. The dummy group is using it.
*/
mlxsw_reg_qpcr_pack(qpcr_pl, MLXSW_SP_THIN_POLICER_ID,
MLXSW_REG_QPCR_IR_UNITS_M, false, 1, 4);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
}
static int mlxsw_sp_trap_dummy_group_init(struct mlxsw_sp *mlxsw_sp)
{
char htgt_pl[MLXSW_REG_HTGT_LEN];
mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_SP_DUMMY,
MLXSW_SP_THIN_POLICER_ID, 0, 1);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
}
int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
{
struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
......@@ -257,6 +289,10 @@ int mlxsw_sp_devlink_traps_init(struct mlxsw_sp *mlxsw_sp)
if (err)
return err;
err = mlxsw_sp_trap_dummy_group_init(mlxsw_sp);
if (err)
return err;
if (WARN_ON(ARRAY_SIZE(mlxsw_sp_listener_devlink_map) !=
ARRAY_SIZE(mlxsw_sp_listeners_arr)))
return -EINVAL;
......@@ -319,26 +355,23 @@ int mlxsw_sp_trap_action_set(struct mlxsw_core *mlxsw_core,
for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener_devlink_map); i++) {
const struct mlxsw_listener *listener;
enum mlxsw_reg_hpkt_action hw_action;
bool enabled;
int err;
if (mlxsw_sp_listener_devlink_map[i] != trap->id)
continue;
listener = &mlxsw_sp_listeners_arr[i];
switch (action) {
case DEVLINK_TRAP_ACTION_DROP:
hw_action = MLXSW_REG_HPKT_ACTION_SET_FW_DEFAULT;
enabled = false;
break;
case DEVLINK_TRAP_ACTION_TRAP:
hw_action = MLXSW_REG_HPKT_ACTION_TRAP_EXCEPTION_TO_CPU;
enabled = true;
break;
default:
return -EINVAL;
}
err = mlxsw_core_trap_action_set(mlxsw_core, listener,
hw_action);
err = mlxsw_core_trap_state_set(mlxsw_core, listener, enabled);
if (err)
return err;
}
......@@ -372,6 +405,12 @@ int mlxsw_sp_trap_group_init(struct mlxsw_core *mlxsw_core,
priority = 0;
tc = 1;
break;
case DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_DROPS:
group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_ACL_DISCARDS;
policer_id = MLXSW_SP_DISCARD_POLICER_ID;
priority = 0;
tc = 1;
break;
default:
return -EINVAL;
}
......
......@@ -102,6 +102,8 @@ enum {
MLXSW_TRAP_ID_ACL1 = 0x1C1,
/* Multicast trap used for routes with trap-and-forward action */
MLXSW_TRAP_ID_ACL2 = 0x1C2,
MLXSW_TRAP_ID_DISCARD_INGRESS_ACL = 0x1C3,
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL = 0x1C4,
MLXSW_TRAP_ID_MAX = 0x1FF
};
......
......@@ -596,6 +596,8 @@ enum devlink_trap_generic_id {
DEVLINK_TRAP_GENERIC_ID_NON_ROUTABLE,
DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
DEVLINK_TRAP_GENERIC_ID_OVERLAY_SMAC_MC,
DEVLINK_TRAP_GENERIC_ID_INGRESS_FLOW_ACTION_DROP,
DEVLINK_TRAP_GENERIC_ID_EGRESS_FLOW_ACTION_DROP,
/* Add new generic trap IDs above */
__DEVLINK_TRAP_GENERIC_ID_MAX,
......@@ -610,6 +612,7 @@ enum devlink_trap_group_generic_id {
DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS,
DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS,
DEVLINK_TRAP_GROUP_GENERIC_ID_TUNNEL_DROPS,
DEVLINK_TRAP_GROUP_GENERIC_ID_ACL_DROPS,
/* Add new generic trap group IDs above */
__DEVLINK_TRAP_GROUP_GENERIC_ID_MAX,
......@@ -671,6 +674,10 @@ enum devlink_trap_group_generic_id {
"decap_error"
#define DEVLINK_TRAP_GENERIC_NAME_OVERLAY_SMAC_MC \
"overlay_smac_is_mc"
#define DEVLINK_TRAP_GENERIC_NAME_INGRESS_FLOW_ACTION_DROP \
"ingress_flow_action_drop"
#define DEVLINK_TRAP_GENERIC_NAME_EGRESS_FLOW_ACTION_DROP \
"egress_flow_action_drop"
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_L2_DROPS \
"l2_drops"
......@@ -680,6 +687,8 @@ enum devlink_trap_group_generic_id {
"buffer_drops"
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_TUNNEL_DROPS \
"tunnel_drops"
#define DEVLINK_TRAP_GROUP_GENERIC_NAME_ACL_DROPS \
"acl_drops"
#define DEVLINK_TRAP_GENERIC(_type, _init_action, _id, _group, _metadata_cap) \
{ \
......
......@@ -7795,6 +7795,8 @@ static const struct devlink_trap devlink_trap_generic[] = {
DEVLINK_TRAP(NON_ROUTABLE, DROP),
DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
};
#define DEVLINK_TRAP_GROUP(_id) \
......@@ -7808,6 +7810,7 @@ static const struct devlink_trap_group devlink_trap_group_generic[] = {
DEVLINK_TRAP_GROUP(L3_DROPS),
DEVLINK_TRAP_GROUP(BUFFER_DROPS),
DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
DEVLINK_TRAP_GROUP(ACL_DROPS),
};
static int devlink_trap_generic_verify(const struct devlink_trap *trap)
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Test devlink-trap ACL drops functionality over mlxsw.
lib_dir=$(dirname $0)/../../../net/forwarding
ALL_TESTS="
ingress_flow_action_drop_test
egress_flow_action_drop_test
"
NUM_NETIFS=4
source $lib_dir/tc_common.sh
source $lib_dir/lib.sh
source $lib_dir/devlink_lib.sh
h1_create()
{
simple_if_init $h1
}
h1_destroy()
{
simple_if_fini $h1
}
h2_create()
{
simple_if_init $h2
}
h2_destroy()
{
simple_if_fini $h2
}
switch_create()
{
ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0
ip link set dev $swp1 master br0
ip link set dev $swp2 master br0
ip link set dev br0 up
ip link set dev $swp1 up
ip link set dev $swp2 up
tc qdisc add dev $swp1 clsact
tc qdisc add dev $swp2 clsact
}
switch_destroy()
{
tc qdisc del dev $swp2 clsact
tc qdisc del dev $swp1 clsact
ip link set dev $swp2 down
ip link set dev $swp1 down
ip link del dev br0
}
setup_prepare()
{
h1=${NETIFS[p1]}
swp1=${NETIFS[p2]}
swp2=${NETIFS[p3]}
h2=${NETIFS[p4]}
h1mac=$(mac_get $h1)
h2mac=$(mac_get $h2)
vrf_prepare
h1_create
h2_create
switch_create
}
cleanup()
{
pre_cleanup
switch_destroy
h2_destroy
h1_destroy
vrf_cleanup
}
ingress_flow_action_drop_test()
{
local mz_pid
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
flower src_mac $h1mac action pass
tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 \
flower dst_ip 192.0.2.2 action drop
$MZ $h1 -c 0 -p 100 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -d 1msec -q &
mz_pid=$!
RET=0
devlink_trap_drop_test ingress_flow_action_drop acl_drops $swp2 101
log_test "ingress_flow_action_drop"
tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
}
egress_flow_action_drop_test()
{
local mz_pid
tc filter add dev $swp2 egress protocol ip pref 2 handle 102 \
flower src_mac $h1mac action pass
tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \
flower dst_ip 192.0.2.2 action drop
$MZ $h1 -c 0 -p 100 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -d 1msec -q &
mz_pid=$!
RET=0
devlink_trap_drop_test egress_flow_action_drop acl_drops $swp2 102
log_test "egress_flow_action_drop"
tc filter del dev $swp2 egress protocol ip pref 1 handle 101 flower
devlink_trap_drop_cleanup $mz_pid $swp2 ip 2 102
}
trap cleanup EXIT
setup_prepare
setup_wait
tests_run
exit $EXIT_STATUS
......@@ -107,11 +107,11 @@ source_mac_is_multicast_test()
RET=0
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
log_test "Source MAC is multicast"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
}
__vlan_tag_mismatch_test()
......@@ -132,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=$!
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
# Add PVID and make sure packets are no longer dropped.
bridge vlan add vid 1 dev $swp1 pvid untagged master
......@@ -148,7 +148,7 @@ __vlan_tag_mismatch_test()
devlink_trap_action_set $trap_name "drop"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
}
vlan_tag_mismatch_untagged_test()
......@@ -193,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=$!
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
# Add the VLAN on the bridge port and make sure packets are no longer
# dropped.
......@@ -212,7 +212,7 @@ ingress_vlan_filter_test()
log_test "Ingress VLAN filter"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
bridge vlan del vid $vid dev $swp1 master
bridge vlan del vid $vid dev $swp2 master
......@@ -237,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=$!
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
# Change STP state to forwarding and make sure packets are no longer
# dropped.
......@@ -254,7 +254,7 @@ __ingress_stp_filter_test()
devlink_trap_action_set $trap_name "drop"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
bridge vlan del vid $vid dev $swp1 master
bridge vlan del vid $vid dev $swp2 master
......@@ -308,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=$!
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
# Allow packets to be flooded to one port.
ip link set dev $swp2 type bridge_slave flood on
......@@ -326,7 +326,7 @@ port_list_is_empty_uc_test()
log_test "Port list is empty - unicast"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
ip link set dev $swp1 type bridge_slave flood on
}
......@@ -354,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=$!
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
# Allow packets to be flooded to one port.
ip link set dev $swp2 type bridge_slave mcast_flood on
......@@ -372,7 +372,7 @@ port_list_is_empty_mc_test()
log_test "Port list is empty - multicast"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
ip link set dev $swp1 type bridge_slave mcast_flood on
}
......@@ -401,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=$!
devlink_trap_drop_test $trap_name $group_name $swp2
devlink_trap_drop_test $trap_name $group_name $swp2 101
# Allow packets to be flooded.
ip link set dev $swp2 type bridge_slave flood on
......@@ -419,7 +419,7 @@ port_loopback_filter_uc_test()
log_test "Port loopback filter - unicast"
devlink_trap_drop_cleanup $mz_pid $swp2 ip
devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101
}
port_loopback_filter_test()
......
......@@ -176,11 +176,11 @@ non_ip_test()
00:00 de:ad:be:ef" &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "Non IP"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
}
__uc_dip_over_mc_dmac_test()
......@@ -206,11 +206,11 @@ __uc_dip_over_mc_dmac_test()
-B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "Unicast destination IP over multicast destination MAC: $desc"
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
}
uc_dip_over_mc_dmac_test()
......@@ -242,11 +242,11 @@ __sip_is_loopback_test()
-b $rp1mac -B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "Source IP is loopback address: $desc"
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
}
sip_is_loopback_test()
......@@ -277,11 +277,11 @@ __dip_is_loopback_test()
-B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "Destination IP is loopback address: $desc"
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
}
dip_is_loopback_test()
......@@ -313,11 +313,11 @@ __sip_is_mc_test()
-b $rp1mac -B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "Source IP is multicast: $desc"
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
}
sip_is_mc_test()
......@@ -345,11 +345,11 @@ ipv4_sip_is_limited_bc_test()
-B $h2_ipv4 -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "IPv4 source IP is limited broadcast"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
}
ipv4_payload_get()
......@@ -399,11 +399,11 @@ __ipv4_header_corrupted_test()
$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "IP header corrupted: $desc: IPv4"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
}
ipv6_payload_get()
......@@ -446,11 +446,11 @@ __ipv6_header_corrupted_test()
$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "IP header corrupted: $desc: IPv6"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip"
devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
}
ip_header_corrupted_test()
......@@ -485,11 +485,11 @@ ipv6_mc_dip_reserved_scope_test()
"33:33:00:00:00:00" -B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "IPv6 multicast destination IP reserved scope"
devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6"
devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101
}
ipv6_mc_dip_interface_local_scope_test()
......@@ -511,11 +511,11 @@ ipv6_mc_dip_interface_local_scope_test()
"33:33:00:00:00:00" -B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "IPv6 multicast destination IP interface-local scope"
devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6"
devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101
}
__blackhole_route_test()
......@@ -542,10 +542,10 @@ __blackhole_route_test()
-B $dip -d 1msec -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $rp2
devlink_trap_drop_test $trap_name $group_name $rp2 101
log_test "Blackhole route: IPv$flags"
devlink_trap_drop_cleanup $mz_pid $rp2 $proto
devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
ip -$flags route del blackhole $subnet
}
......
......@@ -314,11 +314,11 @@ overlay_smac_is_mc_test()
-B 192.0.2.17 -t udp sp=12345,dp=$VXPORT,p=$payload -q &
mz_pid=$!
devlink_trap_drop_test $trap_name $group_name $swp1
devlink_trap_drop_test $trap_name $group_name $swp1 101
log_test "Overlay source MAC is multicast"
devlink_trap_drop_cleanup $mz_pid $swp1 "ip"
devlink_trap_drop_cleanup $mz_pid $swp1 "ip" 1 101
}
trap cleanup EXIT
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
lib_dir=$(dirname $0)/../../../net/forwarding
ALL_TESTS="shared_block_drop_test"
NUM_NETIFS=2
source $lib_dir/tc_common.sh
source $lib_dir/lib.sh
switch_create()
{
simple_if_init $swp1 192.0.2.1/24
simple_if_init $swp2 192.0.2.2/24
}
switch_destroy()
{
simple_if_fini $swp2 192.0.2.2/24
simple_if_fini $swp1 192.0.2.1/24
}
shared_block_drop_test()
{
RET=0
# It is forbidden in mlxsw driver to have mixed-bound
# shared block with a drop rule.
tc qdisc add dev $swp1 ingress_block 22 clsact
check_err $? "Failed to create clsact with ingress block"
tc filter add block 22 protocol ip pref 1 handle 101 flower \
skip_sw dst_ip 192.0.2.2 action drop
check_err $? "Failed to add drop rule to ingress bound block"
tc qdisc add dev $swp2 ingress_block 22 clsact
check_err $? "Failed to create another clsact with ingress shared block"
tc qdisc del dev $swp2 clsact
tc qdisc add dev $swp2 egress_block 22 clsact
check_fail $? "Incorrect success to create another clsact with egress shared block"
tc filter del block 22 protocol ip pref 1 handle 101 flower
tc qdisc add dev $swp2 egress_block 22 clsact
check_err $? "Failed to create another clsact with egress shared block after blocker drop rule removed"
tc filter add block 22 protocol ip pref 1 handle 101 flower \
skip_sw dst_ip 192.0.2.2 action drop
check_fail $? "Incorrect success to add drop rule to mixed bound block"
tc qdisc del dev $swp1 clsact
tc qdisc add dev $swp1 egress_block 22 clsact
check_err $? "Failed to create another clsact with egress shared block"
tc filter add block 22 protocol ip pref 1 handle 101 flower \
skip_sw dst_ip 192.0.2.2 action drop
check_err $? "Failed to add drop rule to egress bound shared block"
tc filter del block 22 protocol ip pref 1 handle 101 flower
tc qdisc del dev $swp2 clsact
tc qdisc del dev $swp1 clsact
log_test "shared block drop"
}
setup_prepare()
{
swp1=${NETIFS[p1]}
swp2=${NETIFS[p2]}
vrf_prepare
switch_create
}
cleanup()
{
pre_cleanup
switch_destroy
vrf_cleanup
}
check_tc_shblock_support
trap cleanup EXIT
setup_prepare
setup_wait
tests_run
exit $EXIT_STATUS
......@@ -373,6 +373,7 @@ devlink_trap_drop_test()
local trap_name=$1; shift
local group_name=$1; shift
local dev=$1; shift
local handle=$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
......@@ -397,7 +398,7 @@ devlink_trap_drop_test()
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
tc_check_packets "dev $dev egress" $handle 0
check_err $? "Packets were not dropped"
}
......@@ -406,7 +407,9 @@ devlink_trap_drop_cleanup()
local mz_pid=$1; shift
local dev=$1; shift
local proto=$1; shift
local pref=$1; shift
local handle=$1; shift
kill $mz_pid && wait $mz_pid &> /dev/null
tc filter del dev $dev egress protocol $proto pref 1 handle 101 flower
tc filter del dev $dev egress protocol $proto pref $pref handle $handle flower
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment