stable: revert multi-core, restore working single-core optimizations

Keep P0-P4 optimizations:
- Fragment mempool (frag_alloc/frag_free)
- WS frame alloca() dynamic stack
- Fragment read_offset (eliminate memmove)
- nclose busy-poll (replace cond_timedwait)
- Remove dead ng_tcp_out()

Revert experimental multi-core changes (moved to feature/multi-core):
- Worker arrays, TLS context switching
- RX hash distribution, TX multi-ring collection

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
wxj
2026-06-30 16:38:55 +00:00
co-authored by Claude
parent 5e57d06b1f
commit d57a0260e8
4 changed files with 67 additions and 172 deletions
+21 -77
View File
@@ -25,83 +25,40 @@ uint8_t gDefaultArpMac[RTE_ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
struct lat_trace g_lat_trace[LAT_TRACE_SIZE];
int g_lat_trace_idx = 0;
static struct ng_tcp_table *g_tcp_tables[MAX_WORKERS + 1];
static struct inout_ring *g_rings[MAX_WORKERS + 1];
static int g_num_workers = DEFAULT_WORKERS;
static struct ng_tcp_table *tInst = NULL;
static struct inout_ring *rInst = NULL;
/* Fragment mempools (replaces rte_malloc for hot-path allocations) */
struct rte_mempool *g_frag_pool = NULL;
struct rte_mempool *g_ofo_pool = NULL;
/* fd → TCB index array (O(1) lookup from socket fd) — shared across all workers */
/* fd → TCB index array (O(1) lookup from socket fd) */
static struct ng_tcp_stream *fd_to_tcb[MAX_FD_ARRAY];
/* Current worker context (set by worker thread at startup, saved/restored by main) */
static int g_cur_worker = 0;
/* ── Multi-worker API ──────────────────────────────────────────── */
void ng_set_num_workers(int n) { if (n >= 1 && n <= MAX_WORKERS) g_num_workers = n; }
int ng_get_num_workers(void) { return g_num_workers; }
void ng_thread_set_worker(int w) { g_cur_worker = w; }
int ng_thread_get_worker(void) { return g_cur_worker; }
/* Forward declarations for lazy init */
static void tcpInstanceInit(int wid);
static void ringInstanceInit(int wid);
/* ══════════════════════════════════════════════════════════════════
* TCP table singleton
* ══════════════════════════════════════════════════════════════════ */
struct ng_tcp_table *tcpInstance(void)
{
int wid = g_cur_worker;
if (g_tcp_tables[wid] == NULL) tcpInstanceInit(wid);
return g_tcp_tables[wid];
if (tInst == NULL)
{
tInst = rte_malloc("ng_tcp_table", sizeof(struct ng_tcp_table), 0);
if (tInst == NULL)
rte_exit(EXIT_FAILURE, "tcpInstance malloc failed\n");
memset(tInst, 0, sizeof(struct ng_tcp_table));
}
return tInst;
}
struct inout_ring *ringInstance(void)
{
int wid = g_cur_worker;
if (g_rings[wid] == NULL) ringInstanceInit(wid);
return g_rings[wid];
}
/* Direct access for main thread to any worker's instances */
struct ng_tcp_table *tcpInstanceFor(int wid)
{
if (wid < 0 || wid > MAX_WORKERS) return NULL;
if (g_tcp_tables[wid] == NULL) tcpInstanceInit(wid);
return g_tcp_tables[wid];
}
struct inout_ring *ringInstanceFor(int wid)
{
if (wid < 0 || wid > MAX_WORKERS) return NULL;
if (g_rings[wid] == NULL) ringInstanceInit(wid);
return g_rings[wid];
}
/* Compute which worker should handle a given 4-tuple flow */
int ng_compute_worker(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport)
{
uint32_t h = sip ^ dip;
h ^= ((uint32_t)sport << 16) | dport;
h ^= (h >> 16);
return (int)(h % g_num_workers) + 1; /* workers are 1..N */
}
/* ── Init helpers (lazy allocation) ────────────────────────────── */
static void tcpInstanceInit(int wid)
{
g_tcp_tables[wid] = rte_malloc("ng_tcp_table", sizeof(struct ng_tcp_table), 0);
if (g_tcp_tables[wid] == NULL)
rte_exit(EXIT_FAILURE, "tcpInstance[%d] malloc failed\n", wid);
memset(g_tcp_tables[wid], 0, sizeof(struct ng_tcp_table));
}
static void ringInstanceInit(int wid)
{
g_rings[wid] = rte_malloc("inout_ring", sizeof(struct inout_ring), 0);
memset(g_rings[wid], 0, sizeof(struct inout_ring));
if (rInst == NULL)
{
rInst = rte_malloc("inout_ring", sizeof(struct inout_ring), 0);
memset(rInst, 0, sizeof(struct inout_ring));
}
return rInst;
}
/* ══════════════════════════════════════════════════════════════════
@@ -224,7 +181,6 @@ struct ng_tcp_stream *ng_tcp_stream_create(uint32_t sip, uint32_t dip,
s->protocol = IPPROTO_TCP;
s->fd = -1;
s->status = NG_TCP_STATUS_CLOSED;
s->worker_id = ng_compute_worker(sip, dip, sport, dport);
/* Sequence numbers (random ISN) */
uint32_t seed = time(NULL);
@@ -634,7 +590,6 @@ static struct rte_mbuf *ng_send_icmp(struct rte_mempool *mbuf_pool,
int ng_tcp_process(struct rte_mbuf *tcpmbuf)
{
if (!tcpmbuf) { printf("[BUG] ng_tcp_process: NULL mbuf\n"); return 0; }
struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(tcpmbuf,
struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
struct rte_tcp_hdr *tcphdr = (struct rte_tcp_hdr *)(iphdr + 1);
@@ -726,18 +681,10 @@ int ng_tcp_process(struct rte_mbuf *tcpmbuf)
int pkt_process(void *arg)
{
struct worker_args *wa = (struct worker_args *)arg;
struct rte_mempool *mbuf_pool = wa->mbuf_pool;
int worker_id = wa->worker_id;
/* Set thread-local worker for tcpInstance()/ringInstance() routing */
ng_thread_set_worker(worker_id);
struct sched_param sp = { .sched_priority = 90 };
sched_setscheduler(0, SCHED_FIFO, &sp);
struct rte_mempool *mbuf_pool = (struct rte_mempool *)arg;
struct inout_ring *ring = ringInstance();
printf("[WORKER %d] pkt_process started on lcore %d\n", worker_id, rte_lcore_id());
while (1)
@@ -745,7 +692,6 @@ int pkt_process(void *arg)
/* ── Phase 1: RX processing ── */
struct rte_mbuf *mbufs[BURST_SIZE];
if (!ring || !ring->in) { printf("\[BUG\] pkt_process: NULL ring\n"); rte_delay_ms(1000); continue; }
unsigned num_recvd = rte_ring_mc_dequeue_burst(ring->in,
(void **)mbufs, BURST_SIZE, NULL);
@@ -818,8 +764,6 @@ int pkt_process(void *arg)
uint64_t now = rte_get_timer_cycles();
struct ng_tcp_table *table = tcpInstance();
struct ng_tcp_stream *s = table->active_head;
static int dbg_active = 0;
if (s && !dbg_active) { printf("[WORKER %d] active_head non-null, processing\n", worker_id); dbg_active = 1; }
while (s)
{
struct ng_tcp_stream *next = s->active_next;