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)
{
}
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;
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;
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;
}
struct qosify_dscp_val val;
uint8_t flags;
+
+ uint64_t packets;
};
#endif
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);
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,
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),
};