From: Pau Espin Pedrol <pespin.s...@gmail.com> It allows setting mappings for instance this way: """ config device option name 'vlan41' option type '8021q' option vid '41' option ifname 'eth1' list ingress_qos_mapping '1:2' list ingress_qos_mapping '2:5' list egress_qos_mapping '0:3' """
Size of mapping arrays (ingress=8, egress=16) taken from linux kernel "struct vlan_dev_priv". Signed-off-by: Pau Espin Pedrol <pespin.s...@gmail.com> Tested-by: Pedro <pedro...@cas.cat> --- system-linux.c | 19 ++++++++++++++++- system.h | 5 +++++ vlandev.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/system-linux.c b/system-linux.c index 62636c4..fa236ad 100644 --- a/system-linux.c +++ b/system-linux.c @@ -1401,9 +1401,10 @@ int system_vlan_del(struct device *dev) int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg) { struct nl_msg *msg; - struct nlattr *linkinfo, *data; + struct nlattr *linkinfo, *data, *qos; struct ifinfomsg iim = { .ifi_family = AF_UNSPEC }; int rv; + int i; msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); @@ -1431,6 +1432,22 @@ int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlande netifd_log_message(L_WARNING, "%s Your kernel is older than linux 3.10.0, 802.1ad is not supported defaulting to 802.1q", vlandev->type->name); #endif + if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) + goto nla_put_failure; + for (i = 0; i < cfg->ingress_qos_mappings_len; i++) + nla_put(msg, IFLA_VLAN_QOS_MAPPING, + sizeof(cfg->ingress_qos_mappings[i]), + &cfg->ingress_qos_mappings[i]); + nla_nest_end(msg, qos); + + if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) + goto nla_put_failure; + for (i = 0; i < cfg->egress_qos_mappings_len; i++) + nla_put(msg, IFLA_VLAN_QOS_MAPPING, + sizeof(cfg->egress_qos_mappings[i]), + &cfg->egress_qos_mappings[i]); + nla_nest_end(msg, qos); + nla_nest_end(msg, data); nla_nest_end(msg, linkinfo); diff --git a/system.h b/system.h index b377416..d8fc0c4 100644 --- a/system.h +++ b/system.h @@ -18,6 +18,7 @@ #include <sys/time.h> #include <sys/socket.h> #include <arpa/inet.h> +#include <linux/if_link.h> #include "device.h" #include "interface-ip.h" #include "iprule.h" @@ -161,6 +162,10 @@ enum vlan_proto { struct vlandev_config { enum vlan_proto proto; uint16_t vid; + struct ifla_vlan_qos_mapping ingress_qos_mappings[8]; + size_t ingress_qos_mappings_len; + struct ifla_vlan_qos_mapping egress_qos_mappings[16]; + size_t egress_qos_mappings_len; }; static inline int system_get_addr_family(unsigned int flags) diff --git a/vlandev.c b/vlandev.c index ceaeb3e..2cc9a19 100644 --- a/vlandev.c +++ b/vlandev.c @@ -13,6 +13,7 @@ */ #include <string.h> +#include <inttypes.h> #include "netifd.h" #include "device.h" @@ -22,12 +23,16 @@ enum { VLANDEV_ATTR_IFNAME, VLANDEV_ATTR_VID, + VLANDEV_ATTR_INGRESS_QOS_MAPPING, + VLANDEV_ATTR_EGRESS_QOS_MAPPING, __VLANDEV_ATTR_MAX }; static const struct blobmsg_policy vlandev_attrs[__VLANDEV_ATTR_MAX] = { [VLANDEV_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_STRING }, [VLANDEV_ATTR_VID] = { "vid", BLOBMSG_TYPE_INT32 }, + [VLANDEV_ATTR_INGRESS_QOS_MAPPING] = { "ingress_qos_mapping", BLOBMSG_TYPE_ARRAY }, + [VLANDEV_ATTR_EGRESS_QOS_MAPPING] = { "egress_qos_mapping", BLOBMSG_TYPE_ARRAY }, }; static const struct uci_blob_param_list vlandev_attr_list = { @@ -152,6 +157,42 @@ vlandev_config_init(struct device *dev) device_add_user(&mvdev->parent, basedev); } +static size_t vlandev_qos_mappings_list_apply(struct ifla_vlan_qos_mapping *qos_mapping, size_t len, struct blob_attr *list) +{ + struct blob_attr *cur; + int rem, rc; + int i = 0; + + blobmsg_for_each_attr(cur, list, rem) { + if (i == len) { + netifd_log_message(L_WARNING, "parsing failed: too many (>%d) qos mappings\n", len); + return 0; + } + + if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) { + netifd_log_message(L_WARNING, "parsing failed: qos mapping attr type != string\n"); + return 0; + } + + if (!blobmsg_check_attr(cur, false)) { + netifd_log_message(L_WARNING, "parsing failed: qos mapping attr blobmsg_check_attr() failed\n"); + return 0; + } + + rc = sscanf(blobmsg_data(cur), "%" PRIu32 ":%" PRIu32, &qos_mapping[i].from, &qos_mapping[i].to); + if (rc != 2) { + netifd_log_message(L_WARNING, "parsing failed: qos mapping not in form <from_nr>:<to_nr>\n"); + return 0; + } + + i++; + } + + return i; +} + + + static void vlandev_apply_settings(struct vlandev_device *mvdev, struct blob_attr **tb) { @@ -161,9 +202,25 @@ vlandev_apply_settings(struct vlandev_device *mvdev, struct blob_attr **tb) cfg->proto = (mvdev->dev.type == &vlan8021q_device_type) ? VLAN_PROTO_8021Q : VLAN_PROTO_8021AD; cfg->vid = 1; + cfg->ingress_qos_mappings_len = 0; + cfg->egress_qos_mappings_len = 0; if ((cur = tb[VLANDEV_ATTR_VID])) cfg->vid = (uint16_t) blobmsg_get_u32(cur); + + if ((cur = tb[VLANDEV_ATTR_INGRESS_QOS_MAPPING])) { + cfg->ingress_qos_mappings_len = + vlandev_qos_mappings_list_apply(cfg->ingress_qos_mappings, + ARRAY_SIZE(cfg->ingress_qos_mappings), + cur); + } + + if ((cur = tb[VLANDEV_ATTR_EGRESS_QOS_MAPPING])) { + cfg->egress_qos_mappings_len = + vlandev_qos_mappings_list_apply(cfg->egress_qos_mappings, + ARRAY_SIZE(cfg->egress_qos_mappings), + cur); + } } static enum dev_change_type -- 2.26.2 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel