summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-10-21 16:01:02 (GMT)
committerThomas Haller <thaller@redhat.com>2015-11-19 15:20:39 (GMT)
commit7ea15f60a726de67f02e6868a8125a59570e956d (patch)
treedad25eb0715fb1a6a9abfeaa82dc4b433e3cbed4
parenta0b2710ed924d5107eae331643304e7364b1421e (diff)
downloadlibnl-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.h8
-rw-r--r--lib/route/link/vlan.c18
-rw-r--r--lib/utils.c2
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