Skip to content

Commit 68fbff6

Browse files
Subbaraya Sundeepdavem330
authored andcommitted
octeontx2-pf: Add police action for TC flower
Added police action for ingress TC flower hardware offload. With this rate limiting can be done per flow. Since rate limiting is tied to RQs in hardware the number of TC flower filters with action as police is limited to number of receive queues of the interface. Both bps and pps modes are supported. Examples to rate limit a flow: $ ethtool -K eth0 hw-tc-offload on $ tc qdisc add dev eth0 ingress $ tc filter add dev eth0 parent ffff: protocol ip \ flower ip_proto udp dst_port 80 action \ police rate 100Mbit burst 32Kbit $ tc filter add dev eth0 parent ffff: \ protocol ip flower dst_mac 5e:b2:34:ee:29:49 \ action police pkts_rate 5000 pkts_burst 2048 Signed-off-by: Subbaraya Sundeep <[email protected]> Signed-off-by: Sunil Kovvuri Goutham <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5d2fdd8 commit 68fbff6

File tree

3 files changed

+178
-23
lines changed

3 files changed

+178
-23
lines changed

drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ struct otx2_nic {
372372

373373
struct otx2_flow_config *flow_cfg;
374374
struct otx2_tc_info tc_info;
375+
unsigned long rq_bmap;
375376
};
376377

377378
static inline bool is_otx2_lbkvf(struct pci_dev *pdev)

drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ static int otx2_set_channels(struct net_device *dev,
286286
if (!channel->rx_count || !channel->tx_count)
287287
return -EINVAL;
288288

289+
if (bitmap_weight(&pfvf->rq_bmap, pfvf->hw.rx_queues) > 1) {
290+
netdev_err(dev,
291+
"Receive queues are in use by TC police action\n");
292+
return -EINVAL;
293+
}
294+
289295
if (if_up)
290296
dev->netdev_ops->ndo_stop(dev);
291297

drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c

Lines changed: 171 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@ struct otx2_tc_flow_stats {
4242
struct otx2_tc_flow {
4343
struct rhash_head node;
4444
unsigned long cookie;
45-
u16 entry;
4645
unsigned int bitpos;
4746
struct rcu_head rcu;
4847
struct otx2_tc_flow_stats stats;
4948
spinlock_t lock; /* lock for stats */
49+
u16 rq;
50+
u16 entry;
51+
u16 leaf_profile;
52+
bool is_act_police;
5053
};
5154

5255
static void otx2_get_egress_burst_cfg(u32 burst, u32 *burst_exp,
@@ -221,15 +224,72 @@ static int otx2_tc_egress_matchall_delete(struct otx2_nic *nic,
221224
return err;
222225
}
223226

227+
static int otx2_tc_act_set_police(struct otx2_nic *nic,
228+
struct otx2_tc_flow *node,
229+
struct flow_cls_offload *f,
230+
u64 rate, u32 burst, u32 mark,
231+
struct npc_install_flow_req *req, bool pps)
232+
{
233+
struct netlink_ext_ack *extack = f->common.extack;
234+
struct otx2_hw *hw = &nic->hw;
235+
int rq_idx, rc;
236+
237+
rq_idx = find_first_zero_bit(&nic->rq_bmap, hw->rx_queues);
238+
if (rq_idx >= hw->rx_queues) {
239+
NL_SET_ERR_MSG_MOD(extack, "Police action rules exceeded");
240+
return -EINVAL;
241+
}
242+
243+
mutex_lock(&nic->mbox.lock);
244+
245+
rc = cn10k_alloc_leaf_profile(nic, &node->leaf_profile);
246+
if (rc) {
247+
mutex_unlock(&nic->mbox.lock);
248+
return rc;
249+
}
250+
251+
rc = cn10k_set_ipolicer_rate(nic, node->leaf_profile, burst, rate, pps);
252+
if (rc)
253+
goto free_leaf;
254+
255+
rc = cn10k_map_unmap_rq_policer(nic, rq_idx, node->leaf_profile, true);
256+
if (rc)
257+
goto free_leaf;
258+
259+
mutex_unlock(&nic->mbox.lock);
260+
261+
req->match_id = mark & 0xFFFFULL;
262+
req->index = rq_idx;
263+
req->op = NIX_RX_ACTIONOP_UCAST;
264+
set_bit(rq_idx, &nic->rq_bmap);
265+
node->is_act_police = true;
266+
node->rq = rq_idx;
267+
268+
return 0;
269+
270+
free_leaf:
271+
if (cn10k_free_leaf_profile(nic, node->leaf_profile))
272+
netdev_err(nic->netdev,
273+
"Unable to free leaf bandwidth profile(%d)\n",
274+
node->leaf_profile);
275+
mutex_unlock(&nic->mbox.lock);
276+
return rc;
277+
}
278+
224279
static int otx2_tc_parse_actions(struct otx2_nic *nic,
225280
struct flow_action *flow_action,
226281
struct npc_install_flow_req *req,
227-
struct flow_cls_offload *f)
282+
struct flow_cls_offload *f,
283+
struct otx2_tc_flow *node)
228284
{
229285
struct netlink_ext_ack *extack = f->common.extack;
230286
struct flow_action_entry *act;
231287
struct net_device *target;
232288
struct otx2_nic *priv;
289+
u32 burst, mark = 0;
290+
u8 nr_police = 0;
291+
bool pps;
292+
u64 rate;
233293
int i;
234294

235295
if (!flow_action_has_entries(flow_action)) {
@@ -262,15 +322,51 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic,
262322
/* use RX_VTAG_TYPE7 which is initialized to strip vlan tag */
263323
req->vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE7;
264324
break;
325+
case FLOW_ACTION_POLICE:
326+
/* Ingress ratelimiting is not supported on OcteonTx2 */
327+
if (is_dev_otx2(nic->pdev)) {
328+
NL_SET_ERR_MSG_MOD(extack,
329+
"Ingress policing not supported on this platform");
330+
return -EOPNOTSUPP;
331+
}
332+
333+
if (act->police.rate_bytes_ps > 0) {
334+
rate = act->police.rate_bytes_ps * 8;
335+
burst = act->police.burst;
336+
} else if (act->police.rate_pkt_ps > 0) {
337+
/* The algorithm used to calculate rate
338+
* mantissa, exponent values for a given token
339+
* rate (token can be byte or packet) requires
340+
* token rate to be mutiplied by 8.
341+
*/
342+
rate = act->police.rate_pkt_ps * 8;
343+
burst = act->police.burst_pkt;
344+
pps = true;
345+
}
346+
nr_police++;
347+
break;
348+
case FLOW_ACTION_MARK:
349+
mark = act->mark;
350+
break;
265351
default:
266352
return -EOPNOTSUPP;
267353
}
268354
}
269355

356+
if (nr_police > 1) {
357+
NL_SET_ERR_MSG_MOD(extack,
358+
"rate limit police offload requires a single action");
359+
return -EOPNOTSUPP;
360+
}
361+
362+
if (nr_police)
363+
return otx2_tc_act_set_police(nic, node, f, rate, burst,
364+
mark, req, pps);
365+
270366
return 0;
271367
}
272368

273-
static int otx2_tc_prepare_flow(struct otx2_nic *nic,
369+
static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
274370
struct flow_cls_offload *f,
275371
struct npc_install_flow_req *req)
276372
{
@@ -467,7 +563,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic,
467563
req->features |= BIT_ULL(NPC_SPORT_SCTP);
468564
}
469565

470-
return otx2_tc_parse_actions(nic, &rule->action, req, f);
566+
return otx2_tc_parse_actions(nic, &rule->action, req, f, node);
471567
}
472568

