dpdk之tcp代码案例

一、dpdk之tcp代码案例

1.tcp.c

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <sys/time.h>  // 用于计算Ping耗时

#include <rte_eal.h>
#include <rte_mbuf.h>
#include <rte_ethdev.h>
#include <rte_mempool.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_udp.h>
#include <rte_arp.h>
#include <rte_net.h>
#include <rte_cycles.h>
#include <rte_icmp.h>  // DPDK ICMP头定义
#include <rte_tcp.h>

#define ENABLE_ARP 1
#define NUM_MBUFS 4096
#define BURST_SIZE 128
#define ENABLE_SEND 1

// ARP表相关配置
#define ARP_TABLE_MAX_ENTRY 64    // ARP表最大条目数
#define ARP_ENTRY_EXPIRE_SEC 300  // ARP条目过期时间(5分钟)
#define ARP_REQUEST_INTERVAL 1    // ARP请求发送间隔
#define ARP_REQUEST_RETRY 3       // ARP请求的重试次数

// ICMP相关配置
#define ICMP_ECHO_DATA_LEN 56     // ICMP回显数据长度(标准Ping包)
#define ICMP_REQUEST_RETRY 4      // Ping重试次数
#define ICMP_REQUEST_TIMEOUT 1    // Ping超时时间(秒)
#define ICMP_ID 0x1234            // ICMP标识符(固定值)

// tcp相关配置
#define TCP_TABLE_MAX_ENTRY 32    // tcp连接表最大条目数
#define TCP_SYN_RETRY    3        // SYN重传次数
#define TCP_SYN_TIMEOUT  3        // SYN超时时间
#define TCP_MSS  1460             // TCP最大分段大小
#define TCP_WINDOW_SIZE  65535    // TCP窗口大小
#define TCP_TTL  64               // TCP ttl
#define TCP_CONN_EXPIRE_SEC 60  // TCP连接过期时间(60秒)
#define TCP_CLOSED_CLEAN_INTERVAL 10  // 清理CLOSED状态条目的间隔(10秒)
#define TCP_TABLE_SIZE TCP_TABLE_MAX_ENTRY          // 根据你的实际定义调整
#define TCP_TIME_WAIT_TIMEOUT 60     // 60秒清理TIME_WAIT
#define TCP_SYN_RECV_TIMEOUT 10      // 10秒清理SYN_RECV半连接

typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;

// 全局端口配置
int global_portid = 0;
static struct rte_ether_addr gPortMacAddr;  // 本地MAC
static u32 gPortIpAddr = 0;                 // 本地IP
static int g_running = 1;                   // 程序运行标志

// MBUF池全局指针
struct rte_mempool *g_mbuf_pool = NULL;

//ICMP ping上下文,用于主动Ping时记录请求信息
typedef struct {
    u32 target_ip;              //目标ip
    u16 seq;                    //序列号
    struct timeval send_time;   //发送时间
    int recv_flag;              //是否收到响应
    double rtt;                 //往返时间
}icmp_ping_ctx_t;

// 全局Ping上下文(线程安全)
static icmp_ping_ctx_t g_ping_ctx;
static pthread_mutex_t g_ping_mutex = PTHREAD_MUTEX_INITIALIZER;

// ARP表条目结构体
typedef struct {
    u32 ip_addr;                // 目标IP地址
    struct rte_ether_addr mac;  // 目标MAC地址
    time_t update_time;         // 最后更新时间
    int valid;                  // 条目是否有效,1有效,0无效
} arp_table_entry_t;

// ARP表结构体
typedef struct {
    arp_table_entry_t entries[ARP_TABLE_MAX_ENTRY];
    pthread_mutex_t mutex;  
} arp_table_t;

arp_table_t g_arp_table;   // 全局ARP表

//TCP连接状态枚举
typedef enum {
    TCP_STATE_CLOSED = 0,
    TCP_STATE_SYN_SENT,
    TCP_STATE_ESTABLISHED,
    TCP_STATE_FIN_WAIT1,
    TCP_STATE_FIN_WAIT2,
    TCP_STATE_CLOSING,
    TCP_STATE_TIME_WAIT,
    TCP_STATE_LISTEN,
    TCP_STATE_SYN_RECV
}tcp_state_t;

// TCP连接条目结构体(新增接收缓冲区处理粘包/乱序)
typedef struct {
    uint32_t src_ip;              // 源IP
    uint32_t dst_ip;              // 目标IP
    uint16_t src_port;            // 源端口
    uint16_t dst_port;            // 目标端口
    tcp_state_t state;            // 连接状态
    uint32_t seq;                 // 发送序列号
    uint32_t ack;                 // 确认序列号
    time_t last_active;           // 最后活动时间
    int valid;                    // 条目是否有效
    // 新增:接收缓冲区(处理粘包/乱序)
    uint8_t recv_buf[4096];       // 接收缓存
    uint32_t recv_buf_len;        // 缓存数据长度
    uint32_t recv_next_seq;       // 期望接收的下一个seq
} tcp_conn_entry_t;

//tcp连接表
typedef struct {
    tcp_conn_entry_t entries[TCP_TABLE_MAX_ENTRY];
    pthread_mutex_t mutex;
}tcp_table_t;

tcp_table_t g_tcp_table;          // 全局TCP连接表


// ====================== 函数前置声明 ======================
static void arp_table_init(void);
static int arp_table_lookup(u32 ip_addr, struct rte_ether_addr *mac);
static int send_arp_request(u32 target_ip);
static int ustack_encode_arp_request(u8 *msg, u32 target_ip);
static int encode_icmp_echo_request(u8 *msg, u32 dip, u16 seq);
static int send_icmp_echo_request(u32 dip, u16 seq);
static void handle_icmp_echo_reply(struct rte_icmp_hdr *icmphdr, struct rte_ipv4_hdr *iphdr);
static void handle_udp_packet(__attribute__((unused))struct rte_ether_hdr *ethhdr, struct rte_ipv4_hdr *iphdr, struct rte_udp_hdr *udphdr);

// TCP相关函数声明
static void tcp_table_init(void);
static void tcp_table_clean_invalid(void);
static void tcp_table_clean_invalid(void);
static int tcp_table_reset_entry(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port);
static uint16_t tcp_checksum(struct rte_ipv4_hdr *ip, struct rte_tcp_hdr *tcp, uint16_t tcp_len);
static int encode_tcp_packet(uint8_t *msg, struct rte_ether_addr *dmac, uint32_t sip, uint32_t dip,
                           uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack,
                           uint8_t flags, uint8_t *payload, uint16_t payload_len);
static int send_tcp_packet(uint32_t dip, uint16_t dport, uint16_t sport, uint32_t seq, 
                         uint32_t ack, uint8_t flags, uint8_t *payload, uint16_t payload_len);
static int tcp_connect(uint32_t dip, uint16_t dport, uint16_t sport);
static int tcp_send_data(uint32_t dip, uint16_t dport, uint16_t sport, uint8_t *data, uint16_t len);
static int tcp_close(uint32_t dip, uint16_t dport, uint16_t sport);
static void handle_tcp_packet(__attribute__((unused))struct rte_ether_hdr *ethhdr, struct rte_ipv4_hdr *iphdr, struct rte_tcp_hdr *tcphdr);
static int tcp_table_add(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, tcp_state_t state);
static int tcp_table_update_state(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, tcp_state_t new_state);
static tcp_conn_entry_t* tcp_table_lookup(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port);
static void tcp_table_print(void);
static uint32_t generate_seq_num(void);

void *cli_thread_func(__attribute__((unused)) void *arg);

// 端口配置,仅仅指定接收数据包的最大长度为以太网的最大帧长
static const struct rte_eth_conf port_conf_default = {
    .rxmode = {.max_rx_pkt_len = RTE_ETHER_MAX_LEN}
};

// ====================== ARP表相关函数 ======================
static void arp_table_init(void){
    memset(&g_arp_table,0,sizeof(arp_table_t));
    pthread_mutex_init(&g_arp_table.mutex,NULL);

    // 初始化所有条目为无效
    for(int i = 0;i < ARP_TABLE_MAX_ENTRY;i++){
        g_arp_table.entries[i].valid = 0;
        g_arp_table.entries[i].ip_addr = 0;
        memset(&g_arp_table.entries[i].mac,0,sizeof(struct rte_ether_addr));
        g_arp_table.entries[i].update_time = 0;
    }
}

static int arp_table_lookup(u32 ip_addr,struct rte_ether_addr *mac){
    pthread_mutex_lock(&g_arp_table.mutex);

    for(int i = 0;i < ARP_TABLE_MAX_ENTRY;i++){
        if(g_arp_table.entries[i].valid && g_arp_table.entries[i].ip_addr == ip_addr){
            // 检查是否过期
            time_t now = time(NULL);
            if(now - g_arp_table.entries[i].update_time > ARP_ENTRY_EXPIRE_SEC){
                printf("⚠️ ARP条目[%s]已过期,自动删除 ⚠️\n", 
                       inet_ntoa(*(struct in_addr*)&ip_addr));

                g_arp_table.entries[i].valid = 0;
                pthread_mutex_unlock(&g_arp_table.mutex);
                return -1;
            }

            // 找到有效条目
            memcpy(mac, &g_arp_table.entries[i].mac, sizeof(struct rte_ether_addr));
            pthread_mutex_unlock(&g_arp_table.mutex);
            return 0;
        }
    }

    pthread_mutex_unlock(&g_arp_table.mutex);
    return -1; // 未找到
}

static int arp_table_update(u32 ip_addr,struct rte_ether_addr *mac){
    pthread_mutex_lock(&g_arp_table.mutex);

    // 先查找是否已有该IP
    for(int i = 0;i < ARP_TABLE_MAX_ENTRY;i++){
        if(g_arp_table.entries[i].ip_addr == ip_addr){
            // 更新现有条目
            memcpy(&g_arp_table.entries[i].mac, mac, sizeof(struct rte_ether_addr));
            g_arp_table.entries[i].update_time = time(NULL);
            g_arp_table.entries[i].valid = 1;
            pthread_mutex_unlock(&g_arp_table.mutex);
            return 0;
        }
    }

    // 查找空条目
    for(int i = 0;i < ARP_TABLE_MAX_ENTRY;i++){
        if(!g_arp_table.entries[i].valid){
            g_arp_table.entries[i].ip_addr = ip_addr;
            memcpy(&g_arp_table.entries[i].mac, mac, sizeof(struct rte_ether_addr));
            g_arp_table.entries[i].update_time = time(NULL);
            g_arp_table.entries[i].valid = 1;
            pthread_mutex_unlock(&g_arp_table.mutex);
            return 0;
        }
    }

    // 表满,替换最旧的条目
    int oldest_idx = 0;
    time_t oldest_time = g_arp_table.entries[0].update_time;
    for (int i = 1; i < ARP_TABLE_MAX_ENTRY; i++) {
        if (g_arp_table.entries[i].update_time < oldest_time) {
            oldest_time = g_arp_table.entries[i].update_time;
            oldest_idx = i;
        }
    }
    
    printf("⚠️ ARP表已满,替换最旧条目[%s] ⚠️\n", 
           inet_ntoa(*(struct in_addr*)&g_arp_table.entries[oldest_idx].ip_addr));
    g_arp_table.entries[oldest_idx].ip_addr = ip_addr;
    memcpy(&g_arp_table.entries[oldest_idx].mac, mac, sizeof(struct rte_ether_addr));
    g_arp_table.entries[oldest_idx].update_time = time(NULL);
    g_arp_table.entries[oldest_idx].valid = 1;
    
    pthread_mutex_unlock(&g_arp_table.mutex);
    return 0;
}

static void arp_table_print(void) {
    printf("\n=================== ARP 表 ===================\n");
    printf("IP地址\t\t\tMAC地址\t\t\t过期时间(秒)\n");
    printf("----------------------------------------------\n");
    
    pthread_mutex_lock(&g_arp_table.mutex);
    time_t now = time(NULL);
    
    for (int i = 0; i < ARP_TABLE_MAX_ENTRY; i++) {
        if (g_arp_table.entries[i].valid) {
            struct in_addr ip_addr;
            ip_addr.s_addr = g_arp_table.entries[i].ip_addr;
            
            int expire_left = ARP_ENTRY_EXPIRE_SEC - (now - g_arp_table.entries[i].update_time);
            if (expire_left < 0) expire_left = 0;
            
            printf("%s\t\t%02x:%02x:%02x:%02x:%02x:%02x\t\t%d\n",
                   inet_ntoa(ip_addr),
                   g_arp_table.entries[i].mac.addr_bytes[0],
                   g_arp_table.entries[i].mac.addr_bytes[1],
                   g_arp_table.entries[i].mac.addr_bytes[2],
                   g_arp_table.entries[i].mac.addr_bytes[3],
                   g_arp_table.entries[i].mac.addr_bytes[4],
                   g_arp_table.entries[i].mac.addr_bytes[5],
                   expire_left);
        }
    }
    
    pthread_mutex_unlock(&g_arp_table.mutex);
    printf("==============================================\n\n");
}

