netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2 1/3] ip: add support of netconf messages
@ 2012-12-12  9:51 Nicolas Dichtel
  2012-12-12  9:51 ` [PATCH iproute2 2/3] ip: add support of 'ip link type ip6tnl' Nicolas Dichtel
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Nicolas Dichtel @ 2012-12-12  9:51 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

Example of the output:
$ ip monitor netconf&
[1] 24901
$ echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
ipv6 dev lo forwarding off
ipv6 dev eth0 forwarding off
ipv6 all forwarding off
$ echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
ipv4 dev eth0 forwarding on

$ ip -6 netconf
ipv6 all forwarding on mc_forwarding 0
$ ip netconf show dev eth0
ipv4 dev eth0 forwarding on rp_filter off mc_forwarding 1

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/libnetlink.h      |   1 +
 include/linux/netconf.h   |  24 ++++++
 include/linux/rtnetlink.h |   9 +++
 ip/Makefile               |   2 +-
 ip/ip.c                   |   1 +
 ip/ip_common.h            |   3 +
 ip/ipmonitor.c            |  16 ++++
 ip/ipnetconf.c            | 183 ++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 238 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/netconf.h
 create mode 100644 ip/ipnetconf.c

diff --git a/include/libnetlink.h b/include/libnetlink.h
index 81649af..4a6b878 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -8,6 +8,7 @@
 #include <linux/if_link.h>
 #include <linux/if_addr.h>
 #include <linux/neighbour.h>
+#include <linux/netconf.h>
 
 struct rtnl_handle
 {
diff --git a/include/linux/netconf.h b/include/linux/netconf.h
new file mode 100644
index 0000000..64804a7
--- /dev/null
+++ b/include/linux/netconf.h
@@ -0,0 +1,24 @@
+#ifndef _UAPI_LINUX_NETCONF_H_
+#define _UAPI_LINUX_NETCONF_H_
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct netconfmsg {
+	__u8	ncm_family;
+};
+
+enum {
+	NETCONFA_UNSPEC,
+	NETCONFA_IFINDEX,
+	NETCONFA_FORWARDING,
+	NETCONFA_RP_FILTER,
+	NETCONFA_MC_FORWARDING,
+	__NETCONFA_MAX
+};
+#define NETCONFA_MAX	(__NETCONFA_MAX - 1)
+
+#define NETCONFA_IFINDEX_ALL		-1
+#define NETCONFA_IFINDEX_DEFAULT	-2
+
+#endif /* _UAPI_LINUX_NETCONF_H_ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 0e3e0c1..a30530e 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -120,6 +120,11 @@ enum {
 	RTM_SETDCB,
 #define RTM_SETDCB RTM_SETDCB
 
+	RTM_NEWNETCONF = 80,
+#define RTM_NEWNETCONF RTM_NEWNETCONF
+	RTM_GETNETCONF = 82,
+#define RTM_GETNETCONF RTM_GETNETCONF
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -585,6 +590,10 @@ enum rtnetlink_groups {
 #define RTNLGRP_PHONET_ROUTE	RTNLGRP_PHONET_ROUTE
 	RTNLGRP_DCB,
 #define RTNLGRP_DCB		RTNLGRP_DCB
+	RTNLGRP_IPV4_NETCONF,
+#define RTNLGRP_IPV4_NETCONF	RTNLGRP_IPV4_NETCONF
+	RTNLGRP_IPV6_NETCONF,
+#define RTNLGRP_IPV6_NETCONF	RTNLGRP_IPV6_NETCONF
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
diff --git a/ip/Makefile b/ip/Makefile
index 1676f0f..4bc33d7 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -4,7 +4,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
     iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
-    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o
+    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/ip.c b/ip/ip.c
index e0f7e60..632d271 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -85,6 +85,7 @@ static const struct cmd {
 	{ "mroute",	do_multiroute },
 	{ "mrule",	do_multirule },
 	{ "netns",	do_netns },
+	{ "netconf",	do_ipnetconf },
 	{ "help",	do_help },
 	{ 0 }
 };
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 2fd66b7..a394669 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -25,6 +25,8 @@ extern int print_prefix(const struct sockaddr_nl *who,
 			struct nlmsghdr *n, void *arg);
 extern int print_rule(const struct sockaddr_nl *who,
 		      struct nlmsghdr *n, void *arg);
+extern int print_netconf(const struct sockaddr_nl *who,
+			 struct nlmsghdr *n, void *arg);
 extern int do_ipaddr(int argc, char **argv);
 extern int do_ipaddrlabel(int argc, char **argv);
 extern int do_iproute(int argc, char **argv);
@@ -43,6 +45,7 @@ extern int do_netns(int argc, char **argv);
 extern int do_xfrm(int argc, char **argv);
 extern int do_ipl2tp(int argc, char **argv);
 extern int do_tcp_metrics(int argc, char **argv);
+extern int do_ipnetconf(int argc, char **argv);
 
 static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
 {
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 4b1d469..d87e58f 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -85,6 +85,12 @@ int accept_msg(const struct sockaddr_nl *who,
 		print_rule(who, n, arg);
 		return 0;
 	}
+	if (n->nlmsg_type == RTM_NEWNETCONF) {
+		if (prefix_banner)
+			fprintf(fp, "[NETCONF]");
+		print_netconf(who, n, arg);
+		return 0;
+	}
 	if (n->nlmsg_type == 15) {
 		char *tstr;
 		time_t secs = ((__u32*)NLMSG_DATA(n))[0];
@@ -118,6 +124,7 @@ int do_ipmonitor(int argc, char **argv)
 	int lroute=0;
 	int lprefix=0;
 	int lneigh=0;
+	int lnetconf=0;
 
 	rtnl_close(&rth);
 	ipaddr_reset_filter(1);
@@ -143,6 +150,9 @@ int do_ipmonitor(int argc, char **argv)
 		} else if (matches(*argv, "neigh") == 0) {
 			lneigh = 1;
 			groups = 0;
+		} else if (matches(*argv, "netconf") == 0) {
+			lnetconf = 1;
+			groups = 0;
 		} else if (strcmp(*argv, "all") == 0) {
 			groups = ~RTMGRP_TC;
 			prefix_banner=1;
@@ -176,6 +186,12 @@ int do_ipmonitor(int argc, char **argv)
 	if (lneigh) {
 		groups |= nl_mgrp(RTNLGRP_NEIGH);
 	}
+	if (lnetconf) {
+		if (!preferred_family || preferred_family == AF_INET)
+			groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF);
+		if (!preferred_family || preferred_family == AF_INET6)
+			groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
+	}
 	if (file) {
 		FILE *fp;
 		fp = fopen(file, "r");
diff --git a/ip/ipnetconf.c b/ip/ipnetconf.c
new file mode 100644
index 0000000..66d667b
--- /dev/null
+++ b/ip/ipnetconf.c
@@ -0,0 +1,183 @@
+/*
+ * ipnetconf.c		"ip netconf".
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Nicolas Dichtel, <nicolas.dichtel@6wind.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+static struct
+{
+	int family;
+	int ifindex;
+} filter;
+
+static void usage(void) __attribute__((noreturn));
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip netconf show [ dev STRING ]\n");
+	exit(-1);
+}
+
+#define NETCONF_RTA(r)	((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct netconfmsg))))
+
+int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	FILE *fp = (FILE*)arg;
+	struct netconfmsg *ncm = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	struct rtattr *tb[NETCONFA_MAX+1];
+
+	if (n->nlmsg_type == NLMSG_ERROR)
+		return -1;
+	if (n->nlmsg_type != RTM_NEWNETCONF) {
+		fprintf(stderr, "Not RTM_NEWNETCONF: %08x %08x %08x\n",
+			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
+
+		return -1;
+	}
+	len -= NLMSG_SPACE(sizeof(*ncm));
+	if (len < 0) {
+		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
+		return -1;
+	}
+
+	if (filter.family && filter.family != ncm->ncm_family)
+		return 0;
+
+	parse_rtattr(tb, NETCONFA_MAX, NETCONF_RTA(ncm),
+		     NLMSG_PAYLOAD(n, sizeof(*ncm)));
+
+	switch (ncm->ncm_family) {
+	case AF_INET:
+		fprintf(fp, "ipv4 ");
+		break;
+	case AF_INET6:
+		fprintf(fp, "ipv6 ");
+		break;
+	default:
+		fprintf(fp, "unknown ");
+		break;
+	}
+
+	if (tb[NETCONFA_IFINDEX]) {
+		int *ifindex = (int *)RTA_DATA(tb[NETCONFA_IFINDEX]);
+
+		switch (*ifindex) {
+		case NETCONFA_IFINDEX_ALL:
+			fprintf(fp, "all ");
+			break;
+		case NETCONFA_IFINDEX_DEFAULT:
+			fprintf(fp, "default ");
+			break;
+		default:
+			fprintf(fp, "dev %s ", ll_index_to_name(*ifindex));
+			break;
+		}
+	}
+
+	if (tb[NETCONFA_FORWARDING])
+		fprintf(fp, "forwarding %s ",
+			*(int *)RTA_DATA(tb[NETCONFA_FORWARDING])?"on":"off");
+	if (tb[NETCONFA_RP_FILTER]) {
+		int rp_filter = *(int *)RTA_DATA(tb[NETCONFA_RP_FILTER]);
+
+		if (rp_filter == 0)
+			fprintf(fp, "rp_filter off ");
+		else if (rp_filter == 1)
+			fprintf(fp, "rp_filter strict ");
+		else if (rp_filter == 2)
+			fprintf(fp, "rp_filter loose ");
+		else
+			fprintf(fp, "rp_filter unknown mode ");
+	}
+	if (tb[NETCONFA_MC_FORWARDING])
+		fprintf(fp, "mc_forwarding %d ",
+			*(int *)RTA_DATA(tb[NETCONFA_MC_FORWARDING]));
+
+	fprintf(fp, "\n");
+	fflush(fp);
+	return 0;
+}
+
+void ipnetconf_reset_filter(void)
+{
+	memset(&filter, 0, sizeof(filter));
+}
+
+int do_show(int argc, char **argv)
+{
+	struct {
+		struct nlmsghdr		n;
+		struct netconfmsg	ncm;
+		char			buf[1024];
+	} req;
+
+	ipnetconf_reset_filter();
+	filter.family = preferred_family;
+	if (filter.family == AF_UNSPEC)
+		filter.family = AF_INET;
+	filter.ifindex = NETCONFA_IFINDEX_ALL;
+
+	while (argc > 0) {
+		if (strcmp(*argv, "dev") == 0) {
+			NEXT_ARG();
+			filter.ifindex = ll_name_to_index(*argv);
+			if (filter.ifindex <= 0) {
+				fprintf(stderr, "Device \"%s\" does not exist.\n",
+					*argv);
+				return -1;
+			}
+		}
+		argv++; argc--;
+	}
+
+	ll_init_map(&rth);
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
+	req.n.nlmsg_type = RTM_GETNETCONF;
+	req.ncm.ncm_family = filter.family;
+	addattr_l(&req.n, sizeof(req), NETCONFA_IFINDEX, &filter.ifindex,
+		  sizeof(filter.ifindex));
+
+	rtnl_send(&rth, &req.n, req.n.nlmsg_len);
+	rtnl_listen(&rth, print_netconf, stdout);
+
+	return 0;
+}
+
+int do_ipnetconf(int argc, char **argv)
+{
+	if (argc > 0) {
+		if (matches(*argv, "show") == 0 ||
+		    matches(*argv, "lst") == 0 ||
+		    matches(*argv, "list") == 0)
+			return do_show(argc-1, argv+1);
+		if (matches(*argv, "help") == 0)
+			usage();
+	} else
+		return do_show(0, NULL);
+
+	fprintf(stderr, "Command \"%s\" is unknown, try \"ip netconf help\".\n", *argv);
+	exit(-1);
+}
-- 
1.8.0.1

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

* [PATCH iproute2 2/3] ip: add support of 'ip link type ip6tnl'
  2012-12-12  9:51 [PATCH iproute2 1/3] ip: add support of netconf messages Nicolas Dichtel
@ 2012-12-12  9:51 ` Nicolas Dichtel
  2012-12-12  9:51 ` [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]' Nicolas Dichtel
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Nicolas Dichtel @ 2012-12-12  9:51 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

This patch allows to manage ip6 tunnels via the interface ip link.
The syntax for parameters is the same that 'ip -6 tunnel'.

It also allows to display tunnels parameters with 'ip -details link' or
'ip -details monitor link'.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/linux/if_tunnel.h |  20 +++
 ip/Makefile               |   2 +-
 ip/iplink.c               |   3 +-
 ip/link_ip6tnl.c          | 344 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 367 insertions(+), 2 deletions(-)
 create mode 100644 ip/link_ip6tnl.c

diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
index 5db5942..aee73d0 100644
--- a/include/linux/if_tunnel.h
+++ b/include/linux/if_tunnel.h
@@ -37,6 +37,26 @@ struct ip_tunnel_parm {
 	struct iphdr		iph;
 };
 
+enum {
+	IFLA_IPTUN_UNSPEC,
+	IFLA_IPTUN_LINK,
+	IFLA_IPTUN_LOCAL,
+	IFLA_IPTUN_REMOTE,
+	IFLA_IPTUN_TTL,
+	IFLA_IPTUN_TOS,
+	IFLA_IPTUN_ENCAP_LIMIT,
+	IFLA_IPTUN_FLOWINFO,
+	IFLA_IPTUN_FLAGS,
+	IFLA_IPTUN_PROTO,
+	IFLA_IPTUN_PMTUDISC,
+	IFLA_IPTUN_6RD_PREFIX,
+	IFLA_IPTUN_6RD_RELAY_PREFIX,
+	IFLA_IPTUN_6RD_PREFIXLEN,
+	IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+	__IFLA_IPTUN_MAX,
+};
+#define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
+
 /* SIT-mode i_flags */
 #define	SIT_ISATAP	0x0001
 
diff --git a/ip/Makefile b/ip/Makefile
index 4bc33d7..abf54bf 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -4,7 +4,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
     iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
-    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o
+    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/iplink.c b/ip/iplink.c
index 7451aa0..8aac9fc 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -83,7 +83,8 @@ void iplink_usage(void)
 
 	if (iplink_have_newlink()) {
 		fprintf(stderr, "\n");
-		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can | bridge | ipoib }\n");
+		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
+		fprintf(stderr, "          bridge | ipoib | ip6tnl }\n");
 	}
 	exit(-1);
 }
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
new file mode 100644
index 0000000..2947364
--- /dev/null
+++ b/ip/link_ip6tnl.c
@@ -0,0 +1,344 @@
+/*
+ * link_ip6tnl.c	ip6tnl driver module
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Nicolas Dichtel <nicolas.dichtel@6wind.com>
+ *
+ */
+
+#include <string.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <linux/ip.h>
+#include <linux/if_tunnel.h>
+#include <linux/ip6_tunnel.h>
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+#include "tunnel.h"
+
+#define IP6_FLOWINFO_TCLASS	htonl(0x0FF00000)
+#define IP6_FLOWINFO_FLOWLABEL	htonl(0x000FFFFF)
+
+#define DEFAULT_TNL_HOP_LIMIT	(64)
+
+static void usage(void) __attribute__((noreturn));
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
+	fprintf(stderr, "          type ip6tnl [ remote ADDR ] [ local ADDR ]\n");
+	fprintf(stderr, "          [ dev PHYS_DEV ] [ encaplimit ELIM ]\n");
+	fprintf(stderr ,"          [ hoplimit HLIM ] [ tclass TCLASS ] [ flowlabel FLOWLABEL ]\n");
+	fprintf(stderr, "          [ dscp inherit ] [ fwmark inherit ]\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Where: NAME      := STRING\n");
+	fprintf(stderr, "       ADDR      := IPV6_ADDRESS\n");
+	fprintf(stderr, "       ELIM      := { none | 0..255 }(default=%d)\n",
+		IPV6_DEFAULT_TNL_ENCAP_LIMIT);
+	fprintf(stderr, "       HLIM      := 0..255 (default=%d)\n",
+		DEFAULT_TNL_HOP_LIMIT);
+	fprintf(stderr, "       TCLASS    := { 0x0..0xff | inherit }\n");
+	fprintf(stderr, "       FLOWLABEL := { 0x0..0xfffff | inherit }\n");
+	exit(-1);
+}
+
+static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
+			       struct nlmsghdr *n)
+{
+	struct {
+		struct nlmsghdr n;
+		struct ifinfomsg i;
+		char buf[2048];
+	} req;
+	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
+	struct rtattr *tb[IFLA_MAX + 1];
+	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
+	int len;
+	struct in6_addr laddr;
+	struct in6_addr raddr;
+	__u8 hop_limit = DEFAULT_TNL_HOP_LIMIT;
+	__u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
+	__u32 flowinfo = 0;
+	__u32 flags = 0;
+	__u32 link = 0;
+	__u8 proto = 0;
+
+	memset(&laddr, 0, sizeof(laddr));
+	memset(&raddr, 0, sizeof(raddr));
+
+	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		memset(&req, 0, sizeof(req));
+
+		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
+		req.n.nlmsg_flags = NLM_F_REQUEST;
+		req.n.nlmsg_type = RTM_GETLINK;
+		req.i.ifi_family = preferred_family;
+		req.i.ifi_index = ifi->ifi_index;
+
+		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+get_failed:
+			fprintf(stderr,
+				"Failed to get existing tunnel info.\n");
+			return -1;
+		}
+
+		len = req.n.nlmsg_len;
+		len -= NLMSG_LENGTH(sizeof(*ifi));
+		if (len < 0)
+			goto get_failed;
+
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
+
+		if (!tb[IFLA_LINKINFO])
+			goto get_failed;
+
+		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+		if (!linkinfo[IFLA_INFO_DATA])
+			goto get_failed;
+
+		parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
+				    linkinfo[IFLA_INFO_DATA]);
+
+		if (iptuninfo[IFLA_IPTUN_LOCAL])
+			memcpy(&laddr, RTA_DATA(iptuninfo[IFLA_IPTUN_LOCAL]),
+			       sizeof(laddr));
+
+		if (iptuninfo[IFLA_IPTUN_REMOTE])
+			memcpy(&raddr, RTA_DATA(iptuninfo[IFLA_IPTUN_REMOTE]),
+			       sizeof(raddr));
+
+		if (iptuninfo[IFLA_IPTUN_TTL])
+			hop_limit = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
+
+		if (iptuninfo[IFLA_IPTUN_ENCAP_LIMIT])
+			encap_limit = rta_getattr_u8(iptuninfo[IFLA_IPTUN_ENCAP_LIMIT]);
+
+		if (iptuninfo[IFLA_IPTUN_FLOWINFO])
+			flowinfo = rta_getattr_u32(iptuninfo[IFLA_IPTUN_FLOWINFO]);
+
+		if (iptuninfo[IFLA_IPTUN_FLAGS])
+			flags = rta_getattr_u32(iptuninfo[IFLA_IPTUN_FLAGS]);
+
+		if (iptuninfo[IFLA_IPTUN_LINK])
+			link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
+
+		if (iptuninfo[IFLA_IPTUN_PROTO])
+			proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]);
+	}
+
+	while (argc > 0) {
+		if (matches(*argv, "mode") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "ipv6/ipv6") == 0 ||
+			    strcmp(*argv, "ip6ip6") == 0)
+				proto = IPPROTO_IPV6;
+			else if (strcmp(*argv, "ip/ipv6") == 0 ||
+				 strcmp(*argv, "ipv4/ipv6") == 0 ||
+				 strcmp(*argv, "ipip6") == 0 ||
+				 strcmp(*argv, "ip4ip6") == 0)
+				proto = IPPROTO_IPIP;
+			else if (strcmp(*argv, "any/ipv6") == 0 ||
+				 strcmp(*argv, "any") == 0)
+				proto = 0;
+			else
+				invarg("Cannot guess tunnel mode.", *argv);
+		} else if (strcmp(*argv, "remote") == 0) {
+			inet_prefix addr;
+			NEXT_ARG();
+			get_prefix(&addr, *argv, preferred_family);
+			if (addr.family == AF_UNSPEC)
+				invarg("\"remote\" address family is AF_UNSPEC", *argv);
+			memcpy(&raddr, addr.data, addr.bytelen);
+		} else if (strcmp(*argv, "local") == 0) {
+			inet_prefix addr;
+			NEXT_ARG();
+			get_prefix(&addr, *argv, preferred_family);
+			if (addr.family == AF_UNSPEC)
+				invarg("\"local\" address family is AF_UNSPEC", *argv);
+			memcpy(&laddr, addr.data, addr.bytelen);
+		} else if (matches(*argv, "dev") == 0) {
+			NEXT_ARG();
+			link = if_nametoindex(*argv);
+			if (link == 0)
+				invarg("\"dev\" is invalid", *argv);
+		} else if (strcmp(*argv, "hoplimit") == 0 ||
+			   strcmp(*argv, "ttl") == 0 ||
+			   strcmp(*argv, "hlim") == 0) {
+			__u8 uval;
+			NEXT_ARG();
+			if (get_u8(&uval, *argv, 0))
+				invarg("invalid HLIM", *argv);
+			hop_limit = uval;
+		} else if (matches(*argv, "encaplimit") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "none") == 0) {
+				flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;
+			} else {
+				__u8 uval;
+				if (get_u8(&uval, *argv, 0) < -1)
+					invarg("invalid ELIM", *argv);
+				encap_limit = uval;
+				flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;
+			}
+		} else if (strcmp(*argv, "tclass") == 0 ||
+			   strcmp(*argv, "tc") == 0 ||
+			   strcmp(*argv, "tos") == 0 ||
+			   matches(*argv, "dsfield") == 0) {
+			__u8 uval;
+			NEXT_ARG();
+			flowinfo &= ~IP6_FLOWINFO_TCLASS;
+			if (strcmp(*argv, "inherit") == 0)
+				flags |= IP6_TNL_F_USE_ORIG_TCLASS;
+			else {
+				if (get_u8(&uval, *argv, 16))
+					invarg("invalid TClass", *argv);
+				flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS;
+				flags &= ~IP6_TNL_F_USE_ORIG_TCLASS;
+			}
+		} else if (strcmp(*argv, "flowlabel") == 0 ||
+			   strcmp(*argv, "fl") == 0) {
+			__u32 uval;
+			NEXT_ARG();
+			flowinfo &= ~IP6_FLOWINFO_FLOWLABEL;
+			if (strcmp(*argv, "inherit") == 0)
+				flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
+			else {
+				if (get_u32(&uval, *argv, 16))
+					invarg("invalid Flowlabel", *argv);
+				if (uval > 0xFFFFF)
+					invarg("invalid Flowlabel", *argv);
+				flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL;
+				flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
+			}
+		} else if (strcmp(*argv, "dscp") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0)
+				invarg("not inherit", *argv);
+			flags |= IP6_TNL_F_RCV_DSCP_COPY;
+		} else if (strcmp(*argv, "fwmark") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0)
+				invarg("not inherit", *argv);
+			flags |= IP6_TNL_F_USE_ORIG_FWMARK;
+		} else
+			usage();
+		argc--, argv++;
+	}
+
+	addattr8(n, 1024, IFLA_IPTUN_PROTO, proto);
+	addattr_l(n, 1024, IFLA_IPTUN_LOCAL, &laddr, sizeof(laddr));
+	addattr_l(n, 1024, IFLA_IPTUN_REMOTE, &raddr, sizeof(raddr));
+	addattr8(n, 1024, IFLA_IPTUN_TTL, hop_limit);
+	addattr8(n, 1024, IFLA_IPTUN_ENCAP_LIMIT, encap_limit);
+	addattr32(n, 1024, IFLA_IPTUN_FLOWINFO, flowinfo);
+	addattr32(n, 1024, IFLA_IPTUN_FLAGS, flags);
+	addattr32(n, 1024, IFLA_IPTUN_LINK, link);
+
+	return 0;
+}
+
+static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
+{
+	char s1[256];
+	char s2[64];
+	int flags = 0;
+	__u32 flowinfo = 0;
+
+	if (!tb)
+		return;
+
+	if (tb[IFLA_IPTUN_FLAGS])
+		flags = rta_getattr_u32(tb[IFLA_IPTUN_FLAGS]);
+
+	if (tb[IFLA_IPTUN_FLOWINFO])
+		flowinfo = rta_getattr_u32(tb[IFLA_IPTUN_FLOWINFO]);
+
+	if (tb[IFLA_IPTUN_PROTO]) {
+		switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) {
+		case IPPROTO_IPIP:
+			fprintf(f, "ipip6 ");
+			break;
+		case IPPROTO_IPV6:
+			fprintf(f, "ip6ip6 ");
+			break;
+		case 0:
+			fprintf(f, "any ");
+			break;
+		}
+	}
+
+	if (tb[IFLA_IPTUN_REMOTE]) {
+		fprintf(f, "remote %s ",
+			rt_addr_n2a(AF_INET6,
+				    RTA_PAYLOAD(tb[IFLA_IPTUN_REMOTE]),
+				    RTA_DATA(tb[IFLA_IPTUN_REMOTE]),
+				    s1, sizeof(s1)));
+	}
+
+	if (tb[IFLA_IPTUN_LOCAL]) {
+		fprintf(f, "local %s ",
+			rt_addr_n2a(AF_INET6,
+				    RTA_PAYLOAD(tb[IFLA_IPTUN_LOCAL]),
+				    RTA_DATA(tb[IFLA_IPTUN_LOCAL]),
+				    s1, sizeof(s1)));
+	}
+
+	if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
+		unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
+		const char *n = if_indextoname(link, s2);
+
+		if (n)
+			fprintf(f, "dev %s ", n);
+		else
+			fprintf(f, "dev %u ", link);
+	}
+
+	if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT)
+		printf("encaplimit none ");
+	else if (tb[IFLA_IPTUN_ENCAP_LIMIT])
+		fprintf(f, "encaplimit %u ",
+			rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]));
+
+	if (tb[IFLA_IPTUN_TTL])
+		fprintf(f, "hoplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
+
+	if (flags & IP6_TNL_F_USE_ORIG_TCLASS)
+		printf("tclass inherit ");
+	else if (tb[IFLA_IPTUN_FLOWINFO]) {
+		__u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS);
+
+		printf("tclass 0x%02x ", (__u8)(val >> 20));
+	}
+
+	if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
+		printf("flowlabel inherit ");
+	else
+		printf("flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+
+	printf("(flowinfo 0x%08x) ", ntohl(flowinfo));
+
+	if (flags & IP6_TNL_F_RCV_DSCP_COPY)
+		printf("dscp inherit ");
+
+	if (flags & IP6_TNL_F_MIP6_DEV)
+		fprintf(f, "mip6 ");
+
+	if (flags & IP6_TNL_F_USE_ORIG_FWMARK)
+		fprintf(f, "fwmark inherit ");
+}
+
+struct link_util ip6tnl_link_util = {
+	.id = "ip6tnl",
+	.maxattr = IFLA_IPTUN_MAX,
+	.parse_opt = ip6tunnel_parse_opt,
+	.print_opt = ip6tunnel_print_opt,
+};
-- 
1.8.0.1

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

* [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'
  2012-12-12  9:51 [PATCH iproute2 1/3] ip: add support of netconf messages Nicolas Dichtel
  2012-12-12  9:51 ` [PATCH iproute2 2/3] ip: add support of 'ip link type ip6tnl' Nicolas Dichtel
