[PATCH net-next v4 4/4] ip link: proto_down config and display.

2015-07-08 Thread anuradhak
From: Anuradha Karuppiah anurad...@cumulusnetworks.com

This patch adds support to set and display the IF_PROTOF_DOWN proto_flag.
One example user space application setting this flag is a multi-chassis
LAG application to handle split-brain situation on peer-link failure.

Example:
root@net-next:~# ip link set eth1 protodown on
root@net-next:~# ip link show eth1
4: eth1: NO-CARRIER,BROADCAST,MULTICAST,UP mtu 1500 qdisc pfifo_fast state 
DOWN mode DEFAULT group default qlen 1000 proto_flags DOWN
link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
root@net-next:~# ip link set eth1 protodown off
root@net-next:~# ip link show eth1
4: eth1: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state UP 
mode DEFAULT group default qlen 1000
link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
root@net-next:~#

Signed-off-by: Anuradha Karuppiah anurad...@cumulusnetworks.com
Signed-off-by: Andy Gospodarek go...@cumulusnetworks.com
Signed-off-by: Roopa Prabhu ro...@cumulusnetworks.com
Signed-off-by: Wilson Kok w...@cumulusnetworks.com
---
 include/linux/if.h  |6 ++
 include/linux/if_link.h |   12 
 ip/ipaddress.c  |   27 +++
 ip/iplink.c |   18 ++
 man/man8/ip-link.8.in   |8 
 5 files changed, 71 insertions(+)

diff --git a/include/linux/if.h b/include/linux/if.h
index a55a9e0..97f53d8 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -156,6 +156,12 @@ enum {
IF_LINK_MODE_DORMANT,   /* limit upward transition to dormant */
 };
 
+/* proto_flags - port state information can be passed to the switch driver and
+ * used to determine the phys state of the switch port */
+enum {
+   IF_PROTOF_DOWN  = 10  /* set switch port phys state down */
+};
+
 /*
  * 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 3d0d613..1d07f3f 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -148,6 +148,7 @@ enum {
IFLA_PHYS_SWITCH_ID,
IFLA_LINK_NETNSID,
IFLA_PHYS_PORT_NAME,
+   IFLA_PROTO_FLAGS_INFO,
__IFLA_MAX
 };
 
@@ -620,4 +621,15 @@ enum {
 
 #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
 
+
+/* proto_flags section */
+enum {
+   IFLA_PROTO_FLAGS_UNSPEC,
+   IFLA_PROTO_FLAGS_VAL,
+   IFLA_PROTO_FLAGS_CHANGE,
+   __IFLA_PROTO_FLAGS_MAX,
+};
+
+#define IFLA_PROTO_FLAGS_MAX (__IFLA_PROTO_FLAGS_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 340e1c9..4078023 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -556,6 +556,30 @@ static void print_link_stats(FILE *fp, struct nlmsghdr *n)
fprintf(fp, %s, _SL_);
 }
 
