]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
tc: m_action: introduce support for hw stats type
authorJiri Pirko <jiri@mellanox.com>
Sat, 14 Mar 2020 09:25:48 +0000 (10:25 +0100)
committerDavid Ahern <dsahern@gmail.com>
Fri, 20 Mar 2020 16:18:44 +0000 (16:18 +0000)
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>
man/man8/tc-actions.8
tc/m_action.c

index bee59f7247faed3710d23f0565e2100b806d3e50..21795193b81e1970a92822b79c4e9bc362b45031 100644 (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
index 4da810c8c0aa769a5fd7c3992977b9dc31723d93..58ae1846033bcbc5fc5d494cd416a1fef033e96c 100644 (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;
 }