@ 2012-12-12  9:51 ` Nicolas Dichtel
  2012-12-12 17:11   ` Stephen Hemminger
  2012-12-12 16:58 ` [PATCH net-next] uapi: add missing netconf.h to export list Stephen Hemminger
  2012-12-12 16:59 ` [PATCH iproute2 1/3] ip: add support of netconf messages Stephen Hemminger
  3 siblings, 1 reply; 10+ messages in thread
From: Nicolas Dichtel @ 2012-12-12  9:51 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Nicolas Dichtel

This patch allows to manage ip tunnels via the interface ip link.
The syntax for parameters is the same that 'ip tunnel'.

It also allows to display tunnels parameters with 'ip -details link' or
'ip -details monitor link'.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 ip/Makefile     |   3 +-
 ip/iplink.c     |   2 +-
 ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 343 insertions(+), 2 deletions(-)
 create mode 100644 ip/link_iptnl.c

diff --git a/ip/Makefile b/ip/Makefile
index abf54bf..2b606d4 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
     iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
-    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
+    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
+    link_iptnl.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/iplink.c b/ip/iplink.c
index 8aac9fc..d73c705 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -84,7 +84,7 @@ void iplink_usage(void)
 	if (iplink_have_newlink()) {
 		fprintf(stderr, "\n");
 		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
-		fprintf(stderr, "          bridge | ipoib | ip6tnl }\n");
+		fprintf(stderr, "          bridge | ipoib | ip6tnl | ipip | sit }\n");
 	}
 	exit(-1);
 }
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
new file mode 100644
index 0000000..238722d
--- /dev/null
+++ b/ip/link_iptnl.c
@@ -0,0 +1,340 @@
+/*
+ * link_iptnl.c	ipip and sit driver module
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Nicolas Dichtel <nicolas.dichtel@6wind.com>
+ *
+ */
+
+#include <string.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <linux/ip.h>
+#include <linux/if_tunnel.h>
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+#include "tunnel.h"
+
+static void usage(int sit) __attribute__((noreturn));
+static void usage(int sit)
+{
+	fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
+	fprintf(stderr, "          type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n");
+	fprintf(stderr, "          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
+	fprintf(stderr, "          [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
+	if (sit)
+		fprintf(stderr, "          [ isatap ]\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Where: NAME := STRING\n");
+	fprintf(stderr, "       ADDR := { IP_ADDRESS | any }\n");
+	fprintf(stderr, "       TOS  := { NUMBER | inherit }\n");
+	fprintf(stderr, "       TTL  := { 1..255 | inherit }\n");
+	exit(-1);
+}
+
+static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
+			      struct nlmsghdr *n)
+{
+	struct {
+		struct nlmsghdr n;
+		struct ifinfomsg i;
+		char buf[2048];
+	} req;
+	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
+	struct rtattr *tb[IFLA_MAX + 1];
+	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
+	int len;
+	__u32 link = 0;
+	__u32 laddr = 0;
+	__u32 raddr = 0;
+	__u8 ttl = 0;
+	__u8 tos = 0;
+	__u8 pmtudisc = 1;
+	__u16 iflags = 0;
+	struct in6_addr ip6rdprefix;
+	__u16 ip6rdprefixlen = 0;
+	__u32 ip6rdrelayprefix = 0;
+	__u16 ip6rdrelayprefixlen = 0;
+
+	memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));
+
+	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		memset(&req, 0, sizeof(req));
+
+		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
+		req.n.nlmsg_flags = NLM_F_REQUEST;
+		req.n.nlmsg_type = RTM_GETLINK;
+		req.i.ifi_family = preferred_family;
+		req.i.ifi_index = ifi->ifi_index;
+
+		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+get_failed:
+			fprintf(stderr,
+				"Failed to get existing tunnel info.\n");
+			return -1;
+		}
+
+		len = req.n.nlmsg_len;
+		len -= NLMSG_LENGTH(sizeof(*ifi));
+		if (len < 0)
+			goto get_failed;
+
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
+
+		if (!tb[IFLA_LINKINFO])
+			goto get_failed;
+
+		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+		if (!linkinfo[IFLA_INFO_DATA])
+			goto get_failed;
+
+		parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
+				    linkinfo[IFLA_INFO_DATA]);
+
+		if (iptuninfo[IFLA_IPTUN_LOCAL])
+			laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
+
+		if (iptuninfo[IFLA_IPTUN_REMOTE])
+			raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
+
+		if (iptuninfo[IFLA_IPTUN_TTL])
+			ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
+
+		if (iptuninfo[IFLA_IPTUN_TOS])
+			tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
+
+		if (iptuninfo[IFLA_IPTUN_PMTUDISC])
+			pmtudisc =
+				rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
+
+		if (iptuninfo[IFLA_IPTUN_FLAGS])
+			iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
+
+		if (iptuninfo[IFLA_IPTUN_LINK])
+			link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
+
+		if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
+			memcpy(&ip6rdprefix,
+			       RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
+			       sizeof(laddr));
+
+		if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
+			ip6rdprefixlen =
+				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
+
+		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
+			ip6rdrelayprefix =
+				rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+
+		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
+			ip6rdrelayprefixlen =
+				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+	}
+
+	while (argc > 0) {
+		if (strcmp(*argv, "remote") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "any"))
+				raddr = get_addr32(*argv);
+			else
+				raddr = 0;
+		} else if (strcmp(*argv, "local") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "any"))
+				laddr = get_addr32(*argv);
+			else
+				laddr = 0;
+		} else if (matches(*argv, "dev") == 0) {
+			NEXT_ARG();
+			link = if_nametoindex(*argv);
+			if (link == 0)
+				invarg("\"dev\" is invalid", *argv);
+		} else if (strcmp(*argv, "ttl") == 0 ||
+			   strcmp(*argv, "hoplimit") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0) {
+				if (get_u8(&ttl, *argv, 0))
+					invarg("invalid TTL\n", *argv);
+			} else
+				ttl = 0;
+		} else if (strcmp(*argv, "tos") == 0 ||
+			   strcmp(*argv, "tclass") == 0 ||
+			   matches(*argv, "dsfield") == 0) {
+			__u32 uval;
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0) {
+				if (rtnl_dsfield_a2n(&uval, *argv))
+					invarg("bad TOS value", *argv);
+				tos = uval;
+			} else
+				tos = 1;
+		} else if (strcmp(*argv, "nopmtudisc") == 0) {
+			pmtudisc = 0;
+		} else if (strcmp(*argv, "pmtudisc") == 0) {
+			pmtudisc = 1;
+		} else if (strcmp(lu->id, "sit") == 0 &&
+			   strcmp(*argv, "isatap") == 0) {
+			iflags |= SIT_ISATAP;
+		} else if (strcmp(*argv, "6rd-prefix") == 0) {
+			inet_prefix prefix;
+			NEXT_ARG();
+			if (get_prefix(&prefix, *argv, AF_INET6))
+				invarg("invalid 6rd_prefix\n", *argv);
+			memcpy(&ip6rdprefix, prefix.data, 16);
+			ip6rdprefixlen = prefix.bitlen;
+		} else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
+			inet_prefix prefix;
+			NEXT_ARG();
+			if (get_prefix(&prefix, *argv, AF_INET))
+				invarg("invalid 6rd-relay_prefix\n", *argv);
+			memcpy(&ip6rdrelayprefix, prefix.data, 4);
+			ip6rdrelayprefixlen = prefix.bitlen;
+		} else if (strcmp(*argv, "6rd-reset") == 0) {
+			inet_prefix prefix;
+			get_prefix(&prefix, "2002::", AF_INET6);
+			memcpy(&ip6rdprefix, prefix.data, 16);
+			ip6rdprefixlen = 16;
+			ip6rdrelayprefix = 0;
+			ip6rdrelayprefixlen = 0;
+		} else
+			usage(strcmp(lu->id, "sit") == 0);
+		argc--, argv++;
+	}
+
+	if (ttl && pmtudisc == 0) {
+		fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
+		exit(-1);
+	}
+
+	addattr32(n, 1024, IFLA_IPTUN_LINK, link);
+	addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
+	addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
+	addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
+	addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
+	addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
+	if (strcmp(lu->id, "sit") == 0) {
+		addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
+		if (ip6rdprefixlen) {
+			addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
+				  &ip6rdprefix, sizeof(ip6rdprefix));
+			addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
+				  ip6rdprefixlen);
+			addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
+				  ip6rdrelayprefix);
+			addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+				  ip6rdrelayprefixlen);
+		}
+	}
+
+	return 0;
+}
+
+static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
+{
+	char s1[1024];
+	char s2[64];
+	const char *local = "any";
+	const char *remote = "any";
+
+	if (!tb)
+		return;
+
+	if (tb[IFLA_IPTUN_REMOTE]) {
+		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
+
+		if (addr)
+			remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
+	}
+
+	fprintf(f, "remote %s ", remote);
+
+	if (tb[IFLA_IPTUN_LOCAL]) {
+		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
+
+		if (addr)
+			local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
+	}
+
+	fprintf(f, "local %s ", local);
+
+	if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
+		unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
+		const char *n = if_indextoname(link, s2);
+
+		if (n)
+			fprintf(f, "dev %s ", n);
+		else
+			fprintf(f, "dev %u ", link);
+	}
+
+	if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
+		fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
+	else
+		fprintf(f, "ttl inherit ");
+
+	if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
+		int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
+
+		fputs("tos ", f);
+		if (tos == 1)
+			fputs("inherit ", f);
+		else
+			fprintf(f, "0x%x ", tos);
+	}
+
+	if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
+		fprintf(f, "pmtudisc ");
+	else
+		fprintf(f, "nopmtudisc ");
+
+	if (tb[IFLA_IPTUN_FLAGS]) {
+	       __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
+
+	      if (iflags & SIT_ISATAP)
+		      fprintf(f, "isatap ");
+	}
+
+	if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
+	    *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) {
+		__u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]);
+		__u16 relayprefixlen =
+			rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+		__u32 relayprefix =
+			rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+
+		printf("6rd-prefix %s/%u ",
+		       inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
+			         s1, sizeof(s1)),
+		       prefixlen);
+		if (relayprefix) {
+			printf("6rd-relay_prefix %s/%u ",
+			       format_host(AF_INET, 4, &relayprefix, s1,
+				           sizeof(s1)),
+			       relayprefixlen);
+		}
+	}
+}
+
+struct link_util ipip_link_util = {
+	.id = "ipip",
+	.maxattr = IFLA_IPTUN_MAX,
+	.parse_opt = iptunnel_parse_opt,
+	.print_opt = iptunnel_print_opt,
+};
+
+struct link_util sit_link_util = {
+	.id = "sit",
+	.maxattr = IFLA_IPTUN_MAX,
+	.parse_opt = iptunnel_parse_opt,
+	.print_opt = iptunnel_print_opt,
+};
-- 
1.8.0.1

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

