1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2019 Netronome Systems, Inc. */
4 #include <linux/hash.h>
5 #include <linux/hashtable.h>
6 #include <linux/jhash.h>
7 #include <linux/math64.h>
8 #include <linux/vmalloc.h>
9 #include <net/pkt_cls.h>
10 #include <net/pkt_sched.h>
14 #include "../nfp_port.h"
16 #define NFP_FL_QOS_UPDATE msecs_to_jiffies(1000)
17 #define NFP_FL_QOS_PPS BIT(15)
18 #define NFP_FL_QOS_METER BIT(10)
20 struct nfp_police_cfg_head
{
28 enum NFP_FL_QOS_TYPES
{
34 /* Police cmsg for configuring a trTCM traffic conditioner (8W/32B)
35 * See RFC 2698 for more details.
36 * ----------------------------------------------------------------
38 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | Reserved |p| Reserved |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * | Token Bucket Peak |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | Token Bucket Committed |
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * | Committed Burst Size |
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 * | Peak Information Rate |
53 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 * | Committed Information Rate |
55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 * Word[0](FLag options):
57 * [15] p(pps) 1 for pps, 0 for bps
59 * Meter control message
60 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
61 * +-------------------------------+-+---+-----+-+---------+-+---+-+
62 * | Reserved |p| Y |TYPE |E|TSHFV |P| PC|R|
63 * +-------------------------------+-+---+-----+-+---------+-+---+-+
65 * +-------------------------------+-------------------------------+
68 struct nfp_police_config
{
69 struct nfp_police_cfg_head head
;
78 struct nfp_police_stats_reply
{
79 struct nfp_police_cfg_head head
;
86 int nfp_flower_offload_one_police(struct nfp_app
*app
, bool ingress
,
87 bool pps
, u32 id
, u32 rate
, u32 burst
)
89 struct nfp_police_config
*config
;
92 skb
= nfp_flower_cmsg_alloc(app
, sizeof(struct nfp_police_config
),
93 NFP_FLOWER_CMSG_TYPE_QOS_MOD
, GFP_KERNEL
);
97 config
= nfp_flower_cmsg_get_data(skb
);
98 memset(config
, 0, sizeof(struct nfp_police_config
));
100 config
->head
.flags_opts
|= cpu_to_be32(NFP_FL_QOS_PPS
);
102 config
->head
.flags_opts
|= cpu_to_be32(NFP_FL_QOS_METER
);
105 config
->head
.port
= cpu_to_be32(id
);
107 config
->head
.meter_id
= cpu_to_be32(id
);
109 config
->bkt_tkn_p
= cpu_to_be32(burst
);
110 config
->bkt_tkn_c
= cpu_to_be32(burst
);
111 config
->pbs
= cpu_to_be32(burst
);
112 config
->cbs
= cpu_to_be32(burst
);
113 config
->pir
= cpu_to_be32(rate
);
114 config
->cir
= cpu_to_be32(rate
);
115 nfp_ctrl_tx(app
->ctrl
, skb
);
120 static int nfp_policer_validate(const struct flow_action
*action
,
121 const struct flow_action_entry
*act
,
122 struct netlink_ext_ack
*extack
,
125 if (act
->police
.exceed
.act_id
!= FLOW_ACTION_DROP
) {
126 NL_SET_ERR_MSG_MOD(extack
,
127 "Offload not supported when exceed action is not drop");
132 if (act
->police
.notexceed
.act_id
!= FLOW_ACTION_CONTINUE
&&
133 act
->police
.notexceed
.act_id
!= FLOW_ACTION_ACCEPT
) {
134 NL_SET_ERR_MSG_MOD(extack
,
135 "Offload not supported when conform action is not continue or ok");
139 if (act
->police
.notexceed
.act_id
!= FLOW_ACTION_PIPE
&&
140 act
->police
.notexceed
.act_id
!= FLOW_ACTION_ACCEPT
) {
141 NL_SET_ERR_MSG_MOD(extack
,
142 "Offload not supported when conform action is not pipe or ok");
147 if (act
->police
.notexceed
.act_id
== FLOW_ACTION_ACCEPT
&&
148 !flow_action_is_last_entry(action
, act
)) {
149 NL_SET_ERR_MSG_MOD(extack
,
150 "Offload not supported when conform action is ok, but action is not last");
154 if (act
->police
.peakrate_bytes_ps
||
155 act
->police
.avrate
|| act
->police
.overhead
) {
156 NL_SET_ERR_MSG_MOD(extack
,
157 "Offload not supported when peakrate/avrate/overhead is configured");
165 nfp_flower_install_rate_limiter(struct nfp_app
*app
, struct net_device
*netdev
,
166 struct tc_cls_matchall_offload
*flow
,
167 struct netlink_ext_ack
*extack
)
169 struct flow_action_entry
*paction
= &flow
->rule
->action
.entries
[0];
170 u32 action_num
= flow
->rule
->action
.num_entries
;
171 struct nfp_flower_priv
*fl_priv
= app
->priv
;
172 struct flow_action_entry
*action
= NULL
;
173 struct nfp_flower_repr_priv
*repr_priv
;
174 u32 netdev_port_id
, i
;
175 struct nfp_repr
*repr
;
184 if (!nfp_netdev_is_nfp_repr(netdev
)) {
185 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: qos rate limit offload not supported on higher level port");
188 repr
= netdev_priv(netdev
);
189 repr_priv
= repr
->app_priv
;
190 netdev_port_id
= nfp_repr_get_port_id(netdev
);
191 pps_support
= !!(fl_priv
->flower_ext_feats
& NFP_FL_FEATS_QOS_PPS
);
193 if (repr_priv
->block_shared
) {
194 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: qos rate limit offload not supported on shared blocks");
198 if (repr
->port
->type
!= NFP_PORT_VF_PORT
) {
199 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: qos rate limit offload not supported on non-VF ports");
204 if (action_num
> 2 || action_num
== 0) {
205 NL_SET_ERR_MSG_MOD(extack
,
206 "unsupported offload: qos rate limit offload only support action number 1 or 2");
210 if (!flow_offload_has_one_action(&flow
->rule
->action
)) {
211 NL_SET_ERR_MSG_MOD(extack
,
212 "unsupported offload: qos rate limit offload requires a single action");
217 if (flow
->common
.prio
!= 1) {
218 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: qos rate limit offload requires highest priority");
222 for (i
= 0 ; i
< action_num
; i
++) {
223 action
= paction
+ i
;
224 if (action
->id
!= FLOW_ACTION_POLICE
) {
225 NL_SET_ERR_MSG_MOD(extack
,
226 "unsupported offload: qos rate limit offload requires police action");
230 err
= nfp_policer_validate(&flow
->rule
->action
, action
, extack
, true);
234 if (action
->police
.rate_bytes_ps
> 0) {
236 NL_SET_ERR_MSG_MOD(extack
,
237 "unsupported offload: qos rate limit offload only support one BPS action");
241 if (action
->police
.rate_pkt_ps
> 0) {
243 NL_SET_ERR_MSG_MOD(extack
,
244 "unsupported offload: FW does not support PPS action");
248 NL_SET_ERR_MSG_MOD(extack
,
249 "unsupported offload: qos rate limit offload only support one PPS action");
255 for (i
= 0 ; i
< action_num
; i
++) {
256 /* Set QoS data for this interface */
257 action
= paction
+ i
;
258 if (action
->police
.rate_bytes_ps
> 0) {
259 rate
= action
->police
.rate_bytes_ps
;
260 burst
= action
->police
.burst
;
261 } else if (action
->police
.rate_pkt_ps
> 0) {
262 rate
= action
->police
.rate_pkt_ps
;
263 burst
= action
->police
.burst_pkt
;
265 NL_SET_ERR_MSG_MOD(extack
,
266 "unsupported offload: qos rate limit is not BPS or PPS");
272 if (action
->police
.rate_pkt_ps
> 0)
274 nfp_flower_offload_one_police(repr
->app
, true,
279 repr_priv
->qos_table
.netdev_port_id
= netdev_port_id
;
280 fl_priv
->qos_rate_limiters
++;
281 if (fl_priv
->qos_rate_limiters
== 1)
282 schedule_delayed_work(&fl_priv
->qos_stats_work
,
289 nfp_flower_remove_rate_limiter(struct nfp_app
*app
, struct net_device
*netdev
,
290 struct tc_cls_matchall_offload
*flow
,
291 struct netlink_ext_ack
*extack
)
293 struct nfp_flower_priv
*fl_priv
= app
->priv
;
294 struct nfp_flower_repr_priv
*repr_priv
;
295 struct nfp_police_config
*config
;
296 u32 netdev_port_id
, i
;
297 struct nfp_repr
*repr
;
301 if (!nfp_netdev_is_nfp_repr(netdev
)) {
302 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: qos rate limit offload not supported on higher level port");
305 repr
= netdev_priv(netdev
);
307 netdev_port_id
= nfp_repr_get_port_id(netdev
);
308 repr_priv
= repr
->app_priv
;
309 pps_support
= !!(fl_priv
->flower_ext_feats
& NFP_FL_FEATS_QOS_PPS
);
311 if (!repr_priv
->qos_table
.netdev_port_id
) {
312 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: cannot remove qos entry that does not exist");
316 memset(&repr_priv
->qos_table
, 0, sizeof(struct nfp_fl_qos
));
317 fl_priv
->qos_rate_limiters
--;
318 if (!fl_priv
->qos_rate_limiters
)
319 cancel_delayed_work_sync(&fl_priv
->qos_stats_work
);
320 for (i
= 0 ; i
< NFP_FL_QOS_TYPE_MAX
; i
++) {
321 if (i
== NFP_FL_QOS_TYPE_PPS
&& !pps_support
)
324 * Clear QoS data for this interface.
325 * There is no need to check if a specific QOS_TYPE was
326 * configured as the firmware handles clearing a QoS entry
327 * safely, even if it wasn't explicitly added.
329 skb
= nfp_flower_cmsg_alloc(repr
->app
, sizeof(struct nfp_police_config
),
330 NFP_FLOWER_CMSG_TYPE_QOS_DEL
, GFP_KERNEL
);
334 config
= nfp_flower_cmsg_get_data(skb
);
335 memset(config
, 0, sizeof(struct nfp_police_config
));
336 if (i
== NFP_FL_QOS_TYPE_PPS
)
337 config
->head
.flags_opts
= cpu_to_be32(NFP_FL_QOS_PPS
);
338 config
->head
.port
= cpu_to_be32(netdev_port_id
);
339 nfp_ctrl_tx(repr
->app
->ctrl
, skb
);
345 void nfp_flower_stats_rlim_reply(struct nfp_app
*app
, struct sk_buff
*skb
)
347 struct nfp_flower_priv
*fl_priv
= app
->priv
;
348 struct nfp_flower_repr_priv
*repr_priv
;
349 struct nfp_police_stats_reply
*msg
;
350 struct nfp_stat_pair
*curr_stats
;
351 struct nfp_stat_pair
*prev_stats
;
352 struct net_device
*netdev
;
353 struct nfp_repr
*repr
;
356 msg
= nfp_flower_cmsg_get_data(skb
);
357 if (be32_to_cpu(msg
->head
.flags_opts
) & NFP_FL_QOS_METER
)
358 return nfp_act_stats_reply(app
, msg
);
360 netdev_port_id
= be32_to_cpu(msg
->head
.port
);
362 netdev
= nfp_app_dev_get(app
, netdev_port_id
, NULL
);
364 goto exit_unlock_rcu
;
366 repr
= netdev_priv(netdev
);
367 repr_priv
= repr
->app_priv
;
368 curr_stats
= &repr_priv
->qos_table
.curr_stats
;
369 prev_stats
= &repr_priv
->qos_table
.prev_stats
;
371 spin_lock_bh(&fl_priv
->qos_stats_lock
);
372 curr_stats
->pkts
= be64_to_cpu(msg
->pass_pkts
) +
373 be64_to_cpu(msg
->drop_pkts
);
374 curr_stats
->bytes
= be64_to_cpu(msg
->pass_bytes
) +
375 be64_to_cpu(msg
->drop_bytes
);
377 if (!repr_priv
->qos_table
.last_update
) {
378 prev_stats
->pkts
= curr_stats
->pkts
;
379 prev_stats
->bytes
= curr_stats
->bytes
;
382 repr_priv
->qos_table
.last_update
= jiffies
;
383 spin_unlock_bh(&fl_priv
->qos_stats_lock
);
390 nfp_flower_stats_rlim_request(struct nfp_flower_priv
*fl_priv
,
391 u32 id
, bool ingress
)
393 struct nfp_police_cfg_head
*head
;
396 skb
= nfp_flower_cmsg_alloc(fl_priv
->app
,
397 sizeof(struct nfp_police_cfg_head
),
398 NFP_FLOWER_CMSG_TYPE_QOS_STATS
,
402 head
= nfp_flower_cmsg_get_data(skb
);
404 memset(head
, 0, sizeof(struct nfp_police_cfg_head
));
406 head
->port
= cpu_to_be32(id
);
408 head
->flags_opts
= cpu_to_be32(NFP_FL_QOS_METER
);
409 head
->meter_id
= cpu_to_be32(id
);
412 nfp_ctrl_tx(fl_priv
->app
->ctrl
, skb
);
416 nfp_flower_stats_rlim_request_all(struct nfp_flower_priv
*fl_priv
)
418 struct nfp_reprs
*repr_set
;
422 repr_set
= rcu_dereference(fl_priv
->app
->reprs
[NFP_REPR_TYPE_VF
]);
424 goto exit_unlock_rcu
;
426 for (i
= 0; i
< repr_set
->num_reprs
; i
++) {
427 struct net_device
*netdev
;
429 netdev
= rcu_dereference(repr_set
->reprs
[i
]);
431 struct nfp_repr
*priv
= netdev_priv(netdev
);
432 struct nfp_flower_repr_priv
*repr_priv
;
435 repr_priv
= priv
->app_priv
;
436 netdev_port_id
= repr_priv
->qos_table
.netdev_port_id
;
440 nfp_flower_stats_rlim_request(fl_priv
,
441 netdev_port_id
, true);
449 static void update_stats_cache(struct work_struct
*work
)
451 struct delayed_work
*delayed_work
;
452 struct nfp_flower_priv
*fl_priv
;
454 delayed_work
= to_delayed_work(work
);
455 fl_priv
= container_of(delayed_work
, struct nfp_flower_priv
,
458 nfp_flower_stats_rlim_request_all(fl_priv
);
459 nfp_flower_stats_meter_request_all(fl_priv
);
461 schedule_delayed_work(&fl_priv
->qos_stats_work
, NFP_FL_QOS_UPDATE
);
465 nfp_flower_stats_rate_limiter(struct nfp_app
*app
, struct net_device
*netdev
,
466 struct tc_cls_matchall_offload
*flow
,
467 struct netlink_ext_ack
*extack
)
469 struct nfp_flower_priv
*fl_priv
= app
->priv
;
470 struct nfp_flower_repr_priv
*repr_priv
;
471 struct nfp_stat_pair
*curr_stats
;
472 struct nfp_stat_pair
*prev_stats
;
473 u64 diff_bytes
, diff_pkts
;
474 struct nfp_repr
*repr
;
476 if (!nfp_netdev_is_nfp_repr(netdev
)) {
477 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: qos rate limit offload not supported on higher level port");
480 repr
= netdev_priv(netdev
);
482 repr_priv
= repr
->app_priv
;
483 if (!repr_priv
->qos_table
.netdev_port_id
) {
484 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: cannot find qos entry for stats update");
488 spin_lock_bh(&fl_priv
->qos_stats_lock
);
489 curr_stats
= &repr_priv
->qos_table
.curr_stats
;
490 prev_stats
= &repr_priv
->qos_table
.prev_stats
;
491 diff_pkts
= curr_stats
->pkts
- prev_stats
->pkts
;
492 diff_bytes
= curr_stats
->bytes
- prev_stats
->bytes
;
493 prev_stats
->pkts
= curr_stats
->pkts
;
494 prev_stats
->bytes
= curr_stats
->bytes
;
495 spin_unlock_bh(&fl_priv
->qos_stats_lock
);
497 flow_stats_update(&flow
->stats
, diff_bytes
, diff_pkts
, 0,
498 repr_priv
->qos_table
.last_update
,
499 FLOW_ACTION_HW_STATS_DELAYED
);
503 void nfp_flower_qos_init(struct nfp_app
*app
)
505 struct nfp_flower_priv
*fl_priv
= app
->priv
;
507 spin_lock_init(&fl_priv
->qos_stats_lock
);
508 mutex_init(&fl_priv
->meter_stats_lock
);
509 nfp_init_meter_table(app
);
511 INIT_DELAYED_WORK(&fl_priv
->qos_stats_work
, &update_stats_cache
);
514 void nfp_flower_qos_cleanup(struct nfp_app
*app
)
516 struct nfp_flower_priv
*fl_priv
= app
->priv
;
518 cancel_delayed_work_sync(&fl_priv
->qos_stats_work
);
521 int nfp_flower_setup_qos_offload(struct nfp_app
*app
, struct net_device
*netdev
,
522 struct tc_cls_matchall_offload
*flow
)
524 struct netlink_ext_ack
*extack
= flow
->common
.extack
;
525 struct nfp_flower_priv
*fl_priv
= app
->priv
;
528 if (!(fl_priv
->flower_ext_feats
& NFP_FL_FEATS_VF_RLIM
)) {
529 NL_SET_ERR_MSG_MOD(extack
, "unsupported offload: loaded firmware does not support qos rate limit offload");
533 mutex_lock(&fl_priv
->nfp_fl_lock
);
534 switch (flow
->command
) {
535 case TC_CLSMATCHALL_REPLACE
:
536 ret
= nfp_flower_install_rate_limiter(app
, netdev
, flow
, extack
);
538 case TC_CLSMATCHALL_DESTROY
:
539 ret
= nfp_flower_remove_rate_limiter(app
, netdev
, flow
, extack
);
541 case TC_CLSMATCHALL_STATS
:
542 ret
= nfp_flower_stats_rate_limiter(app
, netdev
, flow
, extack
);
548 mutex_unlock(&fl_priv
->nfp_fl_lock
);
553 /* Offload tc action, currently only for tc police */
555 static const struct rhashtable_params stats_meter_table_params
= {
556 .key_offset
= offsetof(struct nfp_meter_entry
, meter_id
),
557 .head_offset
= offsetof(struct nfp_meter_entry
, ht_node
),
558 .key_len
= sizeof(u32
),
561 struct nfp_meter_entry
*
562 nfp_flower_search_meter_entry(struct nfp_app
*app
, u32 meter_id
)
564 struct nfp_flower_priv
*priv
= app
->priv
;
566 return rhashtable_lookup_fast(&priv
->meter_table
, &meter_id
,
567 stats_meter_table_params
);
570 static struct nfp_meter_entry
*
571 nfp_flower_add_meter_entry(struct nfp_app
*app
, u32 meter_id
)
573 struct nfp_meter_entry
*meter_entry
= NULL
;
574 struct nfp_flower_priv
*priv
= app
->priv
;
576 meter_entry
= rhashtable_lookup_fast(&priv
->meter_table
,
578 stats_meter_table_params
);
582 meter_entry
= kzalloc(sizeof(*meter_entry
), GFP_KERNEL
);
586 meter_entry
->meter_id
= meter_id
;
587 meter_entry
->used
= jiffies
;
588 if (rhashtable_insert_fast(&priv
->meter_table
, &meter_entry
->ht_node
,
589 stats_meter_table_params
)) {
594 priv
->qos_rate_limiters
++;
595 if (priv
->qos_rate_limiters
== 1)
596 schedule_delayed_work(&priv
->qos_stats_work
,
602 static void nfp_flower_del_meter_entry(struct nfp_app
*app
, u32 meter_id
)
604 struct nfp_meter_entry
*meter_entry
= NULL
;
605 struct nfp_flower_priv
*priv
= app
->priv
;
607 meter_entry
= rhashtable_lookup_fast(&priv
->meter_table
, &meter_id
,
608 stats_meter_table_params
);
612 rhashtable_remove_fast(&priv
->meter_table
,
613 &meter_entry
->ht_node
,
614 stats_meter_table_params
);
616 priv
->qos_rate_limiters
--;
617 if (!priv
->qos_rate_limiters
)
618 cancel_delayed_work_sync(&priv
->qos_stats_work
);
621 int nfp_flower_setup_meter_entry(struct nfp_app
*app
,
622 const struct flow_action_entry
*action
,
623 enum nfp_meter_op op
,
626 struct nfp_flower_priv
*fl_priv
= app
->priv
;
627 struct nfp_meter_entry
*meter_entry
= NULL
;
630 mutex_lock(&fl_priv
->meter_stats_lock
);
634 nfp_flower_del_meter_entry(app
, meter_id
);
637 meter_entry
= nfp_flower_add_meter_entry(app
, meter_id
);
649 if (action
->police
.rate_bytes_ps
> 0) {
650 meter_entry
->bps
= true;
651 meter_entry
->rate
= action
->police
.rate_bytes_ps
;
652 meter_entry
->burst
= action
->police
.burst
;
654 meter_entry
->bps
= false;
655 meter_entry
->rate
= action
->police
.rate_pkt_ps
;
656 meter_entry
->burst
= action
->police
.burst_pkt
;
660 mutex_unlock(&fl_priv
->meter_stats_lock
);
664 int nfp_init_meter_table(struct nfp_app
*app
)
666 struct nfp_flower_priv
*priv
= app
->priv
;
668 return rhashtable_init(&priv
->meter_table
, &stats_meter_table_params
);
672 nfp_flower_stats_meter_request_all(struct nfp_flower_priv
*fl_priv
)
674 struct nfp_meter_entry
*meter_entry
= NULL
;
675 struct rhashtable_iter iter
;
677 mutex_lock(&fl_priv
->meter_stats_lock
);
678 rhashtable_walk_enter(&fl_priv
->meter_table
, &iter
);
679 rhashtable_walk_start(&iter
);
681 while ((meter_entry
= rhashtable_walk_next(&iter
)) != NULL
) {
682 if (IS_ERR(meter_entry
))
684 nfp_flower_stats_rlim_request(fl_priv
,
685 meter_entry
->meter_id
, false);
688 rhashtable_walk_stop(&iter
);
689 rhashtable_walk_exit(&iter
);
690 mutex_unlock(&fl_priv
->meter_stats_lock
);
694 nfp_act_install_actions(struct nfp_app
*app
, struct flow_offload_action
*fl_act
,
695 struct netlink_ext_ack
*extack
)
697 struct flow_action_entry
*paction
= &fl_act
->action
.entries
[0];
698 u32 action_num
= fl_act
->action
.num_entries
;
699 struct nfp_flower_priv
*fl_priv
= app
->priv
;
700 struct flow_action_entry
*action
= NULL
;
701 u32 burst
, i
, meter_id
;
702 bool pps_support
, pps
;
707 pps_support
= !!(fl_priv
->flower_ext_feats
& NFP_FL_FEATS_QOS_PPS
);
709 for (i
= 0 ; i
< action_num
; i
++) {
710 /* Set qos associate data for this interface */
711 action
= paction
+ i
;
712 if (action
->id
!= FLOW_ACTION_POLICE
) {
713 NL_SET_ERR_MSG_MOD(extack
,
714 "unsupported offload: qos rate limit offload requires police action");
718 err
= nfp_policer_validate(&fl_act
->action
, action
, extack
, false);
722 if (action
->police
.rate_bytes_ps
> 0) {
723 rate
= action
->police
.rate_bytes_ps
;
724 burst
= action
->police
.burst
;
725 } else if (action
->police
.rate_pkt_ps
> 0 && pps_support
) {
726 rate
= action
->police
.rate_pkt_ps
;
727 burst
= action
->police
.burst_pkt
;
729 NL_SET_ERR_MSG_MOD(extack
,
730 "unsupported offload: unsupported qos rate limit");
735 meter_id
= action
->hw_index
;
736 if (nfp_flower_setup_meter_entry(app
, action
, NFP_METER_ADD
, meter_id
))
740 if (action
->police
.rate_pkt_ps
> 0)
742 nfp_flower_offload_one_police(app
, false, pps
, meter_id
,
748 return add
? 0 : -EOPNOTSUPP
;
752 nfp_act_remove_actions(struct nfp_app
*app
, struct flow_offload_action
*fl_act
,
753 struct netlink_ext_ack
*extack
)
755 struct nfp_meter_entry
*meter_entry
= NULL
;
756 struct nfp_police_config
*config
;
761 /* Delete qos associate data for this interface */
762 if (fl_act
->id
!= FLOW_ACTION_POLICE
) {
763 NL_SET_ERR_MSG_MOD(extack
,
764 "unsupported offload: qos rate limit offload requires police action");
768 meter_id
= fl_act
->index
;
769 meter_entry
= nfp_flower_search_meter_entry(app
, meter_id
);
771 NL_SET_ERR_MSG_MOD(extack
,
772 "no meter entry when delete the action index.");
775 pps
= !meter_entry
->bps
;
777 skb
= nfp_flower_cmsg_alloc(app
, sizeof(struct nfp_police_config
),
778 NFP_FLOWER_CMSG_TYPE_QOS_DEL
, GFP_KERNEL
);
782 config
= nfp_flower_cmsg_get_data(skb
);
783 memset(config
, 0, sizeof(struct nfp_police_config
));
784 config
->head
.flags_opts
= cpu_to_be32(NFP_FL_QOS_METER
);
785 config
->head
.meter_id
= cpu_to_be32(meter_id
);
787 config
->head
.flags_opts
|= cpu_to_be32(NFP_FL_QOS_PPS
);
789 nfp_ctrl_tx(app
->ctrl
, skb
);
790 nfp_flower_setup_meter_entry(app
, NULL
, NFP_METER_DEL
, meter_id
);
796 nfp_act_stats_reply(struct nfp_app
*app
, void *pmsg
)
798 struct nfp_flower_priv
*fl_priv
= app
->priv
;
799 struct nfp_meter_entry
*meter_entry
= NULL
;
800 struct nfp_police_stats_reply
*msg
= pmsg
;
803 meter_id
= be32_to_cpu(msg
->head
.meter_id
);
804 mutex_lock(&fl_priv
->meter_stats_lock
);
806 meter_entry
= nfp_flower_search_meter_entry(app
, meter_id
);
810 meter_entry
->stats
.curr
.pkts
= be64_to_cpu(msg
->pass_pkts
) +
811 be64_to_cpu(msg
->drop_pkts
);
812 meter_entry
->stats
.curr
.bytes
= be64_to_cpu(msg
->pass_bytes
) +
813 be64_to_cpu(msg
->drop_bytes
);
814 meter_entry
->stats
.curr
.drops
= be64_to_cpu(msg
->drop_pkts
);
815 if (!meter_entry
->stats
.update
) {
816 meter_entry
->stats
.prev
.pkts
= meter_entry
->stats
.curr
.pkts
;
817 meter_entry
->stats
.prev
.bytes
= meter_entry
->stats
.curr
.bytes
;
818 meter_entry
->stats
.prev
.drops
= meter_entry
->stats
.curr
.drops
;
821 meter_entry
->stats
.update
= jiffies
;
824 mutex_unlock(&fl_priv
->meter_stats_lock
);
828 nfp_act_stats_actions(struct nfp_app
*app
, struct flow_offload_action
*fl_act
,
829 struct netlink_ext_ack
*extack
)
831 struct nfp_flower_priv
*fl_priv
= app
->priv
;
832 struct nfp_meter_entry
*meter_entry
= NULL
;
833 u64 diff_bytes
, diff_pkts
, diff_drops
;
836 if (fl_act
->id
!= FLOW_ACTION_POLICE
) {
837 NL_SET_ERR_MSG_MOD(extack
,
838 "unsupported offload: qos rate limit offload requires police action");
842 mutex_lock(&fl_priv
->meter_stats_lock
);
843 meter_entry
= nfp_flower_search_meter_entry(app
, fl_act
->index
);
848 diff_pkts
= meter_entry
->stats
.curr
.pkts
> meter_entry
->stats
.prev
.pkts
?
849 meter_entry
->stats
.curr
.pkts
- meter_entry
->stats
.prev
.pkts
: 0;
850 diff_bytes
= meter_entry
->stats
.curr
.bytes
> meter_entry
->stats
.prev
.bytes
?
851 meter_entry
->stats
.curr
.bytes
- meter_entry
->stats
.prev
.bytes
: 0;
852 diff_drops
= meter_entry
->stats
.curr
.drops
> meter_entry
->stats
.prev
.drops
?
853 meter_entry
->stats
.curr
.drops
- meter_entry
->stats
.prev
.drops
: 0;
855 flow_stats_update(&fl_act
->stats
, diff_bytes
, diff_pkts
, diff_drops
,
856 meter_entry
->stats
.update
,
857 FLOW_ACTION_HW_STATS_DELAYED
);
859 meter_entry
->stats
.prev
.pkts
= meter_entry
->stats
.curr
.pkts
;
860 meter_entry
->stats
.prev
.bytes
= meter_entry
->stats
.curr
.bytes
;
861 meter_entry
->stats
.prev
.drops
= meter_entry
->stats
.curr
.drops
;
864 mutex_unlock(&fl_priv
->meter_stats_lock
);
868 int nfp_setup_tc_act_offload(struct nfp_app
*app
,
869 struct flow_offload_action
*fl_act
)
871 struct netlink_ext_ack
*extack
= fl_act
->extack
;
872 struct nfp_flower_priv
*fl_priv
= app
->priv
;
874 if (!(fl_priv
->flower_ext_feats
& NFP_FL_FEATS_QOS_METER
))
877 switch (fl_act
->command
) {
878 case FLOW_ACT_REPLACE
:
879 return nfp_act_install_actions(app
, fl_act
, extack
);
880 case FLOW_ACT_DESTROY
:
881 return nfp_act_remove_actions(app
, fl_act
, extack
);
883 return nfp_act_stats_actions(app
, fl_act
, extack
);