diff options
| author | Felix Fietkau | 2021-11-12 21:54:51 +0000 |
|---|---|---|
| committer | Felix Fietkau | 2021-11-12 21:54:53 +0000 |
| commit | bfc2cafe2a8c66ffab88a7e5c1ad1b0a4d886271 (patch) | |
| tree | 8a0d68b7b525dca6cd0b3a44afe72e868ea034f3 | |
| parent | 8e48d0b0cbba5b3804af2d99541c56b8b979f168 (diff) | |
| download | qosify-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.c | 96 | ||||
| -rw-r--r-- | qosify.h | 1 | ||||
| -rw-r--r-- | ubus.c | 5 |
3 files changed, 99 insertions, 3 deletions
@@ -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]; @@ -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); @@ -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); |