[PATCH 2/2] route/link: handle RTEXT_FILTER_BRVLAN_COMPRESSED
Tobias Jungel
tobias.jungel at bisdn.de
Thu Nov 26 07:47:58 PST 2015
notifications from the kernel regarding vlan ids are now handled
---
lib/route/link.c | 12 +++-----
lib/route/link/bridge.c | 82 ++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/lib/route/link.c b/lib/route/link.c
index 5ccf629..31381ae 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -523,20 +523,16 @@ errout:
static int parse_af_spec_bridge(struct rtnl_link *link, struct nlattr *attr)
{
struct rtnl_link_af_ops *af_ops;
- struct nlattr *af_attr;
char *af_data;
- int remaining;
int err = 0;
af_ops = af_lookup_and_alloc(link, AF_BRIDGE);
af_data = link->l_af_data[AF_BRIDGE];
- if (af_ops && af_ops->ao_parse_af) {
- nla_for_each_nested(af_attr, attr, remaining) {
- err = af_ops->ao_parse_af(link, af_attr, af_data);
- if (err < 0)
- goto errout;
- }
+ if (af_ops && af_ops->ao_parse_af_full) {
+ err = af_ops->ao_parse_af_full(link, attr, af_data);
+ if (err < 0)
+ goto errout;
}
link->ce_mask |= LINK_ATTR_AF_SPEC;
diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c
index 9510fde..f4243b1 100644
--- a/lib/route/link/bridge.c
+++ b/lib/route/link/bridge.c
@@ -190,6 +190,58 @@ static int bridge_parse_af(struct rtnl_link *link, struct nlattr *attr,
{
struct bridge_data *bd = data;
struct bridge_vlan_info *vinfo = NULL;
+ uint16_t vid_range_start = 0;
+ uint16_t vid_range_flags = -1;
+
+ struct nlattr *af_attr;
+ int remaining;
+
+ nla_for_each_nested(af_attr, attr, remaining) {
+
+ if (nla_type(af_attr) != IFLA_BRIDGE_VLAN_INFO)
+ continue;
+
+ if (nla_len(af_attr) != sizeof(struct bridge_vlan_info))
+ return -EINVAL;
+
+ vinfo = nla_data(af_attr);
+ if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
+ return -EINVAL;
+
+
+ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+ vid_range_start = vinfo->vid;
+ vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
+ continue;
+ }
+
+ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
+ /* sanity check the range flags */
+ if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
+ NL_DBG(1, "VLAN range flags differ; can not handle it.\n");
+ return -EINVAL;
+ }
+ } else {
+ vid_range_start = vinfo->vid;
+ }
+
+ for (; vid_range_start <= vinfo->vid; vid_range_start++) {
+ if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
+ bd->vlan_info.pvid = vinfo->vid;
+
+ if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
+ set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
+
+ set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
+ bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
+ }
+
+ vid_range_flags = -1;
+ }
+
+ return 0;
+
+
if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
return 0;
@@ -202,18 +254,32 @@ static int bridge_parse_af(struct rtnl_link *link, struct nlattr *attr,
return -EINVAL;
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
- NL_DBG(1, "Unexpected BRIDGE_VLAN_INFO_RANGE_BEGIN flag; can not handle it.\n");
- return -EINVAL;
+ vid_range_start = vinfo->vid;
+ vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
+ return 0;
+ }
+
+ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
+ /* sanity check the range flags */
+ if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
+ NL_DBG(1, "VLAN range flags differ; can not handle it.\n");
+ return -EINVAL;
+ }
+ } else {
+ vid_range_start = vinfo->vid;
}
- if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
- bd->vlan_info.pvid = vinfo->vid;
+ for (; vid_range_start <= vinfo->vid; vid_range_start++) {
+ if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
+ bd->vlan_info.pvid = vinfo->vid;
- if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
- set_bit(vinfo->vid, bd->vlan_info.untagged_bitmap);
+ if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
+ set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
- set_bit(vinfo->vid, bd->vlan_info.vlan_bitmap);
+ set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
+ }
+ vid_range_flags = -1;
bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
return 0;
@@ -722,7 +788,7 @@ static struct rtnl_link_af_ops bridge_ops = {
.ao_parse_protinfo = &bridge_parse_protinfo,
.ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details,
.ao_compare = &bridge_compare,
- .ao_parse_af = &bridge_parse_af,
+ .ao_parse_af_full = &bridge_parse_af,
.ao_get_af = &bridge_get_af,
};
--
2.5.0
More information about the libnl
mailing list