]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
vxlan: add ipv6 support
authorWANG Cong <xiyou.wangcong@gmail.com>
Thu, 17 Oct 2013 05:03:48 +0000 (22:03 -0700)
committerStephen Hemminger <stephen@networkplumber.org>
Wed, 30 Oct 2013 23:37:05 +0000 (16:37 -0700)
The kernel already supports it, so add the support
to iproute2 as well.

Cc: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
include/utils.h
ip/iplink_vxlan.c
lib/utils.c

index 24ff19f80530ab5804e58d3a4fb23998d727214c..a3e310eeb5d20bcf89393f2ac0e531805a8f82bf 100644 (file)
@@ -151,6 +151,7 @@ int print_timestamp(FILE *fp);
 extern int cmdlineno;
 extern ssize_t getcmdline(char **line, size_t *len, FILE *in);
 extern int makeargs(char *line, char *argv[], int maxargs);
+extern int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6);
 
 struct iplink_req;
 int iplink_parse(int argc, char **argv, struct iplink_req *req,
index 4304b0d1317488aac86bd52127861a10397ba10d..aa551d89913ac97c5758c6ae3744854841d9c8c3 100644 (file)
@@ -43,6 +43,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
        __u32 saddr = 0;
        __u32 gaddr = 0;
        __u32 daddr = 0;
+       struct in6_addr saddr6 = IN6ADDR_ANY_INIT;
+       struct in6_addr gaddr6 = IN6ADDR_ANY_INIT;
+       struct in6_addr daddr6 = IN6ADDR_ANY_INIT;
        unsigned link = 0;
        __u8 tos = 0;
        __u8 ttl = 0;
@@ -66,21 +69,30 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
                        vni_set = 1;
                } else if (!matches(*argv, "group")) {
                        NEXT_ARG();
-                       gaddr = get_addr32(*argv);
-
-                       if (!IN_MULTICAST(ntohl(gaddr)))
+                       if (!inet_get_addr(*argv, &gaddr, &gaddr6)) {
+                               fprintf(stderr, "Invalid address \"%s\"\n", *argv);
+                               return -1;
+                       }
+                       if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr)))
                                invarg("invalid group address", *argv);
                } else if (!matches(*argv, "remote")) {
                        NEXT_ARG();
-                       daddr = get_addr32(*argv);
-
-                       if (IN_MULTICAST(ntohl(daddr)))
+                       if (!inet_get_addr(*argv, &daddr, &daddr6)) {
+                               fprintf(stderr, "Invalid address \"%s\"\n", *argv);
+                               return -1;
+                       }
+                       if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr)))
                                invarg("invalid remote address", *argv);
                } else if (!matches(*argv, "local")) {
                        NEXT_ARG();
-                       if (strcmp(*argv, "any"))
-                               saddr = get_addr32(*argv);
-                       if (IN_MULTICAST(ntohl(saddr)))
+                       if (strcmp(*argv, "any")) {
+                               if (!inet_get_addr(*argv, &saddr, &saddr6)) {
+                                       fprintf(stderr, "Invalid address \"%s\"\n", *argv);
+                                       return -1;
+                               }
+                       }
+
+                       if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6))
                                invarg("invalid local address", *argv);
                } else if (!matches(*argv, "dev")) {
                        NEXT_ARG();
@@ -167,7 +179,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
                fprintf(stderr, "vxlan: missing virtual network identifier\n");
                return -1;
        }
-       if (gaddr && daddr) {
+       if ((gaddr && daddr) ||
+               (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) &&
+                memcmp(&daddr6, &in6addr_any, sizeof(daddr6)))) {
                fprintf(stderr, "vxlan: both group and remote cannot be specified\n");
                return -1;
        }
@@ -176,8 +190,16 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
                addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
        else if (daddr)
                addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
+       if (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) != 0)
+               addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr));
+       else if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0)
+               addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
+
        if (saddr)
                addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4);
+       else if (memcmp(&saddr6, &in6addr_any, sizeof(saddr6)) != 0)
+               addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6, sizeof(struct in6_addr));
+
        if (link)
                addattr32(n, 1024, IFLA_VXLAN_LINK, link);
        addattr8(n, 1024, IFLA_VXLAN_TTL, ttl);
@@ -229,6 +251,17 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
                                fprintf(f, "remote %s ",
                                        format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
                }
+       } else if (tb[IFLA_VXLAN_GROUP6]) {
+               struct in6_addr addr;
+               memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr));
+               if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) {
+                       if (IN6_IS_ADDR_MULTICAST(&addr))
+                               fprintf(f, "group %s ",
+                                       format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
+                       else
+                               fprintf(f, "remote %s ",
+                                       format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
+               }
        }
 
        if (tb[IFLA_VXLAN_LOCAL]) {
@@ -236,6 +269,12 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
                if (addr)
                        fprintf(f, "local %s ",
                                format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
+       } else if (tb[IFLA_VXLAN_LOCAL6]) {
+               struct in6_addr addr;
+               memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr));
+               if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0)
+                       fprintf(f, "local %s ",
+                               format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1)));
        }
 
        if (tb[IFLA_VXLAN_LINK] &&
index dae1b51812e0b9b03fc5d58337c838d45f91b8f1..4e9c719aead2be0d0e8c3cc7005b36d005ad57fa 100644 (file)
@@ -868,3 +868,11 @@ int makeargs(char *line, char *argv[], int maxargs)
 
        return argc;
 }
+
+int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6)
+{
+       if (strchr(src, ':'))
+               return inet_pton(AF_INET6, src, dst6);
+       else
+               return inet_pton(AF_INET, src, dst);
+}