netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping
@ 2017-10-28  5:13 Roopa Prabhu
  2017-10-28  5:13 ` [PATCH iproute2 net-next v2 1/2] iplink: bridge: support bridge port vlan_tunnel attribute Roopa Prabhu
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Roopa Prabhu @ 2017-10-28  5:13 UTC (permalink / raw)
  To: stephen; +Cc: netdev, nikolay

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This series adds the required options to iplink and bridge commands
to enable per vlan tunnel info on a bridge port provided by
netlink attributes IFLA_BRPORT_VLAN_TUNNEL (flag) and
IFLA_BRIDGE_VLAN_TUNNEL_INFO

enable vlan-tunnel mapping on a bridge port:
$ip link set dev vxlan0 type bridge_slave vlan_tunnel on
$ip link set dev vxlan0 type bridge_slave vlan_tunnel off

or

$bridge link set dev vxlan0 vlan_tunnel on
$bridge link set dev vxlan0 vlan_tunnel off

add vlan tunnel mapping (expects vlans to have been already
configured on the port):
$bridge vlan add dev vxlan0 vid 2000 tunnel_info id 2000
$bridge vlan add dev vxlan0 vid 1000-1001 tunnel_info id 2000-2001

$bridge vlan tunnelshow
port    vlan ids        tunnel id
vxlan0   1000-1001       1000-1001
         2000            2000

$bridge  -j vlan tunnelshow
{
    "dummy0": [],
    "dummy1": [],
    "bridge": [],
    "vxlan0": [{
            "vlan": 1000,
            "vlanEnd": 1001,
            "tunid": 1000,
            "tunidEnd": 1001
        },{
            "vlan": 2000,
            "tunid": 2000
        }
    ]
}

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>

Roopa Prabhu (2):
  iplink: bridge: support bridge port vlan_tunnel attribute
  bridge: vlan: support for per vlan tunnel info

v2 - rebase to latest net-next

 bridge/link.c            |  12 ++
 bridge/vlan.c            | 305 ++++++++++++++++++++++++++++++++++++++++++-----
 ip/iplink_bridge_slave.c |   9 ++
 man/man8/bridge.8        |  12 +-
 man/man8/ip-link.8.in    |   5 +
 5 files changed, 315 insertions(+), 28 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH iproute2 net-next v2 1/2] iplink: bridge: support bridge port vlan_tunnel attribute
  2017-10-28  5:13 [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Roopa Prabhu
@ 2017-10-28  5:13 ` Roopa Prabhu
  2017-10-28  5:13 ` [PATCH iproute2 net-next v2 2/2] bridge: vlan: support for per vlan tunnel info Roopa Prabhu
  2017-10-31 17:06 ` [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Stephen Hemminger
  2 siblings, 0 replies; 4+ messages in thread
From: Roopa Prabhu @ 2017-10-28  5:13 UTC (permalink / raw)
  To: stephen; +Cc: netdev, nikolay

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This config maps to IFLA_BRPORT_VLAN_TUNNEL bridge port netlink
flag attribute. This flag enables vlan to tunnel mapping on a bridge
port. It is off by default.

set vlan_tunnel attribute on bridge port vxlan0:

$ip link set dev vxlan0 type bridge_slave vlan_tunnel on
$ip link set dev vxlan0 type bridge_slave vlan_tunnel off

or via bridge command

$bridge link set dev vxlan0 vlan_tunnel on
$bridge link set dev vxlan0 vlan_tunnel off

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 bridge/link.c            | 14 ++++++++++++++
 ip/iplink_bridge_slave.c |  9 +++++++++
 man/man8/bridge.8        |  6 ++++++
 man/man8/ip-link.8.in    |  5 +++++
 4 files changed, 34 insertions(+)

diff --git a/bridge/link.c b/bridge/link.c
index ae4bb88..65ca47e 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -201,6 +201,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
 				if (prtb[IFLA_BRPORT_NEIGH_SUPPRESS])
 					print_onoff(fp, "neigh_suppress",
 						    rta_getattr_u8(prtb[IFLA_BRPORT_NEIGH_SUPPRESS]));
+				if (prtb[IFLA_BRPORT_VLAN_TUNNEL])
+					print_onoff(fp, "vlan_tunnel",
+						    rta_getattr_u8(prtb[IFLA_BRPORT_VLAN_TUNNEL]));
 			}
 		} else
 			print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO]));
