Initial commit: dpdk-ws-client source code

This commit is contained in:
wxj
2026-06-30 16:33:29 +00:00
parent 0d57633d23
commit 5e57d06b1f
21 changed files with 6070 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
/**
* tcp_output.c — TCP output engine + congestion control
*
* - Congestion control (RFC 5681): slow start, CA, fast retransmit, fast recovery
* - RTO-based retransmission
* - Nagle algorithm
* - Window management
*/
#include "tcp_core.h"
/* ══════════════════════════════════════════════════════════════════
* Build TCP options for outgoing segments
* ══════════════════════════════════════════════════════════════════ */
int ng_tcp_build_options(uint8_t *buf, struct ng_tcp_stream *stream,
int want_syn, int want_syn_ack)
{
int pos = 0;
(void)want_syn_ack;
if (want_syn || want_syn_ack)
{
/* MSS */
buf[pos++] = TCPOPT_MSS;
buf[pos++] = TCPOLEN_MSS;
buf[pos++] = (TCP_MSS_DEFAULT >> 8) & 0xFF;
buf[pos++] = TCP_MSS_DEFAULT & 0xFF;
/* Window Scale */
buf[pos++] = TCPOPT_NOP;
buf[pos++] = TCPOPT_WSCALE;
buf[pos++] = TCPOLEN_WSCALE;
buf[pos++] = TCP_WSCALE_DEFAULT;
/* SACK-permitted */
buf[pos++] = TCPOPT_NOP;
buf[pos++] = TCPOPT_NOP;
buf[pos++] = TCPOPT_SACKP;
buf[pos++] = TCPOLEN_SACKP; /* 2 */
/* Timestamps */
buf[pos++] = TCPOPT_NOP;
buf[pos++] = TCPOPT_NOP;
buf[pos++] = TCPOPT_TIMESTAMP;
buf[pos++] = TCPOLEN_TIMESTAMP;
uint32_t ts = (uint32_t)(rte_get_timer_cycles() / (rte_get_timer_hz() / 1000000));
buf[pos++] = (ts >> 24) & 0xFF;
buf[pos++] = (ts >> 16) & 0xFF;
buf[pos++] = (ts >> 8) & 0xFF;
buf[pos++] = ts & 0xFF;
buf[pos++] = 0;
buf[pos++] = 0;
buf[pos++] = 0;
buf[pos++] = 0; /* TS Echo = 0 */
}
/* Pad to 4-byte boundary */
while (pos & 0x3)
buf[pos++] = TCPOPT_NOP;
return pos;
}
/* ══════════════════════════════════════════════════════════════════
* Congestion control
* ══════════════════════════════════════════════════════════════════ */
void ng_tcp_congestion_ack(struct ng_tcp_stream *s)
{
if (s->in_fast_recovery)
{
s->cwnd = s->ssthresh;
s->in_fast_recovery = 0;
return;
}
if (s->cwnd < s->ssthresh)
{
/* Slow start: exponential */
s->cwnd += s->rcv_mss;
}
else
{
/* Congestion avoidance: linear */
s->cwnd += (s->rcv_mss * s->rcv_mss) / s->cwnd;
if (s->cwnd < TCP_INITIAL_CWND)
s->cwnd = TCP_INITIAL_CWND;
}
}
void ng_tcp_congestion_loss(struct ng_tcp_stream *s)
{
/* Fast retransmit + fast recovery */
uint32_t inflight = (s->snd_nxt > s->snd_una) ? (s->snd_nxt - s->snd_una) : 0;
s->ssthresh = inflight / 2;
if (s->ssthresh < 2 * s->rcv_mss)
s->ssthresh = 2 * s->rcv_mss;
s->cwnd = s->ssthresh + 3 * s->rcv_mss;
s->in_fast_recovery = 1;
s->recover = s->snd_nxt; /* snd_max in practice */
printf("[TCP] Fast retransmit: cwnd=%u ssthresh=%u\n", s->cwnd, s->ssthresh);
}
void ng_tcp_congestion_rto(struct ng_tcp_stream *s)
{
s->ssthresh = (s->snd_nxt - s->snd_una) / 2;
if (s->ssthresh < 2 * s->rcv_mss)
s->ssthresh = 2 * s->rcv_mss;
s->cwnd = s->rcv_mss; /* reset to 1 MSS */
s->in_fast_recovery = 0;
printf("[TCP] RTO: cwnd reset to %u\n", s->cwnd);
}
/* ══════════════════════════════════════════════════════════════════
* Process incoming ACK with SACK
* ══════════════════════════════════════════════════════════════════ */
void ng_tcp_process_ack(struct ng_tcp_stream *stream, uint32_t ack,
uint32_t ack_end)
{
(void)ack_end;
/* Free retransmit ring entries that are now acknowledged */
int count = rte_ring_count(stream->retransmit_ring);
for (int i = 0; i < count; i++)
{
struct ng_tcp_fragment *f = NULL;
rte_ring_mc_dequeue(stream->retransmit_ring, (void **)&f);
if (f == NULL)
continue;
if (SEQ_LEQ(f->seqnum + f->length, ack))
{
/* Fully acknowledged — return to pool */
frag_free(f);
}
else
{
/* Not yet acked — re-enqueue */
rte_ring_mp_enqueue(stream->retransmit_ring, f);
}
}
}
/* ══════════════════════════════════════════════════════════════════
* ng_tcp_output — per-connection send processing
* (Called from ng_tcp_out in tcp_core.c which handles per-stream dequeue)
* Here we handle the scheduling logic that ng_tcp_out doesn't cover:
* zero-window probes, pending retransmits, etc.
* ══════════════════════════════════════════════════════════════════ */
int ng_tcp_output(struct rte_mempool *mbuf_pool)
{
(void)mbuf_pool;
/* The main output logic is in ng_tcp_out (tcp_core.c).
* This function is a placeholder for output scheduling:
* - Zero-window probing
* - Batch send across all connections
* Currently handled inline in pkt_process timer loop.
*/
return 0;
}