ice: Support drop action

Currently the drop action is supported only in switchdev mode.
Add support for offloading receive filters with action drop
in ADQ/non-ADQ modes. This is in addition to other actions
such as forwarding to a VSI (ADQ) or a queue (ADQ/non-ADQ).

Also renamed 'ch_vsi' to 'dest_vsi' as it is valid for multiple
actions such as forward to vsi/queue which may/may not create a
channel vsi.

Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Tested-by: Bharathi Sreenivas <bharathi.sreenivas@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Amritha Nambiar 2022-11-08 14:08:12 -08:00 committed by Tony Nguyen
parent 7d8d7754e6
commit 390889a4b4
2 changed files with 40 additions and 20 deletions

View File

@ -792,7 +792,7 @@ static struct ice_vsi *
ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr) ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
{ {
struct ice_rx_ring *ring = NULL; struct ice_rx_ring *ring = NULL;
struct ice_vsi *ch_vsi = NULL; struct ice_vsi *dest_vsi = NULL;
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
struct device *dev; struct device *dev;
u32 tc_class; u32 tc_class;
@ -810,7 +810,7 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
} }
/* Locate ADQ VSI depending on hw_tc number */ /* Locate ADQ VSI depending on hw_tc number */
ch_vsi = vsi->tc_map_vsi[tc_class]; dest_vsi = vsi->tc_map_vsi[tc_class];
break; break;
case ICE_FWD_TO_Q: case ICE_FWD_TO_Q:
/* Locate the Rx queue */ /* Locate the Rx queue */
@ -824,7 +824,7 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
/* Determine destination VSI even though the action is /* Determine destination VSI even though the action is
* FWD_TO_QUEUE, because QUEUE is associated with VSI * FWD_TO_QUEUE, because QUEUE is associated with VSI
*/ */
ch_vsi = tc_fltr->dest_vsi; dest_vsi = tc_fltr->dest_vsi;
break; break;
default: default:
dev_err(dev, dev_err(dev,
@ -832,13 +832,13 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
tc_fltr->action.fltr_act); tc_fltr->action.fltr_act);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
/* Must have valid ch_vsi (it could be main VSI or ADQ VSI) */ /* Must have valid dest_vsi (it could be main VSI or ADQ VSI) */
if (!ch_vsi) { if (!dest_vsi) {
dev_err(dev, dev_err(dev,
"Unable to add filter because specified destination VSI doesn't exist\n"); "Unable to add filter because specified destination VSI doesn't exist\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
return ch_vsi; return dest_vsi;
} }
/** /**
@ -860,7 +860,7 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
u32 flags = tc_fltr->flags; u32 flags = tc_fltr->flags;
struct ice_vsi *ch_vsi; struct ice_vsi *dest_vsi;
struct device *dev; struct device *dev;
u16 lkups_cnt = 0; u16 lkups_cnt = 0;
u16 l4_proto = 0; u16 l4_proto = 0;
@ -883,9 +883,11 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
} }
/* validate forwarding action VSI and queue */ /* validate forwarding action VSI and queue */
ch_vsi = ice_tc_forward_action(vsi, tc_fltr); if (ice_is_forward_action(tc_fltr->action.fltr_act)) {
if (IS_ERR(ch_vsi)) dest_vsi = ice_tc_forward_action(vsi, tc_fltr);
return PTR_ERR(ch_vsi); if (IS_ERR(dest_vsi))
return PTR_ERR(dest_vsi);
}
lkups_cnt = ice_tc_count_lkups(flags, headers, tc_fltr); lkups_cnt = ice_tc_count_lkups(flags, headers, tc_fltr);
list = kcalloc(lkups_cnt, sizeof(*list), GFP_ATOMIC); list = kcalloc(lkups_cnt, sizeof(*list), GFP_ATOMIC);
@ -904,7 +906,7 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
switch (tc_fltr->action.fltr_act) { switch (tc_fltr->action.fltr_act) {
case ICE_FWD_TO_VSI: case ICE_FWD_TO_VSI:
rule_info.sw_act.vsi_handle = ch_vsi->idx; rule_info.sw_act.vsi_handle = dest_vsi->idx;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI; rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI;
rule_info.sw_act.src = hw->pf_id; rule_info.sw_act.src = hw->pf_id;
rule_info.rx = true; rule_info.rx = true;
@ -915,7 +917,7 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
case ICE_FWD_TO_Q: case ICE_FWD_TO_Q:
/* HW queue number in global space */ /* HW queue number in global space */
rule_info.sw_act.fwd_id.q_id = tc_fltr->action.fwd.q.hw_queue; rule_info.sw_act.fwd_id.q_id = tc_fltr->action.fwd.q.hw_queue;
rule_info.sw_act.vsi_handle = ch_vsi->idx; rule_info.sw_act.vsi_handle = dest_vsi->idx;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_QUEUE; rule_info.priority = ICE_SWITCH_FLTR_PRIO_QUEUE;
rule_info.sw_act.src = hw->pf_id; rule_info.sw_act.src = hw->pf_id;
rule_info.rx = true; rule_info.rx = true;
@ -923,14 +925,15 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
tc_fltr->action.fwd.q.queue, tc_fltr->action.fwd.q.queue,
tc_fltr->action.fwd.q.hw_queue, lkups_cnt); tc_fltr->action.fwd.q.hw_queue, lkups_cnt);
break; break;
default: case ICE_DROP_PACKET:
rule_info.sw_act.flag |= ICE_FLTR_TX; rule_info.sw_act.flag |= ICE_FLTR_RX;
/* In case of Tx (LOOKUP_TX), src needs to be src VSI */ rule_info.sw_act.src = hw->pf_id;
rule_info.sw_act.src = vsi->idx; rule_info.rx = true;
/* 'Rx' is false, direction of rule(LOOKUPTRX) */
rule_info.rx = false;
rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI; rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI;
break; break;
default:
ret = -EOPNOTSUPP;
goto exit;
} }
ret = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, &rule_added); ret = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, &rule_added);
@ -953,11 +956,11 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
tc_fltr->dest_vsi_handle = rule_added.vsi_handle; tc_fltr->dest_vsi_handle = rule_added.vsi_handle;
if (tc_fltr->action.fltr_act == ICE_FWD_TO_VSI || if (tc_fltr->action.fltr_act == ICE_FWD_TO_VSI ||
tc_fltr->action.fltr_act == ICE_FWD_TO_Q) { tc_fltr->action.fltr_act == ICE_FWD_TO_Q) {
tc_fltr->dest_vsi = ch_vsi; tc_fltr->dest_vsi = dest_vsi;
/* keep track of advanced switch filter for /* keep track of advanced switch filter for
* destination VSI * destination VSI
*/ */
ch_vsi->num_chnl_fltr++; dest_vsi->num_chnl_fltr++;
/* keeps track of channel filters for PF VSI */ /* keeps track of channel filters for PF VSI */
if (vsi->type == ICE_VSI_PF && if (vsi->type == ICE_VSI_PF &&
@ -978,6 +981,10 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi,
tc_fltr->action.fwd.q.hw_queue, rule_added.rid, tc_fltr->action.fwd.q.hw_queue, rule_added.rid,
rule_added.rule_id); rule_added.rule_id);
break; break;
case ICE_DROP_PACKET:
dev_dbg(dev, "added switch rule (lkups_cnt %u, flags 0x%x), action is drop, rid %u, rule_id %u\n",
lkups_cnt, flags, rule_added.rid, rule_added.rule_id);
break;
default: default:
break; break;
} }
@ -1712,6 +1719,9 @@ ice_tc_parse_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr,
case FLOW_ACTION_RX_QUEUE_MAPPING: case FLOW_ACTION_RX_QUEUE_MAPPING:
/* forward to queue */ /* forward to queue */
return ice_tc_forward_to_queue(vsi, fltr, act); return ice_tc_forward_to_queue(vsi, fltr, act);
case FLOW_ACTION_DROP:
fltr->action.fltr_act = ICE_DROP_PACKET;
return 0;
default: default:
NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported TC action"); NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported TC action");
return -EOPNOTSUPP; return -EOPNOTSUPP;

View File

@ -211,4 +211,14 @@ ice_del_cls_flower(struct ice_vsi *vsi, struct flow_cls_offload *cls_flower);
void ice_replay_tc_fltrs(struct ice_pf *pf); void ice_replay_tc_fltrs(struct ice_pf *pf);
bool ice_is_tunnel_supported(struct net_device *dev); bool ice_is_tunnel_supported(struct net_device *dev);
static inline bool ice_is_forward_action(enum ice_sw_fwd_act_type fltr_act)
{
switch (fltr_act) {
case ICE_FWD_TO_VSI:
case ICE_FWD_TO_Q:
return true;
default:
return false;
}
}
#endif /* _ICE_TC_LIB_H_ */ #endif /* _ICE_TC_LIB_H_ */