From 5866bddd9aa9eba57623d57f866afaee9a5e2597 Mon Sep 17 00:00:00 2001 From: Tom Herbert Date: Mon, 30 Nov 2015 14:57:28 -0800 Subject: ila: Add support for ILA lwtunnels 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 --- include/linux/ila.h | 15 +++++++++++++ include/utils.h | 4 ++++ ip/iproute_lwtunnel.c | 45 +++++++++++++++++++++++++++++++++++++++ lib/utils.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 include/linux/ila.h 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 1d35149..cc821e8 100644 --- a/include/utils.h +++ b/include/utils.h @@ -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); diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 63322a1..b2764a6 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -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; 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; -- cgit v1.2.3 From e834eb8ebaf7b0ceb504f3dc4adf5c99f38ee93c Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Tue, 1 Dec 2015 01:17:06 +0300 Subject: ip neigh: device is optional for proxy entries Though dumping such entries crashes present kernels. Signed-off-by: Konstantin Khlebnikov --- ip/ipneigh.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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; } -- cgit v1.2.3 From ed6b8652f7d5470cac7fd763b4a47d07a3a0bfb6 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sat, 12 Dec 2015 14:09:48 +0100 Subject: route: Fix printing of locked entries Commit 0f7543322c5fd ("route: ignore RTAX_HOPLIMIT of value -1") accidentally reordered fprintf statements. This patch restores the original ordering. Fixes: 0f7543322c5fd ("route: ignore RTAX_HOPLIMIT of value -1") Signed-off-by: Phil Sutter --- ip/iproute.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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< Date: Tue, 15 Dec 2015 12:18:04 +0100 Subject: lwtunnel: fix argument parsing Currently parse_encap_ip() does not update correctly argv/argc; if multiple lwtunnel arguments are provided, the parsing fails after the first one, i.e. ip route add 172.16.101.0/24 dev vxlan1 encap ip id 42 dst 192.168.255.1 fails with: Error: either "to" is duplicate, or "dst" is a garbage. This commit addresses the issue, stepping to next argument at each iteration of the parsing loop. Fixes: 1e5293056a02 ("lwtunnel: Add encapsulation support to ip route") Signed-off-by: Paolo Abeni --- ip/iproute_lwtunnel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index b2764a6..1243977 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -201,10 +201,14 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, int *argcp, char ***ar } else { break; } + argc--; argv++; } - *argcp = argc; - *argvp = 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; } -- cgit v1.2.3