Skip to content

Commit e79ceb9

Browse files
committed
native-mt: per-thread refactor of shared FreeBSD stack state (CM0-CM3)
CM0: msg_iov __thread + ff_cur_lcore_conf abstraction macro CM1: thread_mode config switch (ff_config) CM2: lcore_conf array-ization + macro-body indexing CM3: per-thread pcpup/cc_cpu/stop_loop/seed/freebsd_clock; add ff_pcpu_thread_init / ff_callout_thread_init; split callout_callwheel_init into per-thread vs global init Gates (cumulative CM0-CM3): clean build PASS (0 error, 51 warning == baseline), review PASS (zero-regression at thread_mode=0), unit tests 197/197 PASS. config.ini intentionally excluded (local test values, not committed).
1 parent b3cb614 commit e79ceb9

13 files changed

Lines changed: 210 additions & 91 deletions

File tree

lib/ff_compat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ uma_zone_t namei_zone;
7777
extern unsigned int rand_r(unsigned int *seed);
7878
extern int ff_adapt_user_proc_add(struct thread *parent_td, struct thread *td);
7979
extern int ff_adapt_user_proc_exit(struct thread *td);
80-
unsigned int seed = 0;
80+
__thread unsigned int seed = 0;
8181

8282
#define M_ZERO 0x0100 /* bzero the allocation */
8383

lib/ff_config.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,8 @@ ini_parse_handler(void* user, const char* section, const char* name,
10321032
pconfig->dpdk.memory = atoi(value);
10331033
} else if (MATCH("dpdk", "no_huge")) {
10341034
pconfig->dpdk.no_huge = atoi(value);
1035+
} else if (MATCH("dpdk", "thread_mode")) {
1036+
pconfig->dpdk.thread_mode = atoi(value);
10351037
} else if (MATCH("dpdk", "lcore_mask")) {
10361038
pconfig->dpdk.lcore_mask = strdup(value);
10371039
return parse_lcore_mask(pconfig, pconfig->dpdk.lcore_mask);
@@ -1458,6 +1460,27 @@ ff_check_config(struct ff_config *cfg)
14581460
}
14591461
}
14601462

1463+
if (cfg->dpdk.thread_mode) {
1464+
/* Single-process multi-thread: force primary, derive nb_threads,
1465+
* collapse to one process, and expose all lcores to EAL via a
1466+
* full-bit proc_mask. Done after per-port lcore checks so those
1467+
* still validate against the original nb_procs=bit-count set. */
1468+
if (cfg->dpdk.proc_type && strcmp(cfg->dpdk.proc_type, "secondary") == 0) {
1469+
fprintf(stderr, "thread_mode=1 is incompatible with proc_type secondary\n");
1470+
return -1;
1471+
}
1472+
if (cfg->dpdk.proc_type) free(cfg->dpdk.proc_type);
1473+
cfg->dpdk.proc_type = strdup("primary");
1474+
1475+
cfg->dpdk.nb_threads = cfg->dpdk.nb_procs;
1476+
cfg->dpdk.nb_procs = 1;
1477+
cfg->dpdk.proc_id = 0;
1478+
if (cfg->dpdk.lcore_mask) {
1479+
if (cfg->dpdk.proc_mask) free(cfg->dpdk.proc_mask);
1480+
cfg->dpdk.proc_mask = strdup(cfg->dpdk.lcore_mask);
1481+
}
1482+
}
1483+
14611484
return 0;
14621485
}
14631486

