tc: m_action: introduce support for hw stats type

Introduce support for per-action hw stats type config.

This patch allows user to specify one of the following types of HW
stats for added action:
immediate - queried during dump time
delayed - polled from HW periodically or sent by HW in async manner
disabled - no stats needed

Note that if "hw_stats" option is not passed, user does not care about
the type, just expects any type of stats.

Examples:
$ tc filter add dev enp0s16np28 ingress proto ip handle 1 pref 1 flower skip_sw dst_ip 192.168.1.1 action drop hw_stats disabled
$ tc -s filter show dev enp0s16np28 ingress
filter protocol ip pref 1 flower chain 0
filter protocol ip pref 1 flower chain 0 handle 0x1
  eth_type ipv4
  dst_ip 192.168.1.1
  skip_sw
  in_hw in_hw_count 2
        action order 1: gact action drop
         random type none pass val 0
         index 1 ref 1 bind 1 installed 7 sec used 2 sec
        Action statistics:
        Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
        backlog 0b 0p requeues 0
        hw_stats disabled

$ tc filter add dev enp0s16np28 ingress proto ip handle 1 pref 1 flower skip_sw dst_ip 192.168.1.1 action drop hw_stats immediate
$ tc -s filter show dev enp0s16np28 ingress
filter protocol ip pref 1 flower chain 0
filter protocol ip pref 1 flower chain 0 handle 0x1
  eth_type ipv4
  dst_ip 192.168.1.1
  skip_sw
  in_hw in_hw_count 2
        action order 1: gact action drop
         random type none pass val 0
         index 1 ref 1 bind 1 installed 11 sec used 4 sec
        Action statistics:
        Sent 102 bytes 1 pkt (dropped 1, overlimits 0 requeues 0)
        Sent software 0 bytes 0 pkt
        Sent hardware 102 bytes 1 pkt
        backlog 0b 0p requeues 0
        hw_stats immediate

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
Jiri Pirko 2020-03-14 10:25:48 +01:00 committed by David Ahern
parent 25091a761f
commit 341903dd3b
2 changed files with 96 additions and 1 deletions

View File

@ -49,6 +49,8 @@ actions \- independently defined actions in tc
] [
.I FLAGS
] [
.I HWSTATSSPEC
] [
.I CONTROL
]
@ -77,6 +79,12 @@ ACTNAME
:=
.I no_percpu
.I HWSTATSSPEC
:=
.BR hw_stats " {"
.IR immediate " | " delayed " | " disabled
.R }
.I ACTDETAIL
:=
.I ACTNAME ACTPARAMS
@ -200,6 +208,29 @@ which indicates that action is expected to have minimal software data-path
traffic and doesn't need to allocate stat counters with percpu allocator.
This option is intended to be used by hardware-offloaded actions.
.TP
.BI hw_stats " HW_STATS"
Specifies the type of HW stats of new action. If omitted, any stats counter type
is going to be used, according to driver and its resources.
The
.I HW_STATS
indicates the type. Any of the following are valid:
.RS
.TP
.B immediate
Means that in dump, user gets the current HW stats state from the device
queried at the dump time.
.TP
.B delayed
Means that in dump, user gets HW stats that might be out of date for
some time, maybe couple of seconds. This is the case when driver polls
stats updates periodically or when it gets async stats update
from the device.
.TP
.B disabled
No HW stats are going to be available in dump.
.RE
.TP
.BI since " MSTIME"
When dumping large number of actions, a millisecond time-filter can be

View File

@ -51,8 +51,9 @@ static void act_usage(void)
" FL := ls | list | flush | <ACTNAMESPEC>\n"
" ACTNAMESPEC := action <ACTNAME>\n"
" ACTISPEC := <ACTNAMESPEC> <INDEXSPEC>\n"
" ACTSPEC := action <ACTDETAIL> [INDEXSPEC]\n"
" ACTSPEC := action <ACTDETAIL> [INDEXSPEC] [HWSTATSSPEC]\n"
" INDEXSPEC := index <32 bit indexvalue>\n"
" HWSTATSSPEC := hw_stats [ immediate | delayed | disabled ]\n"
" ACTDETAIL := <ACTNAME> <ACTPARAMS>\n"
" Example ACTNAME is gact, mirred, bpf, etc\n"
" Each action has its own parameters (ACTPARAMS)\n"
@ -149,6 +150,59 @@ new_cmd(char **argv)
(matches(*argv, "add") == 0);
}
static const struct hw_stats_type_item {
const char *str;
__u8 type;
} hw_stats_type_items[] = {
{ "immediate", TCA_ACT_HW_STATS_TYPE_IMMEDIATE },
{ "delayed", TCA_ACT_HW_STATS_TYPE_DELAYED },
{ "disabled", 0 }, /* no bit set */
};
static void print_hw_stats(const struct rtattr *arg)
{
struct nla_bitfield32 *hw_stats_type_bf = RTA_DATA(arg);
__u8 hw_stats_type;
int i;
hw_stats_type = hw_stats_type_bf->value & hw_stats_type_bf->selector;
print_string(PRINT_FP, NULL, "\t", NULL);
open_json_array(PRINT_ANY, "hw_stats");
for (i = 0; i < ARRAY_SIZE(hw_stats_type_items); i++) {
const struct hw_stats_type_item *item;
item = &hw_stats_type_items[i];
if ((!hw_stats_type && !item->type) ||
hw_stats_type & item->type)
print_string(PRINT_ANY, NULL, " %s", item->str);
}
close_json_array(PRINT_JSON, NULL);
}
static int parse_hw_stats(const char *str, struct nlmsghdr *n)
{
int i;
for (i = 0; i < ARRAY_SIZE(hw_stats_type_items); i++) {
const struct hw_stats_type_item *item;
item = &hw_stats_type_items[i];
if (matches(str, item->str) == 0) {
struct nla_bitfield32 hw_stats_type_bf = {
.value = item->type,
.selector = item->type
};
addattr_l(n, MAX_MSG, TCA_ACT_HW_STATS_TYPE,
&hw_stats_type_bf, sizeof(hw_stats_type_bf));
return 0;
}
}
return -1;
}
int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
{
int argc = *argc_p;
@ -250,6 +304,14 @@ done0:
addattr_l(n, MAX_MSG, TCA_ACT_COOKIE,
&act_ck, act_ck_len);
if (*argv && matches(*argv, "hw_stats") == 0) {
NEXT_ARG();
ret = parse_hw_stats(*argv, n);
if (ret < 0)
invarg("value is invalid\n", *argv);
NEXT_ARG_FWD();
}
if (*argv && strcmp(*argv, "no_percpu") == 0) {
struct nla_bitfield32 flags =
{ TCA_ACT_FLAGS_NO_PERCPU_STATS,
@ -337,6 +399,8 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg)
TCA_ACT_FLAGS_NO_PERCPU_STATS);
print_string(PRINT_FP, NULL, "%s", _SL_);
}
if (tb[TCA_ACT_HW_STATS_TYPE])
print_hw_stats(tb[TCA_ACT_HW_STATS_TYPE]);
return 0;
}