473569
static int otx2_del_mcam_flow_entry(struct otx2_nic *nic, u16 entry)
@@ -502,6 +598,7 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
502598
{
503599
struct otx2_tc_info *tc_info = &nic->tc_info;
504600
struct otx2_tc_flow *flow_node;
601+
int err;
505602

506603
flow_node = rhashtable_lookup_fast(&tc_info->flow_table,
507604
&tc_flow_cmd->cookie,
@@ -512,6 +609,27 @@ static int otx2_tc_del_flow(struct otx2_nic *nic,
512609
return -EINVAL;
513610
}
514611

612+
if (flow_node->is_act_police) {
613+
mutex_lock(&nic->mbox.lock);
614+
615+
err = cn10k_map_unmap_rq_policer(nic, flow_node->rq,
616+
flow_node->leaf_profile, false);
617+
if (err)
618+
netdev_err(nic->netdev,
619+
"Unmapping RQ %d & profile %d failed\n",
620+
flow_node->rq, flow_node->leaf_profile);
621+
622+
err = cn10k_free_leaf_profile(nic, flow_node->leaf_profile);
623+
if (err)
624+
netdev_err(nic->netdev,
625+
"Unable to free leaf bandwidth profile(%d)\n",
626+
flow_node->leaf_profile);
627+
628+
__clear_bit(flow_node->rq, &nic->rq_bmap);
629+
630+
mutex_unlock(&nic->mbox.lock);
631+
}
632+
515633
otx2_del_mcam_flow_entry(nic, flow_node->entry);
516634

517635
WARN_ON(rhashtable_remove_fast(&nic->tc_info.flow_table,
@@ -531,30 +649,30 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
531649
struct netlink_ext_ack *extack = tc_flow_cmd->common.extack;
532650
struct otx2_tc_info *tc_info = &nic->tc_info;
533651
struct otx2_tc_flow *new_node, *old_node;
534-
struct npc_install_flow_req *req;
535-
int rc;
652+
struct npc_install_flow_req *req, dummy;
653+
int rc, err;
536654

537655
if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT))
538656
return -ENOMEM;
539657

658+
if (bitmap_full(tc_info->tc_entries_bitmap, nic->flow_cfg->tc_max_flows)) {
659+
NL_SET_ERR_MSG_MOD(extack,
660+
"Not enough MCAM space to add the flow");
661+
return -ENOMEM;
662+
}
663+
540664
/* allocate memory for the new flow and it's node */
541665
new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
542666
if (!new_node)
543667
return -ENOMEM;
544668
spin_lock_init(&new_node->lock);
545669
new_node->cookie = tc_flow_cmd->cookie;
546670

547-
mutex_lock(&nic->mbox.lock);
548-
req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
549-
if (!req) {
550-
mutex_unlock(&nic->mbox.lock);
551-
return -ENOMEM;
552-
}
671+
memset(&dummy, 0, sizeof(struct npc_install_flow_req));
553672

554-
rc = otx2_tc_prepare_flow(nic, tc_flow_cmd, req);
673+
rc = otx2_tc_prepare_flow(nic, new_node, tc_flow_cmd, &dummy);
555674
if (rc) {
556-
otx2_mbox_reset(&nic->mbox.mbox, 0);
557-
mutex_unlock(&nic->mbox.lock);
675+
kfree_rcu(new_node, rcu);
558676
return rc;
559677
}
560678

@@ -565,14 +683,17 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
565683
if (old_node)
566684
otx2_tc_del_flow(nic, tc_flow_cmd);
567685

568-
if (bitmap_full(tc_info->tc_entries_bitmap, nic->flow_cfg->tc_max_flows)) {
569-
NL_SET_ERR_MSG_MOD(extack,
570-
"Not enough MCAM space to add the flow");
571-
otx2_mbox_reset(&nic->mbox.mbox, 0);
686+
mutex_lock(&nic->mbox.lock);
687+
req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox);
688+
if (!req) {
572689
mutex_unlock(&nic->mbox.lock);
573-
return -ENOMEM;
690+
rc = -ENOMEM;
691+
goto free_leaf;
574692
}
575693

694+
memcpy(&dummy.hdr, &req->hdr, sizeof(struct mbox_msghdr));
695+
memcpy(req, &dummy, sizeof(struct npc_install_flow_req));
696+
576697
new_node->bitpos = find_first_zero_bit(tc_info->tc_entries_bitmap,
577698
nic->flow_cfg->tc_max_flows);
578699
req->channel = nic->hw.rx_chan_base;
@@ -587,7 +708,8 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
587708
if (rc) {
588709
NL_SET_ERR_MSG_MOD(extack, "Failed to install MCAM flow entry");
589710
mutex_unlock(&nic->mbox.lock);
590-
goto out;
711+
kfree_rcu(new_node, rcu);
712+
goto free_leaf;
591713
}
592714
mutex_unlock(&nic->mbox.lock);
593715

@@ -597,12 +719,35 @@ static int otx2_tc_add_flow(struct otx2_nic *nic,
597719
if (rc) {
598720
otx2_del_mcam_flow_entry(nic, req->entry);
599721
kfree_rcu(new_node, rcu);
600-
goto out;
722+
goto free_leaf;
601723
}
602724

603725
set_bit(new_node->bitpos, tc_info->tc_entries_bitmap);
604726
tc_info->num_entries++;
605-
out:
727+
728+
return 0;
729+
730+
free_leaf:
731+
if (new_node->is_act_police) {
732+
mutex_lock(&nic->mbox.lock);
733+
734+
err = cn10k_map_unmap_rq_policer(nic, new_node->rq,
735+
new_node->leaf_profile, false);
736+
if (err)
737+
netdev_err(nic->netdev,
738+
"Unmapping RQ %d & profile %d failed\n",
739+
new_node->rq, new_node->leaf_profile);
740+
err = cn10k_free_leaf_profile(nic, new_node->leaf_profile);
741+
if (err)
742+
netdev_err(nic->netdev,
743+
"Unable to free leaf bandwidth profile(%d)\n",
744+
new_node->leaf_profile);
745+
746+
__clear_bit(new_node->rq, &nic->rq_bmap);
747+
748+
mutex_unlock(&nic->mbox.lock);
749+
}
750+
606751
return rc;
607752
}
608753

@@ -864,6 +1009,9 @@ int otx2_init_tc(struct otx2_nic *nic)
8641009
{
8651010
struct otx2_tc_info *tc = &nic->tc_info;
8661011

1012+
/* Exclude receive queue 0 being used for police action */
1013+
set_bit(0, &nic->rq_bmap);
1014+
8671015
tc->flow_ht_params = tc_flow_ht_params;
8681016
return rhashtable_init(&tc->flow_table, &tc->flow_ht_params);
8691017
}

0 commit comments

Comments
 (0)