static void arp_table_clean_expired(void) {
    pthread_mutex_lock(&g_arp_table.mutex);
    time_t now = time(NULL);
    int cleaned = 0;
    
    for (int i = 0; i < ARP_TABLE_MAX_ENTRY; i++) {
        if (g_arp_table.entries[i].valid && 
            (now - g_arp_table.entries[i].update_time > ARP_ENTRY_EXPIRE_SEC)) {
            g_arp_table.entries[i].valid = 0;
            cleaned++;
        }
    }
    
    pthread_mutex_unlock(&g_arp_table.mutex);
    
    // if (cleaned > 0) {
    //     printf("🧹 清理了%d个过期ARP条目 🧹\n", cleaned);
    // } else {
    //     printf("✅ 无过期ARP条目需要清理 ✅\n");
    // }
}

// ====================== ICMP相关函数 ======================
// 计算ICMP校验和
static uint16_t icmp_checksum(const void *data, uint16_t len) {
    const uint16_t *buf = (const uint16_t *)data;
    uint32_t sum = 0;
    uint16_t result;

    while (len > 1) {
        sum += *buf++;
        len -= 2;
    }

    if (len == 1) {
        sum += *(const uint8_t *)buf;
    }

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    result = ~sum;

    return result;
}

//编码icmp请求
static int encode_icmp_echo_request(u8 *msg,u32 dip,u16 seq){
    //1. 以太网头
    struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg;
    struct rte_ether_addr dmac;
    if (arp_table_lookup(dip, &dmac) < 0) {
        printf("❌ 未找到目标IP[%s]的MAC地址 ❌\n", inet_ntoa(*(struct in_addr*)&dip));
        return -1;
    }
    memcpy(eth->d_addr.addr_bytes, dmac.addr_bytes, RTE_ETHER_ADDR_LEN);
    memcpy(eth->s_addr.addr_bytes, gPortMacAddr.addr_bytes, RTE_ETHER_ADDR_LEN);
    eth->ether_type = htons(RTE_ETHER_TYPE_IPV4);

    //2. IP头
    struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(eth + 1);
    ip->version_ihl = 0x45;  // IPv4,头长20字节
    ip->type_of_service = 0;
    uint16_t ip_total_len = sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_icmp_hdr) + ICMP_ECHO_DATA_LEN;
    ip->total_length = htons(ip_total_len);
    ip->packet_id = 0;
    ip->fragment_offset = 0;
    ip->time_to_live = 64;
    ip->next_proto_id = IPPROTO_ICMP;
    ip->src_addr = gPortIpAddr;
    ip->dst_addr = dip;
    ip->hdr_checksum = 0;
    ip->hdr_checksum = rte_ipv4_cksum(ip);

    //3. ICMP头
    struct rte_icmp_hdr *icmp = (struct rte_icmp_hdr *)(ip + 1);
    icmp->icmp_type = RTE_IP_ICMP_ECHO_REQUEST;  //回显请求
    icmp->icmp_code = 0;
    icmp->icmp_cksum = 0;
    icmp->icmp_ident = htons(ICMP_ID);  //区分一台主机上不同进程发起的ping请求
    icmp->icmp_seq_nb = htons(seq);  //ping包的序号

    // 4. ICMP数据(填充随机数据,标准Ping包56字节)
    uint8_t *icmp_data = (uint8_t *)(icmp + 1);
    for (int i = 0; i < ICMP_ECHO_DATA_LEN; i++) {
        icmp_data[i] = i % 0xFF;  // 填充简单数据
    }

    // 5. 计算ICMP校验和
    icmp->icmp_cksum = icmp_checksum(icmp, sizeof(struct rte_icmp_hdr) + ICMP_ECHO_DATA_LEN);

    return 0;
}

//编码icmp应答包
// 输出:存放组装好的ICMP响应包的内存起始地址
// 输入:原始Ping请求包的以太网头
// 输入:原始Ping请求包的IP头
// 输入:原始Ping请求包的ICMP头
static int encode_icmp_echo_reply(u8 *msg, struct rte_ether_hdr *orig_eth, 
                                  struct rte_ipv4_hdr *orig_ip, struct rte_icmp_hdr *orig_icmp) {
    // 1. 以太网头(源MAC和目标MAC互换)
    struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg;
    memcpy(eth->d_addr.addr_bytes, orig_eth->s_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
    memcpy(eth->s_addr.addr_bytes, gPortMacAddr.addr_bytes, RTE_ETHER_ADDR_LEN);
    eth->ether_type = htons(RTE_ETHER_TYPE_IPV4);

    // 2. IP头(源IP和目标IP互换)
    struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(eth + 1);
    ip->version_ihl = 0x45;
    ip->type_of_service = 0;
    ip->total_length = orig_ip->total_length;  // 长度不变
    ip->packet_id = 0;
    ip->fragment_offset = 0;
    ip->time_to_live = 64;
    ip->next_proto_id = IPPROTO_ICMP;
    ip->src_addr = gPortIpAddr;
    ip->dst_addr = orig_ip->src_addr;
    ip->hdr_checksum = 0;
    ip->hdr_checksum = rte_ipv4_cksum(ip);

    // 3. ICMP头(类型改为响应,复用原ID和序列号)
    struct rte_icmp_hdr *icmp = (struct rte_icmp_hdr *)(ip + 1);
    icmp->icmp_type = RTE_IP_ICMP_ECHO_REPLY;  // 回显响应
    icmp->icmp_code = 0;
    icmp->icmp_cksum = 0;
    icmp->icmp_ident = orig_icmp->icmp_ident;
    icmp->icmp_seq_nb = orig_icmp->icmp_seq_nb;

    // 4. 复用原ICMP数据
    uint16_t icmp_data_len = ntohs(orig_ip->total_length) - sizeof(struct rte_ipv4_hdr) - sizeof(struct rte_icmp_hdr);
    uint8_t *orig_data = (uint8_t *)(orig_icmp + 1);
    uint8_t *reply_data = (uint8_t *)(icmp + 1);
    memcpy(reply_data, orig_data, icmp_data_len);

    // 5. 重新计算ICMP校验和
    icmp->icmp_cksum = icmp_checksum(icmp, sizeof(struct rte_icmp_hdr) + icmp_data_len);

    return 0;
}

//发送icmp请求包
static int send_icmp_echo_request(u32 dip,u16 seq){
    uint16_t total_len = sizeof(struct rte_ether_hdr) + 
                         sizeof(struct rte_ipv4_hdr) + 
                         sizeof(struct rte_icmp_hdr) + 
                         ICMP_ECHO_DATA_LEN;
    
    // 分配MBUF
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(g_mbuf_pool);
    if (!mbuf) {
        printf("❌ 分配ICMP MBUF失败 ❌\n");
        return -1;
    }
    mbuf->pkt_len = total_len;
    mbuf->data_len = total_len;

    // 编码ICMP请求包
    u8 *msg = rte_pktmbuf_mtod(mbuf, u8 *);
    if (encode_icmp_echo_request(msg, dip, seq) < 0) {
        rte_pktmbuf_free(mbuf);
        return -1;
    }

    // 发送ICMP包
    int ret = rte_eth_tx_burst(global_portid, 0, &mbuf, 1);
    if (ret != 1) {
        printf("❌ ICMP请求发送失败 ❌\n");
        rte_pktmbuf_free(mbuf);
        return -1;
    }

    //记录发送时间
    pthread_mutex_lock(&g_ping_mutex);
    gettimeofday(&g_ping_ctx.send_time,NULL);
    g_ping_ctx.seq = seq;
    g_ping_ctx.target_ip = dip;
    g_ping_ctx.recv_flag = 0;
    pthread_mutex_unlock(&g_ping_mutex);

    struct in_addr ip_addr;
    ip_addr.s_addr = dip;
    printf("📤 发送ICMP请求到 %s (seq=%d) 📤\n", inet_ntoa(ip_addr), seq);
    return 0;
}

static void handle_icmp_echo_request(struct rte_ether_hdr *ethhdr, struct rte_ipv4_hdr *iphdr, struct rte_icmp_hdr *icmphdr) {
    // 只处理目标IP为本机的回显请求
    if (iphdr->dst_addr != gPortIpAddr || icmphdr->icmp_type != RTE_IP_ICMP_ECHO_REQUEST) {
        return;
    }

    // 计算数据包总长度
    uint16_t icmp_data_len = ntohs(iphdr->total_length) - sizeof(struct rte_ipv4_hdr) - sizeof(struct rte_icmp_hdr);
    uint16_t total_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_icmp_hdr) + icmp_data_len;

    // 分配MBUF
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(g_mbuf_pool);
    if (!mbuf) {
        printf("❌ 分配ICMP响应MBUF失败 ❌\n");
        return;
    }
    mbuf->pkt_len = total_len;
    mbuf->data_len = total_len;

    // 编码ICMP响应包
    u8 *msg = rte_pktmbuf_mtod(mbuf, u8 *);
    encode_icmp_echo_reply(msg, ethhdr, iphdr, icmphdr);

    // 发送响应包
    int ret = rte_eth_tx_burst(global_portid, 0, &mbuf, 1);
    if (ret != 1) {
        printf("❌ ICMP响应发送失败 ❌\n");
        rte_pktmbuf_free(mbuf);
        return;
    }

    struct in_addr ip_addr;
    ip_addr.s_addr = iphdr->src_addr;
    printf("📥 收到ICMP请求,已响应 %s (seq=%d) 📥\n", 
           inet_ntoa(ip_addr), ntohs(icmphdr->icmp_seq_nb));
}

static void handle_icmp_echo_reply(struct rte_icmp_hdr *icmphdr,struct rte_ipv4_hdr *iphdr){
     pthread_mutex_lock(&g_ping_mutex);
    // 匹配目标IP、ID、序列号
    if (g_ping_ctx.target_ip != iphdr->src_addr || 
        ntohs(icmphdr->icmp_ident) != ICMP_ID || 
        ntohs(icmphdr->icmp_seq_nb) != g_ping_ctx.seq) {
        pthread_mutex_unlock(&g_ping_mutex);
        return;
    }

    // 计算往返时间(RTT)
    struct timeval recv_time;
    gettimeofday(&recv_time, NULL);
    double sec = recv_time.tv_sec - g_ping_ctx.send_time.tv_sec;
    double usec = recv_time.tv_usec - g_ping_ctx.send_time.tv_usec;
    g_ping_ctx.rtt = (sec * 1000) + (usec / 1000);
    g_ping_ctx.recv_flag = 1;

    struct in_addr ip_addr;
    ip_addr.s_addr = iphdr->src_addr;
    printf("📥 收到ICMP响应 from %s (seq=%d) 耗时=%.2f ms 📥\n", 
           inet_ntoa(ip_addr), g_ping_ctx.seq, g_ping_ctx.rtt);
    pthread_mutex_unlock(&g_ping_mutex);
}

static int ping_target(u32 target_ip) {
    // 先发送ARP请求获取MAC
    for (int i = 0; i < ARP_REQUEST_RETRY; i++) {
        send_arp_request(target_ip);
        sleep(ARP_REQUEST_INTERVAL);
        struct rte_ether_addr mac;
        if (arp_table_lookup(target_ip, &mac) == 0) {
            break;
        }
    }

    // 初始化Ping上下文
    pthread_mutex_lock(&g_ping_mutex);
    g_ping_ctx.target_ip = target_ip;
    g_ping_ctx.recv_flag = 0;
    g_ping_ctx.rtt = 0;
    pthread_mutex_unlock(&g_ping_mutex);

    int success = 0;
    struct in_addr ip_addr;
    ip_addr.s_addr = target_ip;
    printf("\n🏓 PING %s (%s) 56(84) bytes of data. 🏓\n", 
           inet_ntoa(ip_addr), inet_ntoa(ip_addr));

    // 发送多个Ping请求
    for (int i = 0; i < ICMP_REQUEST_RETRY; i++) {
        send_icmp_echo_request(target_ip, i + 1);
        // 等待响应
        sleep(ICMP_REQUEST_TIMEOUT);
        
        pthread_mutex_lock(&g_ping_mutex);
        if (g_ping_ctx.recv_flag) {
            success++;
        } else {
            printf("⌛ ICMP请求超时 (seq=%d) ⌛\n", i + 1);
        }
        pthread_mutex_unlock(&g_ping_mutex);
    }

    // 打印Ping统计
    printf("\n--- %s ping 统计 ---\n", inet_ntoa(ip_addr));
    printf("%d 个包已发送, %d 个包已接收, %d%% 丢包率\n", 
           ICMP_REQUEST_RETRY, success, (ICMP_REQUEST_RETRY - success) * 100 / ICMP_REQUEST_RETRY);
    
    return success > 0 ? 0 : -1;
}