* [PATCH net-next] uapi: add missing netconf.h to export list
  2012-12-12  9:51 [PATCH iproute2 1/3] ip: add support of netconf messages Nicolas Dichtel
  2012-12-12  9:51 ` [PATCH iproute2 2/3] ip: add support of 'ip link type ip6tnl' Nicolas Dichtel
  2012-12-12  9:51 ` [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]' Nicolas Dichtel
@ 2012-12-12 16:58 ` Stephen Hemminger
  2012-12-12 17:04   ` Nicolas Dichtel
  2012-12-12 16:59 ` [PATCH iproute2 1/3] ip: add support of netconf messages Stephen Hemminger
  3 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2012-12-12 16:58 UTC (permalink / raw)
  To: David Miller; +Cc: Nicolas Dichtel, netdev

Add netconf.h for use by iproute2.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/include/uapi/linux/Kbuild	2012-10-25 09:11:15.499273810 -0700
+++ b/include/uapi/linux/Kbuild	2012-12-12 08:56:36.130263710 -0800
@@ -258,6 +258,7 @@ header-y += neighbour.h
 header-y += net.h
 header-y += net_dropmon.h
 header-y += net_tstamp.h
+header-y += netconf.h
 header-y += netdevice.h
 header-y += netfilter.h
 header-y += netfilter_arp.h

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

* Re: [PATCH iproute2 1/3] ip: add support of netconf messages
  2012-12-12  9:51 [PATCH iproute2 1/3] ip: add support of netconf messages Nicolas Dichtel
                   ` (2 preceding siblings ...)
  2012-12-12 16:58 ` [PATCH net-next] uapi: add missing netconf.h to export list Stephen Hemminger
@ 2012-12-12 16:59 ` Stephen Hemminger
  2012-12-12 17:03   ` Nicolas Dichtel
  3 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2012-12-12 16:59 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: netdev

Ok, but the headers for all of iproute2 are supposed to come from
sanitized kernel headers from "make headers_install"

You missed that piece in the original patch.

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

* Re: [PATCH iproute2 1/3] ip: add support of netconf messages
  2012-12-12 16:59 ` [PATCH iproute2 1/3] ip: add support of netconf messages Stephen Hemminger
