aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemming@brocade.com>2015-12-17 17:21:15 -0800
committerStephen Hemminger <shemming@brocade.com>2015-12-17 17:21:15 -0800
commit00a2a1748b03427310e5db4e2a6bd0676c0f4d1f (patch)
treebeb2e252e7a46ecbf1ba2a8801ab501a6473103c
parent41d6e33fc9e5b459b7f715acbd6d8dbeddf58576 (diff)
parentf0df40810f1c0bc86cf1fcb6f660b0fd9912b1d3 (diff)
downloadandroid_external_iproute2-00a2a1748b03427310e5db4e2a6bd0676c0f4d1f.tar.gz
android_external_iproute2-00a2a1748b03427310e5db4e2a6bd0676c0f4d1f.tar.bz2
android_external_iproute2-00a2a1748b03427310e5db4e2a6bd0676c0f4d1f.zip
Merge branch 'master' into net-next
-rw-r--r--include/linux/ila.h15
-rw-r--r--include/utils.h4
-rw-r--r--ip/ipneigh.c13
-rw-r--r--ip/iproute.c5
-rw-r--r--ip/iproute_lwtunnel.c51
-rw-r--r--lib/utils.c59
6 files changed, 139 insertions, 8 deletions
diff --git a/include/linux/ila.h b/include/linux/ila.h
new file mode 100644
index 0000000..f08e8d7
--- /dev/null
+++ b/include/linux/ila.h
@@ -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 */
diff --git a/include/utils.h b/include/utils.h
index e830be6..7310f4e 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -97,6 +97,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);
@@ -111,9 +112,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);
diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index 5465584..92b7cd6 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -100,8 +100,9 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
struct ndmsg ndm;
char buf[256];
} req;
- char *d = NULL;
+ char *dev = NULL;
int dst_ok = 0;
+ int dev_ok = 0;
int lladdr_ok = 0;
char * lla = NULL;
inet_prefix dst;
@@ -135,10 +136,12 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
duparg("address", *argv);
get_addr(&dst, *argv, preferred_family);
dst_ok = 1;
+ dev_ok = 1;
req.ndm.ndm_flags |= NTF_PROXY;
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
- d = *argv;
+ dev = *argv;
+ dev_ok = 1;
} else {
if (strcmp(*argv, "to") == 0) {
NEXT_ARG();
@@ -153,7 +156,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
}
argc--; argv++;
}
- if (d == NULL || !dst_ok || dst.family == AF_UNSPEC) {
+ if (!dev_ok || !dst_ok || dst.family == AF_UNSPEC) {
fprintf(stderr, "Device and destination are required arguments.\n");
exit(-1);
}
@@ -175,8 +178,8 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
ll_init_map(&rth);
- if ((req.ndm.ndm_ifindex = ll_name_to_index(d)) == 0) {
- fprintf(stderr, "Cannot find device \"%s\"\n", d);
+ if (dev && (req.ndm.ndm_ifindex = ll_name_to_index(dev)) == 0) {
+ fprintf(stderr, "Cannot find device \"%s\"\n", dev);
return -1;
}
diff --git a/ip/iproute.c b/ip/iproute.c
index c42ea0b..4d86a59 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -577,8 +577,6 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (mxrta[i] == NULL)
continue;
- if (mxlock & (1<<i))
- fprintf(fp, " lock");
if (i != RTAX_CC_ALGO)
val = rta_getattr_u32(mxrta[i]);
@@ -590,6 +588,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
else
fprintf(fp, " metric %d", i);
+ if (mxlock & (1<<i))
+ fprintf(fp, " lock");
+
switch (i) {
case RTAX_FEATURES:
print_rtax_features(fp, val);
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 63322a1..1243977 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -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;
}
}
@@ -178,15 +201,38 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***ar
} else {
break;
}
+ argc--; argv++;
+ }
+
+ /* argv is currently the first unparsed argument,
+ * but the lwt_parse_encap() caller will move to the next,
+ * so step back */
+ *argcp = argc + 1;
+ *argvp = argv - 1;
+
+ 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)
{
struct rtattr *nest;
@@ -213,6 +259,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;
diff --git a/lib/utils.c b/lib/utils.c
index 939a44f..fa35f4d 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -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;