// 处理接收到的UDP包
static void handle_udp_packet(__attribute__((unused))struct rte_ether_hdr *ethhdr, struct rte_ipv4_hdr *iphdr, struct rte_udp_hdr *udphdr) {
    // 只处理目标IP为本机的UDP包
    if (iphdr->dst_addr != gPortIpAddr) {
        return;
    }

    // 计算UDP负载长度
    uint16_t udp_total_len = ntohs(udphdr->dgram_len);
    uint16_t payload_len = udp_total_len - sizeof(struct rte_udp_hdr);
    uint8_t *payload = (uint8_t*)(udphdr + 1);

    // 打印UDP接收信息
    struct in_addr src_ip, dst_ip;
    src_ip.s_addr = iphdr->src_addr;
    dst_ip.s_addr = iphdr->dst_addr;
    printf("📥 收到UDP包 📥\n");
    printf("   源:%s:%d\n", inet_ntoa(src_ip), ntohs(udphdr->src_port));
    printf("   目标:%s:%d\n", inet_ntoa(dst_ip), ntohs(udphdr->dst_port));
    printf("   负载长度:%d字节\n", payload_len);
    printf("   负载内容:%.*s\n", payload_len, payload);
}

// ====================== 端口初始化与ARP发送函数 ======================
static int ustack_init_port(struct rte_mempool *mbuf_pool){
    u16 nb_sys_ports = rte_eth_dev_count_avail();
    if (nb_sys_ports == 0) {
        rte_exit(EXIT_FAILURE, "No Supported eth found\n");
    }

    struct rte_eth_dev_info dev_info;
    rte_eth_dev_info_get(global_portid,&dev_info);

    const int num_rx_queues = 1;
    const int num_tx_queues = 1;

    // 配置以太网端口
    if (rte_eth_dev_configure(global_portid, num_rx_queues, num_tx_queues, &port_conf_default) < 0) {
        rte_exit(EXIT_FAILURE, "Could not configure eth dev\n");
    }

    // 配置rx队列
    if (rte_eth_rx_queue_setup(global_portid, 0, 128, rte_eth_dev_socket_id(global_portid), NULL, mbuf_pool) < 0) {
        rte_exit(EXIT_FAILURE, "Could not setup RX queue\n");
    }

    // 配置tx队列
    struct rte_eth_txconf txq_conf = dev_info.default_txconf;
    txq_conf.offloads = port_conf_default.rxmode.offloads;
    if (rte_eth_tx_queue_setup(global_portid, 0, 512, rte_eth_dev_socket_id(global_portid), &txq_conf) < 0) {
        rte_exit(EXIT_FAILURE, "Could not setup TX queue\n");
    }

    if(rte_eth_dev_start(global_portid) < 0){
        rte_exit(EXIT_FAILURE, "Could not start eth dev\n");
    }

    // 获取本机MAC和IP
    rte_eth_macaddr_get(global_portid, &gPortMacAddr);
    gPortIpAddr = inet_addr("192.168.3.100"); // 可根据实际情况修改

    // 启用混杂模式
    rte_eth_promiscuous_enable(global_portid);

    printf("✅ 端口初始化完成 ✅\n");
    printf("   本机MAC:%02x:%02x:%02x:%02x:%02x:%02x\n",
           gPortMacAddr.addr_bytes[0], gPortMacAddr.addr_bytes[1],
           gPortMacAddr.addr_bytes[2], gPortMacAddr.addr_bytes[3],
           gPortMacAddr.addr_bytes[4], gPortMacAddr.addr_bytes[5]);
    printf("   本机IP:%s\n", inet_ntoa(*(struct in_addr*)&gPortIpAddr));
    return 0;
}

static int ustack_encode_arp_request(u8 *msg,u32 target_ip){
    // 以太网头
    struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg;
    // 广播MAC
    memset(eth->d_addr.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN);
    memcpy(eth->s_addr.addr_bytes, gPortMacAddr.addr_bytes, RTE_ETHER_ADDR_LEN);
    eth->ether_type = htons(RTE_ETHER_TYPE_ARP);

    // ARP头
    struct rte_arp_hdr *arp = (struct rte_arp_hdr *)(eth + 1);
    arp->arp_hardware = htons(RTE_ARP_HRD_ETHER);  // 以太网
    arp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4);
    arp->arp_hlen = RTE_ETHER_ADDR_LEN;
    arp->arp_plen = sizeof(uint32_t);
    arp->arp_opcode = htons(RTE_ARP_OP_REQUEST);

    // ARP发送方(本机)
    memcpy(&arp->arp_data.arp_sha, gPortMacAddr.addr_bytes, RTE_ETHER_ADDR_LEN);
    arp->arp_data.arp_sip = gPortIpAddr;

    // ARP目标方
    memset(&arp->arp_data.arp_tha, 0, RTE_ETHER_ADDR_LEN); // 目标MAC未知
    arp->arp_data.arp_tip = target_ip;

    return 0;
}

static int send_arp_request(u32 target_ip){
    u16 total_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_arp_hdr);

    // 分配MBUF
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(g_mbuf_pool);
    if (!mbuf) {
        printf("❌ 分配ARP MBUF失败 ❌\n");
        return -1;
    }
    mbuf->pkt_len = total_len;
    mbuf->data_len = total_len;
    
    // 填充arp请求包
    u8 *msg = rte_pktmbuf_mtod(mbuf,u8 *);
    ustack_encode_arp_request(msg, target_ip);

    // 发送arp请求
    int ret = rte_eth_tx_burst(global_portid,0,&mbuf,1);
    if (ret != 1) {
        printf("❌ ARP请求发送失败 ❌\n");
        rte_pktmbuf_free(mbuf);
        return -1;
    }

    struct in_addr ip_addr;
    ip_addr.s_addr = target_ip;
    printf("📤 发送ARP请求到 %s 📤\n", inet_ntoa(ip_addr));
    return 0;
}

static void handle_arp_response(struct rte_arp_hdr *ahdr, __attribute__((unused)) struct rte_ether_hdr *ethhdr) {
    // 只处理目标IP为本机的ARP响应
    if (ahdr->arp_data.arp_tip != gPortIpAddr) {
        return;
    }

    // 更新ARP表
    struct rte_ether_addr mac;
    memcpy(&mac, &ahdr->arp_data.arp_sha, RTE_ETHER_ADDR_LEN);
    arp_table_update(ahdr->arp_data.arp_sip, &mac);

    // 打印ARP响应信息
    struct in_addr ip_addr;
    ip_addr.s_addr = ahdr->arp_data.arp_sip;
    printf("📥 收到ARP响应 📥\n");
    printf("   IP:%s -> MAC:%02x:%02x:%02x:%02x:%02x:%02x\n",
           inet_ntoa(ip_addr),
           mac.addr_bytes[0], mac.addr_bytes[1],
           mac.addr_bytes[2], mac.addr_bytes[3],
           mac.addr_bytes[4], mac.addr_bytes[5]);
}

// ====================== UDP相关函数 ======================
static int ustack_encode_udp_pkt(uint8_t *msg, struct rte_ether_addr *dmac,
                                uint32_t sip, uint32_t dip, uint16_t sport,
                                uint16_t dport, uint8_t *payload, uint16_t payload_len) {
    // 1. 以太网头
    struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg;
    memcpy(eth->d_addr.addr_bytes, dmac->addr_bytes, RTE_ETHER_ADDR_LEN);
    memcpy(eth->s_addr.addr_bytes, gPortMacAddr.addr_bytes, RTE_ETHER_ADDR_LEN);
    eth->ether_type = htons(RTE_ETHER_TYPE_IPV4);

    // 2. IP头
    struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(eth + 1);
    ip->version_ihl = 0x45;  // IPv4, 头长20字节
    ip->type_of_service = 0;
    uint16_t ip_total_len = sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr) + payload_len;
    ip->total_length = htons(ip_total_len);
    ip->packet_id = 0;
    ip->fragment_offset = 0;
    ip->time_to_live = 64;
    ip->next_proto_id = IPPROTO_UDP;
    ip->src_addr = sip;
    ip->dst_addr = dip;
    ip->hdr_checksum = 0;
    ip->hdr_checksum = rte_ipv4_cksum(ip);

    // 3. UDP头
    struct rte_udp_hdr *udp = (struct rte_udp_hdr *)(ip + 1);
    udp->src_port = htons(sport);
    udp->dst_port = htons(dport);
    uint16_t udp_len = sizeof(struct rte_udp_hdr) + payload_len;
    udp->dgram_len = htons(udp_len);

    // 4. 拷贝负载
    memcpy((uint8_t*)(udp + 1), payload, payload_len);
    udp->dgram_cksum = 0;
    udp->dgram_cksum = rte_ipv4_udptcp_cksum(ip, udp);

    return 0;
}

static int send_udp_packet(uint32_t dip, uint16_t dport, uint16_t sport, uint8_t *payload, uint16_t payload_len) {
    // 1. 查找ARP表获取目标MAC
    struct rte_ether_addr dmac;
    if (arp_table_lookup(dip, &dmac) < 0) {
        printf("❌ ARP表中未找到%s的MAC地址,请先发送ARP请求 ❌\n", inet_ntoa(*(struct in_addr*)&dip));
        return -1;
    }

    // 2. 计算总长度
    uint16_t total_len = sizeof(struct rte_ether_hdr) + 
                         sizeof(struct rte_ipv4_hdr) + 
                         sizeof(struct rte_udp_hdr) + 
                         payload_len;

    // 3. 分配MBUF
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(g_mbuf_pool);
    if (!mbuf) {
        printf("❌ 分配UDP MBUF失败 ❌\n");
        return -1;
    }
    mbuf->pkt_len = total_len;
    mbuf->data_len = total_len;

    // 4. 编码UDP包
    uint8_t *msg = rte_pktmbuf_mtod(mbuf, uint8_t *);
    ustack_encode_udp_pkt(msg, &dmac, gPortIpAddr, dip, sport, dport, payload, payload_len);

    // 5. 发送UDP包
    int ret = rte_eth_tx_burst(global_portid, 0, &mbuf, 1);
    if (ret != 1) {
        printf("❌ UDP包发送失败 ❌\n");
        rte_pktmbuf_free(mbuf);
        return -1;
    }

    // 打印发送信息
    struct in_addr dst_ip;
    dst_ip.s_addr = dip;
    printf("✅ UDP包发送成功 ✅\n");
    printf("   目标:%s:%d\n", inet_ntoa(dst_ip), dport);
    printf("   源端口:%d\n", sport);
    printf("   负载长度:%d字节\n", payload_len);
    printf("   负载内容:%.*s\n", payload_len, payload);

    return 0;
}

// ====================== TCP相关函数实现 ======================
static void tcp_table_init(void){
    memset(&g_tcp_table,0,sizeof(tcp_table_t));
    pthread_mutex_init(&g_tcp_table.mutex,NULL);

    for(int i = 0;i < TCP_TABLE_MAX_ENTRY;i++){
        g_tcp_table.entries[i].valid = 0;
        g_tcp_table.entries[i].state = TCP_STATE_CLOSED;
        // 新增:初始化接收缓冲区
        memset(g_tcp_table.entries[i].recv_buf, 0, sizeof(g_tcp_table.entries[i].recv_buf));
        g_tcp_table.entries[i].recv_buf_len = 0;
        g_tcp_table.entries[i].recv_next_seq = 0;
    }
}

// 清理无效TCP连接(新增TIME_WAIT/SYN_RECV清理)
static void tcp_table_clean_invalid(void) {
    pthread_mutex_lock(&g_tcp_table.mutex);
    time_t now = time(NULL);
    int cleaned = 0;

    for (int i = 0; i < TCP_TABLE_SIZE; i++) {
        tcp_conn_entry_t *entry = &g_tcp_table.entries[i];
        if (!entry->valid) continue;

        // 清理CLOSED状态(超过清理间隔)
        if (entry->state == TCP_STATE_CLOSED && (now - entry->last_active) > TCP_CLOSED_CLEAN_INTERVAL) {
            memset(entry, 0, sizeof(tcp_conn_entry_t));
            cleaned++;
        }
        // 清理TIME_WAIT状态(标准60秒超时)
        else if (entry->state == TCP_STATE_TIME_WAIT && (now - entry->last_active) > TCP_TIME_WAIT_TIMEOUT) {
            memset(entry, 0, sizeof(tcp_conn_entry_t));
            cleaned++;
        }
        // 清理SYN_RECV半连接(超时10秒未完成三次握手)
        else if (entry->state == TCP_STATE_SYN_RECV && (now - entry->last_active) > TCP_SYN_RECV_TIMEOUT) {
            memset(entry, 0, sizeof(tcp_conn_entry_t));
            cleaned++;
        }
    }

    pthread_mutex_unlock(&g_tcp_table.mutex);
    if (cleaned > 0) {
        printf("🧹 清理了%d个无效TCP连接(TIME_WAIT/SYN_RECV/CLOSED)🧹\n", cleaned);
    }
}

