结构体

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:协议种类

    https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240802101759.png

  • localmac:本地IP

  • status:tcp状态迁移

  • sendbuf:发送环形缓冲区

  • recvbuf:接收环形缓冲区

  • prev:链式结构,指向前一个节点

  • next:链式结构,指向下一个节点

tcp流

https://imagehyj.oss-cn-hangzhou.aliyuncs.com/blog/20240801151317.png

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;
}

项目地址

项目地址