lib/ff_config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ struct ff_config {
289289
int no_huge;
290290
int nb_procs;
291291
int proc_id;
292+
int thread_mode; /* 0=multi-process (default); 1=single-process multi-thread multi-stack */
293+
int nb_threads; /* thread mode: number of threads = lcore_mask set-bit count */
292294
int promiscuous;
293295
int nb_vdev;
294296
int nb_bond;

lib/ff_dpdk_if.c

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,11 @@ static unsigned pkt_tx_delay;
8484
static int timestamp_dynfield_offset = -1;
8585
static uint64_t timestamp_dynflag_mask;
8686
static uint64_t usr_cb_tsc;
87-
static int stop_loop;
87+
/* thread mode: ff_dpdk_stop only stops the calling thread's own loop;
88+
* cross-thread broadcast-stop semantics deferred to CM7/runtime. */
89+
static __thread int stop_loop;
8890

89-
static struct rte_timer freebsd_clock;
91+
static __thread struct rte_timer freebsd_clock;
9092

9193
// Mellanox Linux's driver key
9294
static uint8_t default_rsskey_40bytes[40] = {
@@ -120,7 +122,7 @@ static uint8_t symmetric_rsskey[52] = {
120122
static int rsskey_len = sizeof(default_rsskey_40bytes);
121123
static uint8_t *rsskey = default_rsskey_40bytes;
122124

123-
struct lcore_conf lcore_conf;
125+
struct lcore_conf lcore_conf[RTE_MAX_LCORE];
124126

125127
struct rte_mempool *pktmbuf_pool[NB_SOCKETS];
126128

@@ -411,17 +413,17 @@ init_lcore_conf(void)
411413
ff_global_cfg.dpdk.max_portid);
412414
}
413415

414-
lcore_conf.port_cfgs = ff_global_cfg.dpdk.port_cfgs;
415-
lcore_conf.proc_id = ff_global_cfg.dpdk.proc_id;
416+
ff_cur_lcore_conf()->port_cfgs = ff_global_cfg.dpdk.port_cfgs;
417+
ff_cur_lcore_conf()->proc_id = ff_global_cfg.dpdk.proc_id;
416418

417419
uint16_t socket_id = 0;
418420
if (numa_on) {
419421
socket_id = rte_lcore_to_socket_id(rte_lcore_id());
420422
}
421423

422-
lcore_conf.socket_id = socket_id;
424+
ff_cur_lcore_conf()->socket_id = socket_id;
423425

424-
uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[lcore_conf.proc_id];
426+
uint16_t lcore_id = ff_global_cfg.dpdk.proc_lcore[ff_cur_lcore_conf()->proc_id];
425427
if (!rte_lcore_is_enabled(lcore_id)) {
426428
rte_exit(EXIT_FAILURE, "lcore %u unavailable\n", lcore_id);
427429
}
@@ -442,24 +444,24 @@ init_lcore_conf(void)
442444
continue;
443445
}
444446
ff_log(FF_LOG_INFO, FF_LOGTYPE_FSTACK_LIB, "lcore: %u, port: %u, queue: %u\n", lcore_id, port_id, queueid);
445-
uint16_t nb_rx_queue = lcore_conf.nb_rx_queue;
446-
lcore_conf.rx_queue_list[nb_rx_queue].port_id = port_id;
447-
lcore_conf.rx_queue_list[nb_rx_queue].queue_id = queueid;
448-
lcore_conf.nb_rx_queue++;
447+
uint16_t nb_rx_queue = ff_cur_lcore_conf()->nb_rx_queue;
448+
ff_cur_lcore_conf()->rx_queue_list[nb_rx_queue].port_id = port_id;
449+
ff_cur_lcore_conf()->rx_queue_list[nb_rx_queue].queue_id = queueid;
450+
ff_cur_lcore_conf()->nb_rx_queue++;
449451

450-
lcore_conf.tx_queue_id[port_id] = queueid;
451-
lcore_conf.tx_port_id[lcore_conf.nb_tx_port] = port_id;
452-
lcore_conf.nb_tx_port++;
452+
ff_cur_lcore_conf()->tx_queue_id[port_id] = queueid;
453+
ff_cur_lcore_conf()->tx_port_id[ff_cur_lcore_conf()->nb_tx_port] = port_id;
454+
ff_cur_lcore_conf()->nb_tx_port++;
453455