// 重置指定的TCP连接条目(彻底清空)
static int tcp_table_reset_entry(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) {
    pthread_mutex_lock(&g_tcp_table.mutex);
    
    for (int i = 0; i < TCP_TABLE_MAX_ENTRY; i++) {
        if (g_tcp_table.entries[i].valid &&
            g_tcp_table.entries[i].src_ip == src_ip &&
            g_tcp_table.entries[i].dst_ip == dst_ip &&
            g_tcp_table.entries[i].src_port == src_port &&
            g_tcp_table.entries[i].dst_port == dst_port) {
            
            memset(&g_tcp_table.entries[i], 0, sizeof(tcp_conn_entry_t));
            pthread_mutex_unlock(&g_tcp_table.mutex);
            return 0;
        }
    }
    
    pthread_mutex_unlock(&g_tcp_table.mutex);
    return -1;
}

//生成随机序列号
static u32 generate_seq_num(void){
    static int init = 0;  //标记随机数种子是否被初始化
    if(!init){
        srand(time(NULL));
        init = 1;
    }
    return (u32)rand() | ((u32)rand() << 16);
}

// TCP校验和计算函数
// 参数:ip=IPv4头部指针,tcp=TCP头部指针,tcp_len=TCP报文总长度(头部+数据)
// 返回值:16位的TCP校验和
static uint16_t tcp_checksum(struct rte_ipv4_hdr *ip, struct rte_tcp_hdr *tcp, uint16_t tcp_len) {
    uint32_t sum = 0;
    // 伪头部(严格按网络字节序填充)
    uint8_t pseudo_header[12];
    memset(pseudo_header, 0, 12);
    
    // 源IP(4字节,网络序)
    memcpy(&pseudo_header[0], &ip->src_addr, 4);
    // 目的IP(4字节,网络序)
    memcpy(&pseudo_header[4], &ip->dst_addr, 4);
    // 保留位(1字节)+ 协议号(1字节)
    pseudo_header[8] = 0;
    pseudo_header[9] = IPPROTO_TCP;  // TCP协议号固定为6
    // TCP长度(2字节,网络序)
    uint16_t tcp_len_n = htons(tcp_len);
    memcpy(&pseudo_header[10], &tcp_len_n, 2);
    
    // 计算伪头部校验和
    uint16_t *phdr = (uint16_t *)pseudo_header;
    for (int i = 0; i < 6; i++) {
        sum += phdr[i];
    }
    
    // 计算TCP头部+数据校验和
    uint16_t *tcp_data = (uint16_t *)tcp;
    int len = tcp_len;
    while (len > 1) {
        sum += *tcp_data++;
        len -= 2;
    }
    if (len == 1) {
        sum += *(uint8_t *)tcp_data;
    }
    
    // 折叠校验和
    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    return (uint16_t)(~sum);
}

// 编码TCP数据包
// 编码TCP数据包
static int encode_tcp_packet(uint8_t *msg, struct rte_ether_addr *dmac, uint32_t sip, uint32_t dip,
                           uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack,
                           uint8_t flags, uint8_t *payload, uint16_t payload_len) {

    // 1. 以太网头
    struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg;
    memcpy(eth->d_addr.addr_bytes, dmac->addr_bytes, RTE_ETHER_ADDR_LEN);
    memcpy(eth->s_addr.addr_bytes, gPortMacAddr.addr_bytes, RTE_ETHER_ADDR_LEN);
    eth->ether_type = htons(RTE_ETHER_TYPE_IPV4);

    // 2. IP头
    struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(eth + 1);
    uint16_t tcp_hdr_len = sizeof(struct rte_tcp_hdr); // TCP头部固定20字节
    uint16_t tcp_len = tcp_hdr_len + payload_len;
    uint16_t ip_total_len = sizeof(struct rte_ipv4_hdr) + tcp_len;
    
    ip->version_ihl = 0x45; // IPv4,头长20字节
    ip->type_of_service = 0;
    ip->total_length = htons(ip_total_len);
    ip->packet_id = 0;
    ip->fragment_offset = 0;
    ip->time_to_live = TCP_TTL;
    ip->next_proto_id = IPPROTO_TCP;
    ip->src_addr = sip;
    ip->dst_addr = dip;
    ip->hdr_checksum = 0;
    ip->hdr_checksum = rte_ipv4_cksum(ip);

    // 3. tcp头
    struct rte_tcp_hdr *tcp = (struct rte_tcp_hdr *)(ip + 1);
    tcp->src_port = htons(sport);
    tcp->dst_port = htons(dport);
    tcp->sent_seq = htonl(seq);
    tcp->recv_ack = htonl(ack);
    // 修复:TCP头部长度计算(20字节 = 5 * 4,左移4位占高4位)
    tcp->data_off = 0x50; // 等价于 (5) << 4,固定20字节头部
    tcp->tcp_flags = flags;
    tcp->rx_win = htons(TCP_WINDOW_SIZE);
    tcp->cksum = 0;
    tcp->tcp_urp = 0;

    // 4. 拷贝负载数据
    if (payload_len > 0 && payload != NULL) {
        memcpy((uint8_t *)(tcp + 1), payload, payload_len);
    }

    // 5. 计算TCP校验和
    tcp->cksum = tcp_checksum(ip, tcp, tcp_len);

    return 0;
}

//发送tcp数据包
static int send_tcp_packet(uint32_t dip, uint16_t dport, uint16_t sport, uint32_t seq, 
                         uint32_t ack, uint8_t flags, uint8_t *payload, uint16_t payload_len) {

    //1. 查找arp表获取目标MAC地址
    struct rte_ether_addr dmac;
    if(arp_table_lookup(dip,&dmac) < 0){
        printf("❌ ARP表中未找到%s的MAC地址 ❌\n", inet_ntoa(*(struct in_addr*)&dip));
        return -1;
    }

    // 2. 计算总长度
    uint16_t tcp_len = sizeof(struct rte_tcp_hdr) + payload_len;
    uint16_t total_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + tcp_len;

    // 3. 分配MBUF
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(g_mbuf_pool);
    if (!mbuf) {
        printf("❌ 分配TCP MBUF失败 ❌\n");
        return -1;
    }
    mbuf->pkt_len = total_len;
    mbuf->data_len = total_len;

    // 4. 编码TCP包
    uint8_t *msg = rte_pktmbuf_mtod(mbuf, uint8_t *);
    encode_tcp_packet(msg, &dmac, gPortIpAddr, dip, sport, dport, seq, ack, flags, payload, payload_len);

    // 5. 发送TCP包
    int ret = rte_eth_tx_burst(global_portid, 0, &mbuf, 1);
    if (ret != 1) {
        printf("❌ TCP包发送失败 ❌\n");
        rte_pktmbuf_free(mbuf);
        return -1;
    }

    // 打印发送信息
    struct in_addr dst_ip;
    dst_ip.s_addr = dip;
    char flag_str[32] = {0};
    if (flags & RTE_TCP_SYN_FLAG) strcat(flag_str, "SYN ");
    if (flags & RTE_TCP_ACK_FLAG) strcat(flag_str, "ACK ");
    if (flags & RTE_TCP_FIN_FLAG) strcat(flag_str, "FIN ");
    if (flags & RTE_TCP_RST_FLAG) strcat(flag_str, "RST ");
    
    printf("✅ TCP包发送成功 ✅\n");
    printf("   目标:%s:%d\n", inet_ntoa(dst_ip), dport);
    printf("   源端口:%d\n", sport);
    printf("   标志位:%s\n", flag_str);
    printf("   序列号:%u, 确认号:%u\n", seq, ack);
    printf("   负载长度:%d字节\n", payload_len);
    
    return 0;
}

//添加tcp连接条目
static int tcp_table_add(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, tcp_state_t state) {
    pthread_mutex_lock(&g_tcp_table.mutex);

    //查找空条目
    for(int i = 0;i < TCP_TABLE_MAX_ENTRY;i++){
        if(!g_tcp_table.entries[i].valid){
            g_tcp_table.entries[i].src_ip = src_ip;
            g_tcp_table.entries[i].dst_ip = dst_ip;
            g_tcp_table.entries[i].src_port = src_port;
            g_tcp_table.entries[i].dst_port = dst_port;
            g_tcp_table.entries[i].valid = 1;
            g_tcp_table.entries[i].state = state;
            g_tcp_table.entries[i].seq = generate_seq_num();
            g_tcp_table.entries[i].ack = 0;
            g_tcp_table.entries[i].last_active = time(NULL);
            pthread_mutex_unlock(&g_tcp_table.mutex);
            return 0;
        }
    }

    pthread_mutex_unlock(&g_tcp_table.mutex);
    printf("❌ TCP连接表已满 ❌\n");
    return -1;
}

// 更新TCP连接状态
static int tcp_table_update_state(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port, tcp_state_t new_state) {
    pthread_mutex_lock(&g_tcp_table.mutex);
    
    for (int i = 0; i < TCP_TABLE_MAX_ENTRY; i++) {
        if (g_tcp_table.entries[i].valid &&
            g_tcp_table.entries[i].src_ip == src_ip &&
            g_tcp_table.entries[i].dst_ip == dst_ip &&
            g_tcp_table.entries[i].src_port == src_port &&
            g_tcp_table.entries[i].dst_port == dst_port) {
            
            g_tcp_table.entries[i].state = new_state;
            g_tcp_table.entries[i].last_active = time(NULL);
            pthread_mutex_unlock(&g_tcp_table.mutex);
            return 0;
        }
    }
    
    pthread_mutex_unlock(&g_tcp_table.mutex);
    return -1;
}

// 查找TCP连接(修改:忽略CLOSED状态)
static tcp_conn_entry_t* tcp_table_lookup(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) {
    pthread_mutex_lock(&g_tcp_table.mutex);
    
    for (int i = 0; i < TCP_TABLE_MAX_ENTRY; i++) {
        // 关键修改:增加状态判断,忽略CLOSED状态
        if (g_tcp_table.entries[i].valid &&
            g_tcp_table.entries[i].state != TCP_STATE_CLOSED &&
            g_tcp_table.entries[i].src_ip == src_ip &&
            g_tcp_table.entries[i].dst_ip == dst_ip &&
            g_tcp_table.entries[i].src_port == src_port &&
            g_tcp_table.entries[i].dst_port == dst_port) {
            
            pthread_mutex_unlock(&g_tcp_table.mutex);
            return &g_tcp_table.entries[i];
        }
    }
    
    pthread_mutex_unlock(&g_tcp_table.mutex);
    return NULL;
}

// 打印TCP连接表
static void tcp_table_print(void) {
    printf("\n=================== TCP 连接表 ===================\n");
    printf("源IP\t\t源端口\t目标IP\t\t目标端口\t状态\n");
    printf("--------------------------------------------------\n");
    
    pthread_mutex_lock(&g_tcp_table.mutex);
    //time_t now = time(NULL);
    
    for (int i = 0; i < TCP_TABLE_MAX_ENTRY; i++) {
        if (g_tcp_table.entries[i].valid) {
            // struct in_addr src_ip, dst_ip;
            // src_ip.s_addr = g_tcp_table.entries[i].src_ip;
            // dst_ip.s_addr = g_tcp_table.entries[i].dst_ip;
            
            const char *state_str = "";
            switch (g_tcp_table.entries[i].state) {
                case TCP_STATE_CLOSED: state_str = "CLOSED"; break;
                case TCP_STATE_SYN_SENT: state_str = "SYN_SENT"; break;
                case TCP_STATE_ESTABLISHED: state_str = "ESTABLISHED"; break;
                case TCP_STATE_FIN_WAIT1: state_str = "FIN_WAIT1"; break;
                case TCP_STATE_FIN_WAIT2: state_str = "FIN_WAIT2"; break;
                case TCP_STATE_CLOSING: state_str = "CLOSING"; break;
                case TCP_STATE_TIME_WAIT: state_str = "TIME_WAIT"; break;
                case TCP_STATE_LISTEN: state_str = "LISTEN"; break;
                case TCP_STATE_SYN_RECV: state_str = "SYN_RECV"; break;
                default: state_str = "UNKNOWN";
            }
            
            // 优化tcp_table_print的IP打印
            char src_ip_str[16] = {0};
            char dst_ip_str[16] = {0};
            inet_ntop(AF_INET, &g_tcp_table.entries[i].src_ip, src_ip_str, sizeof(src_ip_str));
            inet_ntop(AF_INET, &g_tcp_table.entries[i].dst_ip, dst_ip_str, sizeof(dst_ip_str));

            printf("%s\t%d\t%s\t%d\t\t%s\n",
                src_ip_str, g_tcp_table.entries[i].src_port,
                dst_ip_str, g_tcp_table.entries[i].dst_port,
                state_str);
        }
    }
    
    pthread_mutex_unlock(&g_tcp_table.mutex);
    printf("==================================================\n\n");
}

//主动建立TCP连接(三次握手)(修改重试逻辑)
static int tcp_connect(uint32_t dip,uint16_t dport,uint16_t sport){
    // 新增:先清理该端口的旧连接条目
    tcp_table_reset_entry(gPortIpAddr, dip, sport, dport);
    
    //1. 先发送ARP请求获取MAC
    for(int i = 0;i <ARP_REQUEST_RETRY;i++){
        send_arp_request(dip);
        sleep(ARP_REQUEST_INTERVAL);
        struct rte_ether_addr mac;
        if(arp_table_lookup(dip,&mac) == 0){
            break;
        }
    }

    //2. 添加连接条目
    if(tcp_table_add(gPortIpAddr, dip, sport, dport, TCP_STATE_SYN_SENT) < 0){
        return -1;
    }

    tcp_conn_entry_t *conn = tcp_table_lookup(gPortIpAddr, dip, sport, dport);
    if (!conn) {
        printf("❌ 无法找到新建的TCP连接条目 ❌\n");
        return -1;
    }

    struct in_addr dst_ip;
    dst_ip.s_addr = dip;
    printf("\n🔌 正在连接 %s:%d 🔌\n", inet_ntoa(dst_ip), dport);

    //3. 发送SYN包(第一次握手)(修改:重试时生成新序列号)
    int retry = 0;
    while(retry < TCP_SYN_RETRY && g_running){
        // 关键修改:每次重试生成新序列号
        if (retry > 0) {
            pthread_mutex_lock(&g_tcp_table.mutex);
            conn->seq = generate_seq_num();
            pthread_mutex_unlock(&g_tcp_table.mutex);
        }
        
        send_tcp_packet(dip, dport, sport, conn->seq, 0, RTE_TCP_SYN_FLAG, NULL, 0);

        // 等待SYN+ACK响应
        for(int i=0; i<TCP_SYN_TIMEOUT*10; i++){
            usleep(100000);
            conn = tcp_table_lookup(gPortIpAddr, dip, sport, dport);
            if (conn && conn->state == TCP_STATE_ESTABLISHED) {
                printf("✅ TCP连接建立成功 ✅\n");
                return 0;
            }
        }
        
        retry++;
        printf("⌛ SYN重试 %d/%d ⌛\n", retry, TCP_SYN_RETRY);
    }

    printf("❌ TCP连接建立失败 ❌\n");
    // 修改:使用reset彻底清空条目,而非仅改状态
    tcp_table_reset_entry(gPortIpAddr, dip, sport, dport);
    return -1;
}

//发送tcp数据
static int tcp_send_data(uint32_t dip, uint16_t dport, uint16_t sport, uint8_t *data, uint16_t len) {
    tcp_conn_entry_t *conn = tcp_table_lookup(gPortIpAddr, dip, sport, dport);
    if (!conn || conn->state != TCP_STATE_ESTABLISHED) {
        printf("❌ 无有效TCP连接或连接未建立 ❌\n");
        return -1;
    }

    // 关键修复:使用当前最新的seq和ack发送数据
    uint32_t current_seq = conn->seq + 1;
    uint32_t current_ack = conn->ack;
    
    // 发送数据(带ACK标志)
    int ret = send_tcp_packet(dip, dport, sport, current_seq, current_ack, 
                             RTE_TCP_ACK_FLAG, data, len);

    if (ret == 0) {
        // 更新序列号
        pthread_mutex_lock(&g_tcp_table.mutex);
        conn->seq = current_seq + len; // 修复:基于发送的seq更新,避免重复
        conn->last_active = time(NULL);
        pthread_mutex_unlock(&g_tcp_table.mutex);
        
        struct in_addr dst_ip;
        dst_ip.s_addr = dip;
        printf("📤 发送TCP数据到 %s:%d (长度:%d字节) 📤\n", 
               inet_ntoa(dst_ip), dport, len);
    }
    
    return ret;                          
}

//关闭tcp连接(四次挥手)(修改:关闭后彻底清理)
static int tcp_close(uint32_t dip,uint16_t dport,uint16_t sport){
    tcp_conn_entry_t *conn = tcp_table_lookup(gPortIpAddr, dip, sport, dport);
    if (!conn || conn->state == TCP_STATE_CLOSED) {
        printf("❌ 无有效TCP连接 ❌\n");
        return -1;
    }

    //1. 发送FIN+ACK包
    tcp_table_update_state(gPortIpAddr,dip,sport,dport,TCP_STATE_FIN_WAIT1);
    send_tcp_packet(dip,dport,sport,conn->seq + 1,conn->ack,
        RTE_TCP_FIN_FLAG | RTE_TCP_ACK_FLAG,NULL,0);

    struct in_addr dst_ip;
    dst_ip.s_addr = dip;
    printf("\n🔚 正在关闭 %s:%d 连接 🔚\n", inet_ntoa(dst_ip), dport);

    // 2. 等待响应
    int timeout = 0;
    while (timeout < TCP_SYN_TIMEOUT * 2 && g_running) {
        conn = tcp_table_lookup(gPortIpAddr, dip, sport, dport);
        if (!conn || conn->state == TCP_STATE_CLOSED) {
            break;
        }
        sleep(1);
        timeout++;
    }

    // 修改:无论是否超时,都彻底清理条目
    tcp_table_reset_entry(gPortIpAddr, dip, sport, dport);
    printf("✅ TCP连接已关闭 ✅\n");
    return 0;
}

