mirror of https://github.com/F-Stack/f-stack.git
Support set multi virtual IPv4/IPv6 net addrs in `config.ini`, instead of use `ff_ifconfig`.
Close #421.
This commit is contained in:
parent
d4e858cfd0
commit
503a15e0ee
15
config.ini
15
config.ini
|
@ -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
|
||||
|
|
100
lib/ff_config.c
100
lib/ff_config.c
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
139
lib/ff_veth.c
139
lib/ff_veth.c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue