[pve-devel] [PATCH] add bridge-vlanrage patches.
Alexandre Derumier
aderumier at odiso.com
Fri Jul 24 09:50:39 CEST 2015
This allow to define vlan range on bridge ports.
example:
bridge vlan add vid 1-4094 dev eth0
(This require iproute2 4.0 utils)
Theses patches are already in kernel 4.0, so we can remove them when will upgrade to 4.X kernel.
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
Makefile | 4 +
bridge-vlandrange1.patch | 166 +++++++++++++++++++++++++++++++++++++++
bridge-vlandrange2.patch | 28 +++++++
bridge-vlandrange3.patch | 196 +++++++++++++++++++++++++++++++++++++++++++++++
bridge-vlandrange4.patch | 47 ++++++++++++
5 files changed, 441 insertions(+)
create mode 100644 bridge-vlandrange1.patch
create mode 100644 bridge-vlandrange2.patch
create mode 100644 bridge-vlandrange3.patch
create mode 100644 bridge-vlandrange4.patch
diff --git a/Makefile b/Makefile
index e7c7764..a2ff8a0 100644
--- a/Makefile
+++ b/Makefile
@@ -201,6 +201,10 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNELSRCTAR}
tar xf ${KERNELSRCTAR}
cat ${KERNEL_SRC}/debian.master/config/config.common.ubuntu ${KERNEL_SRC}/debian.master/config/amd64/config.common.amd64 ${KERNEL_SRC}/debian.master/config/amd64/config.flavour.generic > ${KERNEL_CFG_ORG}
cd ${KERNEL_SRC}; patch -p1 <../bridge-patch.diff
+ cd ${KERNEL_SRC}; patch -p1 <../bridge-vlandrange1.patch
+ cd ${KERNEL_SRC}; patch -p1 <../bridge-vlandrange2.patch
+ cd ${KERNEL_SRC}; patch -p1 <../bridge-vlandrange3.patch
+ cd ${KERNEL_SRC}; patch -p1 <../bridge-vlandrange4.patch
#cd ${KERNEL_SRC}; patch -p1 <../bridge-forward-ipv6-neighbor-solicitation.patch
#cd ${KERNEL_SRC}; patch -p1 <../add-empty-ndo_poll_controller-to-veth.patch
#cd ${KERNEL_SRC}; patch -p1 <../override_for_missing_acs_capabilities.patch
diff --git a/bridge-vlandrange1.patch b/bridge-vlandrange1.patch
new file mode 100644
index 0000000..11b86bb
--- /dev/null
+++ b/bridge-vlandrange1.patch
@@ -0,0 +1,166 @@
+From bdced7ef7838c1c4aebe9f295e44b7f0dcae2109 Mon Sep 17 00:00:00 2001
+From: Roopa Prabhu <roopa at cumulusnetworks.com>
+Date: Sat, 10 Jan 2015 07:31:12 -0800
+Subject: bridge: support for multiple vlans and vlan ranges in setlink and
+ dellink requests
+
+This patch changes bridge IFLA_AF_SPEC netlink attribute parser to
+look for more than one IFLA_BRIDGE_VLAN_INFO attribute. This allows
+userspace to pack more than one vlan in the setlink msg.
+
+The dumps were already sending more than one vlan info in the getlink msg.
+
+This patch also adds bridge_vlan_info flags BRIDGE_VLAN_INFO_RANGE_BEGIN and
+BRIDGE_VLAN_INFO_RANGE_END to indicate start and end of vlan range
+
+This patch also deletes unused ifla_br_policy.
+
+Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+
+diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
+index b03ee8f..eaaea62 100644
+--- a/include/uapi/linux/if_bridge.h
++++ b/include/uapi/linux/if_bridge.h
+@@ -125,6 +125,8 @@ enum {
+ #define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */
+ #define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */
+ #define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */
++#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */
++#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
+
+ struct bridge_vlan_info {
+ __u16 flags;
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 9f5eb55..6f616a2 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -218,57 +218,89 @@ out:
+ return err;
+ }
+
+-static const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
+- [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
+- [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
+- [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
+- .len = sizeof(struct bridge_vlan_info), },
+-};
++static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p,
++ int cmd, struct bridge_vlan_info *vinfo)
++{
++ int err = 0;
++
++ switch (cmd) {
++ case RTM_SETLINK:
++ if (p) {
++ err = nbp_vlan_add(p, vinfo->vid, vinfo->flags);
++ if (err)
++ break;
++
++ if (vinfo->flags & BRIDGE_VLAN_INFO_MASTER)
++ err = br_vlan_add(p->br, vinfo->vid,
++ vinfo->flags);
++ } else {
++ err = br_vlan_add(br, vinfo->vid, vinfo->flags);
++ }
++ break;
++
++ case RTM_DELLINK:
++ if (p) {
++ nbp_vlan_delete(p, vinfo->vid);
++ if (vinfo->flags & BRIDGE_VLAN_INFO_MASTER)
++ br_vlan_delete(p->br, vinfo->vid);
++ } else {
++ br_vlan_delete(br, vinfo->vid);
++ }
++ break;
++ }
++
++ return err;
++}
+
+ static int br_afspec(struct net_bridge *br,
+ struct net_bridge_port *p,
+ struct nlattr *af_spec,
+ int cmd)
+ {
+- struct nlattr *tb[IFLA_BRIDGE_MAX+1];
++ struct bridge_vlan_info *vinfo_start = NULL;
++ struct bridge_vlan_info *vinfo = NULL;
++ struct nlattr *attr;
+ int err = 0;
++ int rem;
+
+- err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, af_spec, ifla_br_policy);
+- if (err)
+- return err;
++ nla_for_each_nested(attr, af_spec, rem) {
++ if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
++ continue;
++ if (nla_len(attr) != sizeof(struct bridge_vlan_info))
++ return -EINVAL;
++ vinfo = nla_data(attr);
++ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
++ if (vinfo_start)
++ return -EINVAL;
++ vinfo_start = vinfo;
++ continue;
++ }
++
++ if (vinfo_start) {
++ struct bridge_vlan_info tmp_vinfo;
++ int v;
+
+- if (tb[IFLA_BRIDGE_VLAN_INFO]) {
+- struct bridge_vlan_info *vinfo;
++ if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
++ return -EINVAL;
+
+- vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
++ if (vinfo->vid <= vinfo_start->vid)
++ return -EINVAL;
+
+- if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
+- return -EINVAL;
++ memcpy(&tmp_vinfo, vinfo_start,
++ sizeof(struct bridge_vlan_info));
+
+- switch (cmd) {
+- case RTM_SETLINK:
+- if (p) {
+- err = nbp_vlan_add(p, vinfo->vid, vinfo->flags);
++ for (v = vinfo_start->vid; v <= vinfo->vid; v++) {
++ tmp_vinfo.vid = v;
++ err = br_vlan_info(br, p, cmd, &tmp_vinfo);
+ if (err)
+ break;
+-
+- if (vinfo->flags & BRIDGE_VLAN_INFO_MASTER)
+- err = br_vlan_add(p->br, vinfo->vid,
+- vinfo->flags);
+- } else
+- err = br_vlan_add(br, vinfo->vid, vinfo->flags);
+-
+- break;
+-
+- case RTM_DELLINK:
+- if (p) {
+- nbp_vlan_delete(p, vinfo->vid);
+- if (vinfo->flags & BRIDGE_VLAN_INFO_MASTER)
+- br_vlan_delete(p->br, vinfo->vid);
+- } else
+- br_vlan_delete(br, vinfo->vid);
+- break;
++ }
++ vinfo_start = NULL;
++ } else {
++ err = br_vlan_info(br, p, cmd, vinfo);
+ }
++ if (err)
++ break;
+ }
+
+ return err;
+--
+cgit v0.10.2
+
diff --git a/bridge-vlandrange2.patch b/bridge-vlandrange2.patch
new file mode 100644
index 0000000..a4335c4
--- /dev/null
+++ b/bridge-vlandrange2.patch
@@ -0,0 +1,28 @@
+From 35a27cee321e7c4e7cba3550b2f48c2ca44d8a72 Mon Sep 17 00:00:00 2001
+From: Roopa Prabhu <roopa at cumulusnetworks.com>
+Date: Sat, 10 Jan 2015 07:31:13 -0800
+Subject: rtnetlink: new filter RTEXT_FILTER_BRVLAN_COMPRESSED
+
+This filter is same as RTEXT_FILTER_BRVLAN except that it tries
+to compress the consecutive vlans into ranges.
+
+This helps on systems with large number of configured vlans.
+
+Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+
+diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
+index d81f22d..a1d1859 100644
+--- a/include/uapi/linux/rtnetlink.h
++++ b/include/uapi/linux/rtnetlink.h
+@@ -636,6 +636,7 @@ struct tcamsg {
+ /* New extended info filters for IFLA_EXT_MASK */
+ #define RTEXT_FILTER_VF (1 << 0)
+ #define RTEXT_FILTER_BRVLAN (1 << 1)
++#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
+
+ /* End of information exported to user level */
+
+--
+cgit v0.10.2
+
diff --git a/bridge-vlandrange3.patch b/bridge-vlandrange3.patch
new file mode 100644
index 0000000..d11f03f
--- /dev/null
+++ b/bridge-vlandrange3.patch
@@ -0,0 +1,196 @@
+From 36cd0ffbab8a65f44ae13fb200bfb5a8f9ea68de Mon Sep 17 00:00:00 2001
+From: Roopa Prabhu <roopa at cumulusnetworks.com>
+Date: Sat, 10 Jan 2015 07:31:14 -0800
+Subject: bridge: new function to pack vlans into ranges during gets
+
+This patch adds new function to pack vlans into ranges
+whereever applicable using the flags BRIDGE_VLAN_INFO_RANGE_BEGIN
+and BRIDGE VLAN_INFO_RANGE_END
+
+Old vlan packing code is moved to a new function and continues to be
+called when filter_mask is RTEXT_FILTER_BRVLAN.
+
+Signed-off-by: Roopa Prabhu <roopa at cumulusnetworks.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 6f616a2..0b03879 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -67,6 +67,118 @@ static int br_port_fill_attrs(struct sk_buff *skb,
+ return 0;
+ }
+
++static int br_fill_ifvlaninfo_range(struct sk_buff *skb, u16 vid_start,
++ u16 vid_end, u16 flags)
++{
++ struct bridge_vlan_info vinfo;
++
++ if ((vid_end - vid_start) > 0) {
++ /* add range to skb */
++ vinfo.vid = vid_start;
++ vinfo.flags = flags | BRIDGE_VLAN_INFO_RANGE_BEGIN;
++ if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
++ sizeof(vinfo), &vinfo))
++ goto nla_put_failure;
++
++ vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
++
++ vinfo.vid = vid_end;
++ vinfo.flags = flags | BRIDGE_VLAN_INFO_RANGE_END;
++ if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
++ sizeof(vinfo), &vinfo))
++ goto nla_put_failure;
++ } else {
++ vinfo.vid = vid_start;
++ vinfo.flags = flags;
++ if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
++ sizeof(vinfo), &vinfo))
++ goto nla_put_failure;
++ }
++
++ return 0;
++
++nla_put_failure:
++ return -EMSGSIZE;
++}
++
++static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
++ const struct net_port_vlans *pv)
++{
++ u16 vid_range_start = 0, vid_range_end = 0;
++ u16 vid_range_flags;
++ u16 pvid, vid, flags;
++ int err = 0;
++
++ /* Pack IFLA_BRIDGE_VLAN_INFO's for every vlan
++ * and mark vlan info with begin and end flags
++ * if vlaninfo represents a range
++ */
++ pvid = br_get_pvid(pv);
++ for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
++ flags = 0;
++ if (vid == pvid)
++ flags |= BRIDGE_VLAN_INFO_PVID;
++
++ if (test_bit(vid, pv->untagged_bitmap))
++ flags |= BRIDGE_VLAN_INFO_UNTAGGED;
++
++ if (vid_range_start == 0) {
++ goto initvars;
++ } else if ((vid - vid_range_end) == 1 &&
++ flags == vid_range_flags) {
++ vid_range_end = vid;
++ continue;
++ } else {
++ err = br_fill_ifvlaninfo_range(skb, vid_range_start,
++ vid_range_end,
++ vid_range_flags);
++ if (err)
++ return err;
++ }
++
++initvars:
++ vid_range_start = vid;
++ vid_range_end = vid;
++ vid_range_flags = flags;
++ }
++
++ /* Call it once more to send any left over vlans */
++ err = br_fill_ifvlaninfo_range(skb, vid_range_start,
++ vid_range_end,
++ vid_range_flags);
++ if (err)
++ return err;
++
++ return 0;
++}
++
++static int br_fill_ifvlaninfo(struct sk_buff *skb,
++ const struct net_port_vlans *pv)
++{
++ struct bridge_vlan_info vinfo;
++ u16 pvid, vid;
++
++ pvid = br_get_pvid(pv);
++ for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
++ vinfo.vid = vid;
++ vinfo.flags = 0;
++ if (vid == pvid)
++ vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
++
++ if (test_bit(vid, pv->untagged_bitmap))
++ vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
++
++ if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
++ sizeof(vinfo), &vinfo))
++ goto nla_put_failure;
++ }
++
++ return 0;
++
++nla_put_failure:
++ return -EMSGSIZE;
++}
++
+ /*
+ * Create one netlink message for one interface
+ * Contains port and master info as well as carrier and bridge state.
+@@ -121,12 +233,11 @@ static int br_fill_ifinfo(struct sk_buff *skb,
+ }
+
+ /* Check if the VID information is requested */
+- if (filter_mask & RTEXT_FILTER_BRVLAN) {
+- struct nlattr *af;
++ if ((filter_mask & RTEXT_FILTER_BRVLAN) ||
++ (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
+ const struct net_port_vlans *pv;
+- struct bridge_vlan_info vinfo;
+- u16 vid;
+- u16 pvid;
++ struct nlattr *af;
++ int err;
+
+ if (port)
+ pv = nbp_get_vlan_info(port);
+@@ -140,21 +251,12 @@ static int br_fill_ifinfo(struct sk_buff *skb,
+ if (!af)
+ goto nla_put_failure;
+
+- pvid = br_get_pvid(pv);
+- for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) {
+- vinfo.vid = vid;
+- vinfo.flags = 0;
+- if (vid == pvid)
+- vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
+-
+- if (test_bit(vid, pv->untagged_bitmap))
+- vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
+-
+- if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
+- sizeof(vinfo), &vinfo))
+- goto nla_put_failure;
+- }
+-
++ if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
++ err = br_fill_ifvlaninfo_compressed(skb, pv);
++ else
++ err = br_fill_ifvlaninfo(skb, pv);
++ if (err)
++ goto nla_put_failure;
+ nla_nest_end(skb, af);
+ }
+
+@@ -209,7 +311,8 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+ int err = 0;
+ struct net_bridge_port *port = br_port_get_rtnl(dev);
+
+- if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN))
++ if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN) &&
++ !(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED))
+ goto out;
+
+ err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI,
+--
+cgit v0.10.2
+
diff --git a/bridge-vlandrange4.patch b/bridge-vlandrange4.patch
new file mode 100644
index 0000000..a044ed4
--- /dev/null
+++ b/bridge-vlandrange4.patch
@@ -0,0 +1,47 @@
+From patchwork Thu Jul 2 12:48:17 2015
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [net] bridge: vlan: fix usage of vlan 0 and 4095 again
+From: Nikolay Aleksandrov <nikolay at cumulusnetworks.com>
+X-Patchwork-Id: 490608
+Message-Id: <1435841297-44200-1-git-send-email-nikolay at cumulusnetworks.com>
+To: netdev at vger.kernel.org
+Cc: vyasevich at gmail.com, bridge at lists.linux-foundation.org,
+ davem at davemloft.net, toshiaki.makita1 at gmail.com,
+ stephen at networkplumber.org, roopa at cumulusnetworks.com,
+ Nikolay Aleksandrov <nikolay at cumulusnetworks.com>
+Date: Thu, 2 Jul 2015 05:48:17 -0700
+
+Vlan ids 0 and 4095 were disallowed by commit:
+8adff41c3d25 ("bridge: Don't use VID 0 and 4095 in vlan filtering")
+but then the check was removed when vlan ranges were introduced by:
+bdced7ef7838 ("bridge: support for multiple vlans and vlan ranges in setlink and dellink requests")
+So reintroduce the vlan range check.
+Before patch:
+[root at testvm ~]# bridge vlan add vid 0 dev eth0 master
+(succeeds)
+After Patch:
+[root at testvm ~]# bridge vlan add vid 0 dev eth0 master
+RTNETLINK answers: Invalid argument
+
+Signed-off-by: Nikolay Aleksandrov <nikolay at cumulusnetworks.com>
+Fixes: bdced7ef7838 ("bridge: support for multiple vlans and vlan ranges in setlink and dellink requests")
+Acked-by: Toshiaki Makita <toshiaki.makita1 at gmail.com>
+---
+ net/bridge/br_netlink.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 6b67ed3831de..364bdc98bd9b 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -457,6 +457,8 @@ static int br_afspec(struct net_bridge *br,
+ if (nla_len(attr) != sizeof(struct bridge_vlan_info))
+ return -EINVAL;
+ vinfo = nla_data(attr);
++ if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
++ return -EINVAL;
+ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+ if (vinfo_start)
+ return -EINVAL;
--
2.1.4
More information about the pve-devel
mailing list