@@ -241,6 +244,8 @@ static void usage(void)
 	fprintf(stderr,	"                               [ learning_sync {on | off} ]\n");
 	fprintf(stderr,	"                               [ flood {on | off} ]\n");
 	fprintf(stderr,	"                               [ mcast_flood {on | off} ]\n");
+	fprintf(stderr,	"                               [ neigh_suppress {on | off} ]\n");
+	fprintf(stderr,	"                               [ vlan_tunnel {on | off} ]\n");
 	fprintf(stderr, "                               [ hwmode {vepa | veb} ]\n");
 	fprintf(stderr, "                               [ self ] [ master ]\n");
 	fprintf(stderr, "       bridge link show [dev DEV]\n");
@@ -280,6 +285,7 @@ static int brlink_modify(int argc, char **argv)
 	__s8 learning = -1;
 	__s8 learning_sync = -1;
 	__s8 flood = -1;
+	__s8 vlan_tunnel = -1;
 	__s8 mcast_flood = -1;
 	__s8 hairpin = -1;
 	__s8 bpdu_guard = -1;
@@ -371,6 +377,11 @@ static int brlink_modify(int argc, char **argv)
 			if (!on_off("neigh_suppress", &neigh_suppress,
 				    *argv))
 				return -1;
+		} else if (strcmp(*argv, "vlan_tunnel") == 0) {
+			NEXT_ARG();
+			if (!on_off("vlan_tunnel", &vlan_tunnel,
+				    *argv))
+				return -1;
 		} else {
 			usage();
 		}
@@ -426,6 +437,9 @@ static int brlink_modify(int argc, char **argv)
 	if (neigh_suppress != -1)
 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_NEIGH_SUPPRESS,
 			 neigh_suppress);
+	if (vlan_tunnel != -1)
+		addattr8(&req.n, sizeof(req), IFLA_BRPORT_VLAN_TUNNEL,
+			 vlan_tunnel);
 
 	addattr_nest_end(&req.n, nest);
 
diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c
index 0d5a011..be0fb4f 100644
--- a/ip/iplink_bridge_slave.c
+++ b/ip/iplink_bridge_slave.c
@@ -39,6 +39,7 @@ static void print_explain(FILE *f)
 		"                        [ mcast_flood {on | off} ]\n"
 		"                        [ group_fwd_mask MASK ]\n"
 		"                        [ neigh_suppress {on | off} ]\n"
+		"                        [ vlan_tunnel {on | off} ]\n"
 	);
 }
 
@@ -283,6 +284,10 @@ static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
 		print_string(PRINT_ANY, "group_fwd_mask_str",
 			     "group_fwd_mask_str %s ", convbuf);
 	}
+
+	if (tb[IFLA_BRPORT_VLAN_TUNNEL])
+		_print_onoff(f, "vlan_tunnel", "vlan_tunnel",
+			     rta_getattr_u8(tb[IFLA_BRPORT_VLAN_TUNNEL]));
 }
 
 static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
@@ -384,6 +389,10 @@ static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
 			if (get_u16(&mask, *argv, 0))
 				invarg("invalid group_fwd_mask", *argv);
 			addattr16(n, 1024, IFLA_BRPORT_GROUP_FWD_MASK, mask);