// 处理接收到的TCP数据包
static void handle_tcp_packet(__attribute__((unused))struct rte_ether_hdr *ethhdr, struct rte_ipv4_hdr *iphdr, struct rte_tcp_hdr *tcphdr) {
    // 1. 严格过滤:只处理目标IP为本机的TCP包
    if (iphdr->dst_addr != gPortIpAddr) {
        return;
    }

    uint32_t src_ip = iphdr->src_addr;    // 对方IP
    uint32_t dst_ip = iphdr->dst_addr;    // 本机IP
    uint16_t src_port = ntohs(tcphdr->src_port);
    uint16_t dst_port = ntohs(tcphdr->dst_port);
    uint32_t seq = ntohl(tcphdr->sent_seq);
    uint32_t ack = ntohl(tcphdr->recv_ack);
    uint8_t flags = tcphdr->tcp_flags;

    // 计算TCP数据长度
    uint16_t ip_len = ntohs(iphdr->total_length);
    uint16_t tcp_len = ip_len - (iphdr->version_ihl & 0x0F) * 4;
    uint16_t data_len = tcp_len - (tcphdr->data_off >> 4) * 4;
    uint8_t *data = (uint8_t*)(tcphdr + 1);

    // ========== 修复inet_ntoa缓冲区覆盖问题 ==========
    char src_ip_str[16] = {0};  // 存储源IP字符串(对方IP)
    char dst_ip_str[16] = {0};  // 存储目标IP字符串(本机IP)
    inet_ntop(AF_INET, &src_ip, src_ip_str, sizeof(src_ip_str));
    inet_ntop(AF_INET, &dst_ip, dst_ip_str, sizeof(dst_ip_str));

    // ========== 增强重复包过滤(seq + 数据长度) ==========
    typedef struct {
        uint32_t src_ip;
        uint32_t dst_ip;
        uint16_t src_port;
        uint16_t dst_port;
        uint32_t seq;
        uint16_t data_len;
        time_t recv_time;
    } tcp_packet_cache_t;

    static tcp_packet_cache_t packet_cache[32] = {0};
    static int cache_idx = 0;
    time_t now = time(NULL);
    int is_duplicate = 0;
    
    // 检查缓存中是否有相同的包(3秒内)
    for (int j = 0; j < 32; j++) {
        if (packet_cache[j].src_ip == src_ip &&
            packet_cache[j].dst_ip == dst_ip &&
            packet_cache[j].src_port == src_port &&
            packet_cache[j].dst_port == dst_port &&
            packet_cache[j].seq == seq &&
            packet_cache[j].data_len == data_len &&
            (now - packet_cache[j].recv_time) < 3) {
            is_duplicate = 1;
            break;
        }
    }
    
    // 重复包直接忽略
    if (is_duplicate) {
        printf("⚠️ 检测到重复TCP包,忽略 ⚠️\n");
        return;
    }
    
    // 更新缓存(FIFO)
    packet_cache[cache_idx].src_ip = src_ip;
    packet_cache[cache_idx].dst_ip = dst_ip;
    packet_cache[cache_idx].src_port = src_port;
    packet_cache[cache_idx].dst_port = dst_port;
    packet_cache[cache_idx].seq = seq;
    packet_cache[cache_idx].data_len = data_len;
    packet_cache[cache_idx].recv_time = now;
    cache_idx = (cache_idx + 1) % 32;

    // 打印TCP包信息
    printf("\n📥 收到TCP包 📥\n");
    printf("   源:%s:%d -> 目标:%s:%d\n", src_ip_str, src_port, dst_ip_str, dst_port);
    printf("   标志位:");
    if (flags & RTE_TCP_SYN_FLAG) printf("SYN ");
    if (flags & RTE_TCP_ACK_FLAG) printf("ACK ");
    if (flags & RTE_TCP_FIN_FLAG) printf("FIN ");
    if (flags & RTE_TCP_RST_FLAG) printf("RST ");
    printf("\n   序列号:%u, 确认号:%u\n", seq, ack);
    printf("   数据长度:%d字节\n", data_len);
    if (data_len > 0) {
        printf("   数据内容:%.*s\n", data_len, data);
    }

    // 2. 查找连接(双向匹配)
    tcp_conn_entry_t *active_conn = tcp_table_lookup(gPortIpAddr, src_ip, dst_port, src_port);
    tcp_conn_entry_t *passive_conn = tcp_table_lookup(src_ip, gPortIpAddr, src_port, dst_port);

    // 3. 处理SYN+ACK包(过滤已建立连接的重复包)
    if ((flags & (RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG)) == (RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG)) {
        if (active_conn && active_conn->state == TCP_STATE_ESTABLISHED) {
            printf("⚠️ 收到已建立连接的重复SYN+ACK包,忽略 ⚠️\n");
            return;
        }
        
        if (active_conn && active_conn->state == TCP_STATE_SYN_SENT) {
            // 更新主动连接状态
            tcp_table_update_state(gPortIpAddr, src_ip, dst_port, src_port, TCP_STATE_ESTABLISHED);
            // 发送ACK包(第三次握手)
            send_tcp_packet(src_ip, src_port, dst_port, ack, seq + 1, RTE_TCP_ACK_FLAG, NULL, 0);
            
            // 核心修复:主动连接 recv_next_seq = seq + 1(对方下一个数据的seq)
            pthread_mutex_lock(&g_tcp_table.mutex);
            active_conn->ack = seq + 1;
            active_conn->recv_next_seq = seq + 1;  // 主动连接必须+1
            pthread_mutex_unlock(&g_tcp_table.mutex);
            
            printf("📩 收到SYN+ACK包,已回复ACK,连接建立 📩\n");
        } else {
            printf("⚠️ 收到无效的SYN+ACK包(无对应SYN_SENT连接)⚠️\n");
        }
        return;
    }

    // 处理SYN包(被动建立连接:对方发SYN给本机)
    else if (flags & RTE_TCP_SYN_FLAG && !(flags & RTE_TCP_ACK_FLAG)) { // 仅纯SYN包
        // 被动连接存储:src_ip=对方,dst_ip=本机,src_port=对方端口,dst_port=本机端口
        if (tcp_table_add(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_SYN_RECV) == 0) {
            uint32_t my_seq = generate_seq_num();
            // 回复SYN+ACK:目标=对方IP:对方端口,源=本机IP:本机端口
            send_tcp_packet(src_ip, src_port, dst_port, my_seq, seq + 1, 
                           RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG, NULL, 0);
            // 记录我方SYN+ACK的seq,用于后续验证
            tcp_conn_entry_t *new_conn = tcp_table_lookup(src_ip, gPortIpAddr, src_port, dst_port);
            if (new_conn) {
                pthread_mutex_lock(&g_tcp_table.mutex);
                new_conn->seq = my_seq;  // 保存我方发送的seq
                new_conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
            }
            printf("📩 收到SYN包,已回复SYN+ACK 📩\n");
        } else {
            printf("❌ TCP连接表已满,无法响应SYN包 ❌\n");
        }
    }

    // 处理FIN包(断开连接)
    else if (flags & RTE_TCP_FIN_FLAG) {
        tcp_conn_entry_t *conn = active_conn ? active_conn : passive_conn;
        if (conn) {
            // 发送ACK响应
            send_tcp_packet(src_ip, src_port, dst_port, ack, seq + 1, RTE_TCP_ACK_FLAG, NULL, 0);
            
            if (conn->state == TCP_STATE_ESTABLISHED) {
                // 区分主动/被动连接,更新正确的状态
                if (active_conn) {
                    tcp_table_update_state(gPortIpAddr, src_ip, dst_port, src_port, TCP_STATE_TIME_WAIT);
                } else {
                    tcp_table_update_state(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_TIME_WAIT);
                }
                send_tcp_packet(src_ip, src_port, dst_port, conn->seq + 1, seq + 1, 
                               RTE_TCP_FIN_FLAG | RTE_TCP_ACK_FLAG, NULL, 0);
            } else {
                if (active_conn) {
                    tcp_table_update_state(gPortIpAddr, src_ip, dst_port, src_port, TCP_STATE_CLOSED);
                } else {
                    tcp_table_update_state(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_CLOSED);
                }
            }
            // 更新最后活动时间
            pthread_mutex_lock(&g_tcp_table.mutex);
            conn->last_active = now;
            pthread_mutex_unlock(&g_tcp_table.mutex);
            
            printf("📩 收到FIN包,连接进入TIME_WAIT/已关闭 📩\n");
        } else {
            printf("⚠️ 收到FIN包但无对应连接,忽略 ⚠️\n");
        }
    }

    // 处理ACK包(拆分:1. 完成三次握手 2. 确认关闭)
    else if (flags & RTE_TCP_ACK_FLAG && data_len == 0) {
        // 场景1:对方回复ACK,完成三次握手(被动连接 → recv_next_seq = seq)
        if (passive_conn && passive_conn->state == TCP_STATE_SYN_RECV) {
            // 验证ACK号是否正确(应为我方SYN+ACK的seq + 1)
            if (ack == (passive_conn->seq + 1)) {
                tcp_table_update_state(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_ESTABLISHED);
                // 被动连接 recv_next_seq = seq(对方下一个数据的seq)
                pthread_mutex_lock(&g_tcp_table.mutex);
                passive_conn->ack = seq + 1;
                passive_conn->recv_next_seq = seq;  // 被动连接不加1
                passive_conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
                printf("✅ 收到第三次握手ACK,连接完全建立(%s:%d -> %s:%d)✅\n",
                       src_ip_str, src_port, dst_ip_str, dst_port);
                return;
            } else {
                printf("⚠️ ACK号不匹配,三次握手失败(期望:%u,实际:%u)⚠️\n",
                       passive_conn->seq + 1, ack);
            }
        }
        // 场景2:ACK包用于确认关闭连接
        else if (active_conn) {
            if (active_conn->state == TCP_STATE_FIN_WAIT1) {
                tcp_table_update_state(gPortIpAddr, src_ip, dst_port, src_port, TCP_STATE_FIN_WAIT2);
                pthread_mutex_lock(&g_tcp_table.mutex);
                active_conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
                printf("📩 收到ACK包,状态更新为FIN_WAIT2 📩\n");
            } else if (active_conn->state == TCP_STATE_FIN_WAIT2) {
                tcp_table_update_state(gPortIpAddr, src_ip, dst_port, src_port, TCP_STATE_CLOSED);
                printf("📩 收到ACK包,主动连接关闭 📩\n");
            }
        } else if (passive_conn) {
            if (passive_conn->state == TCP_STATE_FIN_WAIT1) {
                tcp_table_update_state(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_FIN_WAIT2);
                pthread_mutex_lock(&g_tcp_table.mutex);
                passive_conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
                printf("📩 收到ACK包,状态更新为FIN_WAIT2 📩\n");
            } else if (passive_conn->state == TCP_STATE_FIN_WAIT2) {
                tcp_table_update_state(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_CLOSED);
                printf("📩 收到ACK包,被动连接关闭 📩\n");
            }
        }
    }

    // 处理数据报文(核心修复:区分主动/被动连接的seq逻辑)
    else if (data_len > 0 && flags & RTE_TCP_ACK_FLAG) {
        tcp_conn_entry_t *conn = active_conn ? active_conn : passive_conn;
        
        // 允许SYN_RECV状态接收数据(先完成三次握手)
        if (passive_conn && passive_conn->state == TCP_STATE_SYN_RECV) {
            // 先完成三次握手
            if (ack == (passive_conn->seq + 1)) {
                tcp_table_update_state(src_ip, gPortIpAddr, src_port, dst_port, TCP_STATE_ESTABLISHED);
                // 被动连接 recv_next_seq = seq
                pthread_mutex_lock(&g_tcp_table.mutex);
                passive_conn->ack = seq + 1;
                passive_conn->recv_next_seq = seq;  // 被动连接不加1
                passive_conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
                printf("✅ 收到数据+ACK,完成三次握手,连接建立 ✅\n");
                conn = passive_conn; // 重置conn为已建立的连接
            } else {
                printf("⚠️ ACK号不匹配,无法完成三次握手(期望:%u,实际:%u)⚠️\n",
                       passive_conn->seq + 1, ack);
                return;
            }
        }

        if (conn && conn->state == TCP_STATE_ESTABLISHED) {
            // 初始化期望seq(首次接收,兜底逻辑:区分主动/被动)
            if (conn->recv_next_seq == 0) {
                conn->recv_next_seq = (active_conn ? seq + 1 : seq);
            }

            // 处理有序数据(此时seq已匹配)
            if (seq == conn->recv_next_seq) {
                // 将数据写入接收缓冲区(避免粘包)
                if (conn->recv_buf_len + data_len < sizeof(conn->recv_buf)) {
                    memcpy(conn->recv_buf + conn->recv_buf_len, data, data_len);
                    conn->recv_buf_len += data_len;
                    conn->recv_next_seq += data_len;

                    // 打印完整的接收缓冲区数据
                    printf("📩 接收缓冲区完整数据:%.*s(总长度:%d)📩\n", 
                           conn->recv_buf_len, conn->recv_buf, conn->recv_buf_len);
                } else {
                    printf("⚠️ 接收缓冲区已满,丢弃数据 ⚠️\n");
                    return;
                }

                // 正确回复ACK:ack = 期望的下一个seq
                uint32_t ack_num = conn->recv_next_seq;
                send_tcp_packet(src_ip, src_port, dst_port, conn->seq, ack_num, RTE_TCP_ACK_FLAG, NULL, 0);
                
                // 更新连接状态
                pthread_mutex_lock(&g_tcp_table.mutex);
                conn->ack = ack_num;
                conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
                
                printf("📩 已回复ACK(ack=%u)📩\n", ack_num);

                // ========== 新增:尝试合并缓存的乱序包 ==========
                #define OUT_OF_ORDER_CACHE_SIZE 8
                static struct {
                    uint32_t seq;
                    uint16_t data_len;
                    uint8_t data[1024];
                    time_t recv_time;
                    int valid;
                } ooo_cache[OUT_OF_ORDER_CACHE_SIZE] = {0};

                // 检查缓存中是否有连续的乱序包
                for (int k = 0; k < OUT_OF_ORDER_CACHE_SIZE; k++) {
                    if (ooo_cache[k].valid && ooo_cache[k].seq == conn->recv_next_seq) {
                        // 合并缓存的乱序包
                        if (conn->recv_buf_len + ooo_cache[k].data_len < sizeof(conn->recv_buf)) {
                            memcpy(conn->recv_buf + conn->recv_buf_len, ooo_cache[k].data, ooo_cache[k].data_len);
                            conn->recv_buf_len += ooo_cache[k].data_len;
                            conn->recv_next_seq += ooo_cache[k].data_len;

                            printf("📦 合并缓存的乱序包:%.*s(总长度:%d)📦\n",
                                   ooo_cache[k].data_len, ooo_cache[k].data, conn->recv_buf_len);
                            
                            // 回复ACK
                            ack_num = conn->recv_next_seq;
                            send_tcp_packet(src_ip, src_port, dst_port, conn->seq, ack_num, RTE_TCP_ACK_FLAG, NULL, 0);
                            pthread_mutex_lock(&g_tcp_table.mutex);
                            conn->ack = ack_num;
                            pthread_mutex_unlock(&g_tcp_table.mutex);

                            // 清空该缓存项
                            ooo_cache[k].valid = 0;
                        }
                    }
                }
            } else {
                // ========== 乱序包缓存逻辑 ==========
                #define OUT_OF_ORDER_CACHE_SIZE 8
                static struct {
                    uint32_t seq;
                    uint16_t data_len;
                    uint8_t data[1024];
                    time_t recv_time;
                    int valid;
                } ooo_cache[OUT_OF_ORDER_CACHE_SIZE] = {0};

                // 检查是否已缓存
                int ooo_exists = 0;
                for (int k = 0; k < OUT_OF_ORDER_CACHE_SIZE; k++) {
                    if (ooo_cache[k].valid && ooo_cache[k].seq == seq) {
                        ooo_exists = 1;
                        break;
                    }
                }

                if (!ooo_exists) {
                    // 缓存乱序包
                    for (int k = 0; k < OUT_OF_ORDER_CACHE_SIZE; k++) {
                        if (!ooo_cache[k].valid) {
                            ooo_cache[k].seq = seq;
                            ooo_cache[k].data_len = data_len;
                            memcpy(ooo_cache[k].data, data, data_len);
                            ooo_cache[k].recv_time = now;
                            ooo_cache[k].valid = 1;
                            printf("📦 缓存乱序包(seq:%u,长度:%d)📦\n", seq, data_len);
                            break;
                        }
                    }
                }

                printf("⚠️ 收到乱序TCP包(期望seq:%u,实际:%u),已缓存 ⚠️\n", conn->recv_next_seq, seq);
                
                // 回复ACK(避免对方重传)
                send_tcp_packet(src_ip, src_port, dst_port, conn->seq, conn->recv_next_seq, RTE_TCP_ACK_FLAG, NULL, 0);
                pthread_mutex_lock(&g_tcp_table.mutex);
                conn->last_active = now;
                pthread_mutex_unlock(&g_tcp_table.mutex);
            }
        } else {
            printf("⚠️ 收到数据但连接未建立/无对应连接,忽略 ⚠️\n");
        }
    }

    // 处理RST包(优化:详细日志+安全清理)
    else if (flags & RTE_TCP_RST_FLAG) {
        tcp_conn_entry_t *conn = active_conn ? active_conn : passive_conn;
        if (conn) {
            printf("📩 收到RST包(强制关闭),连接:%s:%d -> %s:%d 📩\n",
                   src_ip_str, src_port, dst_ip_str, dst_port);
            
            // 安全清理连接(重置所有状态)
            if (active_conn) {
                tcp_table_reset_entry(gPortIpAddr, src_ip, dst_port, src_port);
            } else {
                tcp_table_reset_entry(src_ip, gPortIpAddr, src_port, dst_port);
            }
            
            // 打印RST原因提示
            printf("⚠️ 连接被对方强制重置,可能原因:\n");
            printf("   1. 序列号不匹配(期望:%u,实际:%u)\n", conn->recv_next_seq, seq);
            printf("   2. 数据长度超出MSS限制\n");
            printf("   3. 对方主动关闭连接\n");
        } else {
            printf("⚠️ 收到RST包但无对应连接,忽略 ⚠️\n");
        }
    }

    // 处理未知类型的TCP包
    else {
        printf("⚠️ 收到未处理的TCP包(标志位:0x%02x),忽略 ⚠️\n", flags);
    }
}

