]> granicus.if.org Git - libnl/commitdiff
route/vlan: allow clearing vlan ingress map
authorThomas Haller <thaller@redhat.com>
Wed, 21 Oct 2015 16:01:02 +0000 (18:01 +0200)
committerThomas Haller <thaller@redhat.com>
Thu, 19 Nov 2015 15:20:39 +0000 (16:20 +0100)
An entry of the ingress map can be cleared by setting
the "to" part to zero.

Previously, vlan_put_attrs() would skip over zero "to"
and thus the user cannot unset an ingress map entry.

Add a modified-mask to record the state of each ingress
map entry and also sent explicit zeros to kernel.

when we receive a IFLA_VLAN_INGRESS_QOS message from kernel,
vlan_parse() similarly sets the received entries as modified.
This preserves previous behavior when using a received object
to modify a vlan.

Add a capability NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR
to indicate the behavioral change.

Signed-off-by: Thomas Haller <thaller@redhat.com>
include/netlink/utils.h
lib/route/link/vlan.c
lib/utils.c

index ea853a8c7cc26ab4c6956e886d89f4136b22e89d..babe1b2f8f83a240d6991d8ac9efbe0cae20e79a 100644 (file)
@@ -177,6 +177,14 @@ enum {
        NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE = 13,
 #define NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE
 
+       /**
+        * Don't skip over vlan ingress-map entries with "to" field zero when serializing
+        * a netlink message. Previously such entires would be ignored which inhibits the
+        * user from clearing ingress map entries.
+        */
+       NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR = 14,
+#define NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR
+
        __NL_CAPABILITY_MAX,
        NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1),
 #define NL_CAPABILITY_MAX NL_CAPABILITY_MAX
index 017796f8e63c4e9fbf3a442c01e78e8fe643ac8c..118d5a006d03664146a90381ecc03b14d63ba83b 100644 (file)
@@ -44,6 +44,7 @@ struct vlan_info
 {
        uint16_t                vi_vlan_id;
        uint16_t                vi_protocol;
+       unsigned int            vi_ingress_qos_mask:(VLAN_PRIO_MAX+1);
        uint32_t                vi_flags;
        uint32_t                vi_flags_mask;
        uint32_t                vi_ingress_qos[VLAN_PRIO_MAX+1];
@@ -121,6 +122,7 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data,
                struct nlattr *nla;
                int remaining;
 
+               vi->vi_ingress_qos_mask = 0;
                memset(vi->vi_ingress_qos, 0, sizeof(vi->vi_ingress_qos));
 
                nla_for_each_nested(nla, tb[IFLA_VLAN_INGRESS_QOS], remaining) {
@@ -132,6 +134,17 @@ static int vlan_parse(struct rtnl_link *link, struct nlattr *data,
                                return -NLE_INVAL;
                        }
 
+                       /* Kernel will not explicitly serialize mappings with "to" zero
+                        * (although they are implicitly set).
+                        *
+                        * Thus we only mark those as "set" which are explicitly sent.
+                        * That is similar to what we do with the egress map and it preserves
+                        * previous behavior before NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR.
+                        *
+                        * It matters only when a received object is send back to kernel to modify
+                        * the link.
+                        */
+                       vi->vi_ingress_qos_mask |= (1 << map->from);
                        vi->vi_ingress_qos[map->from] = map->to;
                }
 
@@ -211,7 +224,7 @@ static void vlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
                nl_dump_line(p, 
                "      ingress vlan prio -> qos/socket prio mapping:\n");
                for (i = 0, printed = 0; i <= VLAN_PRIO_MAX; i++) {
-                       if (vi->vi_ingress_qos[i]) {
+                       if (vi->vi_ingress_qos_mask & (1 << i)) {
                                if (printed == 0)
                                        nl_dump_line(p, "      ");
                                nl_dump(p, "%x -> %#08x, ",
@@ -300,7 +313,7 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
                        goto nla_put_failure;
 
                for (i = 0; i <= VLAN_PRIO_MAX; i++) {
-                       if (vi->vi_ingress_qos[i]) {
+                       if (vi->vi_ingress_qos_mask & (1 << i)) {
                                map.from = i;
                                map.to = vi->vi_ingress_qos[i];
 
@@ -542,6 +555,7 @@ int rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from,
        if (from < 0 || from > VLAN_PRIO_MAX)
                return -NLE_INVAL;
 
+       vi->vi_ingress_qos_mask |= (1 << from);
        vi->vi_ingress_qos[from] = to;
        vi->vi_mask |= VLAN_HAS_INGRESS_QOS;
 
index 92b481cde8ba031844c73cf8ba92f4a6c09e3ee9..ca98ab3c31bb18ef8d0cb729fc895ac82e826dd1 100644 (file)
@@ -1157,7 +1157,7 @@ int nl_has_capability (int capability)
                        NL_CAPABILITY_VERSION_3_2_27,
                        NL_CAPABILITY_RTNL_LINK_VLAN_PROTOCOL_SERIALZE,
                        NL_CAPABILITY_RTNL_LINK_PARSE_GRE_REMOTE,
-                       0,
+                       NL_CAPABILITY_RTNL_LINK_VLAN_INGRESS_MAP_CLEAR,
                        0,
                        0),
                /* IMPORTANT: these capability numbers are intended to be universal and stable