summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2021-11-12 21:54:51 +0000
committerFelix Fietkau2021-11-12 21:54:53 +0000
commitbfc2cafe2a8c66ffab88a7e5c1ad1b0a4d886271 (patch)
tree8a0d68b7b525dca6cd0b3a44afe72e868ea034f3
parent8e48d0b0cbba5b3804af2d99541c56b8b979f168 (diff)
downloadqosify-bfc2cafe2a8c66ffab88a7e5c1ad1b0a4d886271.tar.gz
map: add support for defining aliases
Aliases can be used to make a distinction between ingress and egress tags, and they make it easier to reconfigure tags without having to update the rule config files Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--map.c96
-rw-r--r--qosify.h1
-rw-r--r--ubus.c5
3 files changed, 99 insertions, 3 deletions
diff --git a/map.c b/map.c
index 92b8a07..303cf39 100644
--- a/map.c
+++ b/map.c
@@ -13,6 +13,7 @@
#include <glob.h>
#include <libubox/uloop.h>
+#include <libubox/avl-cmp.h>
#include "qosify.h"
@@ -21,6 +22,7 @@ static int qosify_map_entry_cmp(const void *k1, const void *k2, void *ptr);
static int qosify_map_fds[__CL_MAP_MAX];
static AVL_TREE(map_data, qosify_map_entry_cmp, false, NULL);
static LIST_HEAD(map_files);
+static AVL_TREE(map_aliases, avl_strcmp, false, NULL);
static uint32_t next_timeout;
static struct qosify_dscp_val qosify_dscp_default[2] = {
{ 0xff, 0xff },
@@ -35,6 +37,11 @@ struct qosify_map_file {
char filename[];
};
+struct qosify_map_alias {
+ struct avl_node avl;
+ struct qosify_dscp_val value;
+};
+
static const struct {
const char *name;
const char *type_name;
@@ -394,11 +401,12 @@ int qosify_map_set_entry(enum qosify_map_id id, bool file, const char *str,
return 0;
}
-int qosify_map_dscp_value(const char *val, struct qosify_dscp_val *dscp_val)
+static int
+__qosify_map_dscp_value(const char *val, uint8_t *dscp_val)
{
unsigned long dscp;
- char *err;
bool fallback = false;
+ char *err;
if (*val == '+') {
fallback = true;
@@ -412,7 +420,35 @@ int qosify_map_dscp_value(const char *val, struct qosify_dscp_val *dscp_val)
if (dscp >= 64)
return -1;
- dscp_val->ingress = dscp_val->egress = dscp + (fallback << 6);
+ *dscp_val = dscp | (fallback << 6);
+
+ return 0;
+}
+
+int qosify_map_dscp_value(const char *val, struct qosify_dscp_val *dscp_val)
+{
+ struct qosify_map_alias *alias;
+ bool fallback = false;
+
+ if (*val == '+') {
+ fallback = true;
+ val++;
+ }
+
+ alias = avl_find_element(&map_aliases, val, alias, avl);
+ if (alias) {
+ *dscp_val = alias->value;
+ } else {
+ if (__qosify_map_dscp_value(val, &dscp_val->egress))
+ return -1;
+
+ dscp_val->ingress = dscp_val->egress;
+ }
+
+ if (fallback) {
+ dscp_val->ingress |= (1 << 6);
+ dscp_val->egress |= (1 << 6);
+ }
return 0;
}
@@ -778,6 +814,60 @@ void qosify_map_dump(struct blob_buf *b)
blobmsg_close_array(b, a);
}
+static int
+qosify_map_create_alias(struct blob_attr *attr)
+{
+ struct qosify_map_alias *alias;
+ enum {
+ MAP_ALIAS_INGRESS,
+ MAP_ALIAS_EGRESS,
+ __MAP_ALIAS_MAX
+ };
+ static const struct blobmsg_policy policy[__MAP_ALIAS_MAX] = {
+ [MAP_ALIAS_INGRESS] = { .type = BLOBMSG_TYPE_STRING },
+ [MAP_ALIAS_EGRESS] = { .type = BLOBMSG_TYPE_STRING },
+ };
+ struct blob_attr *tb[__MAP_ALIAS_MAX];
+ const char *name;
+ char *name_buf;
+
+ if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) != 2)
+ return -1;
+
+ blobmsg_parse_array(policy, __MAP_ALIAS_MAX, tb,
+ blobmsg_data(attr), blobmsg_len(attr));
+
+ if (!tb[MAP_ALIAS_INGRESS] || !tb[MAP_ALIAS_EGRESS])
+ return -1;
+
+ name = blobmsg_name(attr);
+ alias = calloc_a(sizeof(*alias), &name_buf, strlen(name) + 1);
+ alias->avl.key = strcpy(name_buf, name);
+ if (__qosify_map_dscp_value(blobmsg_get_string(tb[MAP_ALIAS_INGRESS]),
+ &alias->value.ingress) ||
+ __qosify_map_dscp_value(blobmsg_get_string(tb[MAP_ALIAS_EGRESS]),
+ &alias->value.egress) ||
+ avl_insert(&map_aliases, &alias->avl)) {
+ free(alias);
+ return -1;
+ }
+
+ return 0;
+}
+
+void qosify_map_set_aliases(struct blob_attr *val)
+{
+ struct qosify_map_alias *alias, *tmp;
+ struct blob_attr *cur;
+ int rem;
+
+ avl_remove_all_elements(&map_aliases, alias, avl, tmp)
+ free(alias);
+
+ blobmsg_for_each_attr(cur, val, rem)
+ qosify_map_create_alias(cur);
+}
+
void qosify_map_update_config(void)
{
int fd = qosify_map_fds[CL_MAP_CONFIG];
diff --git a/qosify.h b/qosify.h
index 872b048..e5ca58a 100644
--- a/qosify.h
+++ b/qosify.h
@@ -81,6 +81,7 @@ void qosify_map_dump(struct blob_buf *b);
void qosify_map_set_dscp_default(enum qosify_map_id id, struct qosify_dscp_val val);
void qosify_map_reset_config(void);
void qosify_map_update_config(void);
+void qosify_map_set_aliases(struct blob_attr *val);
int qosify_map_add_dns_host(char *host, const char *addr, const char *type, int ttl);
int qosify_iface_init(void);
diff --git a/ubus.c b/ubus.c
index d1c0303..fb5a6b7 100644
--- a/ubus.c
+++ b/ubus.c
@@ -138,6 +138,7 @@ enum {
CL_CONFIG_PRIO_PKT_LEN,
CL_CONFIG_INTERFACES,
CL_CONFIG_DEVICES,
+ CL_CONFIG_ALIASES,
__CL_CONFIG_MAX
};
@@ -155,6 +156,7 @@ static const struct blobmsg_policy qosify_config_policy[__CL_CONFIG_MAX] = {
[CL_CONFIG_PRIO_PKT_LEN] = { "prio_max_avg_pkt_len", BLOBMSG_TYPE_INT32 },
[CL_CONFIG_INTERFACES] = { "interfaces", BLOBMSG_TYPE_TABLE },
[CL_CONFIG_DEVICES] = { "devices", BLOBMSG_TYPE_TABLE },
+ [CL_CONFIG_ALIASES] = { "aliases", BLOBMSG_TYPE_TABLE },
};
static int __set_dscp(struct qosify_dscp_val *dest, struct blob_attr *attr, bool reset)
@@ -193,6 +195,9 @@ qosify_ubus_config(struct ubus_context *ctx, struct ubus_object *obj,
if (reset)
qosify_map_reset_config();
+ if ((cur = tb[CL_CONFIG_ALIASES]) != NULL || reset)
+ qosify_map_set_aliases(cur);
+
if ((cur = tb[CL_CONFIG_TIMEOUT]) != NULL)
qosify_map_timeout = blobmsg_get_u32(cur);