This provides support for Ubuntu's Fan Networking [1]. These patches were pulled from: https://code.launchpad.net/~ubuntu-branches/ubuntu/vivid/iproute2/vivid-proposed See revisions 18 and 19. [1] https://wiki.ubuntu.com/FanNetworking diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index 102ce7a..7b8f0e5 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -57,6 +57,9 @@ enum { IFLA_IPTUN_ENCAP_FLAGS, IFLA_IPTUN_ENCAP_SPORT, IFLA_IPTUN_ENCAP_DPORT, + + IFLA_IPTUN_FAN_UNDERLAY = 32, + IFLA_IPTUN_FAN_MAP = 33, __IFLA_IPTUN_MAX, }; #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) @@ -131,4 +134,20 @@ enum { }; #define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) + +enum { + IFLA_FAN_UNSPEC, + IFLA_FAN_MAPPING, + __IFLA_FAN_MAX, +}; + +#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1) + +struct ip_tunnel_fan_map { + __be32 underlay; + __be32 overlay; + __u16 underlay_prefix; + __u16 overlay_prefix; +}; + #endif /* _IF_TUNNEL_H_ */ diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 9d6bc98..ec3f05d 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -49,6 +49,42 @@ static void usage(int sit) print_usage(stderr, sit); exit(-1); } +static int fan_parse_map(int *argcp, char ***argvp, struct nlmsghdr *n) +{ + inet_prefix underlay, overlay; + struct ip_tunnel_fan_map map; + struct rtattr *nest; + char **argv = *argvp; + int argc = *argcp; + + nest = addattr_nest(n, 1024, IFLA_IPTUN_FAN_MAP); + while (argc > 0) { + char *colon = strchr(*argv, ':'); + + if (!colon) + break; + *colon = '\0'; + + if (get_prefix(&overlay, *argv, AF_INET)) + invarg("invalid fan-map overlay", *argv); + if (get_prefix(&underlay, colon + 1, AF_INET)) + invarg("invalid fan-map underlay", colon + 1); + + memcpy(&map.underlay, underlay.data, 4); + map.underlay_prefix = underlay.bitlen; + memcpy(&map.overlay, overlay.data, 4); + map.overlay_prefix = overlay.bitlen; + + argc--, argv++; + + addattr_l(n, 1024, IFLA_FAN_MAPPING, &map, sizeof(map)); + } + addattr_nest_end(n, nest); + + *argcp = argc; + *argvp = argv; + return 0; +} static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) @@ -66,6 +102,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, __u32 link = 0; __u32 laddr = 0; __u32 raddr = 0; + __u32 underlay = 0; __u8 ttl = 0; __u8 tos = 0; __u8 pmtudisc = 1; @@ -174,6 +211,13 @@ get_failed: raddr = get_addr32(*argv); else raddr = 0; + } else if (strcmp(*argv, "underlay") == 0) { + NEXT_ARG(); + underlay = get_addr32(*argv); + } else if (strcmp(*argv, "fan-map") == 0) { + NEXT_ARG(); + if (fan_parse_map(&argc, &argv, n)) + invarg("invalid fan-map", *argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) @@ -318,9 +362,32 @@ get_failed: } } + if (underlay) + addattr32(n, 1024, IFLA_IPTUN_FAN_UNDERLAY, underlay); + return 0; } +static void fan_print_map(FILE *f, struct rtattr *attr) +{ + char b1[INET_ADDRSTRLEN], b2[INET_ADDRSTRLEN]; + struct ip_tunnel_fan_map *m; + struct rtattr *i; + int rem; + + fprintf(f, "fan-map "); + + rem = RTA_PAYLOAD(attr); + for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { + m = RTA_DATA(i); + fprintf(f, "%s/%d:%s/%d ", + rt_addr_n2a(AF_INET, sizeof(m->overlay), &m->overlay, b1, INET_ADDRSTRLEN), + m->overlay_prefix, + rt_addr_n2a(AF_INET, sizeof(m->overlay), &m->underlay, b2, INET_ADDRSTRLEN), + m->underlay_prefix); + } +} + static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { char s1[1024]; @@ -349,6 +416,17 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ fprintf(f, "local %s ", local); + if (tb[IFLA_IPTUN_FAN_UNDERLAY]) { + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_FAN_UNDERLAY]); + + if (addr) + fprintf(f, "underlay %s ", + format_host(AF_INET, 4, &addr, s1, sizeof(s1))); + } + + if (tb[IFLA_IPTUN_FAN_MAP]) + fan_print_map(f, tb[IFLA_IPTUN_FAN_MAP]); + if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); const char *n = if_indextoname(link, s2);