@@ -42,11 +42,14 @@ struct otx2_tc_flow_stats {
4242struct 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
5255static 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+
224279static 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
473569static 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