+static void print_proto_flags(FILE *fp, struct rtattr *tb)
+{
+   struct rtattr *proto_info[IFLA_INFO_MAX+1];
+   uint32_t proto_flags;
+
+   parse_rtattr_nested(proto_info, IFLA_PROTO_FLAGS_MAX, tb);
+
+   if (proto_info[IFLA_PROTO_FLAGS_VAL]) {
+   proto_flags = *(uint32_t *)RTA_DATA(
+   proto_info[IFLA_PROTO_FLAGS_VAL]);
+   if (proto_flags) {
+   fprintf(fp,  proto_flags );
+#define _PROTOF(f) if (proto_flags  IF_PROTOF_##f) { \
+ proto_flags = ~IF_PROTOF_##f ; \
+ fprintf(fp, #f %s, proto_flags ? , : ); }
+   _PROTOF(DOWN);
+#undef _PROTOF
+   if (proto_flags)
+   fprintf(fp, %x, proto_flags);
+   fprintf(fp,  );
+   }
+   }
+}
+
 int print_linkinfo(const struct sockaddr_nl *who,
   struct nlmsghdr *n, void *arg)
 {
@@ -669,6 +693,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (filter.showqueue)
print_queuelen(fp, tb);
 
+   if (tb[IFLA_PROTO_FLAGS_INFO])
+   print_proto_flags(fp, tb[IFLA_PROTO_FLAGS_INFO]);
+
if (!filter.family || filter.family == AF_PACKET || show_details) {
SPRINT_BUF(b1);
fprintf(fp, %s, _SL_);
diff --git a/ip/iplink.c b/ip/iplink.c
index a4a4980..29cb8ce 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -611,6 +611,24 @@ int iplink_parse(int argc, char **argv, struct iplink_req 
*req,
invarg(Invalid \link-netnsid\ value\n, 
*argv);
addattr32(req-n, sizeof(*req), IFLA_LINK_NETNSID,
  link_netnsid);
+   } else if (strcmp(*argv, protodown) == 0) {
+   struct rtattr *proto_info;
+   unsigned int proto_flags = 0;
+
+   NEXT_ARG();
+   if (strcmp(*argv, on) == 0)
+   proto_flags |= IF_PROTOF_DOWN;
+   else if (strcmp(*argv, off) != 0)
+

Re: [PATCH net-next v4 4/4] ip link: proto_down config and display.

2015-07-08 Thread Anuradha Karuppiah
On Wed, Jul 8, 2015 at 6:01 PM, Stephen Hemminger
step...@networkplumber.org wrote:
 On Wed,  8 Jul 2015 14:04:25 -0700
 anurad...@cumulusnetworks.com wrote:

 From: Anuradha Karuppiah anurad...@cumulusnetworks.com

 This patch adds support to set and display the IF_PROTOF_DOWN proto_flag.
 One example user space application setting this flag is a multi-chassis
 LAG application to handle split-brain situation on peer-link failure.

 Example:
 root@net-next:~# ip link set eth1 protodown on
 root@net-next:~# ip link show eth1
 4: eth1: NO-CARRIER,BROADCAST,MULTICAST,UP mtu 1500 qdisc pfifo_fast state 
 DOWN mode DEFAULT group default qlen 1000 proto_flags DOWN
 link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
 root@net-next:~# ip link set eth1 protodown off
 root@net-next:~# ip link show eth1
 4: eth1: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state 
 UP mode DEFAULT group default qlen 1000
 link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
 root@net-next:~#

 Signed-off-by: Anuradha Karuppiah anurad...@cumulusnetworks.com
 Signed-off-by: Andy Gospodarek go...@cumulusnetworks.com
 Signed-off-by: Roopa Prabhu ro...@cumulusnetworks.com
 Signed-off-by: Wilson Kok w...@cumulusnetworks.com
 ---
  include/linux/if.h  |6 ++
  include/linux/if_link.h |   12 
  ip/ipaddress.c  |   27 +++
  ip/iplink.c |   18 ++
  man/man8/ip-link.8.in   |8 
  5 files changed, 71 insertions(+)

 diff --git a/include/linux/if.h b/include/linux/if.h
 index a55a9e0..97f53d8 100644
 --- a/include/linux/if.h
 +++ b/include/linux/if.h
 @@ -156,6 +156,12 @@ enum {
   IF_LINK_MODE_DORMANT,   /* limit upward transition to dormant */
  };

 +/* proto_flags - port state information can be passed to the switch driver 
 and
 + * used to determine the phys state of the switch port */
 +enum {
 + IF_PROTOF_DOWN  = 10  /* set switch port phys state down */
 +};
 +
  /*
   *   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 3d0d613..1d07f3f 100644
 --- a/include/linux/if_link.h
 +++ b/include/linux/if_link.h
 @@ -148,6 +148,7 @@ enum {
   IFLA_PHYS_SWITCH_ID,
   IFLA_LINK_NETNSID,
   IFLA_PHYS_PORT_NAME,
 + IFLA_PROTO_FLAGS_INFO,
   __IFLA_MAX
  };

 @@ -620,4 +621,15 @@ enum {

  #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)

 +
 +/* proto_flags section */
 +enum {
 + IFLA_PROTO_FLAGS_UNSPEC,
 + IFLA_PROTO_FLAGS_VAL,
 + IFLA_PROTO_FLAGS_CHANGE,
 + __IFLA_PROTO_FLAGS_MAX,
 +};
 +
 +#define IFLA_PROTO_FLAGS_MAX (__IFLA_PROTO_FLAGS_MAX - 1)
 +
  #endif /* _LINUX_IF_LINK_H */
 diff --git a/ip/ipaddress.c b/ip/ipaddress.c
 index 340e1c9..4078023 100644
 --- a/ip/ipaddress.c
 +++ b/ip/ipaddress.c
 @@ -556,6 +556,30 @@ static void print_link_stats(FILE *fp, struct nlmsghdr 
 *n)
   fprintf(fp, %s, _SL_);
  }

 +static void print_proto_flags(FILE *fp, struct rtattr *tb)
 +{
 + struct rtattr *proto_info[IFLA_INFO_MAX+1];
 + uint32_t proto_flags;
 +
 + parse_rtattr_nested(proto_info, IFLA_PROTO_FLAGS_MAX, tb);
 +
 + if (proto_info[IFLA_PROTO_FLAGS_VAL]) {
 + proto_flags = *(uint32_t *)RTA_DATA(
 + proto_info[IFLA_PROTO_FLAGS_VAL]);
 + if (proto_flags) {
 + fprintf(fp,  proto_flags );
 +#define _PROTOF(f) if (proto_flags  IF_PROTOF_##f) { \
 +   proto_flags = ~IF_PROTOF_##f ; \
 +   fprintf(fp, #f %s, proto_flags ? , : ); }
 + _PROTOF(DOWN);
 +#undef _PROTOF
 + if (proto_flags)
 + fprintf(fp, %x, proto_flags);
 + fprintf(fp,  );
 + }
 + }
 +}
 +
  int print_linkinfo(const struct sockaddr_nl *who,
  struct nlmsghdr *n, void *arg)
  {
 @@ -669,6 +693,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
   if (filter.showqueue)
   print_queuelen(fp, tb);

 + if (tb[IFLA_PROTO_FLAGS_INFO])
 + print_proto_flags(fp, tb[IFLA_PROTO_FLAGS_INFO]);
 +
   if (!filter.family || filter.family == AF_PACKET || show_details) {
   SPRINT_BUF(b1);
   fprintf(fp, %s, _SL_);
 diff --git a/ip/iplink.c b/ip/iplink.c
 index a4a4980..29cb8ce 100644
 --- a/ip/iplink.c
 +++ b/ip/iplink.c
 @@ -611,6 +611,24 @@ int iplink_parse(int argc, char **argv, struct 
 iplink_req *req,
   invarg(Invalid \link-netnsid\ value\n, 
 *argv);
   addattr32(req-n, sizeof(*req), IFLA_LINK_NETNSID,
 link_netnsid);
 + } else if (strcmp(*argv, protodown) == 0) {
 + struct rtattr *proto_info;
 + unsigned int proto_flags = 0;
 +
 + NEXT_ARG();
 +

Re: [PATCH net-next v4 4/4] ip link: proto_down config and display.

2015-07-08 Thread Stephen Hemminger
On Wed,  8 Jul 2015 14:04:25 -0700
anurad...@cumulusnetworks.com wrote:

 From: Anuradha Karuppiah anurad...@cumulusnetworks.com
 
 This patch adds support to set and display the IF_PROTOF_DOWN proto_flag.
 One example user space application setting this flag is a multi-chassis
 LAG application to handle split-brain situation on peer-link failure.
 
 Example:
 root@net-next:~# ip link set eth1 protodown on
 root@net-next:~# ip link show eth1
 4: eth1: NO-CARRIER,BROADCAST,MULTICAST,UP mtu 1500 qdisc pfifo_fast state 
 DOWN mode DEFAULT group default qlen 1000 proto_flags DOWN
 link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
 root@net-next:~# ip link set eth1 protodown off
 root@net-next:~# ip link show eth1
 4: eth1: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc pfifo_fast state UP 
 mode DEFAULT group default qlen 1000
 link/ether 52:54:00:12:35:01 brd ff:ff:ff:ff:ff:ff
 root@net-next:~#
 
 Signed-off-by: Anuradha Karuppiah anurad...@cumulusnetworks.com
 Signed-off-by: Andy Gospodarek go...@cumulusnetworks.com
 Signed-off-by: Roopa Prabhu ro...@cumulusnetworks.com
 Signed-off-by: Wilson Kok w...@cumulusnetworks.com
 ---
  include/linux/if.h  |6 ++
  include/linux/if_link.h |   12 
  ip/ipaddress.c  |   27 +++
  ip/iplink.c |   18 ++
  man/man8/ip-link.8.in   |8 
  5 files changed, 71 insertions(+)
 
 diff --git a/include/linux/if.h b/include/linux/if.h
 index a55a9e0..97f53d8 100644
 --- a/include/linux/if.h
 +++ b/include/linux/if.h
 @@ -156,6 +156,12 @@ enum {
   IF_LINK_MODE_DORMANT,   /* limit upward transition to dormant */
  };
  
 +/* proto_flags - port state information can be passed to the switch driver 
 and
 + * used to determine the phys state of the switch port */
 +enum {
 + IF_PROTOF_DOWN  = 10  /* set switch port phys state down */
 +};
 +
  /*
   *   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 3d0d613..1d07f3f 100644
 --- a/include/linux/if_link.h
 +++ b/include/linux/if_link.h
 @@ -148,6 +148,7 @@ enum {
   IFLA_PHYS_SWITCH_ID,
   IFLA_LINK_NETNSID,
   IFLA_PHYS_PORT_NAME,
 + IFLA_PROTO_FLAGS_INFO,
   __IFLA_MAX
  };
  
 @@ -620,4 +621,15 @@ enum {
  
  #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
  
 +
 +/* proto_flags section */
 +enum {
 + IFLA_PROTO_FLAGS_UNSPEC,
 + IFLA_PROTO_FLAGS_VAL,
 + IFLA_PROTO_FLAGS_CHANGE,
 + __IFLA_PROTO_FLAGS_MAX,
 +};
 +
 +#define IFLA_PROTO_FLAGS_MAX (__IFLA_PROTO_FLAGS_MAX - 1)
 +
  #endif /* _LINUX_IF_LINK_H */
 diff --git a/ip/ipaddress.c b/ip/ipaddress.c
 index 340e1c9..4078023 100644
 --- a/ip/ipaddress.c
 +++ b/ip/ipaddress.c
 @@ -556,6 +556,30 @@ static void print_link_stats(FILE *fp, struct nlmsghdr 
 *n)
   fprintf(fp, %s, _SL_);
  }
  
 +static void print_proto_flags(FILE *fp, struct rtattr *tb)
 +{
 + struct rtattr *proto_info[IFLA_INFO_MAX+1];
 + uint32_t proto_flags;
 +
 + parse_rtattr_nested(proto_info, IFLA_PROTO_FLAGS_MAX, tb);
 +
 + if (proto_info[IFLA_PROTO_FLAGS_VAL]) {
 + proto_flags = *(uint32_t *)RTA_DATA(
 + proto_info[IFLA_PROTO_FLAGS_VAL]);
 + if (proto_flags) {
 + fprintf(fp,  proto_flags );
 +#define _PROTOF(f) if (proto_flags  IF_PROTOF_##f) { \
 +   proto_flags = ~IF_PROTOF_##f ; \
 +   fprintf(fp, #f %s, proto_flags ? , : ); }
 + _PROTOF(DOWN);
 +#undef _PROTOF
 + if (proto_flags)
 + fprintf(fp, %x, proto_flags);
 + fprintf(fp,  );
 + }
 + }
 +}
 +
  int print_linkinfo(const struct sockaddr_nl *who,
  struct nlmsghdr *n, void *arg)
  {
 @@ -669,6 +693,9 @@ int print_linkinfo(const struct sockaddr_nl *who,
   if (filter.showqueue)
   print_queuelen(fp, tb);
  
 + if (tb[IFLA_PROTO_FLAGS_INFO])
 + print_proto_flags(fp, tb[IFLA_PROTO_FLAGS_INFO]);
 +
   if (!filter.family || filter.family == AF_PACKET || show_details) {
   SPRINT_BUF(b1);
   fprintf(fp, %s, _SL_);
 diff --git a/ip/iplink.c b/ip/iplink.c
 index a4a4980..29cb8ce 100644
 --- a/ip/iplink.c
 +++ b/ip/iplink.c
 @@ -611,6 +611,24 @@ int iplink_parse(int argc, char **argv, struct 
 iplink_req *req,
   invarg(Invalid \link-netnsid\ value\n, 
 *argv);
   addattr32(req-n, sizeof(*req), IFLA_LINK_NETNSID,
 link_netnsid);
 + } else if (strcmp(*argv, protodown) == 0) {
 + struct rtattr *proto_info;
 + unsigned int proto_flags = 0;
 +
 + NEXT_ARG();
 + if (strcmp(*argv, on) == 0)
 +