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 <aderum...@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 <ro...@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 <ro...@cumulusnetworks.com> +Signed-off-by: David S. Miller <da...@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 <ro...@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 <ro...@cumulusnetworks.com> +Signed-off-by: David S. Miller <da...@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 <ro...@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 <ro...@cumulusnetworks.com> +Signed-off-by: David S. Miller <da...@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 <niko...@cumulusnetworks.com> +X-Patchwork-Id: 490608 +Message-Id: <1435841297-44200-1-git-send-email-niko...@cumulusnetworks.com> +To: net...@vger.kernel.org +Cc: vyasev...@gmail.com, bri...@lists.linux-foundation.org, + da...@davemloft.net, toshiaki.maki...@gmail.com, + step...@networkplumber.org, ro...@cumulusnetworks.com, + Nikolay Aleksandrov <niko...@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@testvm ~]# bridge vlan add vid 0 dev eth0 master +(succeeds) +After Patch: +[root@testvm ~]# bridge vlan add vid 0 dev eth0 master +RTNETLINK answers: Invalid argument + +Signed-off-by: Nikolay Aleksandrov <niko...@cumulusnetworks.com> +Fixes: bdced7ef7838 ("bridge: support for multiple vlans and vlan ranges in setlink and dellink requests") +Acked-by: Toshiaki Makita <toshiaki.maki...@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 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel