diff options
author | Thomas Haller <thaller@redhat.com> | 2015-10-21 16:01:02 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-11-19 15:20:39 (GMT) |
commit | 7ea15f60a726de67f02e6868a8125a59570e956d (patch) | |
tree | dad25eb0715fb1a6a9abfeaa82dc4b433e3cbed4 | |
parent | a0b2710ed924d5107eae331643304e7364b1421e (diff) | |
download | libnl-7ea15f60a726de67f02e6868a8125a59570e956d.zip libnl-7ea15f60a726de67f02e6868a8125a59570e956d.tar.gz libnl-7ea15f60a726de67f02e6868a8125a59570e956d.tar.bz2 |
route/vlan: allow clearing vlan ingress map
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>
-rw-r--r-- | include/netlink/utils.h | 8 | ||||
-rw-r--r-- | lib/route/link/vlan.c | 18 | ||||
-rw-r--r-- | lib/utils.c | 2 |
3 files changed, 25 insertions, 3 deletions
diff --git a/include/netlink/utils.h b/include/netlink/utils.h index ea853a8..babe1b2 100644 --- a/include/netlink/utils.h +++ b/include/netlink/utils.h @@ -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 diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c index 017796f..118d5a0 100644 --- a/lib/route/link/vlan.c +++ b/lib/route/link/vlan.c @@ -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; diff --git a/lib/utils.c b/lib/utils.c index 92b481c..ca98ab3 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -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 |