结构体
tcp控制块
// tcp control block
typedef struct __ln_tcp_stream {
int fd;
uint32_t sip;
uint32_t dip;
uint16_t sport;
uint16_t dport;
uint8_t proto;
uint8_t localmac[RTE_ETHER_ADDR_LEN];
LN_TCP_STATUS status;
struct rte_ring* sendbuf;
struct rte_ring* recvbuf;
struct __ln_tcp_stream* prev;
struct __ln_tcp_stream* next;
} ln_tcp_stream;
typedef struct __ln_tcp_table {
int count;
struct __ln_tcp_stream* streams;
} ln_tcp_table;
fd:socket句柄
sip:源IP地址
dip:目的IP地址
sport:源端口号
dport:目的端口号
proto:协议种类
localmac:本地IP
status:tcp状态迁移
sendbuf:发送环形缓冲区
recvbuf:接收环形缓冲区
prev:链式结构,指向前一个节点
next:链式结构,指向下一个节点
tcp流
typedef struct __ln_tcp_fragment {
uint16_t sport;
uint16_t dport;
uint32_t seqnum;
uint32_t acknum;
uint8_t hdr_off;
uint8_t tcp_flags;
uint16_t windows;
uint16_t cksum;
uint16_t urp;
int optlen;
uint32_t option[LN_TCP_OP_LEN];
unsigned char* data;
int length;
} ln_tcp_fragment;
tcp-table
单例模式,tcp control block
链表。
ln_tcp_table* tcpt = NULL;
/*
* 函数名称: get_tcp_table_instance
* 作 者: 黄彦杰 Lenn
* 设计日期: 2024-08-02
* 功能描述: 单例模式,tcp控制块链表
* 返 回 值: 链表头节点
*/
ln_tcp_table* get_tcp_table_instance(void) {
if (tcpt == NULL) {
tcpt = rte_malloc("tcp table", sizeof(ln_tcp_table), 0);
memset(tcpt, 0, sizeof(ln_tcp_table));
}
return tcpt;
}
/*
* 函数名称: ln_tcp_stream_search
* 作 者: 黄彦杰 Lenn
* 设计日期: 2024-08-02
* 功能描述: 搜索对应的tcp控制块
* 返 回 值: 搜索到tcp就返回节点,没有搜索到到返回NULL
*/
static ln_tcp_stream* ln_tcp_stream_search(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport) {
ln_tcp_table* table = get_tcp_table_instance();
ln_tcp_stream* stream = NULL;
for(stream = table->streams; stream != NULL; stream = stream->next) {
if (stream->sip == sip && stream->dip == dip && stream->sport == sport && stream->dport == dport) {
return stream;
}
}
return NULL;
}
/*
* 函数名称: ln_tcp_stream_create
* 作 者: 黄彦杰 Lenn
* 设计日期: 2024-08-02
* 功能描述:
* 返 回 值:
*/
static ln_tcp_stream* ln_tcp_stream_create(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport) {
ln_tcp_stream* stream = rte_malloc("tcp stream", sizeof(ln_tcp_stream), 0);
if (stream == NULL) {
return NULL;
}
stream->sip = sip;
stream->dip = dip;
stream->sport = sport;
stream->dport = dport;
stream->proto = IPPROTO_TCP;
stream->status = LN_TCP_STATUS_LISTEN;
stream->sendbuf = rte_ring_create("send buf", RING_SIZE, rte_socket_id(), 0);
stream->recvbuf = rte_ring_create("recv buf", RING_SIZE, rte_socket_id(), 0);
uint32_t next_seed = time(NULL);
stream->send_next = rand_r(&next_seed) % LN_TCP_MAX_SEQ;
rte_memcpy(stream->localmac, nSrcMac, RTE_ETHER_ADDR_LEN);
ln_tcp_table* table = get_tcp_table_instance();
LL_ADD(stream, table->streams);
return stream;
}
tcpt:tcp控制块链表的句柄,头结点。
get_tcp_table_instance
获取tcp控制链链表的句柄(头结点)。ln_tcp_stream_search
搜过对应的tcp控制块,搜索到就返回节点,否则返回空。
tcp状态转换
tcp状态定义
enum __LN_TCP_STATUS {
LN_TCP_STATUS_CLOSED = 0,
LN_TCP_STATUS_LISTEN,
LN_TCP_STATUS_SYN_RCVD,
LN_TCP_STATUS_SYN_SENT,
LN_TCP_STATUS_ESTABLISHED,
LN_TCP_STATUS_FIN_WAIT_1,
LN_TCP_STATUS_FIN_WAIT_2,
LN_TCP_STATUS_CLOSING,
LN_TCP_STATUS_TIME_WAIT,
LN_TCP_STATUS_CLOSE_WAIT,
LN_TCP_STATUS_LAST_ACK
}
typedef enum __LN_TCP_STATUS LN_TCP_STATUS;
参考tcp状态迁移图,定义tcp的11个状态。
listen状态
/*
* 函数名称: ln_tcp_handle_listen
* 作 者: 黄彦杰 Lenn
* 设计日期: 2024-08-02
* 功能描述:
* 返 回 值:
*/
static int ln_tcp_handle_listen(ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr) {
if (tcphdr->tcp_flags & RTE_TCP_SYN_FLAG) {
if (stream->status == LN_TCP_STATUS_LISTEN) {
ln_tcp_fragment* fragment = rte_malloc("tcp fragment", sizeof(ln_tcp_fragment), 0);
if (fragment == NULL) {
return -1;
}
memset(fragment, 0, sizeof(ln_tcp_fragment));
fragment->sport = tcphdr->dst_port;
fragment->dport = tcphdr->src_port;
fragment->seqnum = stream->send_next;
fragment->acknum = ntohl(tcphdr->sent_seq) + 1;
fragment->tcp_flags = (RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG);
fragment->windows = LN_TCP_INITIAL_WINDOWS;
fragment->hdr_off = 0x50;
fragment->data = NULL;
fragment->length = 0;
rte_ring_mp_enqueue(stream->sendbuf, (void*)fragment);
stream->status = LN_TCP_STATUS_SYN_RCVD;
}
}
return 0;
}
syn_revd
/*
* 函数名称:
* 作 者: 黄彦杰 Lenn
* 设计日期: 2024-08-02
* 功能描述:
* 返 回 值:
*/
static int ln_tcp_handle_syn_revd(ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr) {
if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) {
if (stream->status == LN_TCP_STATUS_SYN_RCVD) {
if (htonl(tcphdr->recv_ack) == stream->send_next + 1) {
// ......
}
stream->status = LN_TCP_STATUS_ESTABLISHED
}
}
return 0;
}
评论