@ 2012-12-12 17:03   ` Nicolas Dichtel
  0 siblings, 0 replies; 10+ messages in thread
From: Nicolas Dichtel @ 2012-12-12 17:03 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

Le 12/12/2012 17:59, Stephen Hemminger a écrit :
> Ok, but the headers for all of iproute2 are supposed to come from
> sanitized kernel headers from "make headers_install"
>
> You missed that piece in the original patch.
>
Right! I will update the patch.

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

* Re: [PATCH net-next] uapi: add missing netconf.h to export list
  2012-12-12 16:58 ` [PATCH net-next] uapi: add missing netconf.h to export list Stephen Hemminger
@ 2012-12-12 17:04   ` Nicolas Dichtel
  2012-12-12 17:40     ` David Miller
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Dichtel @ 2012-12-12 17:04 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev

Le 12/12/2012 17:58, Stephen Hemminger a écrit :
> Add netconf.h for use by iproute2.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>

>
> --- a/include/uapi/linux/Kbuild	2012-10-25 09:11:15.499273810 -0700
> +++ b/include/uapi/linux/Kbuild	2012-12-12 08:56:36.130263710 -0800
> @@ -258,6 +258,7 @@ header-y += neighbour.h
>   header-y += net.h
>   header-y += net_dropmon.h
>   header-y += net_tstamp.h
> +header-y += netconf.h
>   header-y += netdevice.h
>   header-y += netfilter.h
>   header-y += netfilter_arp.h
>

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

