qosify: add support for keeping stats
authorFelix Fietkau <nbd@nbd.name>
Thu, 20 Jul 2023 11:58:09 +0000 (13:58 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 20 Jul 2023 11:58:11 +0000 (13:58 +0200)
Keep the number of packets for every traffic class. This only refers to the
initially matched class and does not account for reclassification based on
prio/bulk thresholds

Signed-off-by: Felix Fietkau <nbd@nbd.name>
map.c
qosify-bpf.c
qosify-bpf.h
qosify.h
ubus.c

diff --git a/map.c b/map.c
index 4785cc597abe8e3d9e049a622c8f9d88ea02ce92..64b481805a8324dd842f7c486ad0b41d7c4cc616 100644 (file)
--- a/map.c
+++ b/map.c
@@ -883,6 +883,32 @@ void qosify_map_dump(struct blob_buf *b)
        blobmsg_close_array(b, a);
 }
 
+void qosify_map_stats(struct blob_buf *b, bool reset)
+{
+       struct qosify_class data;
+       uint32_t i;
+
+       for (i = 0; i < ARRAY_SIZE(map_class); i++) {
+               void *c;
+
+               if (!map_class[i])
+                       continue;
+
+               if (bpf_map_lookup_elem(qosify_map_fds[CL_MAP_CLASS], &i, &data) < 0)
+                       continue;
+
+               c = blobmsg_open_table(b, map_class[i]->name);
+               blobmsg_add_u64(b, "packets", data.packets);
+               blobmsg_close_table(b, c);
+
+               if (!reset)
+                       continue;
+
+               data.packets = 0;
+               bpf_map_update_elem(qosify_map_fds[CL_MAP_CLASS], &i, &data, BPF_ANY);
+       }
+}
+
 static int32_t
 qosify_map_get_class_id(const char *name)
 {
index d508e39169f7618353473e0ddc7a0f2de63b24b8..5d5cf52dc7b5bd4cbeee396502c8ee336aa1a642 100644 (file)
@@ -373,7 +373,8 @@ parse_ipv6(struct qosify_config *config, struct skb_parser_info *info,
 }
 
 static __always_inline int
-dscp_lookup_class(uint8_t *dscp, bool ingress, struct qosify_class **out_class)
+dscp_lookup_class(uint8_t *dscp, bool ingress, struct qosify_class **out_class,
+                 bool counter)
 {
        struct qosify_class *class;
        __u8 fallback_flag;
@@ -391,6 +392,8 @@ dscp_lookup_class(uint8_t *dscp, bool ingress, struct qosify_class **out_class)
        if (!(class->flags & QOSIFY_CLASS_FLAG_PRESENT))
                return -1;
 
+       if (counter)
+           class->packets++;
        *dscp = dscp_val(&class->val, ingress);
        *dscp |= fallback_flag;
        *out_class = class;
@@ -441,12 +444,12 @@ int classify(struct __sk_buff *skb)
                dscp = ip_val->dscp;
        }
 
-       if (dscp_lookup_class(&dscp, ingress, &class))
+       if (dscp_lookup_class(&dscp, ingress, &class, true))
                return TC_ACT_UNSPEC;
 
        if (class) {
                if (check_flow(&class->config, skb, &dscp) &&
-                   dscp_lookup_class(&dscp, ingress, &class))
+                   dscp_lookup_class(&dscp, ingress, &class, false))
                        return TC_ACT_UNSPEC;
        }
 
index df09077a2c2d352fc12596b9fb1da4b1b1b85ccb..a78f777f5f9ee197d38a0fa81c0aa06324efb27f 100644 (file)
@@ -56,6 +56,8 @@ struct qosify_class {
        struct qosify_dscp_val val;
 
        uint8_t flags;
+
+       uint64_t packets;
 };
 
 #endif
index d1260ad1a2837eae019c7bc267864bcdea0222e0..d7d6fec9c37af61b7320a36cab8152f93ecb1338 100644 (file)
--- a/qosify.h
+++ b/qosify.h
@@ -90,6 +90,7 @@ void qosify_map_reload(void);
 void qosify_map_clear_files(void);
 void qosify_map_gc(void);
 void qosify_map_dump(struct blob_buf *b);
+void qosify_map_stats(struct blob_buf *b, bool reset);
 void qosify_map_set_dscp_default(enum qosify_map_id id, uint8_t val);
 void qosify_map_reset_config(void);
 void qosify_map_update_config(void);
diff --git a/ubus.c b/ubus.c
index aaab04382fb411ae104a5c0342f8579be75d90d6..a72d318cf0cf1d6189f2f089d3b5c1b2267de434 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -226,6 +226,28 @@ qosify_ubus_status(struct ubus_context *ctx, struct ubus_object *obj,
        return 0;
 }
 
+static int
+qosify_ubus_get_stats(struct ubus_context *ctx, struct ubus_object *obj,
+                     struct ubus_request_data *req, const char *method,
+                     struct blob_attr *msg)
+{
+       static const struct blobmsg_policy policy =
+               { "reset", BLOBMSG_TYPE_BOOL };
+       struct blob_attr *tb;
+       bool reset = false;
+
+       blobmsg_parse(&policy, 1, &tb, blobmsg_data(msg), blobmsg_len(msg));
+
+       reset = tb && blobmsg_get_u8(tb);
+
+       blob_buf_init(&b, 0);
+       qosify_map_stats(&b, reset);
+       ubus_send_reply(ctx, req, b.head);
+       blob_buf_free(&b);
+
+       return 0;
+}
+
 static int
 qosify_ubus_check_devices(struct ubus_context *ctx, struct ubus_object *obj,
                          struct ubus_request_data *req, const char *method,
@@ -293,6 +315,7 @@ static const struct ubus_method qosify_methods[] = {
        UBUS_METHOD("config", qosify_ubus_config, qosify_config_policy),
        UBUS_METHOD_NOARG("dump", qosify_ubus_dump),
        UBUS_METHOD_NOARG("status", qosify_ubus_status),
+       UBUS_METHOD_NOARG("get_stats", qosify_ubus_get_stats),
        UBUS_METHOD("add_dns_host", qosify_ubus_add_dns_host, qosify_dns_policy),
        UBUS_METHOD_NOARG("check_devices", qosify_ubus_check_devices),
 };