454456
/* Enable pcap dump */
455457
if (ff_global_cfg.pcap.enable) {
456458
ff_enable_pcap(ff_global_cfg.pcap.save_path, ff_global_cfg.pcap.snap_len, ff_global_cfg.pcap.timestamp_precision);
457459
}
458460

459-
lcore_conf.nb_queue_list[port_id] = pconf->nb_lcores;
461+
ff_cur_lcore_conf()->nb_queue_list[port_id] = pconf->nb_lcores;
460462
}
461463

462-
if (lcore_conf.nb_rx_queue == 0) {
464+
if (ff_cur_lcore_conf()->nb_rx_queue == 0) {
463465
rte_exit(EXIT_FAILURE, "lcore %u has nothing to do\n", lcore_id);
464466
}
465467

@@ -485,7 +487,7 @@ init_mem_pool(void)
485487
uint8_t nb_ports = ff_global_cfg.dpdk.nb_ports;
486488
uint32_t nb_lcores = ff_global_cfg.dpdk.nb_procs;
487489
uint32_t nb_tx_queue = nb_lcores;
488-
uint32_t nb_rx_queue = lcore_conf.nb_rx_queue * nb_lcores;
490+
uint32_t nb_rx_queue = ff_cur_lcore_conf()->nb_rx_queue * nb_lcores;
489491
uint16_t max_portid = ff_global_cfg.dpdk.max_portid;
490492

491493
unsigned nb_mbuf = RTE_ALIGN_CEIL (
@@ -592,7 +594,7 @@ init_dispatch_ring(void)
592594
char name_buf[RTE_RING_NAMESIZE];
593595
int queueid;
594596

595-
unsigned socketid = lcore_conf.socket_id;
597+
unsigned socketid = ff_cur_lcore_conf()->socket_id;
596598

597599
/* Create ring according to ports actually being used. */
598600
int nb_ports = ff_global_cfg.dpdk.nb_ports;
@@ -647,7 +649,7 @@ init_msg_ring(void)
647649
{
648650
uint16_t i, j;
649651
uint16_t nb_procs = ff_global_cfg.dpdk.nb_procs;
650-
unsigned socketid = lcore_conf.socket_id;
652+
unsigned socketid = ff_cur_lcore_conf()->socket_id;
651653

652654
/* Create message buffer pool */
653655
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
@@ -716,7 +718,7 @@ init_kni(void)
716718
ff_kni_init(nb_ports, ff_global_cfg.kni.tcp_port,
717719
ff_global_cfg.kni.udp_port);
718720

719-
unsigned socket_id = lcore_conf.socket_id;
721+
unsigned socket_id = ff_cur_lcore_conf()->socket_id;
720722
struct rte_mempool *mbuf_pool = pktmbuf_pool[socket_id];
721723

722724
nb_ports = ff_global_cfg.dpdk.nb_ports;
@@ -1018,7 +1020,7 @@ init_port_start(void)
10181020
uint16_t q;
10191021
for (q = 0; q < nb_queues; q++) {
10201022
if (numa_on) {
1021-
uint16_t lcore_id = lcore_conf.port_cfgs[u_port_id].lcore_list[q];
1023+
uint16_t lcore_id = ff_cur_lcore_conf()->port_cfgs[u_port_id].lcore_list[q];
10221024
socketid = rte_lcore_to_socket_id(lcore_id);
10231025
}
10241026
mbuf_pool = pktmbuf_pool[socketid];
@@ -1902,7 +1904,7 @@ static inline void
19021904
process_packets(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **bufs,
19031905
uint16_t count, struct ff_dpdk_if_context *ctx, int pkts_from_ring)
19041906
{
1905-
struct lcore_conf *qconf = &lcore_conf;
1907+
struct lcore_conf *qconf = ff_cur_lcore_conf();
19061908
uint16_t nb_queues = qconf->nb_queue_list[port_id];
19071909

19081910
uint16_t i;
@@ -2343,7 +2345,7 @@ send_single_packet(struct rte_mbuf *m, uint8_t port)
23432345
uint16_t len;
23442346
struct lcore_conf *qconf;
23452347

2346-
qconf = &lcore_conf;
2348+
qconf = ff_cur_lcore_conf();
23472349
len = qconf->tx_mbufs[port].len;
23482350
qconf->tx_mbufs[port].m_table[len] = m;
23492351
len++;
@@ -2370,7 +2372,7 @@ ff_dpdk_if_send(struct ff_dpdk_if_context *ctx, void *m,
23702372
return -1;
23712373
}
23722374
#ifdef FF_USE_PAGE_ARRAY
2373-
struct lcore_conf *qconf = &lcore_conf;
2375+
struct lcore_conf *qconf = ff_cur_lcore_conf();
23742376
int len = 0;
23752377

23762378
len = ff_if_send_onepkt(ctx, m,total);
@@ -2381,7 +2383,7 @@ ff_dpdk_if_send(struct ff_dpdk_if_context *ctx, void *m,
23812383
qconf->tx_mbufs[ctx->port_id].len = len;
23822384
return 0;
23832385
#endif
2384-
struct rte_mempool *mbuf_pool = pktmbuf_pool[lcore_conf.socket_id];
2386+
struct rte_mempool *mbuf_pool = pktmbuf_pool[ff_cur_lcore_conf()->socket_id];
23852387
struct rte_mbuf *head = rte_pktmbuf_alloc(mbuf_pool);
23862388
if (head == NULL) {
23872389
ff_traffic.tx_dropped++;
@@ -2520,7 +2522,7 @@ ff_dpdk_if_send(struct ff_dpdk_if_context *ctx, void *m,
25202522
int
25212523
ff_dpdk_raw_packet_send(void *data, int total, uint16_t port_id)
25222524
{
2523-
struct rte_mempool *mbuf_pool = pktmbuf_pool[lcore_conf.socket_id];
2525+
struct rte_mempool *mbuf_pool = pktmbuf_pool[ff_cur_lcore_conf()->socket_id];
25242526
struct rte_mbuf *head = rte_pktmbuf_alloc(mbuf_pool);
25252527
if (head == NULL) {
25262528
ff_traffic.tx_dropped++;
@@ -2582,7 +2584,7 @@ main_loop(void *arg)
25822584
prev_tsc = 0;
25832585
usch_tsc = 0;
25842586

2585-
qconf = &lcore_conf;
2587+
qconf = ff_cur_lcore_conf();
25862588

25872589
while (1) {
25882590

@@ -2746,7 +2748,7 @@ main_loop(void *arg)
27462748
int
27472749
ff_dpdk_if_up(void) {
27482750
int i;
2749-
struct lcore_conf *qconf = &lcore_conf;
2751+
struct lcore_conf *qconf = ff_cur_lcore_conf();
27502752
for (i = 0; i < qconf->nb_tx_port; i++) {
27512753
uint16_t port_id = qconf->tx_port_id[i];
27522754

@@ -3102,7 +3104,7 @@ int
31023104
ff_rss_self_queue_info(uint16_t *proc_id, uint16_t *queueid,
31033105
uint16_t *nb_queues, uint16_t *reta_size)
31043106
{
3105-
struct lcore_conf *qconf = &lcore_conf;
3107+
struct lcore_conf *qconf = ff_cur_lcore_conf();
31063108
uint16_t port_id;
31073109

31083110
if (qconf->nb_tx_port == 0)
@@ -3126,7 +3128,7 @@ int
31263128
ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
31273129
uint16_t sport, uint16_t dport)
31283130
{
3129-
struct lcore_conf *qconf = &lcore_conf;
3131+
struct lcore_conf *qconf = ff_cur_lcore_conf();
31303132
struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
31313133
uint16_t nb_queues = qconf->nb_queue_list[ctx->port_id];
31323134

@@ -3383,7 +3385,7 @@ ff_rss_thash_ctx_init(void)
33833385
struct rte_eth_rss_conf rb;
33843386
uint8_t rb_key[64];
33853387
uint16_t rsz = rss_reta_size[port_id];
3386-
uint16_t nbq = lcore_conf.nb_queue_list[port_id];
3388+
uint16_t nbq = ff_cur_lcore_conf()->nb_queue_list[port_id];
33873389

33883390
if (!rss_thash_ready[port_id])
33893391
continue;
@@ -3439,7 +3441,7 @@ int
34393441
ff_rss_adjust_sport(void *softc, uint32_t saddr, uint32_t daddr,
34403442
uint16_t dport, uint16_t *out_sport, uint16_t first, uint16_t last)
34413443
{
3442-
struct lcore_conf *qconf = &lcore_conf;
3444+
struct lcore_conf *qconf = ff_cur_lcore_conf();
34433445
struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
34443446
uint16_t port_id, nb_queues, reta_size, queueid;
34453447
uint32_t desired;
@@ -3629,7 +3631,7 @@ int
36293631
ff_rss_check6(void *softc, const uint8_t *saddr6, const uint8_t *daddr6,
36303632
uint16_t sport, uint16_t dport)
36313633
{
3632-
struct lcore_conf *qconf = &lcore_conf;
3634+
struct lcore_conf *qconf = ff_cur_lcore_conf();
36333635
struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
36343636
uint16_t nb_queues = qconf->nb_queue_list[ctx->port_id];
36353637

@@ -3879,7 +3881,7 @@ ff_rss_adjust_sport6(void *softc, const uint8_t *saddr6,
38793881
const uint8_t *daddr6, uint16_t dport, uint16_t *out_sport,
38803882
uint16_t first, uint16_t last)
38813883
{
3882-
struct lcore_conf *qconf = &lcore_conf;
3884+
struct lcore_conf *qconf = ff_cur_lcore_conf();
38833885
struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc);
38843886
uint16_t port_id, nb_queues, reta_size, queueid;
38853887
uint32_t desired;

lib/ff_freebsd_init.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ extern void uma_startup2(void);
6565

6666
extern void ff_init_thread0(void);
6767

68+
void ff_pcpu_thread_init(void);
69+
6870
struct sx proctree_lock;
69-
struct pcpu *pcpup;
71+
__thread struct pcpu *pcpup;
7072
struct uma_page_head *uma_page_slab_hash;
7173
int uma_page_mask;
7274
extern cpuset_t all_cpus;
@@ -75,6 +77,16 @@ long physmem;
7577

7678
extern void uma_startup1(vm_offset_t);
7779

80+
/* Per-thread pcpu bootstrap. CM3: main thread calls it once (behaviour
81+
* unchanged). Worker per-thread invocation is wired in CM5. */
82+
void
83+
ff_pcpu_thread_init(void)
84+
{
85+
pcpup = malloc(sizeof(struct pcpu), M_DEVBUF, M_ZERO);
86+
pcpu_init(pcpup, 0, sizeof(struct pcpu));
87+
PCPU_SET(prvspace, pcpup);
88+
}
89+
7890
int lo_set_defaultaddr(void)
7991
{
8092
struct in_aliasreq req;
@@ -149,9 +161,7 @@ ff_freebsd_init(void)
149161

150162
physmem = ff_global_cfg.freebsd.physmem;
151163

152-
pcpup = malloc(sizeof(struct pcpu), M_DEVBUF, M_ZERO);
153-
pcpu_init(pcpup, 0, sizeof(struct pcpu));
154-
PCPU_SET(prvspace, pcpup);
164+
ff_pcpu_thread_init();
155165
CPU_SET(0, &all_cpus);
156166

157167
ff_init_thread0();

0 commit comments

Comments
 (0)