* Re: [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'
  2012-12-12  9:51 ` [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]' Nicolas Dichtel
@ 2012-12-12 17:11   ` Stephen Hemminger
  2012-12-12 17:20     ` Nicolas Dichtel
  0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2012-12-12 17:11 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: netdev

On Wed, 12 Dec 2012 10:51:47 +0100
Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:

> This patch allows to manage ip tunnels via the interface ip link.
> The syntax for parameters is the same that 'ip tunnel'.
> 
> It also allows to display tunnels parameters with 'ip -details link' or
> 'ip -details monitor link'.
> 
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
>  ip/Makefile     |   3 +-
>  ip/iplink.c     |   2 +-
>  ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 343 insertions(+), 2 deletions(-)
>  create mode 100644 ip/link_iptnl.c
> 
> diff --git a/ip/Makefile b/ip/Makefile
> index abf54bf..2b606d4 100644
> --- a/ip/Makefile
> +++ b/ip/Makefile
> @@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
>      ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
>      iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
>      iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
> -    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
> +    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
> +    link_iptnl.o
>  
>  RTMONOBJ=rtmon.o
>  
> diff --git a/ip/iplink.c b/ip/iplink.c
> index 8aac9fc..d73c705 100644
> --- a/ip/iplink.c
> +++ b/ip/iplink.c
> @@ -84,7 +84,7 @@ void iplink_usage(void)
>  	if (iplink_have_newlink()) {
>  		fprintf(stderr, "\n");
>  		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
> -		fprintf(stderr, "          bridge | ipoib | ip6tnl }\n");
> +		fprintf(stderr, "          bridge | ipoib | ip6tnl | ipip | sit }\n");
>  	}
>  	exit(-1);
>  }
> diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
> new file mode 100644
> index 0000000..238722d
> --- /dev/null
> +++ b/ip/link_iptnl.c
> @@ -0,0 +1,340 @@
> +/*
> + * link_iptnl.c	ipip and sit driver module
> + *
> + *		This program is free software; you can redistribute it and/or
> + *		modify it under the terms of the GNU General Public License
> + *		as published by the Free Software Foundation; either version
> + *		2 of the License, or (at your option) any later version.
> + *
> + * Authors:	Nicolas Dichtel <nicolas.dichtel@6wind.com>
> + *
> + */
> +
> +#include <string.h>
> +#include <net/if.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <arpa/inet.h>
> +
> +#include <linux/ip.h>
> +#include <linux/if_tunnel.h>
> +#include "rt_names.h"
> +#include "utils.h"
> +#include "ip_common.h"
> +#include "tunnel.h"
> +
> +static void usage(int sit) __attribute__((noreturn));
> +static void usage(int sit)
> +{
> +	fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
> +	fprintf(stderr, "          type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n");
> +	fprintf(stderr, "          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
> +	fprintf(stderr, "          [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
> +	if (sit)
> +		fprintf(stderr, "          [ isatap ]\n");
> +	fprintf(stderr, "\n");
> +	fprintf(stderr, "Where: NAME := STRING\n");
> +	fprintf(stderr, "       ADDR := { IP_ADDRESS | any }\n");
> +	fprintf(stderr, "       TOS  := { NUMBER | inherit }\n");
> +	fprintf(stderr, "       TTL  := { 1..255 | inherit }\n");
> +	exit(-1);
> +}
> +
> +static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
> +			      struct nlmsghdr *n)
> +{
> +	struct {
> +		struct nlmsghdr n;
> +		struct ifinfomsg i;
> +		char buf[2048];
> +	} req;
> +	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
> +	struct rtattr *tb[IFLA_MAX + 1];
> +	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
> +	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
> +	int len;
> +	__u32 link = 0;
> +	__u32 laddr = 0;
> +	__u32 raddr = 0;
> +	__u8 ttl = 0;
> +	__u8 tos = 0;
> +	__u8 pmtudisc = 1;
> +	__u16 iflags = 0;
> +	struct in6_addr ip6rdprefix;
> +	__u16 ip6rdprefixlen = 0;
> +	__u32 ip6rdrelayprefix = 0;
> +	__u16 ip6rdrelayprefixlen = 0;
> +
> +	memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));
> +
> +	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
> +		memset(&req, 0, sizeof(req));
> +
> +		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
> +		req.n.nlmsg_flags = NLM_F_REQUEST;
> +		req.n.nlmsg_type = RTM_GETLINK;
> +		req.i.ifi_family = preferred_family;
> +		req.i.ifi_index = ifi->ifi_index;
> +
> +		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
> +get_failed:
> +			fprintf(stderr,
> +				"Failed to get existing tunnel info.\n");
> +			return -1;
> +		}
> +
> +		len = req.n.nlmsg_len;
> +		len -= NLMSG_LENGTH(sizeof(*ifi));
> +		if (len < 0)
> +			goto get_failed;
> +
> +		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
> +
> +		if (!tb[IFLA_LINKINFO])
> +			goto get_failed;
> +
> +		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
> +
> +		if (!linkinfo[IFLA_INFO_DATA])
> +			goto get_failed;
> +
> +		parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
> +				    linkinfo[IFLA_INFO_DATA]);
> +
> +		if (iptuninfo[IFLA_IPTUN_LOCAL])
> +			laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
> +
> +		if (iptuninfo[IFLA_IPTUN_REMOTE])
> +			raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
> +
> +		if (iptuninfo[IFLA_IPTUN_TTL])
> +			ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
> +
> +		if (iptuninfo[IFLA_IPTUN_TOS])
> +			tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
> +
> +		if (iptuninfo[IFLA_IPTUN_PMTUDISC])
> +			pmtudisc =
> +				rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
> +
> +		if (iptuninfo[IFLA_IPTUN_FLAGS])
> +			iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
> +
> +		if (iptuninfo[IFLA_IPTUN_LINK])
> +			link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
> +
> +		if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
> +			memcpy(&ip6rdprefix,
> +			       RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
> +			       sizeof(laddr));
> +
> +		if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
> +			ip6rdprefixlen =
> +				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
> +
> +		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
> +			ip6rdrelayprefix =
> +				rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
> +
> +		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
> +			ip6rdrelayprefixlen =
> +				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
> +	}
> +
> +	while (argc > 0) {
> +		if (strcmp(*argv, "remote") == 0) {
> +			NEXT_ARG();
> +			if (strcmp(*argv, "any"))
> +				raddr = get_addr32(*argv);
> +			else
> +				raddr = 0;
> +		} else if (strcmp(*argv, "local") == 0) {
> +			NEXT_ARG();
> +			if (strcmp(*argv, "any"))
> +				laddr = get_addr32(*argv);
> +			else
> +				laddr = 0;
> +		} else if (matches(*argv, "dev") == 0) {
> +			NEXT_ARG();
> +			link = if_nametoindex(*argv);
> +			if (link == 0)
> +				invarg("\"dev\" is invalid", *argv);
> +		} else if (strcmp(*argv, "ttl") == 0 ||
> +			   strcmp(*argv, "hoplimit") == 0) {
> +			NEXT_ARG();
> +			if (strcmp(*argv, "inherit") != 0) {
> +				if (get_u8(&ttl, *argv, 0))
> +					invarg("invalid TTL\n", *argv);
> +			} else
> +				ttl = 0;
> +		} else if (strcmp(*argv, "tos") == 0 ||
> +			   strcmp(*argv, "tclass") == 0 ||
> +			   matches(*argv, "dsfield") == 0) {
> +			__u32 uval;
> +			NEXT_ARG();
> +			if (strcmp(*argv, "inherit") != 0) {
> +				if (rtnl_dsfield_a2n(&uval, *argv))
> +					invarg("bad TOS value", *argv);
> +				tos = uval;
> +			} else
> +				tos = 1;
> +		} else if (strcmp(*argv, "nopmtudisc") == 0) {
> +			pmtudisc = 0;
> +		} else if (strcmp(*argv, "pmtudisc") == 0) {
> +			pmtudisc = 1;
> +		} else if (strcmp(lu->id, "sit") == 0 &&
> +			   strcmp(*argv, "isatap") == 0) {
> +			iflags |= SIT_ISATAP;
> +		} else if (strcmp(*argv, "6rd-prefix") == 0) {
> +			inet_prefix prefix;
> +			NEXT_ARG();
> +			if (get_prefix(&prefix, *argv, AF_INET6))
> +				invarg("invalid 6rd_prefix\n", *argv);
> +			memcpy(&ip6rdprefix, prefix.data, 16);
> +			ip6rdprefixlen = prefix.bitlen;
> +		} else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
> +			inet_prefix prefix;
> +			NEXT_ARG();
> +			if (get_prefix(&prefix, *argv, AF_INET))
> +				invarg("invalid 6rd-relay_prefix\n", *argv);
> +			memcpy(&ip6rdrelayprefix, prefix.data, 4);
> +			ip6rdrelayprefixlen = prefix.bitlen;
> +		} else if (strcmp(*argv, "6rd-reset") == 0) {
> +			inet_prefix prefix;
> +			get_prefix(&prefix, "2002::", AF_INET6);
> +			memcpy(&ip6rdprefix, prefix.data, 16);
> +			ip6rdprefixlen = 16;
> +			ip6rdrelayprefix = 0;
> +			ip6rdrelayprefixlen = 0;
> +		} else
> +			usage(strcmp(lu->id, "sit") == 0);
> +		argc--, argv++;
> +	}
> +
> +	if (ttl && pmtudisc == 0) {
> +		fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
> +		exit(-1);
> +	}
> +
> +	addattr32(n, 1024, IFLA_IPTUN_LINK, link);
> +	addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
> +	addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
> +	addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
> +	addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
> +	addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
> +	if (strcmp(lu->id, "sit") == 0) {
> +		addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
> +		if (ip6rdprefixlen) {
> +			addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
> +				  &ip6rdprefix, sizeof(ip6rdprefix));
> +			addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
> +				  ip6rdprefixlen);
> +			addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
> +				  ip6rdrelayprefix);
> +			addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
> +				  ip6rdrelayprefixlen);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
> +{
> +	char s1[1024];
> +	char s2[64];
> +	const char *local = "any";
> +	const char *remote = "any";
> +
> +	if (!tb)
> +		return;
> +
> +	if (tb[IFLA_IPTUN_REMOTE]) {
> +		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
> +
> +		if (addr)
> +			remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
> +	}
> +
> +	fprintf(f, "remote %s ", remote);
> +
> +	if (tb[IFLA_IPTUN_LOCAL]) {
> +		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
> +
> +		if (addr)
> +			local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
> +	}
> +
> +	fprintf(f, "local %s ", local);
> +
> +	if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
> +		unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
> +		const char *n = if_indextoname(link, s2);
> +
> +		if (n)
> +			fprintf(f, "dev %s ", n);
> +		else
> +			fprintf(f, "dev %u ", link);
> +	}
> +
> +	if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
> +		fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
> +	else
> +		fprintf(f, "ttl inherit ");
> +
> +	if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
> +		int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
> +
> +		fputs("tos ", f);
> +		if (tos == 1)
> +			fputs("inherit ", f);
> +		else
> +			fprintf(f, "0x%x ", tos);
> +	}
> +
> +	if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
> +		fprintf(f, "pmtudisc ");
> +	else
> +		fprintf(f, "nopmtudisc ");
> +
> +	if (tb[IFLA_IPTUN_FLAGS]) {
> +	       __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
> +
> +	      if (iflags & SIT_ISATAP)
> +		      fprintf(f, "isatap ");
> +	}
> +
> +	if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
> +	    *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) {
> +		__u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]);
> +		__u16 relayprefixlen =
> +			rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
> +		__u32 relayprefix =
> +			rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
> +
> +		printf("6rd-prefix %s/%u ",
> +		       inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
> +			         s1, sizeof(s1)),
> +		       prefixlen);
> +		if (relayprefix) {
> +			printf("6rd-relay_prefix %s/%u ",
> +			       format_host(AF_INET, 4, &relayprefix, s1,
> +				           sizeof(s1)),
> +			       relayprefixlen);
> +		}
> +	}
> +}
> +
> +struct link_util ipip_link_util = {
> +	.id = "ipip",
> +	.maxattr = IFLA_IPTUN_MAX,
> +	.parse_opt = iptunnel_parse_opt,
> +	.print_opt = iptunnel_print_opt,
> +};
> +
> +struct link_util sit_link_util = {
> +	.id = "sit",
> +	.maxattr = IFLA_IPTUN_MAX,
> +	.parse_opt = iptunnel_parse_opt,
> +	.print_opt = iptunnel_print_opt,
> +};

All applied with minor corrections to header files.

Could you please add man pages for this new functionality?

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

* Re: [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'
  2012-12-12 17:11   ` Stephen Hemminger
@ 2012-12-12 17:20     ` Nicolas Dichtel
  0 siblings, 0 replies; 10+ messages in thread
From: Nicolas Dichtel @ 2012-12-12 17:20 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev

Le 12/12/2012 18:11, Stephen Hemminger a écrit :
> On Wed, 12 Dec 2012 10:51:47 +0100
> Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:
>
>> This patch allows to manage ip tunnels via the interface ip link.
>> The syntax for parameters is the same that 'ip tunnel'.
>>
>> It also allows to display tunnels parameters with 'ip -details link' or
>> 'ip -details monitor link'.
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> ---
>>   ip/Makefile     |   3 +-
>>   ip/iplink.c     |   2 +-
>>   ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 343 insertions(+), 2 deletions(-)
>>   create mode 100644 ip/link_iptnl.c
>>
>> diff --git a/ip/Makefile b/ip/Makefile
>> index abf54bf..2b606d4 100644
>> --- a/ip/Makefile
>> +++ b/ip/Makefile
>> @@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
>>       ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
>>       iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
>>       iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
>> -    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
>> +    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
>> +    link_iptnl.o
>>
>>   RTMONOBJ=rtmon.o
>>
>> diff --git a/ip/iplink.c b/ip/iplink.c
>> index 8aac9fc..d73c705 100644
>> --- a/ip/iplink.c
>> +++ b/ip/iplink.c
>> @@ -84,7 +84,7 @@ void iplink_usage(void)
>>   	if (iplink_have_newlink()) {
>>   		fprintf(stderr, "\n");
>>   		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
>> -		fprintf(stderr, "          bridge | ipoib | ip6tnl }\n");
>> +		fprintf(stderr, "          bridge | ipoib | ip6tnl | ipip | sit }\n");
>>   	}
>>   	exit(-1);
>>   }
>> diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
>> new file mode 100644
>> index 0000000..238722d
>> --- /dev/null
>> +++ b/ip/link_iptnl.c
>> @@ -0,0 +1,340 @@
>> +/*
>> + * link_iptnl.c	ipip and sit driver module
>> + *
>> + *		This program is free software; you can redistribute it and/or
>> + *		modify it under the terms of the GNU General Public License
>> + *		as published by the Free Software Foundation; either version
>> + *		2 of the License, or (at your option) any later version.
>> + *
>> + * Authors:	Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> + *
>> + */
>> +
>> +#include <string.h>
>> +#include <net/if.h>
>> +#include <sys/types.h>
>> +#include <sys/socket.h>
>> +#include <arpa/inet.h>
>> +
>> +#include <linux/ip.h>
>> +#include <linux/if_tunnel.h>
>> +#include "rt_names.h"
>> +#include "utils.h"
>> +#include "ip_common.h"
>> +#include "tunnel.h"
>> +
>> +static void usage(int sit) __attribute__((noreturn));
>> +static void usage(int sit)
>> +{
>> +	fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
>> +	fprintf(stderr, "          type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n");
>> +	fprintf(stderr, "          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
>> +	fprintf(stderr, "          [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
>> +	if (sit)
>> +		fprintf(stderr, "          [ isatap ]\n");
>> +	fprintf(stderr, "\n");
>> +	fprintf(stderr, "Where: NAME := STRING\n");
>> +	fprintf(stderr, "       ADDR := { IP_ADDRESS | any }\n");
>> +	fprintf(stderr, "       TOS  := { NUMBER | inherit }\n");
>> +	fprintf(stderr, "       TTL  := { 1..255 | inherit }\n");
>> +	exit(-1);
>> +}
>> +
>> +static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
>> +			      struct nlmsghdr *n)
>> +{
>> +	struct {
>> +		struct nlmsghdr n;
>> +		struct ifinfomsg i;
>> +		char buf[2048];
>> +	} req;
>> +	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
>> +	struct rtattr *tb[IFLA_MAX + 1];
>> +	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
>> +	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
>> +	int len;
>> +	__u32 link = 0;
>> +	__u32 laddr = 0;
>> +	__u32 raddr = 0;
>> +	__u8 ttl = 0;
>> +	__u8 tos = 0;
>> +	__u8 pmtudisc = 1;
>> +	__u16 iflags = 0;
>> +	struct in6_addr ip6rdprefix;
>> +	__u16 ip6rdprefixlen = 0;
>> +	__u32 ip6rdrelayprefix = 0;
>> +	__u16 ip6rdrelayprefixlen = 0;
>> +
>> +	memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));
>> +
>> +	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
>> +		memset(&req, 0, sizeof(req));
>> +
>> +		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
>> +		req.n.nlmsg_flags = NLM_F_REQUEST;
>> +		req.n.nlmsg_type = RTM_GETLINK;
>> +		req.i.ifi_family = preferred_family;
>> +		req.i.ifi_index = ifi->ifi_index;
>> +
>> +		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
>> +get_failed:
>> +			fprintf(stderr,
>> +				"Failed to get existing tunnel info.\n");
>> +			return -1;
>> +		}
>> +
>> +		len = req.n.nlmsg_len;
>> +		len -= NLMSG_LENGTH(sizeof(*ifi));
>> +		if (len < 0)
>> +			goto get_failed;
>> +
>> +		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
>> +
>> +		if (!tb[IFLA_LINKINFO])
>> +			goto get_failed;
>> +
>> +		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
>> +
>> +		if (!linkinfo[IFLA_INFO_DATA])
>> +			goto get_failed;
>> +
>> +		parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
>> +				    linkinfo[IFLA_INFO_DATA]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_LOCAL])
>> +			laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_REMOTE])
>> +			raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_TTL])
>> +			ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_TOS])
>> +			tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_PMTUDISC])
>> +			pmtudisc =
>> +				rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_FLAGS])
>> +			iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_LINK])
>> +			link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
>> +			memcpy(&ip6rdprefix,
>> +			       RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
>> +			       sizeof(laddr));
>> +
>> +		if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
>> +			ip6rdprefixlen =
>> +				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
>> +			ip6rdrelayprefix =
>> +				rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
>> +
>> +		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
>> +			ip6rdrelayprefixlen =
>> +				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
>> +	}
>> +
>> +	while (argc > 0) {
>> +		if (strcmp(*argv, "remote") == 0) {
>> +			NEXT_ARG();
>> +			if (strcmp(*argv, "any"))
>> +				raddr = get_addr32(*argv);
>> +			else
>> +				raddr = 0;
>> +		} else if (strcmp(*argv, "local") == 0) {
>> +			NEXT_ARG();
>> +			if (strcmp(*argv, "any"))
>> +				laddr = get_addr32(*argv);
>> +			else
>> +				laddr = 0;
>> +		} else if (matches(*argv, "dev") == 0) {
>> +			NEXT_ARG();
>> +			link = if_nametoindex(*argv);
>> +			if (link == 0)
>> +				invarg("\"dev\" is invalid", *argv);
>> +		} else if (strcmp(*argv, "ttl") == 0 ||
>> +			   strcmp(*argv, "hoplimit") == 0) {
>> +			NEXT_ARG();
>> +			if (strcmp(*argv, "inherit") != 0) {
>> +				if (get_u8(&ttl, *argv, 0))
>> +					invarg("invalid TTL\n", *argv);
>> +			} else
>> +				ttl = 0;
>> +		} else if (strcmp(*argv, "tos") == 0 ||
>> +			   strcmp(*argv, "tclass") == 0 ||
>> +			   matches(*argv, "dsfield") == 0) {
>> +			__u32 uval;
>> +			NEXT_ARG();
>> +			if (strcmp(*argv, "inherit") != 0) {
>> +				if (rtnl_dsfield_a2n(&uval, *argv))
>> +					invarg("bad TOS value", *argv);
>> +				tos = uval;
>> +			} else
>> +				tos = 1;
>> +		} else if (strcmp(*argv, "nopmtudisc") == 0) {
>> +			pmtudisc = 0;
>> +		} else if (strcmp(*argv, "pmtudisc") == 0) {
>> +			pmtudisc = 1;
>> +		} else if (strcmp(lu->id, "sit") == 0 &&
>> +			   strcmp(*argv, "isatap") == 0) {
>> +			iflags |= SIT_ISATAP;
>> +		} else if (strcmp(*argv, "6rd-prefix") == 0) {
>> +			inet_prefix prefix;
>> +			NEXT_ARG();
>> +			if (get_prefix(&prefix, *argv, AF_INET6))
>> +				invarg("invalid 6rd_prefix\n", *argv);
>> +			memcpy(&ip6rdprefix, prefix.data, 16);
>> +			ip6rdprefixlen = prefix.bitlen;
>> +		} else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
>> +			inet_prefix prefix;
>> +			NEXT_ARG();
>> +			if (get_prefix(&prefix, *argv, AF_INET))
>> +				invarg("invalid 6rd-relay_prefix\n", *argv);
>> +			memcpy(&ip6rdrelayprefix, prefix.data, 4);
>> +			ip6rdrelayprefixlen = prefix.bitlen;
>> +		} else if (strcmp(*argv, "6rd-reset") == 0) {
>> +			inet_prefix prefix;
>> +			get_prefix(&prefix, "2002::", AF_INET6);
>> +			memcpy(&ip6rdprefix, prefix.data, 16);
>> +			ip6rdprefixlen = 16;
>> +			ip6rdrelayprefix = 0;
>> +			ip6rdrelayprefixlen = 0;
>> +		} else
>> +			usage(strcmp(lu->id, "sit") == 0);
>> +		argc--, argv++;
>> +	}
>> +
>> +	if (ttl && pmtudisc == 0) {
>> +		fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
>> +		exit(-1);
>> +	}
>> +
>> +	addattr32(n, 1024, IFLA_IPTUN_LINK, link);
>> +	addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
>> +	addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
>> +	addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
>> +	addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
>> +	addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
>> +	if (strcmp(lu->id, "sit") == 0) {
>> +		addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
>> +		if (ip6rdprefixlen) {
>> +			addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
>> +				  &ip6rdprefix, sizeof(ip6rdprefix));
>> +			addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
>> +				  ip6rdprefixlen);
>> +			addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
>> +				  ip6rdrelayprefix);
>> +			addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
>> +				  ip6rdrelayprefixlen);
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
>> +{
>> +	char s1[1024];
>> +	char s2[64];
>> +	const char *local = "any";
>> +	const char *remote = "any";
>> +
>> +	if (!tb)
>> +		return;
>> +
>> +	if (tb[IFLA_IPTUN_REMOTE]) {
>> +		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
>> +
>> +		if (addr)
>> +			remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
>> +	}
>> +
>> +	fprintf(f, "remote %s ", remote);
>> +
>> +	if (tb[IFLA_IPTUN_LOCAL]) {
>> +		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
>> +
>> +		if (addr)
>> +			local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
>> +	}
>> +
>> +	fprintf(f, "local %s ", local);
>> +
>> +	if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
>> +		unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
>> +		const char *n = if_indextoname(link, s2);
>> +
>> +		if (n)
>> +			fprintf(f, "dev %s ", n);
>> +		else
>> +			fprintf(f, "dev %u ", link);
>> +	}
>> +
>> +	if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
>> +		fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
>> +	else
>> +		fprintf(f, "ttl inherit ");
>> +
>> +	if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
>> +		int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
>> +
>> +		fputs("tos ", f);
>> +		if (tos == 1)
>> +			fputs("inherit ", f);
>> +		else
>> +			fprintf(f, "0x%x ", tos);
>> +	}
>> +
>> +	if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
>> +		fprintf(f, "pmtudisc ");
>> +	else
>> +		fprintf(f, "nopmtudisc ");
>> +
>> +	if (tb[IFLA_IPTUN_FLAGS]) {
>> +	       __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
>> +
>> +	      if (iflags & SIT_ISATAP)
>> +		      fprintf(f, "isatap ");
>> +	}
>> +
>> +	if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
>> +	    *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) {
>> +		__u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]);
>> +		__u16 relayprefixlen =
>> +			rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
>> +		__u32 relayprefix =
>> +			rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
>> +
>> +		printf("6rd-prefix %s/%u ",
>> +		       inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
>> +			         s1, sizeof(s1)),
>> +		       prefixlen);
>> +		if (relayprefix) {
>> +			printf("6rd-relay_prefix %s/%u ",
>> +			       format_host(AF_INET, 4, &relayprefix, s1,
>> +				           sizeof(s1)),
>> +			       relayprefixlen);
>> +		}
>> +	}
>> +}
>> +
>> +struct link_util ipip_link_util = {
>> +	.id = "ipip",
>> +	.maxattr = IFLA_IPTUN_MAX,
>> +	.parse_opt = iptunnel_parse_opt,
>> +	.print_opt = iptunnel_print_opt,
>> +};
>> +
>> +struct link_util sit_link_util = {
>> +	.id = "sit",
>> +	.maxattr = IFLA_IPTUN_MAX,
>> +	.parse_opt = iptunnel_parse_opt,
>> +	.print_opt = iptunnel_print_opt,
>> +};
>
> All applied with minor corrections to header files.
>
> Could you please add man pages for this new functionality?
>
Ok.

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

* Re: [PATCH net-next] uapi: add missing netconf.h to export list
  2012-12-12 17:04   ` Nicolas Dichtel
@ 2012-12-12 17:40     ` David Miller
  0 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2012-12-12 17:40 UTC (permalink / raw)
  To: nicolas.dichtel; +Cc: shemminger, netdev

From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Wed, 12 Dec 2012 18:04:26 +0100

> Le 12/12/2012 17:58, Stephen Hemminger a écrit :
>> Add netconf.h for use by iproute2.
>>
>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>

Applied.

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

end of thread, other threads:[~2012-12-12 17:40 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-12  9:51 [PATCH iproute2 1/3] ip: add support of netconf messages Nicolas Dichtel
2012-12-12  9:51 ` [PATCH iproute2 2/3] ip: add support of 'ip link type ip6tnl' Nicolas Dichtel
2012-12-12  9:51 ` [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]' Nicolas Dichtel
2012-12-12 17:11   ` Stephen Hemminger
2012-12-12 17:20     ` Nicolas Dichtel
2012-12-12 16:58 ` [PATCH net-next] uapi: add missing netconf.h to export list Stephen Hemminger
2012-12-12 17:04   ` Nicolas Dichtel
2012-12-12 17:40     ` David Miller
2012-12-12 16:59 ` [PATCH iproute2 1/3] ip: add support of netconf messages Stephen Hemminger
2012-12-12 17:03   ` Nicolas Dichtel

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).