// ====================== 命令行交互线程 ======================
void *cli_thread_func(__attribute__((unused)) void *arg) {
    char input[512];
    char cmd[256], param[256];
    char ip_str[32], payload[1024];
    uint16_t sport, dport;
    
    printf("\n==============================================\n");
    printf("           DPDK 交互式网络工具\n");
    printf("==============================================\n");
    printf("命令列表:\n");
    printf("  arp <IP地址>    - 发送ARP请求并更新ARP表\n");
    printf("  arp show        - 显示当前ARP表\n");
    printf("  udp <IP> <DPORT> <SPORT> <负载> - 发送UDP包\n");
    printf("  ping <IP地址>   - 主动Ping目标IP\n");
    printf("  clear           - 清理过期ARP条目\n");
    printf("  tcp connect <IP> <DPORT> <SPORT> - 建立TCP连接\n");
    printf("  tcp send <IP> <DPORT> <SPORT> <数据> - 发送TCP数据\n");
    printf("  tcp close <IP> <DPORT> <SPORT>   - 关闭TCP连接\n");
    printf("  tcp show        - 显示TCP连接表\n");
    printf("  quit/exit       - 退出程序\n");
    printf("==============================================\n\n");

    while (g_running) {
        printf("dpdk-cli> ");
        fflush(stdout);
        
        // 读取输入
        if (fgets(input, sizeof(input), stdin) == NULL) {  // 阻塞,不会CPU空转
            continue;
        }
        
        // 去除换行符
        input[strcspn(input, "\n")] = '\0';
        
        // 空输入跳过
        if (strlen(input) == 0) {
            continue;
        }
        
        // 解析命令
        memset(cmd, 0, sizeof(cmd));
        memset(param, 0, sizeof(param));
        sscanf(input, "%s %[^\n]", cmd, param);
        
        if (strcmp(cmd, "arp") == 0) {
            // ARP命令
            if (strcmp(param, "show") == 0) {
                arp_table_print();
            } else if (strlen(param) > 0) {
                // 发送ARP请求
                uint32_t target_ip = inet_addr(param);
                if (target_ip == INADDR_NONE) {
                    printf("❌ 无效的IP地址格式 ❌\n");
                } else {
                    // 多次重试发送ARP请求
                    for (int i = 0; i < ARP_REQUEST_RETRY; i++) {
                        send_arp_request(target_ip);
                        sleep(ARP_REQUEST_INTERVAL);
                        
                        // 检查是否已获取到MAC
                        struct rte_ether_addr mac;
                        if (arp_table_lookup(target_ip, &mac) == 0) {
                            break;
                        }
                    }
                }
            } else {
                printf("❌ ARP命令用法:arp <IP地址> 或 arp show ❌\n");
            }
        } else if (strcmp(cmd, "udp") == 0) {
            // UDP命令
            memset(ip_str, 0, sizeof(ip_str));
            memset(payload, 0, sizeof(payload));
            
            int ret = sscanf(param, "%s %hu %hu %[^\n]", ip_str, &dport, &sport, payload);
            if (ret < 3) {
                printf("❌ UDP命令用法:udp <IP> <目标端口> <源端口> <负载> ❌\n");
                printf("   示例:udp 192.168.3.1 8080 12345 hello_world ❌\n");
            } else {
                uint32_t dip = inet_addr(ip_str);
                if (dip == INADDR_NONE) {
                    printf("❌ 无效的IP地址格式 ❌\n");
                } else {
                    send_udp_packet(dip, dport, sport, (uint8_t*)payload, strlen(payload));
                }
            }
        } else if (strcmp(cmd, "ping") == 0) {
            // Ping命令
            if (strlen(param) == 0) {
                printf("❌ Ping命令用法:ping <IP地址> ❌\n");
                printf("   示例:ping 192.168.3.1 ❌\n");
            } else {
                uint32_t target_ip = inet_addr(param);
                if (target_ip == INADDR_NONE) {
                    printf("❌ 无效的IP地址格式 ❌\n");
                } else {
                    ping_target(target_ip);
                }
            }
        } else if (strcmp(cmd, "tcp") == 0) {
            // TCP命令
            char sub_cmd[32];
            memset(sub_cmd, 0, sizeof(sub_cmd));
            sscanf(param, "%s", sub_cmd);
            
            if (strcmp(sub_cmd, "connect") == 0) {
                memset(ip_str, 0, sizeof(ip_str));
                int ret = sscanf(param, "%*s %s %hu %hu", ip_str, &dport, &sport);
                if (ret < 3) {
                    printf("❌ TCP连接用法:tcp connect <IP> <目标端口> <源端口> ❌\n");
                    printf("   示例:tcp connect 192.168.3.1 8080 12345 ❌\n");
                } else {
                    uint32_t dip = inet_addr(ip_str);
                    if (dip == INADDR_NONE) {
                        printf("❌ 无效的IP地址格式 ❌\n");
                    } else {
                        tcp_connect(dip, dport, sport);
                    }
                }
            } else if (strcmp(sub_cmd, "send") == 0) {
                memset(ip_str, 0, sizeof(ip_str));
                memset(payload, 0, sizeof(payload));
                int ret = sscanf(param, "%*s %s %hu %hu %[^\n]", ip_str, &dport, &sport, payload);
                if (ret < 4) {
                    printf("❌ TCP发送用法:tcp send <IP> <目标端口> <源端口> <数据> ❌\n");
                    printf("   示例:tcp send 192.168.3.1 8080 12345 hello_tcp ❌\n");
                } else {
                    uint32_t dip = inet_addr(ip_str);
                    if (dip == INADDR_NONE) {
                        printf("❌ 无效的IP地址格式 ❌\n");
                    } else {
                        tcp_send_data(dip, dport, sport, (uint8_t*)payload, strlen(payload));
                    }
                }
            } else if (strcmp(sub_cmd, "close") == 0) {
                memset(ip_str, 0, sizeof(ip_str));
                int ret = sscanf(param, "%*s %s %hu %hu", ip_str, &dport, &sport);
                if (ret < 3) {
                    printf("❌ TCP关闭用法:tcp close <IP> <目标端口> <源端口> ❌\n");
                    printf("   示例:tcp close 192.168.3.1 8080 12345 ❌\n");
                } else {
                    uint32_t dip = inet_addr(ip_str);
                    if (dip == INADDR_NONE) {
                        printf("❌ 无效的IP地址格式 ❌\n");
                    } else {
                        tcp_close(dip, dport, sport);
                    }
                }
            } else if (strcmp(sub_cmd, "show") == 0) {
                tcp_table_print();
            } else {
                printf("❌ 未知TCP子命令:%s ❌\n", sub_cmd);
                printf("   可用子命令:connect, send, close, show ❌\n");
            }
        }
        else if (strcmp(cmd, "clear") == 0) {
            // 清理过期ARP条目
            arp_table_clean_expired();
        }// 在CLI处理逻辑中添加
        else if (strncmp(input, "tcp clean", 8) == 0) {
            char state_str[32] = {0};
            sscanf(input + 9, "%s", state_str);
            
            pthread_mutex_lock(&g_tcp_table.mutex);
            int cleaned = 0;
            for (int i = 0; i < TCP_TABLE_MAX_ENTRY; i++) {
                tcp_conn_entry_t *entry = &g_tcp_table.entries[i];
                if (!entry->valid) continue;

                if (strcmp(state_str, "time_wait") == 0 && entry->state == TCP_STATE_TIME_WAIT) {
                    memset(entry, 0, sizeof(tcp_conn_entry_t));
                    cleaned++;
                } else if (strcmp(state_str, "syn_recv") == 0 && entry->state == TCP_STATE_SYN_RECV) {
                    memset(entry, 0, sizeof(tcp_conn_entry_t));
                    cleaned++;
                } else if (strcmp(state_str, "all") == 0) {
                    memset(entry, 0, sizeof(tcp_conn_entry_t));
                    cleaned++;
                }
            }
            pthread_mutex_unlock(&g_tcp_table.mutex);
            
            printf("✅ 手动清理了%d个%s状态的TCP连接 ✅\n", cleaned, state_str);
        }
        else if (strcmp(cmd, "help") == 0) {
            // 新增help命令逻辑
            printf("\n==============================================\n");
            printf("           DPDK 交互式网络工具 - 帮助\n");
            printf("==============================================\n");
            printf("命令列表:\n");
            printf("  arp <IP地址>    - 发送ARP请求并更新ARP表\n");
            printf("  arp show        - 显示当前ARP表\n");
            printf("  udp <IP> <DPORT> <SPORT> <负载> - 发送UDP包\n");
            printf("  ping <IP地址>   - 主动Ping目标IP\n");
            printf("  clear           - 清理过期ARP条目\n");
            printf("  tcp connect <IP> <DPORT> <SPORT> - 建立TCP连接\n");
            printf("  tcp send <IP> <DPORT> <SPORT> <数据> - 发送TCP数据\n");
            printf("  tcp close <IP> <DPORT> <SPORT>   - 关闭TCP连接\n");
            printf("  tcp show        - 显示TCP连接表\n");
            printf("  help            - 查看帮助信息\n");
            printf("  quit/exit       - 退出程序\n");
            printf("==============================================\n\n");
        
        }else if (strcmp(cmd, "quit") == 0 || strcmp(cmd, "exit") == 0) {
            // 退出程序
            printf("\n👋 正在退出程序...\n");
            g_running = 0;
            break;
        } else {
            printf("❌ 未知命令:%s ❌\n", cmd);
            printf("   输入 'help' 查看命令列表 ❌\n");
        }
    }
    
    return NULL;
}

// ====================== 主函数 ======================
int main(int argc, char *argv[]) {
    // 1. 初始化EAL
    int eal_ret = rte_eal_init(argc, argv);
    if (eal_ret < 0) {
        rte_exit(EXIT_FAILURE, "Error with EAL init\n");
    }
    argc -= eal_ret;
    argv += eal_ret;

    // 2. 创建MBUF池
    g_mbuf_pool = rte_pktmbuf_pool_create(
        "mbuf pool", NUM_MBUFS, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()
    );
    if (g_mbuf_pool == NULL) {
        rte_exit(EXIT_FAILURE, "Could not create mbuf pool\n");
    }

    // 3. 初始化端口
    ustack_init_port(g_mbuf_pool);

    // 4. 初始化ARP表和TCP表
    arp_table_init();
    tcp_table_init();

    // 5. 初始化Ping上下文互斥锁
    pthread_mutex_init(&g_ping_mutex, NULL);

    // 6. 创建命令行交互线程
    pthread_t cli_thread;
    if (pthread_create(&cli_thread, NULL, cli_thread_func, NULL) != 0) {
        rte_exit(EXIT_FAILURE, "Could not create CLI thread\n");
    }

    // 7. 主循环收包(优化:动态休眠,平衡实时性和CPU占用)
    printf("\n🔄 开始数据包监听 🔄\n");

    // 替换原重复包检测逻辑
    typedef struct {
        uint32_t src_ip;
        uint32_t dst_ip;
        uint16_t src_port;
        uint16_t dst_port;
        uint32_t seq;
        uint16_t data_len;  // 新增:数据长度
        time_t recv_time;
    } tcp_packet_cache_t;

    
    // 动态休眠控制变量
    uint32_t empty_recv_count = 0;          
    const uint32_t MAX_EMPTY_BEFORE_SLEEP = 5;
    const useconds_t MIN_SLEEP_US = 1000;       
    const useconds_t MAX_SLEEP_US = 10000;      
    
    // 主函数中收包循环部分(替换原重复包缓存定义)
    while (g_running) {
        struct rte_mbuf *mbufs[BURST_SIZE] = {0};

        // 收包(非阻塞)
        uint16_t num_recvd = rte_eth_rx_burst(global_portid, 0, mbufs, BURST_SIZE);
        if (num_recvd > BURST_SIZE) {
            rte_exit(EXIT_FAILURE, "Error receiving from eth\n");
        }

        // 处理每个包
        if (num_recvd > 0) {
            empty_recv_count = 0;
            
            for (int i = 0; i < num_recvd; i++) {
                struct rte_ether_hdr *ethhdr = rte_pktmbuf_mtod(mbufs[i], struct rte_ether_hdr *);

                // 处理ARP包
                if (ethhdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) {
                    struct rte_arp_hdr *ahdr = (struct rte_arp_hdr *)(ethhdr + 1);
                    if (ahdr->arp_opcode == htons(RTE_ARP_OP_REPLY)) {
                        handle_arp_response(ahdr, ethhdr);
                    }
                }
                // 处理IP包(包含ICMP、UDP、TCP)
                else if (ethhdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
                    struct rte_ipv4_hdr *iphdr = (struct rte_ipv4_hdr *)(ethhdr + 1);
                    // 处理ICMP协议
                    if (iphdr->next_proto_id == IPPROTO_ICMP) {
                        struct rte_icmp_hdr *icmphdr = (struct rte_icmp_hdr *)(iphdr + 1);
                        if (icmphdr->icmp_type == RTE_IP_ICMP_ECHO_REQUEST) {
                            handle_icmp_echo_request(ethhdr, iphdr, icmphdr);
                        } else if (icmphdr->icmp_type == RTE_IP_ICMP_ECHO_REPLY) {
                            handle_icmp_echo_reply(icmphdr, iphdr);
                        } else if (icmphdr->icmp_type == 3) {
                            struct in_addr src_ip;
                            src_ip.s_addr = iphdr->src_addr;
                            printf("⚠️ 收到ICMP不可达报文 from %s(原因:端口未开放)⚠️\n", inet_ntoa(src_ip));
                        }
                    }
                    // 处理UDP协议
                    else if (iphdr->next_proto_id == IPPROTO_UDP) {
                        struct rte_udp_hdr *udphdr = (struct rte_udp_hdr *)(iphdr + 1);
                        handle_udp_packet(ethhdr, iphdr, udphdr);
                    }
                    // 处理TCP协议(重复包过滤已移到handle_tcp_packet内部)
                    else if (iphdr->next_proto_id == IPPROTO_TCP) {
                        struct rte_tcp_hdr *tcphdr = (struct rte_tcp_hdr *)(iphdr + 1);
                        handle_tcp_packet(ethhdr, iphdr, tcphdr);
                    }
                }
                
                // 释放MBUF
                rte_pktmbuf_free(mbufs[i]);
            }
        } else {
            empty_recv_count++;
            if (empty_recv_count >= MAX_EMPTY_BEFORE_SLEEP) {
                useconds_t sleep_us = MIN_SLEEP_US + (empty_recv_count - MAX_EMPTY_BEFORE_SLEEP) * 1000;
                if (sleep_us > MAX_SLEEP_US) {
                    sleep_us = MAX_SLEEP_US;
                }
                usleep(sleep_us);
            }
        }
        
        // 定期清理过期ARP条目和无效TCP连接
        static time_t last_arp_clean = 0;
        static time_t last_tcp_clean = 0;
        time_t now = time(NULL);
        if (now - last_arp_clean > 60) {
            arp_table_clean_expired();
            last_arp_clean = now;
        }
        if (now - last_tcp_clean > TCP_CLOSED_CLEAN_INTERVAL) {
            tcp_table_clean_invalid();
            last_tcp_clean = now;
        }
    }

    // 等待CLI线程退出
    pthread_join(cli_thread, NULL);
    
    // 清理资源
    rte_eth_dev_stop(global_portid);
    rte_eth_dev_close(global_portid);
    rte_mempool_free(g_mbuf_pool);
    pthread_mutex_destroy(&g_ping_mutex);
    
    printf("✅ 程序正常退出 ✅\n");
    return 0;
}

