From bfc2cafe2a8c66ffab88a7e5c1ad1b0a4d886271 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 12 Nov 2021 22:54:51 +0100 Subject: [PATCH] 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 --- map.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- qosify.h | 1 + ubus.c | 5 +++ 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 #include +#include #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); -- 2.30.2