aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2015-12-18 10:50:38 +0100
committerStephen Hemminger <shemming@brocade.com>2015-12-18 11:40:32 -0800
commitd95cdcf52b4c85c280e3a0aceff22238947d92c2 (patch)
tree166a5ddfe8dc42ee0b8a38480379bb351ebf853a
parent926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59 (diff)
downloadandroid_external_iproute2-d95cdcf52b4c85c280e3a0aceff22238947d92c2.tar.gz
android_external_iproute2-d95cdcf52b4c85c280e3a0aceff22238947d92c2.tar.bz2
android_external_iproute2-d95cdcf52b4c85c280e3a0aceff22238947d92c2.zip
lwtunnel: implement support for ip6 encap
Currently ip6 encap support for lwtunnel is missing. This patch implement it, mostly duplicating the ipv4 parts. Also be sure to insert a space after the encap type, when showing lwtunnel, to avoid the tunnel type and the following argument being merged into a single word. Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--ip/iproute_lwtunnel.c92
1 files changed, 91 insertions, 1 deletions
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 1243977..7074906 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -115,6 +115,37 @@ static void print_encap_ila(FILE *fp, struct rtattr *encap)
}
}
+static void print_encap_ip6(FILE *fp, struct rtattr *encap)
+{
+ struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
+ char abuf[256];
+
+ parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
+
+ if (tb[LWTUNNEL_IP6_ID])
+ fprintf(fp, "id %llu ", ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID])));
+
+ if (tb[LWTUNNEL_IP6_SRC])
+ fprintf(fp, "src %s ",
+ rt_addr_n2a(AF_INET6,
+ RTA_PAYLOAD(tb[LWTUNNEL_IP6_SRC]),
+ RTA_DATA(tb[LWTUNNEL_IP6_SRC]),
+ abuf, sizeof(abuf)));
+
+ if (tb[LWTUNNEL_IP6_DST])
+ fprintf(fp, "dst %s ",
+ rt_addr_n2a(AF_INET6,
+ RTA_PAYLOAD(tb[LWTUNNEL_IP6_DST]),
+ RTA_DATA(tb[LWTUNNEL_IP6_DST]),
+ abuf, sizeof(abuf)));
+
+ if (tb[LWTUNNEL_IP6_HOPLIMIT])
+ fprintf(fp, "hoplimit %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT]));
+
+ if (tb[LWTUNNEL_IP6_TC])
+ fprintf(fp, "tc %d ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
+}
+
void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
struct rtattr *encap)
{
@@ -125,7 +156,7 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
et = rta_getattr_u16(encap_type);
- fprintf(fp, " encap %s", format_encap_type(et));
+ fprintf(fp, " encap %s ", format_encap_type(et));
switch (et) {
case LWTUNNEL_ENCAP_MPLS:
@@ -137,6 +168,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
case LWTUNNEL_ENCAP_ILA:
print_encap_ila(fp, encap);
break;
+ case LWTUNNEL_ENCAP_IP6:
+ print_encap_ip6(fp, encap);
+ break;
}
}
@@ -233,6 +267,59 @@ static int parse_encap_ila(struct rtattr *rta, size_t len,
return 0;
}
+static int parse_encap_ip6(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
+{
+ int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
+ char **argv = *argvp;
+ int argc = *argcp;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "id") == 0) {
+ __u64 id;
+ NEXT_ARG();
+ if (id_ok++)
+ duparg2("id", *argv);
+ if (get_u64(&id, *argv, 0))
+ invarg("\"id\" value is invalid\n", *argv);
+ rta_addattr64(rta, len, LWTUNNEL_IP6_ID, htonll(id));
+ } else if (strcmp(*argv, "dst") == 0) {
+ inet_prefix addr;
+ NEXT_ARG();
+ if (dst_ok++)
+ duparg2("dst", *argv);
+ get_addr(&addr, *argv, AF_INET6);
+ rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, &addr.data, addr.bytelen);
+ } else if (strcmp(*argv, "tc") == 0) {
+ __u32 tc;
+ NEXT_ARG();
+ if (tos_ok++)
+ duparg2("tc", *argv);
+ if (rtnl_dsfield_a2n(&tc, *argv))
+ invarg("\"tc\" value is invalid\n", *argv);
+ rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
+ } else if (strcmp(*argv, "hoplimit") == 0) {
+ __u8 hoplimit;
+ NEXT_ARG();
+ if (ttl_ok++)
+ duparg2("hoplimit", *argv);
+ if (get_u8(&hoplimit, *argv, 0))
+ invarg("\"hoplimit\" value is invalid\n", *argv);
+ rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit);
+ } 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;
+}
+
int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
{
struct rtattr *nest;
@@ -262,6 +349,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
case LWTUNNEL_ENCAP_ILA:
parse_encap_ila(rta, len, &argc, &argv);
break;
+ case LWTUNNEL_ENCAP_IP6:
+ parse_encap_ip6(rta, len, &argc, &argv);
+ break;
default:
fprintf(stderr, "Error: unsupported encap type\n");
break;