[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1426864318-25132-4-git-send-email-anuradhak@cumulusnetworks.com>
Date: Fri, 20 Mar 2015 08:11:58 -0700
From: anuradhak@...ulusnetworks.com
To: davem@...emloft.net
Cc: netdev@...r.kernel.org, roopa@...ulusnetworks.com,
gospo@...ulusnetworks.com, wkok@...ulusnetworks.com,
anuradhak@...ulusnetworks.com
Subject: [PATCH iproute2 3/3] ip link: Config and display device proto_down bits.
From: Anuradha Karuppiah <anuradhak@...ulusnetworks.com>
This patch adds support to set the proto_down bits on netdevices. One
example user space application setting this flag is a STP userspace
daemon to implement BPDU guard functionality.
Example:
root@...-next:~# ip link set eth0 protodown stp on
root@...-next:~# ip link show eth0
3: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP,PROTO_DOWN> mtu 1500 qdisc pfifo_fas
t state DOWN mode DEFAULT group default protodown <STP> qlen 1000
link/ether 00:01:00:00:06:ee brd ff:ff:ff:ff:ff:ff
root@...-next:~# ip link set eth0 protodown stp off
root@...-next:~# ip link show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mo
de DEFAULT group default qlen 1000
link/ether 00:01:00:00:06:ee brd ff:ff:ff:ff:ff:ff
root@...-next:~#
Signed-off-by: Anuradha Karuppiah <anuradhak@...ulusnetworks.com>
Signed-off-by: Andy Gospodarek <gospo@...ulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@...ulusnetworks.com>
Signed-off-by: Wilson Kok <wkok@...ulusnetworks.com>
---
include/linux/if.h | 29 +++++++++++++++++++++++++++-
include/linux/if_link.h | 9 +++++++++
ip/ipaddress.c | 24 ++++++++++++++++++++++++
ip/iplink.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++
man/man8/ip-link.8.in | 11 +++++++++++
5 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/include/linux/if.h b/include/linux/if.h
index a55a9e0..4aabba6 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -66,6 +66,8 @@
* @IFF_LOWER_UP: driver signals L1 up. Volatile.
* @IFF_DORMANT: driver signals dormant. Volatile.
* @IFF_ECHO: echo sent packets. Volatile.
+ * @IFF_PROTO_DOWN: protocol is down on the interface. Userspace can toggle
+ * this by toggling the net_device proto_down bits. Volatile.
*/
enum net_device_flags {
IFF_UP = 1<<0, /* sysfs */
@@ -87,6 +89,7 @@ enum net_device_flags {
IFF_LOWER_UP = 1<<16, /* __volatile__ */
IFF_DORMANT = 1<<17, /* __volatile__ */
IFF_ECHO = 1<<18, /* __volatile__ */
+ IFF_PROTO_DOWN = 1<<19, /* __volatile__ */
};
#define IFF_UP IFF_UP
@@ -108,9 +111,11 @@ enum net_device_flags {
#define IFF_LOWER_UP IFF_LOWER_UP
#define IFF_DORMANT IFF_DORMANT
#define IFF_ECHO IFF_ECHO
+#define IFF_PROTO_DOWN IFF_PROTO_DOWN
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
- IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
+ IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT|\
+ IFF_PROTO_DOWN)
#define IF_GET_IFACE 0x0001 /* for querying only */
#define IF_GET_PROTO 0x0002
@@ -156,6 +161,28 @@ enum {
IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
};
+/**
+ * enum net_device_proto_down - &struct net_device proto_down
+ *
+ * These are the &struct net_device proto_down bits and define a list of
+ * protocols that could hold the device in a IFF_PROTO_DOWN state. Setting of
+ * these bits is triggered by userspace. Userspace can query and set these
+ * flags using userspace utilities. There is also a sysfs entry available
+ * which can only be queried. The sysfs entries are available via
+ * /sys/class/net/<dev>/proto_down
+ *
+ *
+ * @IF_LINK_PROTO_DOWN_MLAG: proto_down by a multi-chassis LAG application.
+ * @IF_LINK_PROTO_DOWN_STP: proto_down by an STP application.
+ */
+enum net_device_proto_down {
+ IF_LINK_PROTO_DOWN_MLAG = 1<<0,
+ IF_LINK_PROTO_DOWN_STP = 1<<1,
+};
+
+#define IF_LINK_PROTO_DOWN_MLAG IF_LINK_PROTO_DOWN_MLAG
+#define IF_LINK_PROTO_DOWN_STP IF_LINK_PROTO_DOWN_STP
+
/*
* Device mapping structure. I'd just gone off and designed a
* beautiful scheme using only loadable modules with arguments
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 3450c3f..e9bfb73 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -80,6 +80,13 @@ struct rtnl_link_ifmap {
__u8 port;
};
+/* link protodown */
+struct rtnl_link_protodown {
+ __u32 proto_down; /* Bitmap of protocols that want
+ * to hold the device down */
+ __u32 proto_down_change; /* Change mask for proto_down */
+};
+
/*
* IFLA_AF_SPEC
* Contains nested attributes for address family specific attributes.
@@ -147,6 +154,8 @@ enum {
IFLA_CARRIER_CHANGES,
IFLA_PHYS_SWITCH_ID,
IFLA_LINK_NETNSID,
+ IFLA_LINKPROTODOWN, /* Bitmap of protocols that want to
+ * hold the device down */
__IFLA_MAX
};
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 99a6ab5..f750d0e 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -119,6 +119,7 @@ static void print_link_flags(FILE *fp, unsigned flags, unsigned mdown)
_PF(LOWER_UP);
_PF(DORMANT);
_PF(ECHO);
+ _PF(PROTO_DOWN);
#undef _PF
if (flags)
fprintf(fp, "%x", flags);
@@ -203,6 +204,26 @@ static char *parse_link_kind(struct rtattr *tb)
return "";
}
+static void print_linkprotodown(FILE *fp,
+ struct rtnl_link_protodown *link_proto_down)
+{
+ unsigned int proto_down = link_proto_down->proto_down;
+
+ if (!proto_down)
+ return;
+
+ fprintf(fp, "protodown <");
+#define _PDNF(f) if (proto_down&IF_LINK_PROTO_DOWN_##f) { \
+ proto_down &= ~IF_LINK_PROTO_DOWN_##f ; \
+ fprintf(fp, #f "%s", proto_down ? "," : ""); }
+ _PDNF(MLAG);
+ _PDNF(STP);
+#undef _PDNF
+ if (proto_down)
+ fprintf(fp, "%x", proto_down);
+ fprintf(fp, "> ");
+}
+
static void print_linktype(FILE *fp, struct rtattr *tb)
{
struct rtattr *linkinfo[IFLA_INFO_MAX+1];
@@ -657,6 +678,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
fprintf(fp, "group %s ", rtnl_group_n2a(group, b1, sizeof(b1)));
}
+ if (do_link && tb[IFLA_LINKPROTODOWN])
+ print_linkprotodown(fp, RTA_DATA(tb[IFLA_LINKPROTODOWN]));
+
if (filter.showqueue)
print_queuelen(fp, tb);
diff --git a/ip/iplink.c b/ip/iplink.c
index 5893ee4..f4a52c2 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -72,6 +72,7 @@ void iplink_usage(void)
fprintf(stderr, " [ mtu MTU ]\n");
fprintf(stderr, " [ netns PID ]\n");
fprintf(stderr, " [ netns NAME ]\n");
+ fprintf(stderr, " [ protodown PROTODOWNTYPE { on | off } ]\n");
fprintf(stderr, " [ link-netnsid ID ]\n");
fprintf(stderr, " [ alias NAME ]\n");
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
@@ -94,6 +95,7 @@ void iplink_usage(void)
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
fprintf(stderr, " bond_slave | ipvlan }\n");
}
+ fprintf(stderr, "PROTODOWNTYPE := { mlag | stp }\n");
exit(-1);
}
@@ -175,6 +177,30 @@ static int get_addr_gen_mode(const char *mode)
return -1;
}
+static int get_link_proto_down_type(const char *type)
+{
+ if (matches(type, "mlag") == 0)
+ return IF_LINK_PROTO_DOWN_MLAG;
+ if (matches(type, "stp") == 0)
+ return IF_LINK_PROTO_DOWN_STP;
+ return 0;
+}
+
+static int fill_link_proto_down_value(
+ struct rtnl_link_protodown *link_proto_down, char *set_type)
+{
+ if (matches(set_type, "on") == 0) {
+ link_proto_down->proto_down =
+ link_proto_down->proto_down_change;
+ return 0;
+ }
+ if (matches(set_type, "off") == 0) {
+ link_proto_down->proto_down = 0;
+ return 0;
+ }
+ return -1;
+}
+
#if IPLINK_IOCTL_COMPAT
static int have_rtnl_newlink = -1;
@@ -554,6 +580,28 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
if (mode < 0)
invarg("Invalid link mode\n", *argv);
addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
+ } else if (strcmp(*argv, "protodown") == 0) {
+ struct rtnl_link_protodown link_proto_down;
+ char proto_down_str[64];
+
+ NEXT_ARG();
+ link_proto_down.proto_down_change =
+ get_link_proto_down_type(*argv);
+ if (!link_proto_down.proto_down_change)
+ invarg("Invalid \"protodown\" value\n", *argv);
+ sprintf(proto_down_str, "protodown %s", *argv);
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ if (fill_link_proto_down_value(
+ &link_proto_down, *argv) < 0){
+ return on_off(proto_down_str, *argv);
+ }
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_LINKPROTODOWN, &link_proto_down,
+ sizeof(link_proto_down));
+ } else {
+ return on_off(proto_down_str, *argv);
+ }
} else if (strcmp(*argv, "state") == 0) {
int state;
NEXT_ARG();
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 9bbf2d3..3745e3a 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -113,6 +113,9 @@ ip-link \- network device configuration
.B netns
.IR NETNSNAME " |"
.br
+.BI "protodown " PROTODOWNTYPE
+.RB "{ " on " | " off " } |"
+.br
.B alias
.IR NAME " |"
.br
@@ -687,6 +690,14 @@ tool can be used. But it allows to change network namespace only for physical de
.IR PID .
.TP
+.BI "protodown " PROTODOWNTYPE " on|off"
+protodown the device for a specific protocol type
+
+.IR PROTODOWNTYPE " := [ "
+.BR mlag " | "
+.BR stp " ]"
+
+.TP
.BI alias " NAME"
give the device a symbolic name for easy reference.
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists