]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
ila: Add support for ILA lwtunnels
authorTom Herbert <tom@herbertland.com>
Mon, 30 Nov 2015 22:57:28 +0000 (14:57 -0800)
committerStephen Hemminger <shemming@brocade.com>
Fri, 18 Dec 2015 01:07:07 +0000 (17:07 -0800)
This patch:
 - Adds a utility function for parsing a 64 bit address
 - Adds a utility function for converting a 64 bit address to ASCII
 - Adds and ILA encap type in lwt tunnels

Signed-off-by: Tom Herbert <tom@herbertland.com>
include/linux/ila.h [new file with mode: 0644]
include/utils.h
ip/iproute_lwtunnel.c
lib/utils.c

diff --git a/include/linux/ila.h b/include/linux/ila.h
new file mode 100644 (file)
index 0000000..f08e8d7
--- /dev/null
@@ -0,0 +1,15 @@
+/* ila.h - ILA Interface */
+
+#ifndef _LINUX_ILA_H
+#define _LINUX_ILA_H
+
+enum {
+       ILA_ATTR_UNSPEC,
+       ILA_ATTR_LOCATOR,                       /* u64 */
+
+       __ILA_ATTR_MAX,
+};
+
+#define ILA_ATTR_MAX           (__ILA_ATTR_MAX - 1)
+
+#endif /* _LINUX_ILA_H */
index 1d351490a150e0c84e6411cf155370b4571576ed..cc821e80b257e719b363edaa51c745996377385b 100644 (file)
@@ -93,6 +93,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family);
 int get_addr(inet_prefix *dst, const char *arg, int family);
 int get_prefix(inet_prefix *dst, char *arg, int family);
 int mask2bits(__u32 netmask);
+int get_addr_ila(__u64 *val, const char *arg);
 
 int get_integer(int *val, const char *arg, int base);
 int get_unsigned(unsigned *val, const char *arg, int base);
@@ -107,9 +108,12 @@ int get_u16(__u16 *val, const char *arg, int base);
 int get_s16(__s16 *val, const char *arg, int base);
 int get_u8(__u8 *val, const char *arg, int base);
 int get_s8(__s8 *val, const char *arg, int base);
+int get_addr64(__u64 *ap, const char *cp);
 
 char* hexstring_n2a(const __u8 *str, int len, char *buf, int blen);
 __u8* hexstring_a2n(const char *str, __u8 *buf, int blen);
+#define ADDR64_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
+int addr64_n2a(__u64 addr, char *buff, size_t len);
 
 int af_bit_len(int af);
 int af_byte_len(int af);
index 63322a182f581c59b9bf2509401f06e34a762bf3..b2764a6caf73b3ac4a4ca556571cf03d3040b54a 100644 (file)
@@ -16,6 +16,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
+#include <linux/ila.h>
 #include <linux/lwtunnel.h>
 #include <linux/mpls_iptunnel.h>
 #include <errno.h>
@@ -32,6 +33,8 @@ static int read_encap_type(const char *name)
                return LWTUNNEL_ENCAP_IP;
        else if (strcmp(name, "ip6") == 0)
                return LWTUNNEL_ENCAP_IP6;
+       else if (strcmp(name, "ila") == 0)
+               return LWTUNNEL_ENCAP_ILA;
        else
                return LWTUNNEL_ENCAP_NONE;
 }
@@ -45,6 +48,8 @@ static const char *format_encap_type(int type)
                return "ip";
        case LWTUNNEL_ENCAP_IP6:
                return "ip6";
+       case LWTUNNEL_ENCAP_ILA:
+               return "ila";
        default:
                return "unknown";
        }
@@ -95,6 +100,21 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap)
                fprintf(fp, "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
 }
 
+static void print_encap_ila(FILE *fp, struct rtattr *encap)
+{
+       struct rtattr *tb[ILA_ATTR_MAX+1];
+
+       parse_rtattr_nested(tb, ILA_ATTR_MAX, encap);
+
+       if (tb[ILA_ATTR_LOCATOR]) {
+               char abuf[ADDR64_BUF_SIZE];
+
+               addr64_n2a(*(__u64 *)RTA_DATA(tb[ILA_ATTR_LOCATOR]),
+                          abuf, sizeof(abuf));
+               fprintf(fp, " %s ", abuf);
+       }
+}
+
 void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
                          struct rtattr *encap)
 {
@@ -114,6 +134,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
        case LWTUNNEL_ENCAP_IP:
                print_encap_ip(fp, encap);
                break;
+       case LWTUNNEL_ENCAP_ILA:
+               print_encap_ila(fp, encap);
+               break;
        }
 }
 
@@ -186,6 +209,25 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***ar
        return 0;
 }
 
+static int parse_encap_ila(struct rtattr *rta, size_t len,
+                          int *argcp, char ***argvp)
+{
+       __u64 locator;
+       int argc = *argcp;
+       char **argv = *argvp;
+
+       if (get_addr64(&locator, *argv) < 0) {
+               fprintf(stderr, "Bad locator: %s\n", *argv);
+               exit(1);
+       }
+
+       rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator);
+
+       *argcp = argc;
+       *argvp = argv;
+
+       return 0;
+}
 
 int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
 {
@@ -213,6 +255,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
        case LWTUNNEL_ENCAP_IP:
                parse_encap_ip(rta, len, &argc, &argv);
                break;
+       case LWTUNNEL_ENCAP_ILA:
+               parse_encap_ila(rta, len, &argc, &argv);
+               break;
        default:
                fprintf(stderr, "Error: unsupported encap type\n");
                break;
index 939a44f0dd32849058cac27a24c3190e3f699bf7..fa35f4d044064a2fc94f1b67f3ff0938bb23d842 100644 (file)
@@ -384,6 +384,41 @@ static int get_addr_ipv4(__u8 *ap, const char *cp)
        return 1;
 }
 
+int get_addr64(__u64 *ap, const char *cp)
+{
+       int i;
+
+       union {
+               __u16 v16[4];
+               __u64 v64;
+       } val;
+
+       for (i = 0; i < 4; i++) {
+               unsigned long n;
+               char *endp;
+
+               n = strtoul(cp, &endp, 16);
+               if (n > 0xffff)
+                       return -1;      /* bogus network value */
+
+               if (endp == cp) /* no digits */
+                       return -1;
+
+               val.v16[i] = htons(n);
+
+               if (*endp == '\0')
+                       break;
+
+               if (i == 3 || *endp != ':')
+                       return -1;      /* extra characters */
+               cp = endp + 1;
+       }
+
+       *ap = val.v64;
+
+       return 1;
+}
+
 int get_addr_1(inet_prefix *addr, const char *name, int family)
 {
        memset(addr, 0, sizeof(*addr));
@@ -838,6 +873,30 @@ __u8* hexstring_a2n(const char *str, __u8 *buf, int blen)
        return buf;
 }
 
+int addr64_n2a(__u64 addr, char *buff, size_t len)
+{
+       __u16 *words = (__u16 *)&addr;
+       __u16 v;
+       int i, ret;
+       size_t written = 0;
+       char *sep = ":";
+
+       for (i = 0; i < 4; i++) {
+               v = ntohs(words[i]);
+
+               if (i == 3)
+                       sep = "";
+
+               ret = snprintf(&buff[written], len - written, "%x%s", v, sep);
+               if (ret < 0)
+                       return ret;
+
+               written += ret;
+       }
+
+       return written;
+}
+
 int print_timestamp(FILE *fp)
 {
        struct timeval tv;