+		} else if (matches(*argv, "vlan_tunnel") == 0) {
+			NEXT_ARG();
+			bridge_slave_parse_on_off("vlan_tunnel", *argv, n,
+						  IFLA_BRPORT_VLAN_TUNNEL);
 		} else if (matches(*argv, "help") == 0) {
 			explain();
 			return -1;
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index fdba0fe..d3c5b1e 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -44,6 +44,8 @@ bridge \- show / manipulate bridge addresses and devices
 .BR flood " { " on " | " off " } ] [ "
 .BR hwmode " { " vepa " | " veb " } ] [ "
 .BR mcast_flood " { " on " | " off " } ] [ "
+.BR neigh_suppress " { " on " | " off " } ] [ "
+.BR vlan_tunnel " { " on " | " off " } ] [ "
 .BR self " ] [ " master " ]"
 
 .ti -8
@@ -327,6 +329,10 @@ Controls whether a given port will be flooded with multicast traffic for which t
 Controls whether neigh discovery (arp and nd) proxy and suppression is enabled on the port. By default this flag is off.
 
 .TP
+.BR "vlan_tunnel on " or " vlan_tunnel off "
+Controls whether vlan to tunnel mapping is enabled on the port. By default this flag is off.
+
+.TP
 .BI self
 link setting is configured on specified physical device
 
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 153665c..71b328c 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -1750,6 +1750,8 @@ the following additional arguments are supported:
 .BR group_fwd_mask " MASK"
 ] [
 .BR neigh_suppress " { " on " | " off " } ]"
+] [
+.BR vlan_tunnel " { " on " | " off " } ]"
 
 .in +8
 .sp
@@ -1830,6 +1832,9 @@ option above.
 .BR neigh_suppress " { " on " | " off " }"
 - controls whether neigh discovery (arp and nd) proxy and suppression is enabled on the port. By default this flag is off.
 
+.BR vlan_tunnel " { " on " | " off " }"
+- Controls whether vlan to tunnel mapping is enabled on the port. By default this flag is off.
+
 .in -8
 
 .TP
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH iproute2 net-next v2 2/2] bridge: vlan: support for per vlan tunnel info
  2017-10-28  5:13 [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Roopa Prabhu
  2017-10-28  5:13 ` [PATCH iproute2 net-next v2 1/2] iplink: bridge: support bridge port vlan_tunnel attribute Roopa Prabhu
@ 2017-10-28  5:13 ` Roopa Prabhu
  2017-10-31 17:06 ` [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Stephen Hemminger
  2 siblings, 0 replies; 4+ messages in thread
From: Roopa Prabhu @ 2017-10-28  5:13 UTC (permalink / raw)
  To: stephen; +Cc: netdev, nikolay

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This patch uses kernel bridge vlan attribute
IFLA_BRIDGE_VLAN_TUNNEL_INFO to set/delete/show per vlan tunnel info.

$bridge vlan add dev vxlan0 vid 2000 tunnel_info id 2000
$bridge vlan add dev vxlan0 vid 1000-1001 tunnel_info id 2000-2001

$bridge vlan tunnelshow
port    vlan ids        tunnel id
vxlan0   1000-1001       1000-1001
         2000            2000

$bridge  -j vlan tunnelshow
{
    "dummy0": [],
    "dummy1": [],
    "bridge": [],
    "vxlan0": [{
            "vlan": 1000,
            "vlanEnd": 1001,
            "tunid": 1000,
            "tunidEnd": 1001
        },{
            "vlan": 2000,
            "tunid": 2000
        }
    ]
}

This patch also fixes a json termination bug in print_vlan
when filter vlan is provided by the user.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 bridge/vlan.c     | 328 ++++++++++++++++++++++++++++++++++++++++++++++++------
 man/man8/bridge.8 |  14 ++-
 2 files changed, 307 insertions(+), 35 deletions(-)

diff --git a/bridge/vlan.c b/bridge/vlan.c
index 4ca91c1..0f78a9e 100644
--- a/bridge/vlan.c
+++ b/bridge/vlan.c
@@ -16,18 +16,114 @@
 
 static unsigned int filter_index, filter_vlan;
 static int last_ifidx = -1;
+static int show_vlan_tunnel_info = 0;
 
 json_writer_t *jw_global;
 
 static void usage(void)
 {
 	fprintf(stderr,
-		"Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ pvid ] [ untagged ]\n"
+		"Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ tunnel_info id TUNNEL_ID ]\n"
+		"                                                     [ pvid ] [ untagged ]\n"
 		"                                                     [ self ] [ master ]\n"
-		"       bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n");
+		"       bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n"
+		"       bridge vlan { tunnelshow } [ dev DEV ] [ vid VLAN_ID ]\n");
 	exit(-1);
 }
 
+static int parse_tunnel_info(int *argcp, char ***argvp, __u32 *tun_id_start,
+			     __u32 *tun_id_end)
+{
+	char **argv = *argvp;
+	int argc = *argcp;
+	char *t;
+
+	NEXT_ARG();
+	if (!matches(*argv, "id")) {
+		NEXT_ARG();
+		t = strchr(*argv, '-');
+		if (t) {
+			*t = '\0';
+			if (get_u32(tun_id_start, *argv, 0) ||
+				    *tun_id_start >= 1u << 24)
+				invarg("invalid tun id", *argv);
+			if (get_u32(tun_id_end, t + 1, 0) ||
+				    *tun_id_end >= 1u << 24)
+				invarg("invalid tun id", *argv);
+
+		} else {
+			if (get_u32(tun_id_start, *argv, 0) ||
+				    *tun_id_start >= 1u << 24)
+				invarg("invalid tun id", *argv);
+		}
+	} else {
+		invarg("tunnel id expected", *argv);
+	}
+
+	*argcp = argc;
+	*argvp = argv;
+
+	return 0;
+}
+
+static int add_tunnel_info(struct nlmsghdr *n, int reqsize,
+			   __u16 vid, __u32 tun_id, __u16 flags)
+{
+	struct rtattr *tinfo;
+
+	tinfo = addattr_nest(n, reqsize, IFLA_BRIDGE_VLAN_TUNNEL_INFO);
+	addattr32(n, reqsize, IFLA_BRIDGE_VLAN_TUNNEL_ID, tun_id);
+	addattr32(n, reqsize, IFLA_BRIDGE_VLAN_TUNNEL_VID, vid);
+	addattr32(n, reqsize, IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, flags);
+
+	addattr_nest_end(n, tinfo);
+
+	return 0;
+}
+
+static int add_tunnel_info_range(struct nlmsghdr *n, int reqsize,
+				 __u16 vid_start, int16_t vid_end,
+				 __u32 tun_id_start, __u32 tun_id_end)
+{
+	if (vid_end != -1 && (vid_end - vid_start) > 0) {
+		add_tunnel_info(n, reqsize, vid_start, tun_id_start,
+				BRIDGE_VLAN_INFO_RANGE_BEGIN);
+
+		add_tunnel_info(n, reqsize, vid_end, tun_id_end,
+				BRIDGE_VLAN_INFO_RANGE_END);
+	} else {
+		add_tunnel_info(n, reqsize, vid_start, tun_id_start, 0);
+	}
+
+	return 0;
+}
+
+static int add_vlan_info_range(struct nlmsghdr *n, int reqsize, __u16 vid_start,
+			       int16_t vid_end, __u16 flags)
+{
+	struct bridge_vlan_info vinfo = {};
+
+	vinfo.flags = flags;
+	vinfo.vid = vid_start;
+	if (vid_end != -1) {
+		/* send vlan range start */
+		addattr_l(n, reqsize, IFLA_BRIDGE_VLAN_INFO, &vinfo,
+			  sizeof(vinfo));
+		vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
+
+		/* Now send the vlan range end */
+		vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_END;
+		vinfo.vid = vid_end;
+		addattr_l(n, reqsize, IFLA_BRIDGE_VLAN_INFO, &vinfo,
+			  sizeof(vinfo));
+	} else {
+		addattr_l(n, reqsize, IFLA_BRIDGE_VLAN_INFO, &vinfo,
+			  sizeof(vinfo));
+	}
+
+	return 0;
+}
+
 static int vlan_modify(int cmd, int argc, char **argv)
 {
 	struct {
@@ -45,7 +141,10 @@ static int vlan_modify(int cmd, int argc, char **argv)
 	short vid_end = -1;
 	struct rtattr *afspec;
 	struct bridge_vlan_info vinfo = {};
+	bool tunnel_info_set = false;
 	unsigned short flags = 0;
+	__u32 tun_id_start = 0;
+	__u32 tun_id_end = 0;
 
 	while (argc > 0) {
 		if (strcmp(*argv, "dev") == 0) {
@@ -73,6 +172,12 @@ static int vlan_modify(int cmd, int argc, char **argv)
 			vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
 		} else if (strcmp(*argv, "untagged") == 0) {
 			vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
+		} else if (strcmp(*argv, "tunnel_info") == 0) {
+				if (parse_tunnel_info(&argc, &argv,
+						      &tun_id_start,
+						      &tun_id_end))
+					return -1;
+				tunnel_info_set = true;
 		} else {
 			if (matches(*argv, "help") == 0)
 				NEXT_ARG();
@@ -114,22 +219,12 @@ static int vlan_modify(int cmd, int argc, char **argv)
 	if (flags)
 		addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags);
 
-	vinfo.vid = vid;
-	if (vid_end != -1) {
-		/* send vlan range start */
-		addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo,
-			  sizeof(vinfo));
-		vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
-
-		/* Now send the vlan range end */
-		vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_END;
-		vinfo.vid = vid_end;
-		addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo,
-			  sizeof(vinfo));
-	} else {
-		addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo,
-			  sizeof(vinfo));
-	}
+	if (tunnel_info_set)
+		add_tunnel_info_range(&req.n, sizeof(req), vid, vid_end,
+				      tun_id_start, tun_id_end);
+	else
+		add_vlan_info_range(&req.n, sizeof(req), vid, vid_end,
+				    vinfo.flags);
 
 	addattr_nest_end(&req.n, afspec);
 
@@ -146,14 +241,14 @@ static int vlan_modify(int cmd, int argc, char **argv)
  *             which are less than filter_vlan)
  * return  1 - print the entry and continue
  */
-static int filter_vlan_check(struct bridge_vlan_info *vinfo)
+static int filter_vlan_check(__u16 vid, __u16 flags)
 {
 	/* if we're filtering we should stop on the first greater entry */
-	if (filter_vlan && vinfo->vid > filter_vlan &&
-	    !(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
+	if (filter_vlan && vid > filter_vlan &&
+	    !(flags & BRIDGE_VLAN_INFO_RANGE_END))
 		return -1;
-	if ((vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) ||
-	    vinfo->vid < filter_vlan)
+	if ((flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) ||
+	    vid < filter_vlan)
 		return 0;
 
 	return 1;
@@ -181,6 +276,150 @@ static void start_json_vlan_flags_array(bool *vlan_flags)
 	*vlan_flags = true;
 }
 
+static void print_vlan_tunnel_info(FILE *fp, struct rtattr *tb, int ifindex)
+{
+	bool jsonw_end_parray = false;
+	struct rtattr *i, *list = tb;
+	int rem = RTA_PAYLOAD(list);
+	__u16 last_vid_start = 0;
+	__u32 last_tunid_start = 0;
+
+	if (!filter_vlan) {
+		print_vlan_port(fp, ifindex);
+		jsonw_end_parray = 1;
+	}
+
+	for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
+		struct rtattr *ttb[IFLA_BRIDGE_VLAN_TUNNEL_MAX+1];
+		__u32 tunnel_id = 0;
+		__u16 tunnel_vid = 0;
+		__u16 tunnel_flags = 0;
+		int vcheck_ret;
+
+		if (i->rta_type != IFLA_BRIDGE_VLAN_TUNNEL_INFO)
+			continue;
+
+		parse_rtattr(ttb, IFLA_BRIDGE_VLAN_TUNNEL_MAX,
+			     RTA_DATA(i), RTA_PAYLOAD(i));
+
+		if (ttb[IFLA_BRIDGE_VLAN_TUNNEL_VID])
+			tunnel_vid =
+				rta_getattr_u32(ttb[IFLA_BRIDGE_VLAN_TUNNEL_VID]);
+		else
+			continue;
+
+		if (ttb[IFLA_BRIDGE_VLAN_TUNNEL_ID])
+			tunnel_id =
+				rta_getattr_u32(ttb[IFLA_BRIDGE_VLAN_TUNNEL_ID]);
+
+		if (ttb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS])
+			tunnel_flags =
+				rta_getattr_u32(ttb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS]);
+
+		if (!(tunnel_flags & BRIDGE_VLAN_INFO_RANGE_END)) {
+			last_vid_start = tunnel_vid;
+			last_tunid_start = tunnel_id;
+		}
+		vcheck_ret = filter_vlan_check(tunnel_vid, tunnel_flags);
+		if (vcheck_ret == -1)
+			break;
+		else if (vcheck_ret == 0)
+			continue;
+
+		if (tunnel_flags & BRIDGE_VLAN_INFO_RANGE_BEGIN)
+			continue;
+
+		if (filter_vlan) {
+			print_vlan_port(fp, ifindex);
+			jsonw_end_parray = 1;
+		}
+
+		if (jw_global) {
+			jsonw_start_object(jw_global);
+			jsonw_uint_field(jw_global, "vlan",
+					 last_vid_start);
+		} else {
+			fprintf(fp, "\t %hu", last_vid_start);
+		}
+		if (last_vid_start != tunnel_vid) {
+			if (jw_global)
+				jsonw_uint_field(jw_global, "vlanEnd",
+						 tunnel_vid);
+			else
+				fprintf(fp, "-%hu", tunnel_vid);
+		}
+
+		if (jw_global) {
+			jsonw_uint_field(jw_global, "tunid",
+					 last_tunid_start);
+		} else {
+			fprintf(fp, "\t %hu", last_tunid_start);
+		}
+		if (last_vid_start != tunnel_vid) {
+			if (jw_global)
+				jsonw_uint_field(jw_global, "tunidEnd",
+						 tunnel_id);
+			else
+				fprintf(fp, "-%hu", tunnel_id);
+		}
+
+		if (jw_global)
+			jsonw_end_object(jw_global);
+		else
+			fprintf(fp, "\n");
+	}
+
+	if (jsonw_end_parray) {
+		if (jw_global)
+			jsonw_end_array(jw_global);
+		else
+			fprintf(fp, "\n");
+	}
+}
+
+static int print_vlan_tunnel(const struct sockaddr_nl *who,
+			     struct nlmsghdr *n,
+			     void *arg)
+{
+	struct ifinfomsg *ifm = NLMSG_DATA(n);
+	struct rtattr *tb[IFLA_MAX+1];
+	int len = n->nlmsg_len;
+	FILE *fp = arg;
+
+	if (n->nlmsg_type != RTM_NEWLINK) {
+		fprintf(stderr, "Not RTM_NEWLINK: %08x %08x %08x\n",
+			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+		return 0;
+	}
+
+	len -= NLMSG_LENGTH(sizeof(*ifm));
+	if (len < 0) {
+		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
+		return -1;
+	}
+
+	if (ifm->ifi_family != AF_BRIDGE)
+		return 0;
+
+	if (filter_index && filter_index != ifm->ifi_index)
+		return 0;
+
+	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len);
+
+	/* if AF_SPEC isn't there, vlan table is not preset for this port */
+	if (!tb[IFLA_AF_SPEC]) {
+		if (!filter_vlan && !jw_global)
+			fprintf(fp, "%s\tNone\n",
+				ll_index_to_name(ifm->ifi_index));
+		return 0;
+	}
+
+	print_vlan_tunnel_info(fp, tb[IFLA_AF_SPEC], ifm->ifi_index);
+
+	fflush(fp);
+	return 0;
+}
+
 static int print_vlan(const struct sockaddr_nl *who,
 		      struct nlmsghdr *n,
 		      void *arg)
@@ -219,13 +458,7 @@ static int print_vlan(const struct sockaddr_nl *who,
 	}
 
 	print_vlan_info(fp, tb[IFLA_AF_SPEC], ifm->ifi_index);
-	if (!filter_vlan) {
-		if (jw_global)
-			jsonw_end_array(jw_global);
-		else
-			fprintf(fp, "\n");
 
-	}
 	fflush(fp);
 	return 0;
 }
@@ -315,6 +548,7 @@ static int print_vlan_stats(const struct sockaddr_nl *who,
 static int vlan_show(int argc, char **argv)
 {
 	char *filter_dev = NULL;
+	int ret = 0;
 
 	while (argc > 0) {
 		if (strcmp(*argv, "dev") == 0) {
@@ -356,10 +590,19 @@ static int vlan_show(int argc, char **argv)
 			}
 			jsonw_start_object(jw_global);
 		} else {
-			printf("port\tvlan ids\n");
+			if (show_vlan_tunnel_info)
+				printf("port\tvlan ids\ttunnel id\n");
+			else
+				printf("port\tvlan ids\n");
 		}
 
-		if (rtnl_dump_filter(&rth, print_vlan, stdout) < 0) {
+		if (show_vlan_tunnel_info)
+			ret = rtnl_dump_filter(&rth, print_vlan_tunnel,
+					       stdout);
+		else
+			ret = rtnl_dump_filter(&rth, print_vlan, stdout);
+
+		if (ret < 0) {
 			fprintf(stderr, "Dump ternminated\n");
 			exit(1);
 		}
@@ -408,9 +651,12 @@ void print_vlan_info(FILE *fp, struct rtattr *tb, int ifindex)
 	int rem = RTA_PAYLOAD(list);
 	__u16 last_vid_start = 0;
 	bool vlan_flags = false;
+	bool jsonw_end_parray = false;
 
-	if (!filter_vlan)
+	if (!filter_vlan) {
 		print_vlan_port(fp, ifindex);
+		jsonw_end_parray = true;
+	}
 
 	for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
 		struct bridge_vlan_info *vinfo;
@@ -423,14 +669,16 @@ void print_vlan_info(FILE *fp, struct rtattr *tb, int ifindex)
 
 		if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
 			last_vid_start = vinfo->vid;
-		vcheck_ret = filter_vlan_check(vinfo);
+		vcheck_ret = filter_vlan_check(vinfo->vid, vinfo->flags);
 		if (vcheck_ret == -1)
 			break;
 		else if (vcheck_ret == 0)
 			continue;
 
-		if (filter_vlan)
+		if (filter_vlan) {
 			print_vlan_port(fp, ifindex);
+			jsonw_end_parray = true;
+		}
 		if (jw_global) {
 			jsonw_start_object(jw_global);
 			jsonw_uint_field(jw_global, "vlan",
@@ -474,6 +722,14 @@ void print_vlan_info(FILE *fp, struct rtattr *tb, int ifindex)
 		else
 			fprintf(fp, "\n");
 	}
+
+	if (jsonw_end_parray) {
+		if (jw_global)
+			jsonw_end_array(jw_global);
+		else
+			fprintf(fp, "\n");
+
+	}
 }
 
 int do_vlan(int argc, char **argv)
@@ -489,6 +745,10 @@ int do_vlan(int argc, char **argv)
 		    matches(*argv, "lst") == 0 ||
 		    matches(*argv, "list") == 0)
 			return vlan_show(argc-1, argv+1);
+		if (matches(*argv, "tunnelshow") == 0) {
+			show_vlan_tunnel_info = 1;
+			return vlan_show(argc-1, argv+1);
+		}
 		if (matches(*argv, "help") == 0)
 			usage();
 	} else {
diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
index d3c5b1e..d6baa81 100644
--- a/man/man8/bridge.8
+++ b/man/man8/bridge.8
@@ -105,11 +105,13 @@ bridge \- show / manipulate bridge addresses and devices
 .IR DEV
 .B vid
 .IR VID " [ "
+.BR tunnel_info
+.IR TUNNEL_ID " ] [ "
 .BR pvid " ] [ " untagged " ] [ "
 .BR self " ] [ " master " ] "
 
 .ti -8
-.BR "bridge vlan" " [ " show " ] [ "
+.BR "bridge vlan" " [ " show " | " tunnelshow " ] [ "
 .B dev
 .IR DEV " ]"
 
@@ -562,6 +564,12 @@ the interface with which this vlan is associated.
 the VLAN ID that identifies the vlan.
 
 .TP
+.BI tunnel_info " TUNNEL_ID"
+the TUNNEL ID that maps to this vlan. The tunnel id is set in dst_metadata for
+every packet that belongs to this vlan (applicable to bridge ports with vlan_tunnel
+flag set).
+
+.TP
 .BI pvid
 the vlan specified is to be considered a PVID at ingress.
 Any untagged frames will be assigned to this VLAN.
@@ -598,6 +606,10 @@ With the
 .B -statistics
 option, the command displays per-vlan traffic statistics.
 
+.SS bridge vlan tunnelshow - list vlan tunnel mapping.
+
+This command displays the current vlan tunnel info mapping.
+
 .SH bridge monitor - state monitoring
 
 The
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping
  2017-10-28  5:13 [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Roopa Prabhu
  2017-10-28  5:13 ` [PATCH iproute2 net-next v2 1/2] iplink: bridge: support bridge port vlan_tunnel attribute Roopa Prabhu
  2017-10-28  5:13 ` [PATCH iproute2 net-next v2 2/2] bridge: vlan: support for per vlan tunnel info Roopa Prabhu
@ 2017-10-31 17:06 ` Stephen Hemminger
  2 siblings, 0 replies; 4+ messages in thread
From: Stephen Hemminger @ 2017-10-31 17:06 UTC (permalink / raw)
  To: Roopa Prabhu; +Cc: netdev, nikolay

On Fri, 27 Oct 2017 22:13:48 -0700
Roopa Prabhu <roopa@cumulusnetworks.com> wrote:

> From: Roopa Prabhu <roopa@cumulusnetworks.com>
> 
> This series adds the required options to iplink and bridge commands
> to enable per vlan tunnel info on a bridge port provided by
> netlink attributes IFLA_BRPORT_VLAN_TUNNEL (flag) and
> IFLA_BRIDGE_VLAN_TUNNEL_INFO
> 
> enable vlan-tunnel mapping on a bridge port:
> $ip link set dev vxlan0 type bridge_slave vlan_tunnel on
> $ip link set dev vxlan0 type bridge_slave vlan_tunnel off
> 
> or
> 
> $bridge link set dev vxlan0 vlan_tunnel on
> $bridge link set dev vxlan0 vlan_tunnel off
> 
> add vlan tunnel mapping (expects vlans to have been already
> configured on the port):
> $bridge vlan add dev vxlan0 vid 2000 tunnel_info id 2000
> $bridge vlan add dev vxlan0 vid 1000-1001 tunnel_info id 2000-2001
> 
> $bridge vlan tunnelshow
> port    vlan ids        tunnel id
> vxlan0   1000-1001       1000-1001
>          2000            2000
> 
> $bridge  -j vlan tunnelshow
> {
>     "dummy0": [],
>     "dummy1": [],
>     "bridge": [],
>     "vxlan0": [{
>             "vlan": 1000,
>             "vlanEnd": 1001,
>             "tunid": 1000,
>             "tunidEnd": 1001
>         },{
>             "vlan": 2000,
>             "tunid": 2000
>         }
>     ]
> }
> 
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
> 
> Roopa Prabhu (2):
>   iplink: bridge: support bridge port vlan_tunnel attribute
>   bridge: vlan: support for per vlan tunnel info
> 
> v2 - rebase to latest net-next
> 
>  bridge/link.c            |  12 ++
>  bridge/vlan.c            | 305 ++++++++++++++++++++++++++++++++++++++++++-----
>  ip/iplink_bridge_slave.c |   9 ++
>  man/man8/bridge.8        |  12 +-
>  man/man8/ip-link.8.in    |   5 +
>  5 files changed, 315 insertions(+), 28 deletions(-)
> 

Applied to net-next

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-10-31 17:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-28  5:13 [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Roopa Prabhu
2017-10-28  5:13 ` [PATCH iproute2 net-next v2 1/2] iplink: bridge: support bridge port vlan_tunnel attribute Roopa Prabhu
2017-10-28  5:13 ` [PATCH iproute2 net-next v2 2/2] bridge: vlan: support for per vlan tunnel info Roopa Prabhu
2017-10-31 17:06 ` [PATCH iproute2 net-next v2 0/2] bridge: support for vlan to tunnel mapping Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).