2.Makefile

cpp 复制代码
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2010-2014 Intel Corporation

# binary name
APP = tcp

# all source are stored in SRCS-y
SRCS-y := tcp.c

# Build using pkg-config variables if possible
ifeq ($(shell pkg-config --exists libdpdk && echo 0),0)

all: shared
.PHONY: shared static
shared: build/$(APP)-shared
	ln -sf $(APP)-shared build/$(APP)
static: build/$(APP)-static
	ln -sf $(APP)-static build/$(APP)

PKGCONF=pkg-config --define-prefix

PC_FILE := $(shell $(PKGCONF) --path libdpdk)
CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
CFLAGS += -DALLOW_EXPERIMENTAL_API
LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)

build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)

build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)

build:
	@mkdir -p $@

.PHONY: clean
clean:
	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
	test -d build && rmdir -p build || true

else # Build using legacy build system

ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif

# Default target, detect a build directory, by looking for a path with a .config
RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config)))))

include $(RTE_SDK)/mk/rte.vars.mk

ifneq ($(CONFIG_RTE_EXEC_ENV_LINUX),y)
$(error This application can only operate in a linux environment, \
please change the definition of the RTE_TARGET environment variable)
endif

CFLAGS += -O3
CFLAGS += -DALLOW_EXPERIMENTAL_API
CFLAGS += $(WERROR_FLAGS)

include $(RTE_SDK)/mk/rte.extapp.mk
endif

3.代码讲解

在原有 ARP 表管理 + ICMP/UDP 基础上,新增了完整的 TCP 协议栈核心能力(支持主动建立连接、被动响应连接、数据收发、连接断开、乱序包处理等)。以下是 TCP 模块的核心流程和关键模块详解:

TCP 模块核心流程

复制代码
main() // 程序入口(仅展示TCP相关部分)
├─ tcp_table_init()      // 1. 初始化TCP连接表(32个条目,默认CLOSED,初始化互斥锁+接收缓冲区)
├─ pthread_create()      // 2. 命令行交互线程新增TCP子命令:connect/send/close/show/clean
└─ 无限循环(核心:批量收包+TCP包处理)
   ├─ rte_eth_rx_burst() // 批量接收数据包
   ├─ 遍历每个收包
   │  ├─ 解析以太头→IPv4头→过滤TCP包(next_proto_id=IPPROTO_TCP)
   │  ├─ handle_tcp_packet() // 核心:处理TCP包(三次握手/数据收发/四次挥手/RST处理)
   │  │  ├─ 重复包过滤(基于src/dst IP+端口+seq+数据长度,3秒缓存)
   │  │  ├─ 处理SYN包(被动建立连接→回复SYN+ACK)
   │  │  ├─ 处理SYN+ACK包(完成主动连接三次握手→回复ACK)
   │  │  ├─ 处理ACK包(完成三次握手/确认关闭)
   │  │  ├─ 处理数据包(有序接收/乱序缓存/粘包处理→回复ACK)
   │  │  ├─ 处理FIN包(四次挥手→回复ACK+FIN)
   │  │  └─ 处理RST包(强制关闭连接→清理连接条目)
   │  └─ rte_pktmbuf_free() // 释放MBUF
   └─ 定期清理无效TCP连接(每10秒)
      ├─ 清理CLOSED状态条目(超过10秒)
      ├─ 清理TIME_WAIT状态条目(超过60秒)
      └─ 清理SYN_RECV半连接(超过10秒未完成三次握手)

TCP 关键模块详解

1. TCP 连接表管理模块(核心基础)
复制代码
tcp_table_t(全局TCP连接表)
├─ tcp_table_init()      // 初始化:32个条目,默认valid=0/state=CLOSED,初始化接收缓冲区(4096字节)
├─ tcp_table_add()       // 添加连接条目
│  ├─ 查找空条目,填充src/dst IP+端口、状态、随机seq(generate_seq_num())
│  ├─ 记录最后活动时间,初始化互斥锁保证线程安全
│  └─ 表满则返回错误
├─ tcp_table_lookup()    // 查找连接条目
│  ├─ 按src/dst IP+端口匹配,忽略CLOSED状态
│  ├─ 加锁保证多线程安全
│  └─ 返回匹配的连接条目指针(NULL=未找到)
├─ tcp_table_update_state() // 更新连接状态
│  ├─ 匹配连接条目→修改state→更新最后活动时间
│  └─ 支持状态:CLOSED/SYN_SENT/ESTABLISHED/FIN_WAIT1/FIN_WAIT2/TIME_WAIT/SYN_RECV
├─ tcp_table_reset_entry() // 重置连接条目(彻底清空,区别于仅改状态)
├─ tcp_table_clean_invalid() // 清理无效连接
│  ├─ 清理CLOSED条目(超过10秒)
│  ├─ 清理TIME_WAIT条目(标准60秒超时)
│  ├─ 清理SYN_RECV半连接(10秒未完成三次握手)
│  └─ 打印清理数量,保证连接表整洁
└─ tcp_table_print()     // 打印连接表
   ├─ 显示源IP/端口、目标IP/端口、连接状态
   └─ 格式化输出,便于调试
2. TCP 数据包编解码模块(收发基础)
复制代码
├─ tcp_checksum() // 计算TCP校验和(含伪头部:源/目标IP+协议号+TCP长度)
│  ├─ 先计算伪头部校验和,再计算TCP头+数据校验和
│  └─ 折叠校验和(高16位+低16位)→ 取反得到最终值
├─ encode_tcp_packet() // 编码TCP数据包
│  ├─ 以太头:从ARP表获取目标MAC,源MAC为本机
│  ├─ IPv4头:版本4+头长20字节,TTL=64,协议=TCP,自动计算IP校验和
│  ├─ TCP头:源/目标端口、seq/ack、标志位(SYN/ACK/FIN/RST)、窗口大小(65535)
│  ├─ 拷贝负载数据(如有)
│  └─ 计算并填充TCP校验和
└─ send_tcp_packet() // 发送TCP数据包
   ├─ 查找ARP表获取目标MAC(失败则返回错误)
   ├─ 分配MBUF,调用encode_tcp_packet()编码
   ├─ rte_eth_tx_burst()发送(单次1个包)
   └─ 打印发送信息(目标IP+端口、标志位、seq/ack、负载长度)
3. TCP 主动连接管理模块(三次握手 / 数据发送 / 四次挥
复制代码
├─ tcp_connect() // 主动建立TCP连接(三次握手)
│  ├─ 先发送ARP请求获取目标MAC(重试3次)
│  ├─ 添加连接条目(状态=SYN_SENT)
│  ├─ 发送SYN包(第一次握手,重试3次,每次生成新seq)
│  ├─ 等待SYN+ACK响应(超时3秒)
│  ├─ 收到SYN+ACK后回复ACK(第三次握手),更新状态=ESTABLISHED
│  └─ 超时则清理连接条目,返回失败
├─ tcp_send_data() // 发送TCP数据(仅ESTABLISHED状态)
│  ├─ 查找有效连接(状态=ESTABLISHED)
│  ├─ 基于当前seq/ack发送数据(带ACK标志)
│  ├─ 更新本地seq(seq += 数据长度)
│  └─ 打印发送数据信息(目标IP+端口、数据长度/内容)
└─ tcp_close() // 主动关闭TCP连接(四次挥手)
   ├─ 查找有效连接,更新状态=FIN_WAIT1
   ├─ 发送FIN+ACK包(第一次挥手)
   ├─ 等待响应(超时6秒)
   └─ 无论是否超时,彻底清理连接条目
4. TCP 被动包处理模块(核心逻辑)
复制代码
handle_tcp_packet() // 处理收到的TCP包
├─ 前置过滤:仅处理目标IP为本机的TCP包,解析src/dst IP+端口、seq/ack、标志位、数据
├─ 重复包过滤:缓存32个包(src/dst IP+端口+seq+数据长度),3秒内重复则忽略
├─ 分场景处理:
│  ├─ 处理SYN包(仅SYN):
│  │  ├─ 添加被动连接条目(状态=SYN_RECV)
│  │  ├─ 回复SYN+ACK包(第二次握手)
│  │  └─ 记录我方seq,用于后续验证
│  ├─ 处理SYN+ACK包:
│  │  ├─ 匹配SYN_SENT状态的连接
│  │  ├─ 回复ACK包(第三次握手),更新状态=ESTABLISHED
│  │  └─ 初始化recv_next_seq(对方下一个数据的seq)
│  ├─ 处理ACK包(无数据):
│  │  ├─ 完成被动连接三次握手(验证ack=我方seq+1),更新状态=ESTABLISHED
│  │  ├─ 确认关闭连接(FIN_WAIT1→FIN_WAIT2,FIN_WAIT2→CLOSED)
│  │  └─ 更新最后活动时间
│  ├─ 处理数据包(带ACK标志+数据):
│  │  ├─ 有序数据:写入接收缓冲区,更新recv_next_seq,回复ACK(ack=recv_next_seq)
│  │  ├─ 乱序数据:缓存8个乱序包(seq不匹配),后续有序包到达后自动合并
│  │  ├─ 粘包处理:接收缓冲区累积数据,打印完整缓存内容
│  │  └─ 缓冲区满则丢弃数据,打印警告
│  ├─ 处理FIN包:
│  │  ├─ 回复ACK包(确认关闭)
│  │  ├─ 主动连接:更新状态=TIME_WAIT,回复FIN+ACK
│  │  └─ 被动连接:更新状态=TIME_WAIT,后续自动清理
│  └─ 处理RST包:
│     ├─ 查找对应连接条目,强制设置state=CLOSED、valid=0
│     └─ 打印强制关闭信息,直接返回(不再处理)
└─ 未知包处理:打印警告,忽略
5. TCP 命令行交互模块(用户操作)
复制代码
cli_thread_func() // 命令行线程新增TCP子命令
├─ "tcp connect <IP> <DPORT> <SPORT>":调用tcp_connect()建立主动连接
├─ "tcp send <IP> <DPORT> <SPORT> <数据>":调用tcp_send_data()发送数据
├─ "tcp close <IP> <DPORT> <SPORT>":调用tcp_close()关闭连接
├─ "tcp show":调用tcp_table_print()打印连接表
├─ "tcp clean <state>":手动清理指定状态的连接
│  ├─ "tcp clean time_wait":清理TIME_WAIT状态
│  ├─ "tcp clean syn_recv":清理SYN_RECV状态
│  └─ "tcp clean all":清理所有连接
└─ 输入校验:检查IP格式、端口范围、参数完整性,错误则提示用法

4.运行案例

0voice · GitHub

相关推荐
Jtti2 小时前
怎么避免国外服务器的丢包问题?
运维·服务器
m0_737302582 小时前
腾讯云TDSQL-C+CVM,软硬协同驱动数据库性能革命
服务器
Knight_AL2 小时前
深入理解 ZLMediaKit HTTP Hook 机制
网络·网络协议·http
2501_945837432 小时前
腾讯云星星海S7,风冷液冷双适配引领绿色算力
服务器
工业引擎Robot2 小时前
安川机器人IO分配修改教程
网络
上海云盾安全满满2 小时前
高防IP怎样应对复杂CC攻击
网络·网络协议·tcp/ip
网安小白的进阶之路2 小时前
B模块 安全通信网络 第二门课 核心网路由技术-2-BGP属性-选路原则-路由优选
网络·安全·智能路由器
草莓熊Lotso2 小时前
Linux 进程等待与程序替换全解析:从僵尸进程防治到 exec 函数实战
linux·运维·服务器·开发语言·c++·人工智能·python
德彪稳坐倒骑驴2 小时前
PySpark on Linux系统配置 Hadoop3.1.3+Spark3.4.4(PySpark3)
linux·运维·服务器