From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
To: Stephen Hemminger <shemminger@vyatta.com>
Cc: netdev@vger.kernel.org
Subject: Re: [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'
Date: Wed, 12 Dec 2012 18:20:30 +0100 [thread overview]
Message-ID: <50C8BCDE.1080802@6wind.com> (raw)
In-Reply-To: <20121212091118.390b8a2b@nehalam.linuxnetplumber.net>
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.
next prev parent reply other threads:[~2012-12-12 17:20 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50C8BCDE.1080802@6wind.com \
--to=nicolas.dichtel@6wind.com \
--cc=netdev@vger.kernel.org \
--cc=shemminger@vyatta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.