diff --git a/config.ini b/config.ini index 73702a7e9..f826168d1 100644 --- a/config.ini +++ b/config.ini @@ -79,6 +79,11 @@ addr=192.168.1.2 netmask=255.255.225.0 broadcast=192.168.1.255 gateway=192.168.1.1 +# IPv6 net addr +# Optional parameters +#addr6=ff::02 +#prefix_len=64 +#gateway6=ff::01 # lcore list used to handle this port # the format is same as port_list diff --git a/lib/ff_config.c b/lib/ff_config.c index cb5aa8c8e..933fec9ae 100644 --- a/lib/ff_config.c +++ b/lib/ff_config.c @@ -430,6 +430,21 @@ port_cfg_handler(struct ff_config *cfg, const char *section, return parse_port_slave_list(cur, value); } +#ifdef INET6 + else if (0 == strcmp(name, "addr6")) + { + cur->addr6_str = strdup(value); + } + else if (0 == strcmp(name, "prefix_len")) + { + cur->prefix_len = atoi(value); + } + else if (0 == strcmp(name, "gateway6")) + { + cur->gateway6_str = strdup(value); + } +#endif + return 1; } diff --git a/lib/ff_config.h b/lib/ff_config.h index 047f84e7f..37630b1aa 100644 --- a/lib/ff_config.h +++ b/lib/ff_config.h @@ -61,6 +61,13 @@ struct ff_port_cfg { char *netmask; char *broadcast; char *gateway; + +#ifdef INET6 + char *addr6_str; + char *gateway6_str; + uint8_t prefix_len; +#endif + char *pcap; uint16_t snaplen; uint32_t savelen; diff --git a/lib/ff_veth.c b/lib/ff_veth.c index 3e70ac83e..58455db0b 100644 --- a/lib/ff_veth.c +++ b/lib/ff_veth.c @@ -51,6 +51,7 @@ #include #include +#include #include @@ -68,6 +69,12 @@ struct ff_veth_softc { in_addr_t broadcast; in_addr_t gateway; +#ifdef INET6 + struct in6_addr ip6; + struct in6_addr gateway6; + uint8_t prefix_length; +#endif /* INET6 */ + struct ff_dpdk_if_context *host_ctx; }; @@ -80,6 +87,24 @@ ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) inet_pton(AF_INET, cfg->broadcast, &sc->broadcast); inet_pton(AF_INET, cfg->gateway, &sc->gateway); +#ifdef INET6 + if (cfg->addr6_str) { + inet_pton(AF_INET6_LINUX, cfg->addr6_str, &sc->ip6); + printf("%s: Addr6: %s\n", sc->host_ifname, cfg->addr6_str); + + if (cfg->gateway6_str) { + inet_pton(AF_INET6_LINUX, cfg->gateway6_str, &sc->gateway6); + printf("%s: Gateway6: %s\n", sc->host_ifname, cfg->gateway6_str); + } else { + printf("%s: No gateway6 config found.\n", sc->host_ifname); + } + + sc->prefix_length = cfg->prefix_len == 0 ? 64 : cfg->prefix_len; + } else { + printf("%s: No addr6 config found.\n", sc->host_ifname); + } +#endif /* INET6 */ + return 0; } @@ -309,6 +334,57 @@ ff_veth_set_gateway(struct ff_veth_softc *sc) (struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB); } +#ifdef INET6 +static int +ff_veth_setaddr6(struct ff_veth_softc *sc) +{ + struct in6_aliasreq ifr6; + bzero(&ifr6, sizeof(ifr6)); + strcpy(ifr6.ifra_name, sc->ifp->if_dname); + + ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr; + ifr6.ifra_addr.sin6_family = AF_INET6; + ifr6.ifra_addr.sin6_addr = sc->ip6; + + ifr6.ifra_prefixmask.sin6_len = sizeof ifr6.ifra_prefixmask; + memset(&ifr6.ifra_prefixmask.sin6_addr, 0xff, sc->prefix_length / 8); + uint8_t mask_size_mod = sc->prefix_length % 8; + if (mask_size_mod) + { + ifr6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr8[sc->prefix_length / 8] = ((1 << mask_size_mod) - 1) << (8 - mask_size_mod); + } + + ifr6.ifra_lifetime.ia6t_pltime = ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + + struct socket *so = NULL; + socreate(AF_INET6, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread); + int ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread); + + sofree(so); + + return ret; +} + +static int +ff_veth_set_gateway6(struct ff_veth_softc *sc) +{ + struct sockaddr_in6 gw, dst, nm; + + bzero(&gw, sizeof(gw)); + bzero(&dst, sizeof(dst)); + bzero(&nm, sizeof(nm)); + + gw.sin6_len = dst.sin6_len = nm.sin6_len = sizeof(struct sockaddr_in6); + gw.sin6_family = dst.sin6_family = AF_INET6; + + gw.sin6_addr = sc->gateway6; + //dst.sin6_addr = nm.sin6_addr = 0; + + return rtrequest_fib(RTM_ADD, (struct sockaddr *)&dst, (struct sockaddr *)&gw, + (struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB); +} +#endif /* INET6 */ + static int ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) { @@ -360,6 +436,23 @@ ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg) printf("ff_veth_set_gateway failed\n"); } +#ifdef INET6 + // Set IPv6 + if (cfg->addr6_str) { + ret = ff_veth_setaddr6(sc); + if (ret != 0) { + printf("ff_veth_setaddr6 failed\n"); + } + + if (cfg->gateway6_str) { + ret = ff_veth_set_gateway6(sc); + if (ret != 0) { + printf("ff_veth_set_gateway6 failed\n"); + } + } + } +#endif /* INET6 */ + return (0); }