mirror of https://github.com/F-Stack/f-stack.git
multiple NIC support
In current implementation, cores and ports are one to one mapped, this PR allowed user to specify the core list used to handle single port. for example cores 1,2,3 handle port 0 and cores 4,5,6 handle port 1. - Add `port_list` config to dpdk section (used to specify the enabled port list) - Add `lcore_list` config to port section(used to specify the core list mapped to that port) - Delete `nb_ports` config in dpdk section - Delete `port_mask` config in dpdk section
This commit is contained in:
parent
e81d492e9b
commit
80a6164c5c
24
config.ini
24
config.ini
|
@ -1,12 +1,7 @@
|
|||
[dpdk]
|
||||
## Hexadecimal bitmask of cores to run on.
|
||||
lcore_mask=1
|
||||
## Port mask, enable and disable ports.
|
||||
## Default: all ports are enabled.
|
||||
#port_mask=1
|
||||
channel=4
|
||||
## Number of ports.
|
||||
nb_ports=1
|
||||
promiscuous=1
|
||||
numa_on=1
|
||||
## TCP segment offload, default: disabled.
|
||||
|
@ -14,6 +9,20 @@ tso=0
|
|||
## HW vlan strip, default: enabled.
|
||||
vlan_strip=1
|
||||
|
||||
# enabled port list
|
||||
#
|
||||
# EBNF grammar:
|
||||
#
|
||||
# exp ::= num_list {"," num_list}
|
||||
# num_list ::= <num> | <range>
|
||||
# range ::= <num>"-"<num>
|
||||
# num ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
|
||||
#
|
||||
# examples
|
||||
# 1-3 ports 1,2,3 are enabled
|
||||
# 1-3,4,7 ports 1,2,3,4,7 are enabled
|
||||
port_list=0
|
||||
|
||||
## Port config section
|
||||
## According to dpdk.nb_ports: port0, port1...
|
||||
[port0]
|
||||
|
@ -21,6 +30,11 @@ addr=192.168.1.2
|
|||
netmask=255.255.255.0
|
||||
broadcast=192.168.1.255
|
||||
gateway=192.168.1.1
|
||||
# lcore list used to handle this port
|
||||
# the format is same as port_list
|
||||
|
||||
# lcore_list= 0
|
||||
|
||||
## Packet capture path, this will hurt performance
|
||||
#pcap=./a.pcap
|
||||
|
||||
|
|
199
lib/ff_config.c
199
lib/ff_config.c
|
@ -31,6 +31,7 @@
|
|||
#include <getopt.h>
|
||||
#include <ctype.h>
|
||||
#include <rte_config.h>
|
||||
#include <rte_string_fns.h>
|
||||
|
||||
#include "ff_config.h"
|
||||
#include "ff_ini_parser.h"
|
||||
|
@ -190,23 +191,170 @@ freebsd_conf_handler(struct ff_config *cfg, const char *section,
|
|||
|
||||
return 1;
|
||||
}
|
||||
// A recursive binary search function. It returns location of x in
|
||||
// given array arr[l..r] is present, otherwise -1
|
||||
static int
|
||||
uint16_binary_search(uint16_t arr[], int l, int r, uint16_t x)
|
||||
{
|
||||
if (r >= l) {
|
||||
int mid = l + (r - l)/2;
|
||||
|
||||
// If the element is present at the middle itself
|
||||
if (arr[mid] == x) return mid;
|
||||
|
||||
// If element is smaller than mid, then it can only be present
|
||||
// in left subarray
|
||||
if (arr[mid] > x) return uint16_binary_search(arr, l, mid-1, x);
|
||||
|
||||
// Else the element can only be present in right subarray
|
||||
return uint16_binary_search(arr, mid+1, r, x);
|
||||
}
|
||||
|
||||
// We reach here when element is not present in array
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
uint16_cmp (const void * a, const void * b)
|
||||
{
|
||||
return ( *(uint16_t*)a - *(uint16_t*)b );
|
||||
}
|
||||
|
||||
static inline void
|
||||
sort_uint16_array(uint16_t arr[], int n)
|
||||
{
|
||||
qsort(arr, n, sizeof(uint16_t), uint16_cmp);
|
||||
}
|
||||
|
||||
static inline char *
|
||||
__strstrip(char *s)
|
||||
{
|
||||
char *end = s + strlen(s) - 1;
|
||||
while(*s == ' ') s++;
|
||||
for (; end >= s; --end) {
|
||||
if (*end != ' ') break;
|
||||
}
|
||||
*(++end) = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
static int
|
||||
__parse_config_list(uint16_t *arr, int *sz, const char *value) {
|
||||
int i, j;
|
||||
char input[4096];
|
||||
char *tokens[128];
|
||||
int nTokens = 0;
|
||||
char *endptr;
|
||||
int nr_ele = 0;
|
||||
int max_ele = *sz;
|
||||
|
||||
strncpy(input, value, 4096);
|
||||
nTokens = rte_strsplit(input, sizeof(input), tokens, 128, ',');
|
||||
for (i = 0; i < nTokens; i++) {
|
||||
char *tok = tokens[i];
|
||||
char *middle = strchr(tok, '-');
|
||||
if (middle == NULL) {
|
||||
tok = __strstrip(tok);
|
||||
long v = strtol(tok, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
fprintf(stderr, "%s is not a integer.", tok);
|
||||
return 0;
|
||||
}
|
||||
if (nr_ele > max_ele) {
|
||||
fprintf(stderr, "too many elements in list %s\n", value);
|
||||
return 0;
|
||||
}
|
||||
arr[nr_ele++] = (uint16_t)v;
|
||||
} else {
|
||||
*middle = '\0';
|
||||
char *lbound = __strstrip(tok);
|
||||
char *rbound = __strstrip(middle+1);
|
||||
long lv = strtol(lbound, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
fprintf(stderr, "%s is not a integer.", lbound);
|
||||
return 0;
|
||||
}
|
||||
long rv = strtol(rbound, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
fprintf(stderr, "%s is not a integer.", rbound);
|
||||
return 0;
|
||||
}
|
||||
for (j = lv; j <= rv; ++j) {
|
||||
if (nr_ele > max_ele) {
|
||||
fprintf(stderr, "too many elements in list %s.\n", value);
|
||||
return 0;
|
||||
}
|
||||
arr[nr_ele++] = (uint16_t)j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nr_ele <= 0) {
|
||||
printf("list %s is empty\n", value);
|
||||
return 1;
|
||||
}
|
||||
sort_uint16_array(arr, nr_ele);
|
||||
*sz = nr_ele;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_port_lcore_list(struct ff_port_cfg *cfg, const char *v_str)
|
||||
{
|
||||
cfg->nb_lcores = DPDK_MAX_LCORE;
|
||||
uint16_t *cores = cfg->lcore_list;
|
||||
return __parse_config_list(cores, &cfg->nb_lcores, v_str);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_port_list(struct ff_config *cfg, const char *v_str)
|
||||
{
|
||||
int res;
|
||||
uint16_t ports[RTE_MAX_ETHPORTS];
|
||||
int sz = RTE_MAX_ETHPORTS;
|
||||
|
||||
res = __parse_config_list(ports, &sz, v_str);
|
||||
if (! res) return res;
|
||||
|
||||
uint16_t *portid_list = malloc(sizeof(uint16_t)*sz);
|
||||
|
||||
if (portid_list == NULL) {
|
||||
fprintf(stderr, "parse_port_list malloc failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy(portid_list, ports, sz*sizeof(uint16_t));
|
||||
|
||||
cfg->dpdk.portid_list = portid_list;
|
||||
cfg->dpdk.nb_ports = sz;
|
||||
cfg->dpdk.max_portid = portid_list[sz-1];
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
port_cfg_handler(struct ff_config *cfg, const char *section,
|
||||
const char *name, const char *value) {
|
||||
|
||||
if (cfg->dpdk.nb_ports == 0) {
|
||||
fprintf(stderr, "port_cfg_handler: must config dpdk.nb_ports first\n");
|
||||
fprintf(stderr, "port_cfg_handler: must config dpdk.port_list first\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cfg->dpdk.port_cfgs == NULL) {
|
||||
struct ff_port_cfg *pc = calloc(cfg->dpdk.nb_ports, sizeof(struct ff_port_cfg));
|
||||
struct ff_port_cfg *pc = calloc(RTE_MAX_ETHPORTS, sizeof(struct ff_port_cfg));
|
||||
if (pc == NULL) {
|
||||
fprintf(stderr, "port_cfg_handler malloc failed\n");
|
||||
return 0;
|
||||
}
|
||||
// initialize lcore list and nb_lcores
|
||||
int i;
|
||||
for (i = 0; i < cfg->dpdk.nb_ports; ++i) {
|
||||
uint16_t portid = cfg->dpdk.portid_list[i];
|
||||
|
||||
struct ff_port_cfg *pconf = &pc[portid];
|
||||
pconf->port_id = portid;
|
||||
pconf->nb_lcores = ff_global_cfg.dpdk.nb_procs;
|
||||
memcpy(pconf->lcore_list, ff_global_cfg.dpdk.proc_lcore,
|
||||
pconf->nb_lcores*sizeof(uint16_t));
|
||||
}
|
||||
cfg->dpdk.port_cfgs = pc;
|
||||
}
|
||||
|
||||
|
@ -218,8 +366,8 @@ port_cfg_handler(struct ff_config *cfg, const char *section,
|
|||
}
|
||||
|
||||
/* just return true if portid >= nb_ports because it has no effect */
|
||||
if (portid >= cfg->dpdk.nb_ports) {
|
||||
fprintf(stderr, "port_cfg_handler section[%s] max than nb_ports\n", section);
|
||||
if (portid > cfg->dpdk.max_portid) {
|
||||
fprintf(stderr, "port_cfg_handler section[%s] bigger than max port id\n", section);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -239,6 +387,8 @@ port_cfg_handler(struct ff_config *cfg, const char *section,
|
|||
cur->gateway = strdup(value);
|
||||
} else if (strcmp(name, "pcap") == 0) {
|
||||
cur->pcap = strdup(value);
|
||||
} else if (strcmp(name, "lcore_list") == 0) {
|
||||
return parse_port_lcore_list(cur, value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -262,10 +412,8 @@ ini_parse_handler(void* user, const char* section, const char* name,
|
|||
} else if (MATCH("dpdk", "lcore_mask")) {
|
||||
pconfig->dpdk.lcore_mask = strdup(value);
|
||||
return parse_lcore_mask(pconfig, pconfig->dpdk.lcore_mask);
|
||||
} else if (MATCH("dpdk", "port_mask")) {
|
||||
pconfig->dpdk.port_mask = atoi(value);
|
||||
} else if (MATCH("dpdk", "nb_ports")) {
|
||||
pconfig->dpdk.nb_ports = atoi(value);
|
||||
} else if (MATCH("dpdk", "port_list")) {
|
||||
return parse_port_list(pconfig, value);
|
||||
} else if (MATCH("dpdk", "promiscuous")) {
|
||||
pconfig->dpdk.promiscuous = atoi(value);
|
||||
} else if (MATCH("dpdk", "numa_on")) {
|
||||
|
@ -398,11 +546,43 @@ ff_check_config(struct ff_config *cfg)
|
|||
|
||||
int i;
|
||||
for (i = 0; i < cfg->dpdk.nb_ports; i++) {
|
||||
struct ff_port_cfg *pc = &cfg->dpdk.port_cfgs[i];
|
||||
uint16_t portid = cfg->dpdk.portid_list[i];
|
||||
struct ff_port_cfg *pc = &cfg->dpdk.port_cfgs[portid];
|
||||
CHECK_VALID(addr);
|
||||
CHECK_VALID(netmask);
|
||||
CHECK_VALID(broadcast);
|
||||
CHECK_VALID(gateway);
|
||||
// check if the lcores in lcore_list are enabled.
|
||||
int k;
|
||||
for (k = 0; k < pc->nb_lcores; k++) {
|
||||
uint16_t lcore_id = pc->lcore_list[k];
|
||||
if (uint16_binary_search(cfg->dpdk.proc_lcore, 0,
|
||||
cfg->dpdk.nb_procs-1, lcore_id) < 0) {
|
||||
fprintf(stderr, "lcore %d is not enabled.\n", lcore_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* only primary process process KNI, so if KNI enabled,
|
||||
* primary lcore must stay in every enabled ports' lcore_list
|
||||
*/
|
||||
if (cfg->kni.enable &&
|
||||
strcmp(cfg->dpdk.proc_type, "primary") == 0) {
|
||||
int found = 0;
|
||||
int j;
|
||||
uint16_t lcore_id = cfg->dpdk.proc_lcore[cfg->dpdk.proc_id];
|
||||
for (j = 0; j < pc->nb_lcores; j++) {
|
||||
if (pc->lcore_list[j] == lcore_id) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (! found) {
|
||||
fprintf(stderr,
|
||||
"primary lcore %d should stay in port %d's lcore_list.\n",
|
||||
lcore_id, pc->port_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -451,4 +631,3 @@ ff_load_config(int argc, char *const argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
// dpdk argc, argv, max argc: 4, member of dpdk_config
|
||||
#define DPDK_CONFIG_NUM 4
|
||||
#define DPDK_CONFIG_MAXLEN 64
|
||||
#define DPDK_MAX_LCORE 128
|
||||
|
||||
extern int dpdk_argc;
|
||||
extern char *dpdk_argv[DPDK_CONFIG_NUM + 1];
|
||||
|
@ -52,6 +53,9 @@ struct ff_port_cfg {
|
|||
char *broadcast;
|
||||
char *gateway;
|
||||
char *pcap;
|
||||
|
||||
int nb_lcores;
|
||||
uint16_t lcore_list[DPDK_MAX_LCORE];
|
||||
};
|
||||
|
||||
struct ff_freebsd_cfg {
|
||||
|
@ -70,22 +74,23 @@ struct ff_config {
|
|||
char *lcore_mask;
|
||||
/* mask of current proc on all lcores */
|
||||
char *proc_mask;
|
||||
/* mask of enabled ports
|
||||
* use uint32_t because num of max ports is 32
|
||||
*/
|
||||
uint32_t port_mask;
|
||||
|
||||
int nb_channel;
|
||||
int memory;
|
||||
int no_huge;
|
||||
int nb_procs;
|
||||
int proc_id;
|
||||
int nb_ports;
|
||||
int promiscuous;
|
||||
int numa_on;
|
||||
int tso;
|
||||
int vlan_strip;
|
||||
/* list of proc-lcore */
|
||||
uint16_t *proc_lcore;
|
||||
|
||||
int nb_ports;
|
||||
uint16_t *portid_list;
|
||||
uint16_t max_portid;
|
||||
// MAP(portid => struct ff_port_cfg*)
|
||||
struct ff_port_cfg *port_cfgs;
|
||||
} dpdk;
|
||||
|
||||
|
|
159
lib/ff_dpdk_if.c
159
lib/ff_dpdk_if.c
|
@ -145,12 +145,13 @@ struct lcore_rx_queue {
|
|||
|
||||
struct lcore_conf {
|
||||
uint16_t proc_id;
|
||||
uint16_t nb_procs;
|
||||
uint16_t socket_id;
|
||||
int16_t nb_queue_list[RTE_MAX_ETHPORTS];
|
||||
struct ff_port_cfg *port_cfgs;
|
||||
|
||||
uint16_t nb_rx_queue;
|
||||
uint16_t *proc_lcore;
|
||||
struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE];
|
||||
uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
|
||||
int16_t tx_queue_id[RTE_MAX_ETHPORTS];
|
||||
struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];
|
||||
char *pcap[RTE_MAX_ETHPORTS];
|
||||
} __rte_cache_aligned;
|
||||
|
@ -231,7 +232,7 @@ check_all_ports_link_status(void)
|
|||
for (count = 0; count <= MAX_CHECK_TIME; count++) {
|
||||
all_ports_up = 1;
|
||||
for (i = 0; i < nb_ports; i++) {
|
||||
uint8_t portid = ff_global_cfg.dpdk.port_cfgs[i].port_id;
|
||||
uint8_t portid = ff_global_cfg.dpdk.portid_list[i];
|
||||
memset(&link, 0, sizeof(link));
|
||||
rte_eth_link_get_nowait(portid, &link);
|
||||
|
||||
|
@ -276,24 +277,31 @@ check_all_ports_link_status(void)
|
|||
static int
|
||||
init_lcore_conf(void)
|
||||
{
|
||||
uint8_t nb_ports = rte_eth_dev_count();
|
||||
if (nb_ports == 0) {
|
||||
/*
|
||||
* set all elements in tx_queue_id to -1, so we can use this array to check
|
||||
* if port is processed by this core.
|
||||
*/
|
||||
int k;
|
||||
for (k = 0; k < RTE_MAX_ETHPORTS; ++k) {
|
||||
lcore_conf.tx_queue_id[k] = -1;
|
||||
lcore_conf.nb_queue_list[k] = -1;
|
||||
}
|
||||
lcore_conf.port_cfgs = ff_global_cfg.dpdk.port_cfgs;
|
||||
|
||||
uint8_t nb_dev_ports = rte_eth_dev_count();
|
||||
if (nb_dev_ports == 0) {
|
||||
rte_exit(EXIT_FAILURE, "No probed ethernet devices\n");
|
||||
}
|
||||
if (ff_global_cfg.dpdk.max_portid >= nb_dev_ports) {
|
||||
rte_exit(EXIT_FAILURE, "this machine doesn't have port %d.\n",
|
||||
ff_global_cfg.dpdk.max_portid);
|
||||
}
|
||||
|
||||
lcore_conf.proc_id = ff_global_cfg.dpdk.proc_id;
|
||||
lcore_conf.nb_procs = ff_global_cfg.dpdk.nb_procs;
|
||||
|
||||
lcore_conf.proc_lcore = rte_zmalloc(NULL,
|
||||
sizeof(uint16_t) * lcore_conf.nb_procs, 0);
|
||||
if (lcore_conf.proc_lcore == NULL) {
|
||||
rte_exit(EXIT_FAILURE, "rte_zmalloc proc_lcore failed\n");
|
||||
}
|
||||
rte_memcpy(lcore_conf.proc_lcore, ff_global_cfg.dpdk.proc_lcore,
|
||||
sizeof(uint16_t) * lcore_conf.nb_procs);
|
||||
uint16_t proc_id;
|
||||
for (proc_id = 0; proc_id < lcore_conf.nb_procs; proc_id++) {
|
||||
uint16_t lcore_id = lcore_conf.proc_lcore[proc_id];
|
||||
for (proc_id = 0; proc_id < ff_global_cfg.dpdk.nb_procs; proc_id++) {
|
||||
uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[proc_id];
|
||||
if (!lcore_config[lcore_id].detected) {
|
||||
rte_exit(EXIT_FAILURE, "lcore %u unavailable\n", lcore_id);
|
||||
}
|
||||
|
@ -306,35 +314,34 @@ init_lcore_conf(void)
|
|||
|
||||
lcore_conf.socket_id = socket_id;
|
||||
|
||||
/* Currently, proc id 1:1 map to rx/tx queue id per port. */
|
||||
uint8_t port_id, enabled_ports = 0;
|
||||
for (port_id = 0; port_id < nb_ports; port_id++) {
|
||||
if (ff_global_cfg.dpdk.port_mask &&
|
||||
(ff_global_cfg.dpdk.port_mask & (1 << port_id)) == 0) {
|
||||
printf("\nSkipping disabled port %d\n", port_id);
|
||||
uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[lcore_conf.proc_id];
|
||||
int j;
|
||||
for (j = 0; j < ff_global_cfg.dpdk.nb_ports; ++j) {
|
||||
uint16_t port_id = ff_global_cfg.dpdk.portid_list[j];
|
||||
struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id];
|
||||
|
||||
int queueid = -1;
|
||||
int i;
|
||||
for (i = 0; i < pconf->nb_lcores; i++) {
|
||||
if (pconf->lcore_list[i] == lcore_id) {
|
||||
queueid = i;
|
||||
}
|
||||
}
|
||||
if (queueid < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port_id >= ff_global_cfg.dpdk.nb_ports) {
|
||||
printf("\nSkipping non-configured port %d\n", port_id);
|
||||
break;
|
||||
}
|
||||
|
||||
printf("lcore: %u, port: %u, queue: %u\n", lcore_id, port_id, queueid);
|
||||
uint16_t nb_rx_queue = lcore_conf.nb_rx_queue;
|
||||
lcore_conf.rx_queue_list[nb_rx_queue].port_id = port_id;
|
||||
lcore_conf.rx_queue_list[nb_rx_queue].queue_id = lcore_conf.proc_id;
|
||||
lcore_conf.rx_queue_list[nb_rx_queue].queue_id = queueid;
|
||||
lcore_conf.nb_rx_queue++;
|
||||
|
||||
lcore_conf.tx_queue_id[port_id] = lcore_conf.proc_id;
|
||||
lcore_conf.pcap[port_id] = ff_global_cfg.dpdk.port_cfgs[enabled_ports].pcap;
|
||||
lcore_conf.tx_queue_id[port_id] = queueid;
|
||||
|
||||
ff_global_cfg.dpdk.port_cfgs[enabled_ports].port_id = port_id;
|
||||
|
||||
enabled_ports++;
|
||||
lcore_conf.pcap[port_id] = pconf->pcap;
|
||||
lcore_conf.nb_queue_list[port_id] = pconf->nb_lcores;
|
||||
}
|
||||
|
||||
ff_global_cfg.dpdk.nb_ports = enabled_ports;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -360,8 +367,8 @@ init_mem_pool(void)
|
|||
uint16_t i, lcore_id;
|
||||
char s[64];
|
||||
|
||||
for (i = 0; i < lcore_conf.nb_procs; i++) {
|
||||
lcore_id = lcore_conf.proc_lcore[i];
|
||||
for (i = 0; i < ff_global_cfg.dpdk.nb_procs; i++) {
|
||||
lcore_id = ff_global_cfg.dpdk.proc_lcore[i];
|
||||
if (numa_on) {
|
||||
socketid = rte_lcore_to_socket_id(lcore_id);
|
||||
}
|
||||
|
@ -424,13 +431,13 @@ init_arp_ring(void)
|
|||
int proc_id = ff_global_cfg.dpdk.proc_id;
|
||||
|
||||
/* Allocate arp ring ptr according to eth dev count. */
|
||||
int nb_ports = rte_eth_dev_count();
|
||||
int nb_dev_ports = rte_eth_dev_count();
|
||||
for(i = 0; i < nb_procs; ++i) {
|
||||
snprintf(name_buf, RTE_RING_NAMESIZE, "ring_ptr_%d_%d",
|
||||
proc_id, i);
|
||||
|
||||
arp_ring[i] = rte_zmalloc(name_buf,
|
||||
sizeof(struct rte_ring *) * nb_ports,
|
||||
sizeof(struct rte_ring *) * nb_dev_ports,
|
||||
RTE_CACHE_LINE_SIZE);
|
||||
if (arp_ring[i] == NULL) {
|
||||
rte_exit(EXIT_FAILURE, "rte_zmalloc(%s (struct rte_ring*)) "
|
||||
|
@ -441,9 +448,9 @@ init_arp_ring(void)
|
|||
unsigned socketid = lcore_conf.socket_id;
|
||||
|
||||
/* Create ring according to ports actually being used. */
|
||||
nb_ports = ff_global_cfg.dpdk.nb_ports;
|
||||
int nb_ports = ff_global_cfg.dpdk.nb_ports;
|
||||
for (j = 0; j < nb_ports; j++) {
|
||||
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[j].port_id;
|
||||
uint16_t port_id = ff_global_cfg.dpdk.portid_list[j];
|
||||
|
||||
for(i = 0; i < nb_procs; ++i) {
|
||||
snprintf(name_buf, RTE_RING_NAMESIZE, "arp_ring_%d_%d", i, port_id);
|
||||
|
@ -531,7 +538,7 @@ init_kni(void)
|
|||
nb_ports = ff_global_cfg.dpdk.nb_ports;
|
||||
int i, ret;
|
||||
for (i = 0; i < nb_ports; i++) {
|
||||
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[i].port_id;
|
||||
uint16_t port_id = ff_global_cfg.dpdk.portid_list[i];
|
||||
ff_kni_alloc(port_id, socket_id, mbuf_pool, KNI_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
|
@ -567,26 +574,27 @@ static int
|
|||
init_port_start(void)
|
||||
{
|
||||
int nb_ports = ff_global_cfg.dpdk.nb_ports;
|
||||
uint16_t nb_procs = ff_global_cfg.dpdk.nb_procs;
|
||||
unsigned socketid = rte_lcore_to_socket_id(rte_lcore_id());
|
||||
struct rte_mempool *mbuf_pool = pktmbuf_pool[socketid];
|
||||
uint16_t i;
|
||||
|
||||
for (i = 0; i < nb_ports; i++) {
|
||||
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[i].port_id;
|
||||
uint16_t port_id = ff_global_cfg.dpdk.portid_list[i];
|
||||
struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id];
|
||||
uint16_t nb_queues = pconf->nb_lcores;
|
||||
|
||||
struct rte_eth_dev_info dev_info;
|
||||
rte_eth_dev_info_get(port_id, &dev_info);
|
||||
|
||||
if (nb_procs > dev_info.max_rx_queues) {
|
||||
if (nb_queues > dev_info.max_rx_queues) {
|
||||
rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_rx_queues[%d]\n",
|
||||
nb_procs,
|
||||
nb_queues,
|
||||
dev_info.max_rx_queues);
|
||||
}
|
||||
|
||||
if (nb_procs > dev_info.max_tx_queues) {
|
||||
if (nb_queues > dev_info.max_tx_queues) {
|
||||
rte_exit(EXIT_FAILURE, "num_procs[%d] bigger than max_tx_queues[%d]\n",
|
||||
nb_procs,
|
||||
nb_queues,
|
||||
dev_info.max_tx_queues);
|
||||
}
|
||||
|
||||
|
@ -599,7 +607,7 @@ init_port_start(void)
|
|||
addr.addr_bytes[2], addr.addr_bytes[3],
|
||||
addr.addr_bytes[4], addr.addr_bytes[5]);
|
||||
|
||||
rte_memcpy(ff_global_cfg.dpdk.port_cfgs[i].mac,
|
||||
rte_memcpy(pconf->mac,
|
||||
addr.addr_bytes, ETHER_ADDR_LEN);
|
||||
|
||||
/* Clear txq_flags - we do not need multi-mempool and refcnt */
|
||||
|
@ -655,7 +663,7 @@ init_port_start(void)
|
|||
if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
|
||||
printf("LRO is supported\n");
|
||||
port_conf.rxmode.enable_lro = 1;
|
||||
ff_global_cfg.dpdk.port_cfgs[i].hw_features.rx_lro = 1;
|
||||
pconf->hw_features.rx_lro = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -665,24 +673,24 @@ init_port_start(void)
|
|||
(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)) {
|
||||
printf("RX checksum offload supported\n");
|
||||
port_conf.rxmode.hw_ip_checksum = 1;
|
||||
ff_global_cfg.dpdk.port_cfgs[i].hw_features.rx_csum = 1;
|
||||
pconf->hw_features.rx_csum = 1;
|
||||
}
|
||||
|
||||
if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {
|
||||
printf("TX ip checksum offload supported\n");
|
||||
ff_global_cfg.dpdk.port_cfgs[i].hw_features.tx_csum_ip = 1;
|
||||
pconf->hw_features.tx_csum_ip = 1;
|
||||
}
|
||||
|
||||
if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) &&
|
||||
(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)) {
|
||||
printf("TX TCP&UDP checksum offload supported\n");
|
||||
ff_global_cfg.dpdk.port_cfgs[i].hw_features.tx_csum_l4 = 1;
|
||||
pconf->hw_features.tx_csum_l4 = 1;
|
||||
}
|
||||
|
||||
if (ff_global_cfg.dpdk.tso) {
|
||||
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
|
||||
printf("TSO is supported\n");
|
||||
ff_global_cfg.dpdk.port_cfgs[i].hw_features.tx_tso = 1;
|
||||
pconf->hw_features.tx_tso = 1;
|
||||
}
|
||||
} else {
|
||||
printf("TSO is disabled\n");
|
||||
|
@ -701,14 +709,12 @@ init_port_start(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Currently, proc id 1:1 map to queue id per port. */
|
||||
int ret = rte_eth_dev_configure(port_id, nb_procs, nb_procs, &port_conf);
|
||||
int ret = rte_eth_dev_configure(port_id, nb_queues, nb_queues, &port_conf);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t q;
|
||||
for (q = 0; q < nb_procs; q++) {
|
||||
for (q = 0; q < nb_queues; q++) {
|
||||
ret = rte_eth_tx_queue_setup(port_id, q, TX_QUEUE_SIZE,
|
||||
socketid, &dev_info.default_txconf);
|
||||
if (ret < 0) {
|
||||
|
@ -727,7 +733,7 @@ init_port_start(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (nb_procs > 1) {
|
||||
if (nb_queues > 1) {
|
||||
/* set HW rss hash function to Toeplitz. */
|
||||
if (!rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_HASH)) {
|
||||
struct rte_eth_hash_filter_info info = {0};
|
||||
|
@ -741,7 +747,7 @@ init_port_start(void)
|
|||
}
|
||||
}
|
||||
|
||||
set_rss_table(port_id, dev_info.reta_size, nb_procs);
|
||||
set_rss_table(port_id, dev_info.reta_size, nb_queues);
|
||||
}
|
||||
|
||||
/* Enable RX in promiscuous mode for the Ethernet device. */
|
||||
|
@ -756,8 +762,8 @@ init_port_start(void)
|
|||
}
|
||||
|
||||
/* Enable pcap dump */
|
||||
if (ff_global_cfg.dpdk.port_cfgs[i].pcap) {
|
||||
ff_enable_pcap(ff_global_cfg.dpdk.port_cfgs[i].pcap);
|
||||
if (pconf->pcap) {
|
||||
ff_enable_pcap(pconf->pcap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -917,13 +923,17 @@ process_packets(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **bufs,
|
|||
struct rte_mbuf *mbuf_clone;
|
||||
if (pkts_from_ring == 0) {
|
||||
uint16_t i;
|
||||
for(i = 0; i < qconf->nb_procs; ++i) {
|
||||
int16_t nb_queues = qconf->nb_queue_list[port_id];
|
||||
assert(nb_queues != -1);
|
||||
|
||||
for(i = 0; i < nb_queues; ++i) {
|
||||
if(i == queue_id)
|
||||
continue;
|
||||
|
||||
unsigned socket_id = 0;
|
||||
if (numa_on) {
|
||||
socket_id = rte_lcore_to_socket_id(qconf->proc_lcore[i]);
|
||||
uint16_t lcore_id = qconf->port_cfgs[port_id].lcore_list[i];
|
||||
socket_id = rte_lcore_to_socket_id(lcore_id);
|
||||
}
|
||||
mbuf_pool = pktmbuf_pool[socket_id];
|
||||
mbuf_clone = rte_pktmbuf_clone(rtem, mbuf_pool);
|
||||
|
@ -1333,8 +1343,13 @@ ff_dpdk_if_up(void) {
|
|||
int nb_ports = ff_global_cfg.dpdk.nb_ports;
|
||||
int i;
|
||||
for (i = 0; i < nb_ports; i++) {
|
||||
uint8_t port_id = ff_global_cfg.dpdk.port_cfgs[i].port_id;
|
||||
veth_ctx[port_id] = ff_veth_attach(ff_global_cfg.dpdk.port_cfgs + i);
|
||||
uint16_t port_id = ff_global_cfg.dpdk.portid_list[i];
|
||||
// if port's lcore list does't contain current core, just skip this port
|
||||
if (lcore_conf.tx_queue_id[port_id] < 0) {
|
||||
continue;
|
||||
}
|
||||
struct ff_port_cfg *pconf = &ff_global_cfg.dpdk.port_cfgs[port_id];
|
||||
veth_ctx[port_id] = ff_veth_attach(pconf);
|
||||
if (veth_ctx[port_id] == NULL) {
|
||||
rte_exit(EXIT_FAILURE, "ff_veth_attach failed");
|
||||
}
|
||||
|
@ -1388,13 +1403,15 @@ ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
|
|||
uint16_t sport, uint16_t dport)
|
||||
{
|
||||
struct lcore_conf *qconf = &lcore_conf;
|
||||
struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
|
||||
uint16_t nb_queues = qconf->nb_queue_list[ctx->port_id];
|
||||
|
||||
if (qconf->nb_procs == 1) {
|
||||
if (nb_queues == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
|
||||
uint16_t reta_size = rss_reta_size[ctx->port_id];
|
||||
uint16_t queueid = qconf->tx_queue_id[ctx->port_id];
|
||||
|
||||
uint8_t data[sizeof(saddr) + sizeof(daddr) + sizeof(sport) +
|
||||
sizeof(dport)];
|
||||
|
@ -1416,7 +1433,5 @@ ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
|
|||
uint32_t hash = toeplitz_hash(sizeof(default_rsskey_40bytes),
|
||||
default_rsskey_40bytes, datalen, data);
|
||||
|
||||
return ((hash & (reta_size - 1)) % qconf->nb_procs) == qconf->proc_id;
|
||||
return ((hash & (reta_size - 1)) % nb_queues) == queueid;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue