Support set multi virtual IPv4/IPv6 net addrs in `config.ini`, instead of use `ff_ifconfig`.

Close #421.
This commit is contained in:
fengbojiang 2021-06-16 19:24:35 +08:00
parent 2ea8dd153c
commit 4e3599d820
4 changed files with 254 additions and 12 deletions

View File

@ -84,12 +84,23 @@ 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
# IPv6 net addr, Optional parameters.
#addr6=ff::02
#prefix_len=64
#gateway6=ff::01
# Multi virtual IPv4/IPv6 net addr, Optional parameters.
# `vip_ifname`: default `f-stack-x`
# `vip_addr`: Separated by semicolons, MAX number 64;
Only support netmask 255.255.255.255, broadcast x.x.x.255 now, hard code in `ff_veth_setvaddr`.
# `vip_addr6`: Separated by semicolons, MAX number 64.
# `vip_prefix_len`: All addr6 use the same prefix now, default 64.
#vip_ifname=lo0
#vip_addr=192.168.1.3;192.168.1.4;192.168.1.5;192.168.1.6
#vip_addr6=ff::03;ff::04;ff::05;ff::06;ff::07
#vip_prefix_len=64
# lcore list used to handle this port
# the format is same as port_list
#lcore_list=0

View File

@ -366,6 +366,81 @@ parse_port_slave_list(struct ff_port_cfg *cfg, const char *v_str)
return res;
}
static int
vip_cfg_hander(struct ff_port_cfg *cur)
{
//vip cfg
int ret;
char *vip_addr_array[VIP_MAX_NUM];
ret = rte_strsplit(cur->vip_addr_str, strlen(cur->vip_addr_str), &vip_addr_array[0], VIP_MAX_NUM, ';');
if (ret <= 0) {
fprintf(stdout, "vip_cfg_hander nb_vip is 0, not set vip_addr or set invalid vip_addr %s\n",
cur->vip_addr_str);
return 1;
}
cur->nb_vip = ret;
cur->vip_addr_array = (char **)calloc(cur->nb_vip, sizeof(char *));
if (cur->vip_addr_array == NULL) {
fprintf(stderr, "vip_cfg_hander malloc failed\n");
goto err;
}
memcpy(cur->vip_addr_array, vip_addr_array, cur->nb_vip * sizeof(char *));
return 1;
err:
cur->nb_vip = 0;
if (cur->vip_addr_array) {
free(cur->vip_addr_array);
cur->vip_addr_array = NULL;
}
return 0;
}
#ifdef INET6
static int
vip6_cfg_hander(struct ff_port_cfg *cur)
{
//vip6 cfg
int ret;
char *vip_addr6_array[VIP_MAX_NUM];
ret = rte_strsplit(cur->vip_addr6_str, strlen(cur->vip_addr6_str),
&vip_addr6_array[0], VIP_MAX_NUM, ';');
if (ret == 0) {
fprintf(stdout, "vip6_cfg_hander nb_vip6 is 0, not set vip_addr6 or set invalid vip_addr6 %s\n",
cur->vip_addr6_str);
return 1;
}
cur->nb_vip6 = ret;
cur->vip_addr6_array = (char **) calloc(cur->nb_vip6, sizeof(char *));
if (cur->vip_addr6_array == NULL) {
fprintf(stderr, "port_cfg_handler malloc failed\n");
goto fail;
}
memcpy(cur->vip_addr6_array, vip_addr6_array, cur->nb_vip6 * sizeof(char *));
return 1;
fail:
cur->nb_vip6 = 0;
if (cur->vip_addr6_array) {
free(cur->vip_addr6_array);
cur->vip_addr6_array = NULL;
}
return 0;
}
#endif
static int
port_cfg_handler(struct ff_config *cfg, const char *section,
const char *name, const char *value) {
@ -426,20 +501,29 @@ port_cfg_handler(struct ff_config *cfg, const char *section,
return parse_port_lcore_list(cur, value);
} else if (strcmp(name, "slave_port_list") == 0) {
return parse_port_slave_list(cur, value);
} else if (strcmp(name, "vip_addr") == 0) {
cur->vip_addr_str = strdup(value);
if (cur->vip_addr_str) {
return vip_cfg_hander(cur);
}
} else if (strcmp(name, "vip_ifname") == 0) {
cur->vip_ifname = strdup(value);
}
#ifdef INET6
else if (0 == strcmp(name, "addr6"))
{
else if (0 == strcmp(name, "addr6")) {
cur->addr6_str = strdup(value);
}
else if (0 == strcmp(name, "prefix_len"))
{
} else if (0 == strcmp(name, "prefix_len")) {
cur->prefix_len = atoi(value);
}
else if (0 == strcmp(name, "gateway6"))
{
} else if (0 == strcmp(name, "gateway6")) {
cur->gateway6_str = strdup(value);
} else if (strcmp(name, "vip_addr6") == 0) {
cur->vip_addr6_str = strdup(value);
if (cur->vip_addr_str) {
return vip6_cfg_hander(cur);
}
} else if (0 == strcmp(name, "vip_prefix_len")) {
cur->vip_prefix_len = atoi(value);
}
#endif

View File

@ -44,6 +44,8 @@ extern char *dpdk_argv[DPDK_CONFIG_NUM + 1];
#define MAX_PKT_BURST 32
#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
#define VIP_MAX_NUM 64
struct ff_hw_features {
uint8_t rx_csum;
uint8_t rx_lro;
@ -62,10 +64,20 @@ struct ff_port_cfg {
char *broadcast;
char *gateway;
char *vip_ifname;
char *vip_addr_str;
char **vip_addr_array;
uint32_t nb_vip;
#ifdef INET6
char *addr6_str;
char *gateway6_str;
uint8_t prefix_len;
char *vip_addr6_str;
char **vip_addr6_array;
uint32_t nb_vip6;
uint8_t vip_prefix_len;
#endif
int nb_lcores;

View File

@ -69,10 +69,17 @@ struct ff_veth_softc {
in_addr_t broadcast;
in_addr_t gateway;
uint8_t nb_vip;
in_addr_t vip[VIP_MAX_NUM];
#ifdef INET6
struct in6_addr ip6;
struct in6_addr gateway6;
uint8_t prefix_length;
uint8_t nb_vip6;
uint8_t vip_prefix_length;
struct in6_addr vip6[VIP_MAX_NUM];
#endif /* INET6 */
struct ff_dpdk_if_context *host_ctx;
@ -81,12 +88,26 @@ struct ff_veth_softc {
static int
ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
{
int i, j;
memcpy(sc->mac, cfg->mac, ETHER_ADDR_LEN);
inet_pton(AF_INET, cfg->addr, &sc->ip);
inet_pton(AF_INET, cfg->netmask, &sc->netmask);
inet_pton(AF_INET, cfg->broadcast, &sc->broadcast);
inet_pton(AF_INET, cfg->gateway, &sc->gateway);
if (cfg->nb_vip) {
for (i = 0, j = 0; i < cfg->nb_vip; ++i) {
if (inet_pton(AF_INET, cfg->vip_addr_array[i], &sc->vip[j])) {
j++;
} else {
printf("ff_veth_config inet_pton vip %s failed.\n", cfg->vip_addr_array[i]);
}
}
sc->nb_vip = j;
}
#ifdef INET6
if (cfg->addr6_str) {
inet_pton(AF_INET6_LINUX, cfg->addr6_str, &sc->ip6);
@ -103,6 +124,19 @@ ff_veth_config(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
} else {
printf("%s: No addr6 config found.\n", sc->host_ifname);
}
if (cfg->nb_vip6) {
for (i = 0, j = 0; i < cfg->nb_vip6; ++i) {
if (inet_pton(AF_INET6_LINUX, cfg->vip_addr6_array[i], &sc->vip6[j])) {
j++;
} else {
printf("ff_veth_config inet_pton vip6 %s failed.\n", cfg->vip_addr6_array[i]);
}
}
sc->nb_vip6 = j;
sc->vip_prefix_length = cfg->vip_prefix_len == 0 ? 64 : cfg->vip_prefix_len;
}
#endif /* INET6 */
return 0;
@ -334,6 +368,52 @@ ff_veth_set_gateway(struct ff_veth_softc *sc)
(struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
}
static int
ff_veth_setvaddr(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
{
struct in_aliasreq req;
bzero(&req, sizeof req);
if (cfg->vip_ifname) {
strlcpy(req.ifra_name, cfg->vip_ifname, IFNAMSIZ);
} else {
strlcpy(req.ifra_name, sc->ifp->if_dname, IFNAMSIZ);
}
struct sockaddr_in sa;
bzero(&sa, sizeof(sa));
sa.sin_len = sizeof(sa);
sa.sin_family = AF_INET;
int i, ret;
struct socket *so = NULL;
socreate(AF_INET, &so, SOCK_DGRAM, 0, curthread->td_ucred, curthread);
for (i = 0; i < sc->nb_vip; ++i) {
sa.sin_addr.s_addr = sc->vip[i];
bcopy(&sa, &req.ifra_addr, sizeof(sa));
// Only support '255.255.255.255' netmask now
sa.sin_addr.s_addr = 0xFFFFFFFF;
bcopy(&sa, &req.ifra_mask, sizeof(sa));
// Only support 'x.x.x.255' broadaddr now
sa.sin_addr.s_addr = sc->vip[i] | 0xFF000000;
bcopy(&sa, &req.ifra_broadaddr, sizeof(sa));
ret = ifioctl(so, SIOCAIFADDR, (caddr_t)&req, curthread);
if (ret < 0) {
printf("ff_veth_setvaddr ifioctl SIOCAIFADDR error\n");
goto done;
}
}
done:
sofree(so);
return ret;
}
#ifdef INET6
static int
ff_veth_setaddr6(struct ff_veth_softc *sc)
@ -351,7 +431,8 @@ ff_veth_setaddr6(struct ff_veth_softc *sc)
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_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;
@ -383,6 +464,52 @@ ff_veth_set_gateway6(struct ff_veth_softc *sc)
return rtrequest_fib(RTM_ADD, (struct sockaddr *)&dst, (struct sockaddr *)&gw,
(struct sockaddr *)&nm, RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
}
static int
ff_veth_setvaddr6(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
{
struct in6_aliasreq ifr6;
bzero(&ifr6, sizeof(ifr6));
if (cfg->vip_ifname) {
strlcpy(ifr6.ifra_name, cfg->vip_ifname, IFNAMSIZ);
} else {
strlcpy(ifr6.ifra_name, sc->ifp->if_dname, IFNAMSIZ);
}
ifr6.ifra_addr.sin6_len = sizeof ifr6.ifra_addr;
ifr6.ifra_addr.sin6_family = AF_INET6;
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 i, ret;
for (i = 0; i < sc->nb_vip6; ++i) {
ifr6.ifra_addr.sin6_addr = sc->vip6[i];
ret = ifioctl(so, SIOCAIFADDR_IN6, (caddr_t)&ifr6, curthread);
if (ret < 0) {
printf("ff_veth_setvaddr6 ifioctl SIOCAIFADDR error\n");
goto done;
}
}
done:
sofree(so);
return ret;
}
#endif /* INET6 */
static int
@ -426,7 +553,7 @@ ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
return -1;
}
//set ip
// Set ip
int ret = ff_veth_setaddr(sc);
if (ret != 0) {
printf("ff_veth_setaddr failed\n");
@ -436,6 +563,10 @@ ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
printf("ff_veth_set_gateway failed\n");
}
if (sc->nb_vip) {
ret = ff_veth_setvaddr(sc, cfg);
}
#ifdef INET6
// Set IPv6
if (cfg->addr6_str) {
@ -451,6 +582,10 @@ ff_veth_setup_interface(struct ff_veth_softc *sc, struct ff_port_cfg *cfg)
}
}
}
if (sc->nb_vip6) {
ret = ff_veth_setvaddr6(sc, cfg);
}
#endif /* INET6 */
return (0);