├── run.sh ├── .vscode ├── dryrun.log ├── configurationCache.log ├── targets.log ├── tasks.json ├── c_cpp_properties.json ├── launch.json ├── settings.json └── test.c ├── Makefile ├── README.md ├── udp.h ├── tcp.h ├── udp.c ├── common.h ├── netfamily.c ├── tcp.c ├── common.c └── nty_tree.h /run.sh: -------------------------------------------------------------------------------- 1 | #服务名称 2 | ./build/test -------------------------------------------------------------------------------- /.vscode/dryrun.log: -------------------------------------------------------------------------------- 1 | make.exe all --dry-run --keep-going --print-directory 2 | 'make.exe' �����ڲ����ⲿ���Ҳ���ǿ����еij��� 3 | ���������ļ��� 4 | 5 | -------------------------------------------------------------------------------- /.vscode/configurationCache.log: -------------------------------------------------------------------------------- 1 | {"buildTargets":["all"],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} -------------------------------------------------------------------------------- /.vscode/targets.log: -------------------------------------------------------------------------------- 1 | make.exe all --print-data-base --no-builtin-variables --no-builtin-rules --question 2 | 'make.exe' �����ڲ����ⲿ���Ҳ���ǿ����еij��� 3 | ���������ļ��� 4 | 5 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "shell", 6 | "label":"dpdk-build", 7 | "command": "/usr/bin/make", 8 | "args": [], 9 | "options":{ 10 | "cwd":"${workspaceFolder}" 11 | }, 12 | "problemMatcher":[ 13 | "$gcc" 14 | ], 15 | "group":"build", 16 | "detail": "" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include $(RTE_SDK)/mk/rte.vars.mk 2 | 3 | # binary name 4 | APP = test 5 | 6 | # all source are stored in SRCS-y 7 | SRCS-y := netfamily.c 8 | SRCS-y += common.c 9 | SRCS-y += tcp.c 10 | SRCS-y += udp.c 11 | CFLAGS += -Wall -g 12 | # CFLAGS += -D ENABLE_SINGLE_EPOLL 13 | CFLAGS += -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wformat=0 14 | LDLIBS += -lpthread 15 | 16 | INC += $(sort $(wildcard *.h)) 17 | 18 | include $(RTE_SDK)/mk/rte.extapp.mk 19 | 20 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "linux-gcc-x64", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "/media/dpdk-stable-19.11.12/lib/**", 8 | "/media/dpdk-stable-19.11.12/x86_64-native-linuxapp-gcc/include/**" 9 | ], 10 | "defines": [], 11 | "compilerPath": "/opt/rh/devtoolset-9/root/usr/bin/gcc", 12 | "cStandard": "${default}", 13 | "cppStandard": "${default}", 14 | "intelliSenseMode": "linux-gcc-x64" 15 | } 16 | ], 17 | "version": 4 18 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DPDK-TCP-UDP_Protocol_Stack 2 | Simple protocol stack based on dpdk(使用dpdk搭建协议栈) 3 | 4 | 为了对协议栈了解更深入一些,借助dpdk-19.11实现一个简易协议栈。 5 | 6 | 本项目要完成的工作如下: 7 | 1. dpdk相关配置 8 | 2. 实现协议栈,主要针对TCP与UDP,包含三次握手、四次挥手 9 | 3. 实现服务端socket系统调用api:socket、bind、listen、accept、recv、send、recvfrom、sendto、recv、send、close 10 | 4. 实现epoll多线程 11 | 12 | ## 使用 13 | 1. 环境:安装dpdp-19.11,多队列网卡 14 | 2. make clean;make 15 | 3. sh run.sh 16 | 17 | ## 测试 18 | 1. 在虚拟机中执行该代码 19 | 2. windows中可以使用类似网络调试助手的工具软件给虚拟机发送tcp/udp数据包 20 | 测试时,需要在客户端增加一条arp表项,目的是为了客户端能根据mac地址将数据包发送至服务端 21 | 具体方法如下: 22 | https://www.sohu.com/a/502006584_121258626 23 | 24 | ## 注意 25 | 本项目目前正在逐步优化,欢迎同学们指出不足哈! 26 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C/C++ Runner: Debug Session", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "args": [], 9 | "stopAtEntry": false, 10 | "cwd": "e:/codeTest/test_netfamily", 11 | "environment": [], 12 | "program": "e:/codeTest/test_netfamily/build/Debug/outDebug", 13 | "internalConsoleOptions": "openOnSessionStart", 14 | "MIMode": "gdb", 15 | "miDebuggerPath": "D:/DevC++/DevCpp/MinGW64/bin/gdb.exe", 16 | "console": "integratedTerminal", 17 | "setupCommands": [ 18 | { 19 | "description": "Enable pretty-printing for gdb", 20 | "text": "-enable-pretty-printing", 21 | "ignoreFailures": true 22 | } 23 | ] 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /udp.h: -------------------------------------------------------------------------------- 1 | #ifndef __UDP_H__ 2 | #define __UDP_H__ 3 | 4 | #include "common.h" 5 | 6 | int udp_process(struct rte_mbuf *pstUdpMbuf); 7 | int udp_out(struct rte_mempool *mbuf_pool); 8 | 9 | // udp control block 10 | struct localhost 11 | { 12 | int fd; 13 | 14 | //unsigned int status; // 15 | uint32_t localip; // ip --> mac 16 | unsigned char localmac[RTE_ETHER_ADDR_LEN]; 17 | uint16_t localport; 18 | 19 | unsigned char protocol; 20 | 21 | struct rte_ring *sndbuf; 22 | struct rte_ring *rcvbuf; 23 | 24 | struct localhost *prev; 25 | struct localhost *next; 26 | 27 | pthread_cond_t cond; 28 | pthread_mutex_t mutex; 29 | }; 30 | 31 | struct offload 32 | { 33 | uint32_t sip; 34 | uint32_t dip; 35 | 36 | uint16_t sport; 37 | uint16_t dport; 38 | 39 | int protocol; 40 | 41 | unsigned char *data; 42 | uint16_t length; 43 | 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef __TCP_H__ 2 | #define __TCP_H__ 3 | 4 | #include "common.h" 5 | 6 | int tcp_process(struct rte_mbuf *pstTcpMbuf); 7 | int tcp_out(struct rte_mempool *pstMbufPool); 8 | 9 | // 11种tcp连接状态 10 | typedef enum _ENUM_TCP_STATUS 11 | { 12 | TCP_STATUS_CLOSED = 0, 13 | TCP_STATUS_LISTEN, 14 | TCP_STATUS_SYN_RCVD, 15 | TCP_STATUS_SYN_SENT, 16 | TCP_STATUS_ESTABLISHED, 17 | 18 | TCP_STATUS_FIN_WAIT_1, 19 | TCP_STATUS_FIN_WAIT_2, 20 | TCP_STATUS_CLOSING, 21 | TCP_STATUS_TIME_WAIT, 22 | 23 | TCP_STATUS_CLOSE_WAIT, 24 | TCP_STATUS_LAST_ACK 25 | 26 | }TCP_STATUS; 27 | 28 | // tcb control block 29 | struct tcp_stream 30 | { 31 | int fd; 32 | 33 | uint32_t dip; 34 | uint8_t localmac[RTE_ETHER_ADDR_LEN]; 35 | uint16_t dport; 36 | 37 | uint8_t protocol; 38 | 39 | uint16_t sport; 40 | uint32_t sip; 41 | 42 | uint32_t snd_nxt; // seqnum 43 | uint32_t rcv_nxt; // acknum 44 | 45 | TCP_STATUS status; 46 | 47 | struct rte_ring *sndbuf; 48 | struct rte_ring *rcvbuf; 49 | 50 | struct tcp_stream *prev; 51 | struct tcp_stream *next; 52 | 53 | pthread_cond_t cond; 54 | pthread_mutex_t mutex; 55 | }; 56 | 57 | struct tcp_table 58 | { 59 | int count; 60 | //struct tcp_stream *listener_set; // 61 | #if ENABLE_SINGLE_EPOLL 62 | struct eventpoll *ep; // single epoll 63 | #endif 64 | struct tcp_stream *tcb_set; 65 | }; 66 | 67 | struct tcp_fragment 68 | { 69 | uint16_t sport; 70 | uint16_t dport; 71 | uint32_t seqnum; 72 | uint32_t acknum; 73 | uint8_t hdrlen_off; 74 | uint8_t tcp_flags; 75 | uint16_t windows; 76 | uint16_t cksum; 77 | uint16_t tcp_urp; 78 | 79 | int optlen; 80 | uint32_t option[D_TCP_OPTION_LENGTH]; 81 | 82 | unsigned char *data; 83 | uint32_t length; 84 | }; 85 | 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp_Runner.cCompilerPath": "D:/DevC++/DevCpp/MinGW64/bin/gcc.exe", 3 | "C_Cpp_Runner.cppCompilerPath": "D:/DevC++/DevCpp/MinGW64/bin/g++.exe", 4 | "C_Cpp_Runner.debuggerPath": "D:/DevC++/DevCpp/MinGW64/bin/gdb.exe", 5 | "C_Cpp_Runner.cStandard": "", 6 | "C_Cpp_Runner.cppStandard": "", 7 | "C_Cpp_Runner.msvcBatchPath": "", 8 | "C_Cpp_Runner.warnings": [ 9 | "-Wall", 10 | "-Wextra", 11 | "-Wpedantic" 12 | ], 13 | "C_Cpp_Runner.enableWarnings": true, 14 | "C_Cpp_Runner.warningsAsError": false, 15 | "C_Cpp_Runner.compilerArgs": [], 16 | "C_Cpp_Runner.linkerArgs": [], 17 | "C_Cpp_Runner.includePaths": [], 18 | "C_Cpp_Runner.includeSearch": [ 19 | "*", 20 | "**/*" 21 | ], 22 | "C_Cpp_Runner.excludeSearch": [ 23 | "**/build", 24 | "**/build/**", 25 | "**/.*", 26 | "**/.*/**", 27 | "**/.vscode", 28 | "**/.vscode/**" 29 | ], 30 | "files.associations": { 31 | "*.c": "c", 32 | "stdio.h": "c", 33 | "math.h": "c", 34 | "common.h": "c", 35 | "cstdlib": "c", 36 | "tcp.h": "c", 37 | "bitset": "c", 38 | "chrono": "c", 39 | "cstring": "c", 40 | "list": "c", 41 | "stdlib.h": "c", 42 | "inet.h": "c", 43 | "udp.h": "c" 44 | }, 45 | "C_Cpp_Runner.useMsvc": false, 46 | "C_Cpp_Runner.msvcWarnings": [ 47 | "/W4", 48 | "/permissive-", 49 | "/w14242", 50 | "/w14287", 51 | "/w14296", 52 | "/w14311", 53 | "/w14826", 54 | "/w44062", 55 | "/w44242", 56 | "/w14905", 57 | "/w14906", 58 | "/w14263", 59 | "/w44265", 60 | "/w14928" 61 | ], 62 | "C_Cpp_Runner.useAddressSanitizer": false, 63 | "C_Cpp_Runner.useUndefinedSanitizer": false, 64 | "C_Cpp_Runner.useLeakSanitizer": false, 65 | "C_Cpp_Runner.showCompilationTime": false, 66 | "C_Cpp_Runner.useLinkTimeOptimization": false, 67 | "C_Cpp_Runner.msvcSecureNoWarnings": false 68 | } -------------------------------------------------------------------------------- /udp.c: -------------------------------------------------------------------------------- 1 | #include "udp.h" 2 | 3 | 4 | int udp_process(struct rte_mbuf *pstUdpMbuf) 5 | { 6 | struct rte_ipv4_hdr *pstIpHdr; 7 | struct rte_udp_hdr *pstUdpHdr; 8 | struct localhost *pstHost; 9 | struct offload *pstOffLoad; 10 | 11 | pstIpHdr = rte_pktmbuf_mtod_offset(pstUdpMbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); 12 | pstUdpHdr = (struct rte_udp_hdr *)(pstIpHdr + 1); 13 | 14 | pstHost = get_hostinfo_fromip_port(pstIpHdr->dst_addr, pstUdpHdr->dst_port, pstIpHdr->next_proto_id); 15 | if (pstHost == NULL) 16 | { 17 | rte_pktmbuf_free(pstUdpMbuf); 18 | return -3; 19 | } 20 | 21 | struct in_addr addr; 22 | addr.s_addr = pstIpHdr->src_addr; 23 | printf("udp_process ---> src: %s:%d \n", inet_ntoa(addr), ntohs(pstUdpHdr->src_port)); 24 | 25 | pstOffLoad = rte_malloc("offload", sizeof(struct offload), 0); 26 | if (pstOffLoad == NULL) 27 | { 28 | rte_pktmbuf_free(pstUdpMbuf); 29 | return -1; 30 | } 31 | 32 | pstOffLoad->dip = pstIpHdr->dst_addr; 33 | pstOffLoad->sip = pstIpHdr->src_addr; 34 | pstOffLoad->sport = pstUdpHdr->src_port; 35 | pstOffLoad->dport = pstUdpHdr->dst_port; 36 | pstOffLoad->protocol = IPPROTO_UDP; 37 | pstOffLoad->length = ntohs(pstUdpHdr->dgram_len); 38 | pstOffLoad->data = rte_malloc("unsigned char*", pstOffLoad->length - sizeof(struct rte_udp_hdr), 0); 39 | if (pstOffLoad->data == NULL) 40 | { 41 | rte_pktmbuf_free(pstUdpMbuf); 42 | rte_free(pstOffLoad); 43 | return -2; 44 | } 45 | 46 | rte_memcpy(pstOffLoad->data, (unsigned char *)(pstUdpHdr+1), pstOffLoad->length - sizeof(struct rte_udp_hdr)); 47 | 48 | rte_ring_mp_enqueue(pstHost->rcvbuf, pstOffLoad); // recv buffer 49 | 50 | pthread_mutex_lock(&pstHost->mutex); 51 | pthread_cond_signal(&pstHost->cond); 52 | pthread_mutex_unlock(&pstHost->mutex); 53 | 54 | rte_pktmbuf_free(pstUdpMbuf); 55 | 56 | return 0; 57 | } 58 | 59 | static int ng_encode_udp_apppkt(uint8_t *msg, uint32_t sip, uint32_t dip, 60 | uint16_t sport, uint16_t dport, uint8_t *srcmac, uint8_t *dstmac, 61 | unsigned char *data, uint16_t total_len) 62 | { 63 | struct rte_ether_hdr *pstEth; 64 | struct rte_ipv4_hdr *pstIp; 65 | struct rte_udp_hdr *pstUdp; 66 | 67 | // 1 ethhdr 68 | pstEth = (struct rte_ether_hdr *)msg; 69 | rte_memcpy(pstEth->s_addr.addr_bytes, srcmac, RTE_ETHER_ADDR_LEN); 70 | rte_memcpy(pstEth->d_addr.addr_bytes, dstmac, RTE_ETHER_ADDR_LEN); 71 | pstEth->ether_type = htons(RTE_ETHER_TYPE_IPV4); 72 | 73 | // 2 iphdr 74 | pstIp = (struct rte_ipv4_hdr *)(pstEth + 1); 75 | pstIp->version_ihl = 0x45; 76 | pstIp->type_of_service = 0; 77 | pstIp->total_length = htons(total_len - sizeof(struct rte_ether_hdr)); 78 | pstIp->packet_id = 0; 79 | pstIp->fragment_offset = 0; 80 | pstIp->time_to_live = 64; // ttl = 64 81 | pstIp->next_proto_id = IPPROTO_UDP; 82 | pstIp->src_addr = sip; 83 | pstIp->dst_addr = dip; 84 | pstIp->hdr_checksum = 0; 85 | pstIp->hdr_checksum = rte_ipv4_cksum(pstIp); 86 | 87 | // 3 udphdr 88 | pstUdp = (struct rte_udp_hdr *)(pstIp + 1); 89 | pstUdp->src_port = sport; 90 | pstUdp->dst_port = dport; 91 | uint16_t udplen = total_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr); 92 | pstUdp->dgram_len = htons(udplen); 93 | rte_memcpy((uint8_t*)(pstUdp + 1), data, udplen); 94 | pstUdp->dgram_cksum = 0; 95 | pstUdp->dgram_cksum = rte_ipv4_udptcp_cksum(pstIp, pstUdp); 96 | 97 | return 0; 98 | } 99 | 100 | static struct rte_mbuf * ng_udp_pkt(struct rte_mempool *mbuf_pool, uint32_t sip, uint32_t dip, 101 | uint16_t sport, uint16_t dport, unsigned char *srcmac, unsigned char *dstmac, 102 | unsigned char *data, uint16_t length) 103 | { 104 | unsigned int uiTotalLen; 105 | struct rte_mbuf *pstMbuf; 106 | unsigned char *pucPktData; 107 | 108 | uiTotalLen = length + 42; // 42 = eth + ip 109 | pstMbuf = rte_pktmbuf_alloc(mbuf_pool); 110 | if (!pstMbuf) 111 | rte_exit(EXIT_FAILURE, "rte_pktmbuf_alloc\n"); 112 | 113 | pstMbuf->pkt_len = uiTotalLen; 114 | pstMbuf->data_len = uiTotalLen; 115 | pucPktData = rte_pktmbuf_mtod(pstMbuf, unsigned char*); 116 | 117 | ng_encode_udp_apppkt(pucPktData, sip, dip, sport, dport, srcmac, dstmac, 118 | data, uiTotalLen); 119 | 120 | return pstMbuf; 121 | } 122 | 123 | int udp_out(struct rte_mempool *pstMbufPool) 124 | { 125 | struct localhost *pstHost; 126 | 127 | for(pstHost = g_pstHost; pstHost != NULL; pstHost = pstHost->next) 128 | { 129 | struct offload *pstOffLoad = NULL; 130 | int iSendCnt = rte_ring_mc_dequeue(pstHost->sndbuf, (void **)&pstOffLoad); 131 | if(iSendCnt < 0) 132 | continue; 133 | 134 | struct in_addr addr; 135 | addr.s_addr = pstOffLoad->dip; 136 | printf("udp_out ---> src: %s:%d \n", inet_ntoa(addr), ntohs(pstOffLoad->dport)); 137 | 138 | unsigned char *dstmac = ng_get_dst_macaddr(pstOffLoad->dip); // 查询对端mac地址 139 | if (dstmac == NULL) // 先广播发个arp包确定对端mac地址 140 | { 141 | struct rte_mbuf *pstArpbuf = ng_send_arp(pstMbufPool, RTE_ARP_OP_REQUEST, g_aucDefaultArpMac, 142 | pstOffLoad->sip, pstOffLoad->dip); 143 | 144 | rte_ring_mp_enqueue_burst(g_pstRingIns->pstOutRing, (void **)&pstArpbuf, 1, NULL); 145 | 146 | rte_ring_mp_enqueue(pstHost->sndbuf, pstOffLoad); // 将取出的udp数据再次写入队列 147 | } 148 | else 149 | { 150 | struct rte_mbuf *pstUdpbuf = ng_udp_pkt(pstMbufPool, pstOffLoad->sip, pstOffLoad->dip, 151 | pstOffLoad->sport, pstOffLoad->dport, pstHost->localmac, 152 | dstmac, pstOffLoad->data, pstOffLoad->length); 153 | 154 | rte_ring_mp_enqueue_burst(g_pstRingIns->pstOutRing, (void **)&pstUdpbuf, 1, NULL); 155 | 156 | if (pstOffLoad->data != NULL) 157 | rte_free(pstOffLoad->data); 158 | 159 | rte_free(pstOffLoad); 160 | } 161 | } 162 | 163 | return 0; 164 | } -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "nty_tree.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define D_PORT_ID 0 27 | 28 | #define D_MAX_PACKET_SIZE 2048 29 | #define D_RING_SIZE 1024 30 | #define D_BURST_SIZE 32 31 | 32 | #define D_DEFAULT_FD_NUM 3 33 | #define D_MAX_FD_COUNT 1024 34 | 35 | #define D_NUM_MBUFS (4096-1) 36 | #define D_UDP_BUFFER_SIZE 1024 37 | 38 | #define D_TCP_OPTION_LENGTH 10 39 | #define D_TCP_INITIAL_WINDOW 14600 40 | #define D_TCP_MAX_SEQ 0xffffffff 41 | #define D_TCP_BUFFER_SIZE 1024 42 | // 头插法 43 | #define LL_ADD(item, list) do \ 44 | { \ 45 | item->prev = NULL; \ 46 | item->next = list; \ 47 | if (list != NULL) list->prev = item; \ 48 | list = item; \ 49 | } while(0) 50 | 51 | #define LL_REMOVE(item, list) do \ 52 | { \ 53 | if (item->prev != NULL) item->prev->next = item->next; \ 54 | if (item->next != NULL) item->next->prev = item->prev; \ 55 | if (list == item) list = item->next; \ 56 | item->prev = item->next = NULL; \ 57 | } while(0) 58 | 59 | // 网卡的输入、输出队列 60 | struct St_InOut_Ring 61 | { 62 | struct rte_ring *pstInRing; 63 | struct rte_ring *pstOutRing; 64 | }; 65 | 66 | // arp表的单个条目 67 | struct arp_entry 68 | { 69 | uint32_t ip; 70 | unsigned char hwaddr[RTE_ETHER_ADDR_LEN]; 71 | 72 | unsigned char type; 73 | 74 | struct arp_entry *next; 75 | struct arp_entry *prev; 76 | }; 77 | 78 | // arp表结构 79 | struct arp_table 80 | { 81 | struct arp_entry *entries; 82 | int count; 83 | 84 | pthread_spinlock_t spinlock; 85 | }; 86 | 87 | enum EPOLL_EVENTS 88 | { 89 | EPOLLNONE = 0x0000, 90 | EPOLLIN = 0x0001, 91 | EPOLLPRI = 0x0002, 92 | EPOLLOUT = 0x0004, 93 | EPOLLRDNORM = 0x0040, 94 | EPOLLRDBAND = 0x0080, 95 | EPOLLWRNORM = 0x0100, 96 | EPOLLWRBAND = 0x0200, 97 | EPOLLMSG = 0x0400, 98 | EPOLLERR = 0x0008, 99 | EPOLLHUP = 0x0010, 100 | EPOLLRDHUP = 0x2000, 101 | EPOLLONESHOT = (1 << 30), 102 | EPOLLET = (1 << 31) 103 | 104 | }; 105 | 106 | #define EPOLL_CTL_ADD 1 107 | #define EPOLL_CTL_DEL 2 108 | #define EPOLL_CTL_MOD 3 109 | 110 | typedef union epoll_data 111 | { 112 | void *ptr; 113 | int fd; 114 | uint32_t u32; 115 | uint64_t u64; 116 | } epoll_data_t; 117 | 118 | struct epoll_event 119 | { 120 | uint32_t events; 121 | epoll_data_t data; 122 | }; 123 | 124 | struct epitem 125 | { 126 | RB_ENTRY(epitem) rbn; 127 | LIST_ENTRY(epitem) rdlink; 128 | int rdy; //exist in list 129 | 130 | int sockfd; 131 | struct epoll_event event; 132 | }; 133 | 134 | static int sockfd_cmp(struct epitem *ep1, struct epitem *ep2) 135 | { 136 | if (ep1->sockfd < ep2->sockfd) return -1; 137 | else if (ep1->sockfd == ep2->sockfd) return 0; 138 | return 1; 139 | } 140 | 141 | RB_HEAD(_epoll_rb_socket, epitem); 142 | RB_GENERATE_STATIC(_epoll_rb_socket, epitem, rbn, sockfd_cmp); 143 | 144 | typedef struct _epoll_rb_socket ep_rb_tree; 145 | 146 | struct eventpoll 147 | { 148 | int fd; 149 | 150 | ep_rb_tree rbr; 151 | int rbcnt; 152 | 153 | LIST_HEAD( ,epitem) rdlist; 154 | int rdnum; 155 | 156 | int waiting; 157 | 158 | pthread_mutex_t mtx; //rbtree update 159 | pthread_spinlock_t lock; //rdlist update 160 | 161 | pthread_cond_t cond; //block for event 162 | pthread_mutex_t cdmtx; //mutex for cond 163 | 164 | }; 165 | 166 | extern struct St_InOut_Ring *g_pstRingIns; 167 | extern unsigned char g_ucFdTable[D_MAX_FD_COUNT]; 168 | extern struct localhost *g_pstHost; 169 | extern struct rte_ether_addr g_stCpuMac; 170 | extern struct arp_table *g_pstArpTbl; 171 | extern struct tcp_table *g_pstTcpTbl; 172 | extern unsigned char g_aucDefaultArpMac[RTE_ETHER_ADDR_LEN]; 173 | 174 | void dbg_print(char *info, unsigned char *dat, int dat_len); 175 | 176 | // arp相关 177 | int ng_arp_entry_insert(uint32_t ip, unsigned char *mac); 178 | unsigned char* ng_get_dst_macaddr(uint32_t dip); 179 | struct rte_mbuf *ng_send_arp(struct rte_mempool *mbuf_pool, uint16_t opcode, unsigned char *dst_mac, 180 | uint32_t sip, uint32_t dip); 181 | 182 | // search 183 | struct localhost * get_hostinfo_fromip_port(uint32_t dip, uint16_t port, unsigned char proto); 184 | void* get_hostinfo_fromfd(int iSockFd); 185 | 186 | struct tcp_table *tcpInstance(void); 187 | struct tcp_stream * tcp_stream_search(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport); 188 | 189 | // socket api 190 | int nsocket(__attribute__((unused)) int domain, int type, __attribute__((unused)) int protocol); 191 | int nbind(int sockfd, const struct sockaddr *addr, __attribute__((unused)) socklen_t addrlen); 192 | int nlisten(int sockfd, __attribute__((unused)) int backlog); 193 | int naccept(int sockfd, struct sockaddr *addr, __attribute__((unused)) socklen_t *addrlen); 194 | ssize_t nsend(int sockfd, const void *buf, size_t len,__attribute__((unused)) int flags); 195 | ssize_t nrecv(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags); 196 | ssize_t nrecvfrom(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags, 197 | struct sockaddr *src_addr, __attribute__((unused)) socklen_t *addrlen); 198 | ssize_t nsendto(int sockfd, const void *buf, size_t len, __attribute__((unused)) int flags, 199 | const struct sockaddr *dest_addr, __attribute__((unused)) socklen_t addrlen); 200 | int nclose(int fd); 201 | 202 | // epoll 203 | int epoll_event_callback(struct eventpoll *ep, int sockid, uint32_t event); 204 | int nepoll_create(int size); 205 | int nepoll_ctl(int epfd, int op, int sockid, struct epoll_event *event); 206 | int nepoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); 207 | 208 | 209 | #endif -------------------------------------------------------------------------------- /netfamily.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "common.h" 6 | #include "tcp.h" 7 | #include "udp.h" 8 | 9 | #define MAKE_IPV4_ADDR(a, b, c, d) (a + (b<<8) + (c<<16) + (d<<24)) 10 | 11 | static uint32_t gLocalIp = MAKE_IPV4_ADDR(192, 168, 100, 77); 12 | 13 | struct rte_ether_addr g_stCpuMac; 14 | struct rte_kni *g_pstKni; // todo:后续将全局变量统一初始化,不再使用getInstance() 15 | struct St_InOut_Ring *g_pstRingIns = NULL; // todo:后续将全局变量统一初始化,不再使用getInstance() 16 | struct localhost *g_pstHost = NULL; // todo:后续将全局变量统一初始化,不再使用getInstance() 17 | struct arp_table *g_pstArpTbl = NULL; // todo:后续将全局变量统一初始化,不再使用getInstance() 18 | struct tcp_table *g_pstTcpTbl = NULL; // todo:后续将全局变量统一初始化,不再使用getInstance() 19 | 20 | unsigned char g_aucDefaultArpMac[RTE_ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 21 | 22 | unsigned char g_ucFdTable[D_MAX_FD_COUNT] = {0}; 23 | 24 | static struct St_InOut_Ring *ringInstance(void) 25 | { 26 | if (g_pstRingIns == NULL) 27 | { 28 | g_pstRingIns = rte_malloc("in/out ring", sizeof(struct St_InOut_Ring), 0); 29 | memset(g_pstRingIns, 0, sizeof(struct St_InOut_Ring)); 30 | } 31 | 32 | return g_pstRingIns; 33 | } 34 | 35 | void ng_init_port(struct rte_mempool *pstMbufPoolPub) 36 | { 37 | unsigned int uiPortsNum; 38 | const int iRxQueueNum = 1; 39 | const int iTxQueueNum = 1; 40 | int iRet; 41 | struct rte_eth_dev_info stDevInfo; 42 | struct rte_eth_txconf stTxConf; 43 | struct rte_eth_conf stPortConf = // 端口配置信息 44 | { 45 | .rxmode = {.max_rx_pkt_len = 1518 } // RTE_ETHER_MAX_LEN = 1518 46 | }; 47 | 48 | uiPortsNum = rte_eth_dev_count_avail(); 49 | if (uiPortsNum == 0) 50 | rte_exit(EXIT_FAILURE, "No Supported eth found\n"); 51 | 52 | rte_eth_dev_info_get(D_PORT_ID, &stDevInfo); 53 | 54 | // 配置以太网设备 55 | rte_eth_dev_configure(D_PORT_ID, iRxQueueNum, iTxQueueNum, &stPortConf); 56 | 57 | iRet = rte_eth_rx_queue_setup(D_PORT_ID, 0 , 1024, rte_eth_dev_socket_id(D_PORT_ID), NULL, pstMbufPoolPub); 58 | if(iRet < 0) 59 | rte_exit(EXIT_FAILURE, "Could not setup RX queue!\n"); 60 | 61 | stTxConf = stDevInfo.default_txconf; 62 | stTxConf.offloads = stPortConf.txmode.offloads; 63 | iRet = rte_eth_tx_queue_setup(D_PORT_ID, 0 , 1024, rte_eth_dev_socket_id(D_PORT_ID), &stTxConf); 64 | if (iRet < 0) 65 | rte_exit(EXIT_FAILURE, "Could not setup TX queue\n"); 66 | 67 | if (rte_eth_dev_start(D_PORT_ID) < 0 ) 68 | rte_exit(EXIT_FAILURE, "Could not start\n"); 69 | 70 | rte_eth_promiscuous_enable(D_PORT_ID); 71 | } 72 | 73 | static int ng_config_network_if(uint16_t port_id, unsigned char if_up) { 74 | 75 | if (!rte_eth_dev_is_valid_port(port_id)) { 76 | return -EINVAL; 77 | } 78 | 79 | int ret = 0; 80 | if (if_up) { 81 | 82 | rte_eth_dev_stop(port_id); 83 | ret = rte_eth_dev_start(port_id); 84 | 85 | } else { 86 | 87 | rte_eth_dev_stop(port_id); 88 | 89 | } 90 | 91 | if (ret < 0) { 92 | printf("Failed to start port : %d\n", port_id); 93 | } 94 | 95 | return 0; 96 | } 97 | 98 | static struct rte_kni *ng_alloc_kni(struct rte_mempool *mbuf_pool) { 99 | 100 | struct rte_kni *kni_hanlder = NULL; 101 | 102 | struct rte_kni_conf conf; 103 | memset(&conf, 0, sizeof(conf)); 104 | 105 | snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", D_PORT_ID); 106 | conf.group_id = D_PORT_ID; 107 | conf.mbuf_size = D_MAX_PACKET_SIZE; 108 | rte_eth_macaddr_get(D_PORT_ID, (struct rte_ether_addr *)conf.mac_addr); 109 | rte_eth_dev_get_mtu(D_PORT_ID, &conf.mtu); 110 | 111 | // print_ethaddr("ng_alloc_kni: ", (struct ether_addr *)conf.mac_addr); 112 | 113 | /* 114 | struct rte_eth_dev_info dev_info; 115 | memset(&dev_info, 0, sizeof(dev_info)); 116 | rte_eth_dev_info_get(D_PORT_ID, &dev_info); 117 | */ 118 | 119 | 120 | struct rte_kni_ops ops; 121 | memset(&ops, 0, sizeof(ops)); 122 | 123 | ops.port_id = D_PORT_ID; 124 | ops.config_network_if = ng_config_network_if; 125 | 126 | kni_hanlder = rte_kni_alloc(mbuf_pool, &conf, &ops); 127 | if (!kni_hanlder) { 128 | rte_exit(EXIT_FAILURE, "Failed to create kni for port : %d\n", D_PORT_ID); 129 | } 130 | 131 | return kni_hanlder; 132 | } 133 | 134 | static int pkt_process(void *arg) 135 | { 136 | struct rte_mempool *pstMbufPool; 137 | int iRxNum; 138 | int i; 139 | struct rte_ether_hdr *pstEthHdr; 140 | struct rte_arp_hdr *pstArpHdr; 141 | struct rte_ipv4_hdr *pstIpHdr; 142 | 143 | pstMbufPool = (struct rte_mempool *)arg; 144 | while(1) 145 | { 146 | struct rte_mbuf *pstMbuf[32]; 147 | iRxNum = rte_ring_mc_dequeue_burst(g_pstRingIns->pstInRing, (void**)pstMbuf, D_BURST_SIZE, NULL); 148 | 149 | if(iRxNum <= 0) 150 | continue; 151 | 152 | for(i = 0; i < iRxNum; ++i) 153 | { 154 | pstEthHdr = rte_pktmbuf_mtod_offset(pstMbuf[i], struct rte_ether_hdr *, 0); 155 | 156 | if (pstEthHdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)){ 157 | pstArpHdr = rte_pktmbuf_mtod_offset(pstMbuf[i], struct rte_arp_hdr *, 158 | sizeof(struct rte_ether_hdr)); 159 | 160 | struct in_addr addr; 161 | addr.s_addr = pstArpHdr->arp_data.arp_tip; 162 | printf("arp ---> src: %s ", inet_ntoa(addr)); 163 | 164 | addr.s_addr = gLocalIp; 165 | printf(" local: %s \n", inet_ntoa(addr)); 166 | 167 | if (pstArpHdr->arp_data.arp_tip == gLocalIp){ 168 | ng_arp_entry_insert(pstIpHdr->src_addr, pstEthHdr->s_addr.addr_bytes); 169 | } 170 | } 171 | 172 | if (pstEthHdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) //IPv4: 0800 173 | { 174 | pstIpHdr = rte_pktmbuf_mtod_offset(pstMbuf[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); 175 | 176 | // 维护一个arp表 177 | // ng_arp_entry_insert(pstIpHdr->src_addr, pstEthHdr->s_addr.addr_bytes); 178 | if(pstIpHdr->next_proto_id == IPPROTO_UDP) // udp 179 | { 180 | // udp process 181 | udp_process(pstMbuf[i]); 182 | } 183 | else if(pstIpHdr->next_proto_id == IPPROTO_TCP) // tcp 184 | { 185 | // printf("tcp_process ---\n"); 186 | tcp_process(pstMbuf[i]); 187 | } 188 | else 189 | { 190 | rte_kni_tx_burst(g_pstKni, pstMbuf, iRxNum); 191 | // printf("tcp/udp --> rte_kni_handle_request\n"); 192 | } 193 | } 194 | else 195 | { 196 | // ifconfig vEth0 192.168.181.169 up 197 | rte_kni_tx_burst(g_pstKni, pstMbuf, iRxNum); 198 | // printf("ip --> rte_kni_handle_request\n"); 199 | } 200 | } 201 | 202 | rte_kni_handle_request(g_pstKni); 203 | 204 | // to send 205 | udp_out(pstMbufPool); 206 | tcp_out(pstMbufPool); 207 | } 208 | return 0; 209 | } 210 | 211 | int udp_server_entry(__attribute__((unused)) void *arg) 212 | { 213 | int iConnfd; 214 | struct sockaddr_in stLocalAddr, stClientAddr; 215 | socklen_t uiAddrLen = sizeof(stClientAddr);; 216 | char acBuf[D_UDP_BUFFER_SIZE] = {0}; 217 | 218 | iConnfd = nsocket(AF_INET, SOCK_DGRAM, 0); 219 | if (iConnfd == -1) 220 | { 221 | printf("nsocket failed\n"); 222 | return -1; 223 | } 224 | 225 | memset(&stLocalAddr, 0, sizeof(struct sockaddr_in)); 226 | 227 | stLocalAddr.sin_port = htons(8889); 228 | stLocalAddr.sin_family = AF_INET; 229 | stLocalAddr.sin_addr.s_addr = inet_addr("192.168.100.77"); 230 | 231 | nbind(iConnfd, (struct sockaddr*)&stLocalAddr, sizeof(stLocalAddr)); 232 | 233 | while (1) 234 | { 235 | if (nrecvfrom(iConnfd, acBuf, D_UDP_BUFFER_SIZE, 0, 236 | (struct sockaddr*)&stClientAddr, &uiAddrLen) < 0) 237 | { 238 | continue; 239 | } 240 | else 241 | { 242 | printf("recv from %s:%d, data:%s\n", inet_ntoa(stClientAddr.sin_addr), 243 | ntohs(stClientAddr.sin_port), acBuf); 244 | nsendto(iConnfd, acBuf, strlen(acBuf), 0, 245 | (struct sockaddr*)&stClientAddr, sizeof(stClientAddr)); 246 | } 247 | } 248 | 249 | nclose(iConnfd); 250 | 251 | return 0; 252 | } 253 | 254 | #define BUFFER_SIZE 1024 255 | 256 | #ifdef ENABLE_SINGLE_EPOLL 257 | 258 | int tcp_server_entry(__attribute__((unused)) void *arg) 259 | { 260 | int listenfd = nsocket(AF_INET, SOCK_STREAM, 0); 261 | if (listenfd == -1) 262 | { 263 | return -1; 264 | } 265 | 266 | struct sockaddr_in servaddr; 267 | memset(&servaddr, 0, sizeof(struct sockaddr)); 268 | servaddr.sin_family = AF_INET; 269 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 270 | servaddr.sin_port = htons(9999); 271 | nbind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); 272 | 273 | nlisten(listenfd, 10); 274 | 275 | int epfd = nepoll_create(1); 276 | struct epoll_event ev, events[1024]; 277 | ev.data.fd = listenfd; 278 | ev.events |= EPOLLIN; 279 | nepoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev); 280 | 281 | char buff[BUFFER_SIZE] = {'\0'}; 282 | while(1) 283 | { 284 | int nready = nepoll_wait(epfd, events, 1024, 5); 285 | if(nready < 0) 286 | continue; 287 | 288 | for(int i = 0; i < nready; ++i) 289 | { 290 | int fd = events[i].data.fd; 291 | if(listenfd == fd) 292 | { 293 | struct sockaddr_in client; 294 | socklen_t len = sizeof(client); 295 | int connfd = naccept(listenfd, (struct sockaddr*)&client, &len); 296 | 297 | struct epoll_event ev; 298 | ev.events = EPOLLIN; 299 | ev.data.fd = connfd; 300 | nepoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev); 301 | } 302 | else 303 | { 304 | int n = nrecv(fd, buff, BUFFER_SIZE, 0); //block 305 | if (n > 0) 306 | { 307 | printf(" arno --> recv: %s\n", buff); 308 | nsend(fd, buff, n, 0); 309 | } 310 | else 311 | { 312 | printf("error: %s\n", strerror(errno)); 313 | nepoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); 314 | nclose(fd); 315 | } 316 | } 317 | } 318 | } 319 | 320 | return 0; 321 | } 322 | 323 | #else 324 | int tcp_server_entry(__attribute__((unused)) void *arg) 325 | { 326 | int listenfd; 327 | int iRet = -1; 328 | struct sockaddr_in servaddr; 329 | 330 | listenfd = nsocket(AF_INET, SOCK_STREAM, 0); 331 | if (listenfd == -1) 332 | { 333 | printf("[%s][%d] nsocket error!\n", __FUNCTION__, __LINE__); 334 | return -1; 335 | } 336 | 337 | memset(&servaddr, 0, sizeof(struct sockaddr)); 338 | servaddr.sin_family = AF_INET; 339 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 340 | servaddr.sin_port = htons(9999); 341 | iRet = nbind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); 342 | if(iRet < 0) 343 | { 344 | printf("nbind error!\n"); 345 | return -1; 346 | } 347 | 348 | nlisten(listenfd, 10); 349 | 350 | while (1) 351 | { 352 | struct sockaddr_in client; 353 | socklen_t len = sizeof(client); 354 | int connfd = naccept(listenfd, (struct sockaddr*)&client, &len); 355 | 356 | char buff[D_TCP_BUFFER_SIZE] = {0}; 357 | while (1) 358 | { 359 | int n = nrecv(connfd, buff, D_TCP_BUFFER_SIZE, 0); //block 360 | if (n > 0) 361 | { 362 | printf("recv: %s\n", buff); 363 | nsend(connfd, buff, n, 0); 364 | } 365 | else if (n == 0) 366 | { 367 | printf("nclose()\n"); 368 | nclose(connfd); 369 | break; 370 | } 371 | else 372 | { //nonblock 373 | 374 | } 375 | } 376 | 377 | } 378 | nclose(listenfd); 379 | 380 | return 0; 381 | } 382 | 383 | #endif 384 | 385 | int main(int argc, char *argv[]) 386 | { 387 | struct rte_mempool *pstMbufPoolPub; 388 | struct St_InOut_Ring *pstRing; 389 | struct rte_mbuf *pstRecvMbuf[32] = {NULL}; 390 | struct rte_mbuf *pstSendMbuf[32] = {NULL}; 391 | int iRxNum; 392 | int iTotalNum; 393 | int iOffset; 394 | int iTxNum; 395 | 396 | unsigned int uiCoreId; 397 | 398 | if(rte_eal_init(argc, argv) < 0) 399 | rte_exit(EXIT_FAILURE, "Error with EAL init\n"); 400 | 401 | pstMbufPoolPub = rte_pktmbuf_pool_create("MBUF_POOL_PUB", D_NUM_MBUFS, 0, 0, 402 | RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 403 | if(pstMbufPoolPub == NULL) 404 | { 405 | printf("rte_errno = %x, errmsg = %s\n", rte_errno, rte_strerror(rte_errno)); 406 | return -1; 407 | } 408 | 409 | if (rte_kni_init(D_PORT_ID) < 0) 410 | rte_exit(EXIT_FAILURE, "kni init failed\n"); 411 | 412 | ng_init_port(pstMbufPoolPub); 413 | g_pstKni = ng_alloc_kni(pstMbufPoolPub); 414 | 415 | rte_eth_macaddr_get(D_PORT_ID, &g_stCpuMac); 416 | 417 | pstRing = ringInstance(); 418 | if(pstRing == NULL) 419 | rte_exit(EXIT_FAILURE, "ring buffer init failed\n"); 420 | 421 | pstRing->pstInRing = rte_ring_create("in ring", D_RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 422 | pstRing->pstOutRing = rte_ring_create("out ring", D_RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 423 | 424 | uiCoreId = rte_lcore_id(); 425 | 426 | uiCoreId = rte_get_next_lcore(uiCoreId, 1, 0); 427 | rte_eal_remote_launch(pkt_process, pstMbufPoolPub, uiCoreId); 428 | 429 | uiCoreId = rte_get_next_lcore(uiCoreId, 1, 0); 430 | rte_eal_remote_launch(udp_server_entry, pstMbufPoolPub, uiCoreId); 431 | 432 | // uiCoreId = rte_get_next_lcore(uiCoreId, 1, 0); 433 | // rte_eal_remote_launch(tcp_server_entry, pstMbufPoolPub, uiCoreId); 434 | 435 | while (1) 436 | { 437 | // rx 438 | iRxNum = rte_eth_rx_burst(D_PORT_ID, 0, pstRecvMbuf, D_BURST_SIZE); 439 | if(iRxNum > 0) 440 | rte_ring_sp_enqueue_burst(pstRing->pstInRing, (void**)pstRecvMbuf, iRxNum, NULL); 441 | 442 | // tx 443 | iTotalNum = rte_ring_sc_dequeue_burst(pstRing->pstOutRing, (void**)pstSendMbuf, D_BURST_SIZE, NULL); 444 | if(iTotalNum > 0) 445 | { 446 | iOffset = 0; 447 | while(iOffset < iTotalNum) 448 | { 449 | iTxNum = rte_eth_tx_burst(D_PORT_ID, 0, &pstSendMbuf[iOffset], iTotalNum - iOffset); 450 | if(iTxNum > 0) 451 | iOffset += iTxNum; 452 | } 453 | } 454 | } 455 | 456 | } 457 | -------------------------------------------------------------------------------- /tcp.c: -------------------------------------------------------------------------------- 1 | #include "tcp.h" 2 | 3 | static struct tcp_stream * tcp_stream_create(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport) 4 | { 5 | char acBuf[32] = {0}; 6 | unsigned int uiSeed; 7 | struct tcp_stream *pstStream = rte_malloc("tcp_stream", sizeof(struct tcp_stream), 0); 8 | if (pstStream == NULL) 9 | return NULL; 10 | 11 | <<<<<<< HEAD 12 | printf("tcp_stream_create!\n"); 13 | 14 | ======= 15 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 16 | pstStream->sip = sip; 17 | pstStream->dip = dip; 18 | pstStream->sport = sport; 19 | pstStream->dport = dport; 20 | pstStream->protocol = IPPROTO_TCP; 21 | pstStream->fd = -1; 22 | pstStream->status = TCP_STATUS_LISTEN; 23 | 24 | sprintf(acBuf, "sndbuf%x%d", sip, sport); 25 | pstStream->sndbuf = rte_ring_create(acBuf, D_RING_SIZE, rte_socket_id(), 0); 26 | sprintf(acBuf, "rcvbuf%x%d", sip, sport); 27 | pstStream->rcvbuf = rte_ring_create(acBuf, D_RING_SIZE, rte_socket_id(), 0); 28 | 29 | // seq num 30 | uiSeed = time(NULL); 31 | pstStream->snd_nxt = rand_r(&uiSeed) % D_TCP_MAX_SEQ; 32 | rte_memcpy(pstStream->localmac, &g_stCpuMac, RTE_ETHER_ADDR_LEN); 33 | 34 | pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER; 35 | rte_memcpy(&pstStream->cond, &blank_cond, sizeof(pthread_cond_t)); 36 | 37 | pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER; 38 | rte_memcpy(&pstStream->mutex, &blank_mutex, sizeof(pthread_mutex_t)); 39 | 40 | return pstStream; 41 | } 42 | 43 | static int tcp_handle_listen(struct tcp_stream *pstStream, struct rte_tcp_hdr *pstTcphdr, 44 | struct rte_ipv4_hdr *pstIphdr) 45 | { 46 | if (pstTcphdr->tcp_flags & RTE_TCP_SYN_FLAG) 47 | { 48 | if (pstStream->status == TCP_STATUS_LISTEN) 49 | { 50 | struct tcp_stream *pstSyn = tcp_stream_create(pstIphdr->src_addr, pstIphdr->dst_addr, 51 | pstTcphdr->src_port, pstTcphdr->dst_port); 52 | LL_ADD(pstSyn, g_pstTcpTbl->tcb_set); 53 | 54 | struct tcp_fragment *pstFragment = rte_malloc("tcp_fragment", sizeof(struct tcp_fragment), 0); 55 | if (pstFragment == NULL) 56 | return -1; 57 | memset(pstFragment, 0, sizeof(struct tcp_fragment)); 58 | 59 | pstFragment->sport = pstTcphdr->dst_port; 60 | pstFragment->dport = pstTcphdr->src_port; 61 | 62 | struct in_addr addr; 63 | addr.s_addr = pstSyn->sip; 64 | printf("tcp ---> src: %s:%d ", inet_ntoa(addr), ntohs(pstTcphdr->src_port)); 65 | 66 | addr.s_addr = pstSyn->dip; 67 | printf(" ---> dst: %s:%d \n", inet_ntoa(addr), ntohs(pstTcphdr->dst_port)); 68 | 69 | pstFragment->seqnum = pstSyn->snd_nxt; 70 | pstFragment->acknum = ntohl(pstTcphdr->sent_seq) + 1; 71 | pstSyn->rcv_nxt = pstFragment->acknum; 72 | 73 | pstFragment->tcp_flags = (RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG); 74 | pstFragment->windows = D_TCP_INITIAL_WINDOW; 75 | pstFragment->hdrlen_off = 0x50; 76 | 77 | pstFragment->data = NULL; 78 | pstFragment->length = 0; 79 | 80 | rte_ring_mp_enqueue(pstSyn->sndbuf, pstFragment); 81 | 82 | pstSyn->status = TCP_STATUS_SYN_RCVD; 83 | } 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | static int tcp_handle_syn_rcvd(struct tcp_stream *pstStream, struct rte_tcp_hdr *pstTcphdr) 90 | { 91 | if (pstTcphdr->tcp_flags & RTE_TCP_ACK_FLAG) 92 | { 93 | if (pstStream->status == TCP_STATUS_SYN_RCVD) 94 | { 95 | uint32_t acknum = ntohl(pstTcphdr->recv_ack); 96 | if (acknum == pstStream->snd_nxt + 1) 97 | { 98 | printf("ack response success!\n"); 99 | } 100 | else 101 | { 102 | printf("ack response error! \n"); 103 | } 104 | 105 | pstStream->status = TCP_STATUS_ESTABLISHED; 106 | 107 | // accept 108 | struct tcp_stream *pstListener = tcp_stream_search(0, 0, 0, pstStream->dport); 109 | if (pstListener == NULL) 110 | { 111 | rte_exit(EXIT_FAILURE, "tcp_stream_search failed\n"); 112 | } 113 | 114 | pthread_mutex_lock(&pstListener->mutex); 115 | pthread_cond_signal(&pstListener->cond); // 唤醒accept中的等待 116 | pthread_mutex_unlock(&pstListener->mutex); 117 | 118 | #if ENABLE_SINGLE_EPOLL 119 | 120 | <<<<<<< HEAD 121 | epoll_event_callback(g_pstTcpTbl->ep, pstListener->fd, EPOLLIN); 122 | ======= 123 | struct ng_tcp_table *table = tcpInstance(); 124 | epoll_event_callback(table->ep, listener->fd, EPOLLIN); 125 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 126 | #endif 127 | } 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | static int ng_tcp_enqueue_recvbuffer(struct tcp_stream *pstStream, struct rte_tcp_hdr *pstTcphdr, int iTcplen) 134 | { 135 | struct tcp_fragment *pstFragment = rte_malloc("tcp_fragment", sizeof(struct tcp_fragment), 0); 136 | if (pstFragment == NULL) 137 | return -1; 138 | 139 | memset(pstFragment, 0, sizeof(struct tcp_fragment)); 140 | pstFragment->dport = ntohs(pstTcphdr->dst_port); 141 | pstFragment->sport = ntohs(pstTcphdr->src_port); 142 | 143 | // data_off:前4位表示包头到数据域起始位置之间的大小 144 | // 每一位表示4Byte,最大表示为 15*4Byte 大小 145 | uint8_t hdrlen = pstTcphdr->data_off >> 4; 146 | int payloadlen = iTcplen - hdrlen * 4; // 数据域长度 147 | <<<<<<< HEAD 148 | // if (pstTcphdr->tcp_flags & RTE_TCP_FIN_FLAG) 149 | // printf("iTcplen = %d\n", iTcplen); 150 | // printf("payloadlen = %d\n", payloadlen); 151 | 152 | ======= 153 | if (pstTcphdr->tcp_flags & RTE_TCP_FIN_FLAG) 154 | printf("iTcplen = %d\n", iTcplen); 155 | printf("payloadlen = %d\n", payloadlen); 156 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 157 | if(payloadlen > 0) 158 | { 159 | uint8_t *payload = (uint8_t*)pstTcphdr + hdrlen * 4; 160 | 161 | pstFragment->data = rte_malloc("unsigned char *", payloadlen+1, 0); 162 | if (pstFragment->data == NULL) 163 | { 164 | rte_free(pstFragment); 165 | return -1; 166 | } 167 | 168 | memset(pstFragment->data, 0, payloadlen + 1); 169 | rte_memcpy(pstFragment->data, payload, payloadlen); 170 | pstFragment->length = payloadlen; 171 | } 172 | else if(payloadlen == 0) 173 | { 174 | pstFragment->length = 0; 175 | pstFragment->data = NULL; 176 | } 177 | 178 | rte_ring_mp_enqueue(pstStream->rcvbuf, pstFragment); 179 | 180 | pthread_mutex_lock(&pstStream->mutex); 181 | pthread_cond_signal(&pstStream->cond); 182 | pthread_mutex_unlock(&pstStream->mutex); 183 | 184 | return 0; 185 | } 186 | 187 | static int ng_tcp_send_ackpkt(struct tcp_stream *pstStream, struct rte_tcp_hdr *pstTcphdr) 188 | { 189 | struct tcp_fragment *pstAckFrag = rte_malloc("tcp_fragment", sizeof(struct tcp_fragment), 0); 190 | if (pstAckFrag == NULL) 191 | return -1; 192 | 193 | memset(pstAckFrag, 0, sizeof(struct tcp_fragment)); 194 | pstAckFrag->dport = pstTcphdr->src_port; 195 | pstAckFrag->sport = pstTcphdr->dst_port; 196 | 197 | // remote 198 | 199 | <<<<<<< HEAD 200 | printf("tcp_send_ackpkt: %d, %d\n", ntohs(pstStream->rcv_nxt), ntohs(pstTcphdr->sent_seq)); 201 | ======= 202 | printf("tcp_send_ackpkt: %d, %d\n", pstStream->rcv_nxt, ntohs(pstTcphdr->sent_seq)); 203 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 204 | 205 | pstAckFrag->acknum = pstStream->rcv_nxt; 206 | pstAckFrag->seqnum = pstStream->snd_nxt; 207 | pstAckFrag->tcp_flags = RTE_TCP_ACK_FLAG; 208 | pstAckFrag->windows = D_TCP_INITIAL_WINDOW; 209 | pstAckFrag->hdrlen_off = 0x50; 210 | pstAckFrag->data = NULL; 211 | pstAckFrag->length = 0; 212 | 213 | rte_ring_mp_enqueue(pstStream->sndbuf, pstAckFrag); 214 | 215 | return 0; 216 | } 217 | 218 | static int tcp_handle_established(struct tcp_stream *pstStream, struct rte_tcp_hdr *pstTcphdr, int iTcplen) 219 | { 220 | if (pstTcphdr->tcp_flags & RTE_TCP_SYN_FLAG) // 异常:收到对端的SYN重传包 221 | { 222 | <<<<<<< HEAD 223 | // printf("RTE_TCP_SYN_FLAG\n"); 224 | ======= 225 | printf("RTE_TCP_SYN_FLAG\n"); 226 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 227 | } 228 | if(pstTcphdr->tcp_flags & RTE_TCP_PSH_FLAG) // 收到对端的数据包,TCP数据域不为0 229 | { 230 | ng_tcp_enqueue_recvbuffer(pstStream, pstTcphdr, iTcplen); 231 | 232 | #if ENABLE_SINGLE_EPOLL 233 | <<<<<<< HEAD 234 | epoll_event_callback(g_pstTcpTbl->ep, pstStream->fd, EPOLLIN); 235 | ======= 236 | struct ng_tcp_table *table = tcpInstance(); 237 | epoll_event_callback(table->ep, stream->fd, EPOLLIN); 238 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 239 | #endif 240 | 241 | uint8_t hdrlen = pstTcphdr->data_off >> 4; 242 | int payloadlen = iTcplen - hdrlen * 4; 243 | 244 | <<<<<<< HEAD 245 | pstStream->rcv_nxt = pstStream->rcv_nxt + payloadlen; // ntohl(pstStream->rcv_nxt + payloadlen); 246 | ======= 247 | pstStream->rcv_nxt = ntohl(pstStream->rcv_nxt + payloadlen); 248 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 249 | pstStream->snd_nxt = ntohl(pstTcphdr->recv_ack); 250 | 251 | ng_tcp_send_ackpkt(pstStream, pstTcphdr); 252 | } 253 | if(pstTcphdr->tcp_flags & RTE_TCP_ACK_FLAG) // 异常:收到对端的ACK重传包 254 | { 255 | <<<<<<< HEAD 256 | // printf("RTE_TCP_ACK_FLAG\n"); 257 | ======= 258 | printf("RTE_TCP_ACK_FLAG\n"); 259 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 260 | } 261 | if (pstTcphdr->tcp_flags & RTE_TCP_FIN_FLAG) // 对端关闭连接 262 | { 263 | printf("RTE_TCP_FIN_FLAG\n"); 264 | pstStream->status = TCP_STATUS_CLOSE_WAIT; 265 | 266 | <<<<<<< HEAD 267 | // 通知recv函数接收数据包 268 | ng_tcp_enqueue_recvbuffer(pstStream, pstTcphdr, pstTcphdr->data_off >> 4); 269 | 270 | #if ENABLE_SINGLE_EPOLL 271 | epoll_event_callback(g_pstTcpTbl->ep, pstStream->fd, EPOLLIN); 272 | #endif 273 | // send ack ptk 274 | pstStream->rcv_nxt = pstStream->rcv_nxt + 1;// ntohl(pstStream->rcv_nxt + 1); 275 | pstStream->snd_nxt = ntohl(pstTcphdr->recv_ack); 276 | 277 | // 发送ACK响应至对端 278 | ng_tcp_send_ackpkt(pstStream, pstTcphdr); 279 | ======= 280 | ng_tcp_enqueue_recvbuffer(pstStream, pstTcphdr, pstTcphdr->data_off >> 4); 281 | 282 | #if ENABLE_SINGLE_EPOLL 283 | 284 | struct ng_tcp_table *table = tcpInstance(); 285 | epoll_event_callback(table->ep, stream->fd, EPOLLIN); 286 | 287 | #endif 288 | // send ack ptk 289 | pstStream->rcv_nxt = ntohl(pstStream->rcv_nxt + 1); 290 | pstStream->snd_nxt = ntohl(pstTcphdr->recv_ack); 291 | 292 | ng_tcp_send_ackpkt(pstStream, pstTcphdr); 293 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 294 | } 295 | 296 | return 0; 297 | } 298 | 299 | static int tcp_handle_close_wait(struct tcp_stream *stream, struct rte_tcp_hdr *tcphdr) 300 | { 301 | if (tcphdr->tcp_flags & RTE_TCP_FIN_FLAG) 302 | { 303 | if (stream->status == TCP_STATUS_CLOSE_WAIT) 304 | { 305 | 306 | } 307 | } 308 | 309 | return 0; 310 | } 311 | 312 | static int tcp_handle_last_ack(struct tcp_stream *stream, struct rte_tcp_hdr *tcphdr) 313 | { 314 | if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) 315 | { 316 | if (stream->status == TCP_STATUS_LAST_ACK) 317 | { 318 | stream->status = TCP_STATUS_CLOSED; 319 | printf("tcp_handle_last_ack\n"); 320 | 321 | LL_REMOVE(stream, g_pstTcpTbl->tcb_set); 322 | 323 | rte_ring_free(stream->sndbuf); 324 | rte_ring_free(stream->rcvbuf); 325 | 326 | rte_free(stream); 327 | } 328 | } 329 | 330 | return 0; 331 | } 332 | 333 | int tcp_process(struct rte_mbuf *pstTcpMbuf) 334 | { 335 | struct rte_ipv4_hdr *pstIpHdr; 336 | struct rte_tcp_hdr *pstTcpHdr; 337 | struct tcp_stream *pstTcpStream; 338 | <<<<<<< HEAD 339 | unsigned short usOldTcpCkSum; 340 | ======= 341 | unsigned short usOldTcpCkSum; 342 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 343 | unsigned short usNewTcpCkSum; 344 | 345 | pstIpHdr = rte_pktmbuf_mtod_offset(pstTcpMbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); 346 | pstTcpHdr = (struct rte_tcp_hdr *)(pstIpHdr + 1); 347 | 348 | // 校验和 349 | usOldTcpCkSum = pstTcpHdr->cksum; 350 | pstTcpHdr->cksum = 0; 351 | usNewTcpCkSum = rte_ipv4_udptcp_cksum(pstIpHdr, pstTcpHdr); 352 | if (usOldTcpCkSum != usNewTcpCkSum) 353 | { 354 | printf("cksum: %x, tcp cksum: %x\n", usOldTcpCkSum, usNewTcpCkSum); 355 | rte_pktmbuf_free(pstTcpMbuf); 356 | return -1; 357 | } 358 | 359 | // 搜索涵盖了半连接队列和全连接队列 360 | // 搜索的stream,根据status状态调用对应处理函数 361 | pstTcpStream = tcp_stream_search(pstIpHdr->src_addr, pstIpHdr->dst_addr, 362 | pstTcpHdr->src_port, pstTcpHdr->dst_port); 363 | if (pstTcpStream == NULL) 364 | { 365 | <<<<<<< HEAD 366 | ======= 367 | puts("no tcb create!"); 368 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 369 | rte_pktmbuf_free(pstTcpMbuf); 370 | return -2; 371 | } 372 | 373 | switch(pstTcpStream->status) 374 | { 375 | case TCP_STATUS_CLOSED: //client 376 | break; 377 | 378 | case TCP_STATUS_LISTEN: // server 379 | tcp_handle_listen(pstTcpStream, pstTcpHdr, pstIpHdr); 380 | break; 381 | 382 | case TCP_STATUS_SYN_RCVD: // server 383 | tcp_handle_syn_rcvd(pstTcpStream, pstTcpHdr); 384 | break; 385 | 386 | case TCP_STATUS_SYN_SENT: // client 387 | break; 388 | 389 | case TCP_STATUS_ESTABLISHED: // server | client 390 | { 391 | int tcplen = ntohs(pstIpHdr->total_length) - sizeof(struct rte_ipv4_hdr); 392 | tcp_handle_established(pstTcpStream, pstTcpHdr, tcplen); 393 | printf("tcplen = %d\n", tcplen); 394 | break; 395 | } 396 | case TCP_STATUS_FIN_WAIT_1: // ~client 397 | break; 398 | 399 | case TCP_STATUS_FIN_WAIT_2: // ~client 400 | break; 401 | 402 | case TCP_STATUS_CLOSING: // ~client 403 | break; 404 | 405 | case TCP_STATUS_TIME_WAIT: // ~client 406 | break; 407 | 408 | case TCP_STATUS_CLOSE_WAIT: // ~server 409 | tcp_handle_close_wait(pstTcpStream, pstTcpHdr); 410 | break; 411 | 412 | case TCP_STATUS_LAST_ACK: // ~server 413 | tcp_handle_last_ack(pstTcpStream, pstTcpHdr); 414 | break; 415 | } 416 | 417 | return 0; 418 | } 419 | 420 | static int ng_encode_tcp_apppkt(uint8_t *msg, uint32_t sip, uint32_t dip, 421 | uint8_t *srcmac, uint8_t *dstmac, struct tcp_fragment *fragment, unsigned int total_len) 422 | { 423 | struct rte_ether_hdr *pstEth; 424 | struct rte_ipv4_hdr *pstIp; 425 | struct rte_tcp_hdr *pstTcp; 426 | 427 | // 1 ethhdr 428 | pstEth = (struct rte_ether_hdr *)msg; 429 | rte_memcpy(pstEth->s_addr.addr_bytes, srcmac, RTE_ETHER_ADDR_LEN); 430 | rte_memcpy(pstEth->d_addr.addr_bytes, dstmac, RTE_ETHER_ADDR_LEN); 431 | pstEth->ether_type = htons(RTE_ETHER_TYPE_IPV4); 432 | 433 | // 2 iphdr 434 | pstIp = (struct rte_ipv4_hdr *)(pstEth + 1); 435 | pstIp->version_ihl = 0x45; 436 | pstIp->type_of_service = 0; 437 | pstIp->total_length = htons(total_len - sizeof(struct rte_ether_hdr)); 438 | pstIp->packet_id = 0; 439 | pstIp->fragment_offset = 0; 440 | pstIp->time_to_live = 64; // ttl = 64 441 | pstIp->next_proto_id = IPPROTO_TCP; 442 | pstIp->src_addr = sip; 443 | pstIp->dst_addr = dip; 444 | pstIp->hdr_checksum = 0; 445 | pstIp->hdr_checksum = rte_ipv4_cksum(pstIp); 446 | 447 | // 3 tcphdr 448 | pstTcp = (struct rte_tcp_hdr *)(pstIp + 1); 449 | pstTcp->src_port = fragment->sport; 450 | pstTcp->dst_port = fragment->dport; 451 | pstTcp->sent_seq = htonl(fragment->seqnum); 452 | pstTcp->recv_ack = htonl(fragment->acknum); 453 | pstTcp->data_off = fragment->hdrlen_off; 454 | pstTcp->rx_win = fragment->windows; 455 | pstTcp->tcp_urp = fragment->tcp_urp; 456 | pstTcp->tcp_flags = fragment->tcp_flags; 457 | if (fragment->data != NULL) 458 | { 459 | uint8_t *payload = (uint8_t*)(pstTcp + 1) + fragment->optlen * sizeof(uint32_t); 460 | rte_memcpy(payload, fragment->data, fragment->length); 461 | } 462 | pstTcp->cksum = 0; 463 | pstTcp->cksum = rte_ipv4_udptcp_cksum(pstIp, pstTcp); 464 | 465 | return 0; 466 | } 467 | 468 | 469 | static struct rte_mbuf * ng_tcp_pkt(struct rte_mempool *mbuf_pool, uint32_t sip, uint32_t dip, 470 | uint8_t *srcmac, uint8_t *dstmac, struct tcp_fragment *fragment) 471 | { 472 | unsigned int uiTotalLen; 473 | struct rte_mbuf *pstMbuf; 474 | unsigned char *pucPktData; 475 | 476 | uiTotalLen = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr) + 477 | fragment->optlen * sizeof(uint32_t) + fragment->length; 478 | 479 | pstMbuf = rte_pktmbuf_alloc(mbuf_pool); 480 | if (!pstMbuf) 481 | rte_exit(EXIT_FAILURE, "rte_pktmbuf_alloc\n"); 482 | 483 | pstMbuf->pkt_len = uiTotalLen; 484 | pstMbuf->data_len = uiTotalLen; 485 | pucPktData = rte_pktmbuf_mtod(pstMbuf, unsigned char*); 486 | 487 | ng_encode_tcp_apppkt(pucPktData, sip, dip, srcmac, dstmac, fragment, uiTotalLen); 488 | 489 | return pstMbuf; 490 | } 491 | 492 | int tcp_out(struct rte_mempool *pstMbufPool) 493 | { 494 | struct tcp_table *pstTable = tcpInstance(); 495 | struct tcp_stream *pstStream = NULL; 496 | <<<<<<< HEAD 497 | 498 | ======= 499 | 500 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 501 | for(pstStream = pstTable->tcb_set; pstStream != NULL; pstStream = pstStream->next) 502 | { 503 | if(pstStream->sndbuf == NULL) 504 | continue; 505 | 506 | struct tcp_fragment *pstFragment = NULL; 507 | int iSendCnt = rte_ring_mc_dequeue(pstStream->sndbuf, (void**)&pstFragment); 508 | if (iSendCnt < 0) 509 | continue; 510 | 511 | <<<<<<< HEAD 512 | // struct in_addr addr; 513 | // addr.s_addr = pstStream->sip; 514 | // printf("tcp_out ---> src: %s:%d \n", inet_ntoa(addr), ntohs(pstFragment->dport)); 515 | ======= 516 | struct in_addr addr; 517 | addr.s_addr = pstStream->sip; 518 | printf("tcp_out ---> src: %s:%d \n", inet_ntoa(addr), ntohs(pstFragment->dport)); 519 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 520 | 521 | uint8_t *dstmac = ng_get_dst_macaddr(pstStream->sip); // 这里的源ip指的是对端ip 522 | if (dstmac == NULL) // 先广播发个arp包确定对端mac地址 523 | { 524 | <<<<<<< HEAD 525 | printf("ng_send_arp\n"); 526 | ======= 527 | //printf("ng_send_arp\n"); 528 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 529 | struct rte_mbuf *pstArpbuf = ng_send_arp(pstMbufPool, RTE_ARP_OP_REQUEST, g_aucDefaultArpMac, 530 | pstStream->dip, pstStream->sip); 531 | 532 | rte_ring_mp_enqueue_burst(g_pstRingIns->pstOutRing, (void **)&pstArpbuf, 1, NULL); 533 | 534 | rte_ring_mp_enqueue(pstStream->sndbuf, pstFragment); // 将取出的数据再次放入队列 535 | } 536 | else 537 | { 538 | <<<<<<< HEAD 539 | printf("ng_send_data\n"); 540 | ======= 541 | >>>>>>> c472b4b5fbedc52450a9bd050d196d2515ca995f 542 | struct rte_mbuf *pstTcpBuf = ng_tcp_pkt(pstMbufPool, pstStream->dip, pstStream->sip, 543 | pstStream->localmac, dstmac, pstFragment); 544 | 545 | rte_ring_mp_enqueue_burst(g_pstRingIns->pstOutRing, (void **)&pstTcpBuf, 1, NULL); 546 | 547 | if (pstFragment->data != NULL) 548 | rte_free(pstFragment->data); 549 | 550 | rte_free(pstFragment); 551 | } 552 | } 553 | 554 | return 0; 555 | } -------------------------------------------------------------------------------- /common.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "udp.h" 3 | #include "tcp.h" 4 | 5 | 6 | void dbg_print(char *info, unsigned char *dat, int dat_len) 7 | { 8 | int i; 9 | 10 | printf("\n%s:%d\n", info, dat_len); 11 | for (i = 0; i < dat_len; i++) 12 | { 13 | if (i && (i % 16 == 0)) 14 | printf("\n"); 15 | printf("%02x ", dat[i]); 16 | } 17 | printf("\n"); 18 | } 19 | 20 | struct tcp_table *tcpInstance(void) 21 | { 22 | if (g_pstTcpTbl == NULL) 23 | { 24 | g_pstTcpTbl = rte_malloc("tcp_table", sizeof(struct tcp_table), 0); 25 | memset(g_pstTcpTbl, 0, sizeof(struct tcp_table)); 26 | } 27 | return g_pstTcpTbl; 28 | } 29 | 30 | // todo:分割establish和listen为两个函数 31 | struct tcp_stream * tcp_stream_search(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport) 32 | { 33 | struct tcp_table *pstTable = tcpInstance(); 34 | struct tcp_stream *iter = NULL; 35 | 36 | for (iter = pstTable->tcb_set; iter != NULL; iter = iter->next) // established 37 | { 38 | if (iter->sip == sip && iter->dip == dip && 39 | iter->sport == sport && iter->dport == dport) 40 | { 41 | return iter; 42 | } 43 | 44 | } 45 | 46 | for (iter = pstTable->tcb_set; iter != NULL; iter = iter->next) 47 | { 48 | if (iter->dport == dport && iter->status == TCP_STATUS_LISTEN) // listen 49 | { 50 | return iter; 51 | } 52 | } 53 | 54 | return NULL; 55 | } 56 | 57 | // 从全连接队列中取 58 | static struct tcp_stream *get_accept_tcb(uint16_t dport) 59 | { 60 | struct tcp_stream *apt; 61 | for (apt = g_pstTcpTbl->tcb_set; apt != NULL; apt = apt->next) 62 | { 63 | if (dport == apt->dport && apt->fd == -1) 64 | { 65 | return apt; 66 | } 67 | } 68 | 69 | return NULL; 70 | } 71 | 72 | int get_fd_frombitmap(void) 73 | { 74 | int fd = D_DEFAULT_FD_NUM; 75 | for (; fd < D_MAX_FD_COUNT; fd ++) 76 | { 77 | if ((g_ucFdTable[fd/8] & (0x1 << (fd % 8))) == 0) 78 | { 79 | g_ucFdTable[fd/8] |= (0x1 << (fd % 8)); 80 | return fd; 81 | } 82 | } 83 | 84 | return -1; 85 | } 86 | 87 | int set_fd_frombitmap(int fd) 88 | { 89 | if (fd >= D_MAX_FD_COUNT) 90 | return -1; 91 | 92 | g_ucFdTable[fd/8] &= ~(0x1 << (fd % 8)); 93 | 94 | return 0; 95 | } 96 | 97 | struct localhost *get_hostinfo_fromip_port(uint32_t dip, uint16_t port, unsigned char proto) 98 | { 99 | struct localhost *pstHost = NULL; 100 | 101 | for (pstHost = g_pstHost; pstHost != NULL; pstHost = pstHost->next) 102 | { 103 | if (dip == pstHost->localip && port == pstHost->localport && proto == pstHost->protocol) 104 | return pstHost; 105 | } 106 | 107 | return NULL; 108 | } 109 | 110 | // todo: 改成三个接口 111 | void* get_hostinfo_fromfd(int iSockFd) 112 | { 113 | struct localhost *pstHost = NULL; 114 | struct tcp_stream *pstStream = NULL; 115 | 116 | for (pstHost = g_pstHost; pstHost != NULL; pstHost = g_pstHost->next) 117 | { 118 | if (iSockFd == pstHost->fd) 119 | return pstHost; 120 | } 121 | 122 | for (pstStream = g_pstTcpTbl->tcb_set; pstStream != NULL; pstStream = pstStream->next) { 123 | if (iSockFd == pstStream->fd) { 124 | return pstStream; 125 | } 126 | } 127 | 128 | 129 | #if ENABLE_SINGLE_EPOLL 130 | 131 | struct eventpoll *ep = g_pstTcpTbl->ep; 132 | if (ep != NULL) 133 | { 134 | if (ep->fd == iSockFd) 135 | { 136 | return ep; 137 | } 138 | } 139 | 140 | #endif 141 | 142 | return NULL; 143 | } 144 | 145 | static struct arp_table *arp_table_instance(void) 146 | { 147 | if (g_pstArpTbl == NULL) 148 | { 149 | g_pstArpTbl = rte_malloc("arp table", sizeof(struct arp_table), 0); 150 | if (g_pstArpTbl == NULL) 151 | rte_exit(EXIT_FAILURE, "rte_malloc arp table failed\n"); 152 | 153 | memset(g_pstArpTbl, 0, sizeof(struct arp_table)); 154 | 155 | pthread_spin_init(&g_pstArpTbl->spinlock, PTHREAD_PROCESS_SHARED); 156 | } 157 | 158 | return g_pstArpTbl; 159 | } 160 | 161 | unsigned char* ng_get_dst_macaddr(uint32_t dip) 162 | { 163 | struct arp_entry *pstIter; 164 | struct arp_table *pstTbl = arp_table_instance(); 165 | 166 | int count = pstTbl->count; 167 | 168 | for (pstIter = pstTbl->entries; count-- != 0 && pstIter != NULL; pstIter = pstIter->next) 169 | { 170 | if (dip == pstIter->ip) 171 | return pstIter->hwaddr; 172 | } 173 | 174 | return NULL; 175 | } 176 | 177 | int ng_arp_entry_insert(uint32_t ip, unsigned char *mac) 178 | { 179 | struct arp_table *pstTbl = arp_table_instance(); 180 | struct arp_entry *pstEntry = NULL; 181 | unsigned char *pstHwaddr = NULL; 182 | 183 | pstHwaddr = ng_get_dst_macaddr(ip); 184 | if(pstHwaddr == NULL) 185 | { 186 | pstEntry = rte_malloc("arp_entry", sizeof(struct arp_entry), 0); 187 | if (pstEntry) 188 | { 189 | memset(pstEntry, 0, sizeof(struct arp_entry)); 190 | 191 | pstEntry->ip = ip; 192 | rte_memcpy(pstEntry->hwaddr, mac, RTE_ETHER_ADDR_LEN); 193 | pstEntry->type = 0; 194 | 195 | pthread_spin_lock(&pstTbl->spinlock); 196 | LL_ADD(pstEntry, pstTbl->entries); 197 | pstTbl->count ++; 198 | pthread_spin_unlock(&pstTbl->spinlock); 199 | } 200 | return 1; 201 | } 202 | 203 | return 0; 204 | } 205 | 206 | static int ng_encode_arp_pkt(unsigned char *msg, uint16_t opcode, unsigned char *dst_mac, 207 | uint32_t sip, uint32_t dip) 208 | { 209 | struct rte_ether_hdr *pstEth = NULL; 210 | struct rte_arp_hdr *pstArp = NULL; 211 | unsigned char aucMac[RTE_ETHER_ADDR_LEN] = {0x0}; 212 | 213 | // eth 214 | pstEth = (struct rte_ether_hdr*)msg; 215 | rte_memcpy(pstEth->s_addr.addr_bytes, &g_stCpuMac, RTE_ETHER_ADDR_LEN); 216 | if (!strncmp((const char *)dst_mac, (const char *)g_aucDefaultArpMac, RTE_ETHER_ADDR_LEN)) 217 | { 218 | rte_memcpy(pstEth->d_addr.addr_bytes, aucMac, RTE_ETHER_ADDR_LEN); 219 | } 220 | else 221 | { 222 | rte_memcpy(pstEth->d_addr.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN); 223 | } 224 | pstEth->ether_type = htons(RTE_ETHER_TYPE_ARP); 225 | 226 | // arp 227 | pstArp = (struct rte_arp_hdr *)(pstEth + 1); 228 | pstArp->arp_hardware = htons(1); // 硬件类型:1 以太网 229 | pstArp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4); // 协议类型:0x0800 IP地址 230 | pstArp->arp_hlen = RTE_ETHER_ADDR_LEN; // 硬件地址长度:6 231 | pstArp->arp_plen = sizeof(uint32_t); // 协议地址长度:4 232 | pstArp->arp_opcode = htons(opcode); // OP 233 | 234 | rte_memcpy(pstArp->arp_data.arp_sha.addr_bytes, &g_stCpuMac, RTE_ETHER_ADDR_LEN); 235 | rte_memcpy(pstArp->arp_data.arp_tha.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN); 236 | 237 | pstArp->arp_data.arp_sip = sip; 238 | pstArp->arp_data.arp_tip = dip; 239 | 240 | return 0; 241 | } 242 | 243 | struct rte_mbuf *ng_send_arp(struct rte_mempool *mbuf_pool, uint16_t opcode, unsigned char *dst_mac, 244 | uint32_t sip, uint32_t dip) 245 | { 246 | const unsigned int uiTotalLen = sizeof(struct rte_ether_hdr) + sizeof(struct rte_arp_hdr); 247 | unsigned char *pucPktData; 248 | 249 | struct rte_mbuf *pstMbuf = rte_pktmbuf_alloc(mbuf_pool); 250 | if (!pstMbuf) 251 | rte_exit(EXIT_FAILURE, "ng_send_arp rte_pktmbuf_alloc\n"); 252 | 253 | pstMbuf->pkt_len = uiTotalLen; 254 | pstMbuf->data_len = uiTotalLen; 255 | 256 | pucPktData = rte_pktmbuf_mtod(pstMbuf, unsigned char *); 257 | ng_encode_arp_pkt(pucPktData, opcode, dst_mac, sip, dip); 258 | 259 | return pstMbuf; 260 | } 261 | 262 | int nsocket(__attribute__((unused)) int domain, int type, __attribute__((unused)) int protocol) 263 | { 264 | int iFd; 265 | struct localhost *pstHost; 266 | pthread_cond_t pctCond = PTHREAD_COND_INITIALIZER; 267 | pthread_mutex_t pmtMutex = PTHREAD_MUTEX_INITIALIZER; 268 | 269 | iFd = get_fd_frombitmap(); 270 | if(type == SOCK_DGRAM) // udp 271 | { 272 | pstHost = rte_malloc("localhost", sizeof(struct localhost), 0); 273 | if(pstHost == NULL) 274 | { 275 | printf("[%s][%d]: rte_malloc fail!\n", __FUNCTION__, __LINE__); 276 | return -1; 277 | } 278 | 279 | memset(pstHost, 0x00, sizeof(struct localhost)); 280 | pstHost->fd = iFd; 281 | pstHost->protocol = IPPROTO_UDP; 282 | pstHost->rcvbuf = rte_ring_create("recv buffer", D_RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 283 | if (pstHost->rcvbuf == NULL) 284 | { 285 | printf("[%s][%d]: rte_ring_create fail!\n", __FUNCTION__, __LINE__); 286 | rte_free(pstHost); 287 | return -1; 288 | } 289 | pstHost->sndbuf = rte_ring_create("send buffer", D_RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 290 | if (pstHost->sndbuf == NULL) 291 | { 292 | printf("[%s][%d]: rte_ring_create fail!\n", __FUNCTION__, __LINE__); 293 | rte_ring_free(pstHost->rcvbuf); 294 | rte_free(pstHost); 295 | return -1; 296 | } 297 | 298 | rte_memcpy(&pstHost->cond, &pctCond, sizeof(pthread_cond_t)); 299 | 300 | rte_memcpy(&pstHost->mutex, &pmtMutex, sizeof(pthread_mutex_t)); 301 | 302 | LL_ADD(pstHost, g_pstHost); 303 | } 304 | else if(type == SOCK_STREAM) // tcp 305 | { 306 | struct tcp_stream *pstStream = rte_malloc("tcp_stream", sizeof(struct tcp_stream), 0); 307 | if (pstStream == NULL) 308 | return -1; 309 | 310 | memset(pstStream, 0, sizeof(struct tcp_stream)); 311 | pstStream->fd = iFd; 312 | pstStream->protocol = IPPROTO_TCP; 313 | pstStream->next = pstStream->prev = NULL; 314 | 315 | pstStream->rcvbuf = rte_ring_create("tcp recv buffer", D_RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 316 | if (pstStream->rcvbuf == NULL) 317 | { 318 | rte_free(pstStream); 319 | return -1; 320 | } 321 | pstStream->sndbuf = rte_ring_create("tcp send buffer", D_RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 322 | if (pstStream->sndbuf == NULL) 323 | { 324 | rte_ring_free(pstStream->rcvbuf); 325 | rte_free(pstStream); 326 | return -1; 327 | } 328 | 329 | pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER; 330 | rte_memcpy(&pstStream->cond, &blank_cond, sizeof(pthread_cond_t)); 331 | 332 | pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER; 333 | rte_memcpy(&pstStream->mutex, &blank_mutex, sizeof(pthread_mutex_t)); 334 | 335 | g_pstTcpTbl = tcpInstance(); 336 | LL_ADD(pstStream, g_pstTcpTbl->tcb_set); // todo :hash 337 | } 338 | 339 | return iFd; 340 | } 341 | 342 | int nbind(int sockfd, const struct sockaddr *addr, __attribute__((unused)) socklen_t addrlen) 343 | { 344 | void *info = NULL; 345 | 346 | info = get_hostinfo_fromfd(sockfd); 347 | if(info == NULL) 348 | return -1; 349 | 350 | struct localhost *pstHostInfo = (struct localhost *)info; 351 | if(pstHostInfo->protocol == IPPROTO_UDP) 352 | { 353 | const struct sockaddr_in *pstAddr = (const struct sockaddr_in *)addr; 354 | pstHostInfo->localport = pstAddr->sin_port; 355 | rte_memcpy(&pstHostInfo->localip, &pstAddr->sin_addr.s_addr, sizeof(uint32_t)); 356 | rte_memcpy(pstHostInfo->localmac, &g_stCpuMac, RTE_ETHER_ADDR_LEN); 357 | } 358 | else if(pstHostInfo->protocol == IPPROTO_TCP) 359 | { 360 | struct tcp_stream* pstStream = (struct tcp_stream*)pstHostInfo; 361 | 362 | const struct sockaddr_in *pstAddr = (const struct sockaddr_in *)addr; 363 | pstStream->dport = pstAddr->sin_port; 364 | rte_memcpy(&pstStream->dip, &pstAddr->sin_addr.s_addr, sizeof(uint32_t)); 365 | rte_memcpy(pstStream->localmac, &g_stCpuMac, RTE_ETHER_ADDR_LEN); 366 | 367 | pstStream->status = TCP_STATUS_CLOSED; 368 | } 369 | 370 | return 0; 371 | } 372 | 373 | int nlisten(int sockfd, __attribute__((unused)) int backlog) 374 | { 375 | void *pstHostInfo = get_hostinfo_fromfd(sockfd); 376 | if (pstHostInfo == NULL) 377 | return -1; 378 | 379 | struct tcp_stream *pstStream = (struct tcp_stream *)pstHostInfo; 380 | if (pstStream->protocol == IPPROTO_TCP) 381 | { 382 | pstStream->status = TCP_STATUS_LISTEN; 383 | } 384 | 385 | return 0; 386 | } 387 | 388 | int naccept(int sockfd, struct sockaddr *addr, __attribute__((unused)) socklen_t *addrlen) 389 | { 390 | void *pstHostInfo = get_hostinfo_fromfd(sockfd); 391 | if (pstHostInfo == NULL) 392 | return -1; 393 | 394 | struct tcp_stream *pstStream = (struct tcp_stream *)pstHostInfo; 395 | if (pstStream->protocol == IPPROTO_TCP) 396 | { 397 | struct tcp_stream *pstAccept = NULL; 398 | 399 | pthread_mutex_lock(&pstStream->mutex); 400 | while((pstAccept = get_accept_tcb(pstStream->dport)) == NULL) 401 | { 402 | pthread_cond_wait(&pstStream->cond, &pstStream->mutex); 403 | } 404 | pthread_mutex_unlock(&pstStream->mutex); 405 | 406 | pstAccept->fd = get_fd_frombitmap(); 407 | 408 | struct sockaddr_in *saddr = (struct sockaddr_in *)addr; 409 | saddr->sin_port = pstAccept->sport; 410 | rte_memcpy(&saddr->sin_addr.s_addr, &pstAccept->sip, sizeof(uint32_t)); 411 | 412 | return pstAccept->fd; 413 | } 414 | 415 | return -1; 416 | } 417 | 418 | ssize_t nsend(int sockfd, const void *buf, size_t len,__attribute__((unused)) int flags) 419 | { 420 | unsigned int uiLength = 0; 421 | void *pstHostInfo = get_hostinfo_fromfd(sockfd); 422 | if (pstHostInfo == NULL) 423 | return -1; 424 | 425 | struct tcp_stream *pstStream = (struct tcp_stream *)pstHostInfo; 426 | if(pstStream->protocol == IPPROTO_TCP) 427 | { 428 | struct tcp_fragment *pstFragment = rte_malloc("tcp_fragment", sizeof(struct tcp_fragment), 0); 429 | if (pstFragment == NULL) 430 | { 431 | return -2; 432 | } 433 | 434 | memset(pstFragment, 0, sizeof(struct tcp_fragment)); 435 | pstFragment->dport = pstStream->sport; 436 | pstFragment->sport = pstStream->dport; 437 | pstFragment->acknum = pstStream->rcv_nxt; 438 | pstFragment->seqnum = pstStream->snd_nxt; 439 | pstFragment->tcp_flags = RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG; 440 | pstFragment->windows = D_TCP_INITIAL_WINDOW; 441 | pstFragment->hdrlen_off = 0x50; 442 | 443 | pstFragment->data = rte_malloc("unsigned char *", len + 1, 0); 444 | if (pstFragment->data == NULL) 445 | { 446 | rte_free(pstFragment); 447 | return -1; 448 | } 449 | memset(pstFragment->data, 0, len+1); 450 | 451 | rte_memcpy(pstFragment->data, buf, len); 452 | pstFragment->length = len; 453 | uiLength = pstFragment->length; 454 | 455 | puts("ready to send!"); 456 | rte_ring_mp_enqueue(pstStream->sndbuf, pstFragment); 457 | } 458 | 459 | return uiLength; 460 | } 461 | 462 | ssize_t nrecv(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags) 463 | { 464 | ssize_t length = 0; 465 | void *pstHostInfo = get_hostinfo_fromfd(sockfd); 466 | if (pstHostInfo == NULL) 467 | return -1; 468 | 469 | struct tcp_stream *pstStream = (struct tcp_stream *)pstHostInfo; 470 | if(pstStream->protocol == IPPROTO_TCP) 471 | { 472 | struct tcp_fragment *pstFragment = NULL; 473 | int iRcvNum = 0; 474 | 475 | // 等待接收队列中的数据到来 476 | pthread_mutex_lock(&pstStream->mutex); 477 | while ((iRcvNum = rte_ring_mc_dequeue(pstStream->rcvbuf, (void **)&pstFragment)) < 0) 478 | { 479 | pthread_cond_wait(&pstStream->cond, &pstStream->mutex); 480 | } 481 | pthread_mutex_unlock(&pstStream->mutex); 482 | 483 | if (pstFragment->length > len) 484 | { 485 | rte_memcpy(buf, pstFragment->data, len); 486 | 487 | uint32_t i = 0; 488 | for(i = 0; i < pstFragment->length - len; i ++) 489 | { 490 | pstFragment->data[i] = pstFragment->data[len + i]; 491 | } 492 | pstFragment->length = pstFragment->length - len; 493 | length = pstFragment->length; 494 | 495 | rte_ring_mp_enqueue(pstStream->rcvbuf, pstFragment); 496 | } 497 | else if(pstFragment->length == 0) 498 | { 499 | rte_free(pstFragment); 500 | return 0; 501 | } 502 | else 503 | { 504 | rte_memcpy(buf, pstFragment->data, pstFragment->length); 505 | length = pstFragment->length; 506 | 507 | rte_free(pstFragment->data); 508 | pstFragment->data = NULL; 509 | 510 | rte_free(pstFragment); 511 | } 512 | } 513 | 514 | return length; 515 | } 516 | 517 | ssize_t nrecvfrom(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags, 518 | struct sockaddr *src_addr, __attribute__((unused)) socklen_t *addrlen) 519 | { 520 | struct localhost *pstHostInfo = NULL; 521 | struct offload *pstOffLoad = NULL; 522 | struct sockaddr_in *pstAddr = NULL; 523 | unsigned char *pucPtr = NULL; 524 | int iLen = 0; 525 | int iRet = -1; 526 | 527 | pstHostInfo = (struct localhost *)get_hostinfo_fromfd(sockfd); 528 | if(pstHostInfo == NULL) 529 | return -1; 530 | 531 | pthread_mutex_lock(&pstHostInfo->mutex); 532 | while((iRet = rte_ring_mc_dequeue(pstHostInfo->rcvbuf, (void**)&pstOffLoad)) < 0) 533 | { 534 | pthread_cond_wait(&pstHostInfo->cond, &pstHostInfo->mutex); 535 | } 536 | pthread_mutex_unlock(&pstHostInfo->mutex); 537 | 538 | pstAddr = (struct sockaddr_in *)src_addr; 539 | pstAddr->sin_port = pstOffLoad->sport; 540 | rte_memcpy(&pstAddr->sin_addr.s_addr, &pstOffLoad->sip, sizeof(uint32_t)); 541 | 542 | if(len < pstOffLoad->length) 543 | { 544 | rte_memcpy(buf, pstOffLoad->data, len); 545 | 546 | pucPtr = rte_malloc("unsigned char *", pstOffLoad->length - len, 0); 547 | rte_memcpy(pucPtr, pstOffLoad->data + len, pstOffLoad->length - len); 548 | 549 | pstOffLoad->length -= len; 550 | rte_free(pstOffLoad->data); 551 | pstOffLoad->data = pucPtr; 552 | 553 | rte_ring_mp_enqueue(pstHostInfo->rcvbuf, pstOffLoad); 554 | 555 | return len; 556 | } 557 | 558 | iLen = pstOffLoad->length; 559 | rte_memcpy(buf, pstOffLoad->data, pstOffLoad->length); 560 | 561 | rte_free(pstOffLoad->data); 562 | rte_free(pstOffLoad); 563 | 564 | return iLen; 565 | } 566 | 567 | ssize_t nsendto(int sockfd, const void *buf, size_t len, __attribute__((unused)) int flags, 568 | const struct sockaddr *dest_addr, __attribute__((unused)) socklen_t addrlen) 569 | { 570 | struct localhost *pstHostInfo = NULL; 571 | struct offload *pstOffLoad = NULL; 572 | const struct sockaddr_in *pstAddr = (const struct sockaddr_in *)dest_addr; 573 | 574 | pstHostInfo = (struct localhost *)get_hostinfo_fromfd(sockfd); 575 | if(pstHostInfo == NULL) 576 | return -1; 577 | 578 | pstOffLoad = rte_malloc("offload", sizeof(struct offload), 0); 579 | if (pstOffLoad == NULL) 580 | return -1; 581 | 582 | pstOffLoad->dip = pstAddr->sin_addr.s_addr; 583 | pstOffLoad->dport = pstAddr->sin_port; 584 | pstOffLoad->sip = pstHostInfo->localip; 585 | pstOffLoad->sport = pstHostInfo->localport; 586 | pstOffLoad->length = len; 587 | 588 | 589 | struct in_addr addr; 590 | addr.s_addr = pstOffLoad->dip; 591 | printf("nsendto ---> src: %s:%d \n", inet_ntoa(addr), ntohs(pstOffLoad->dport)); 592 | 593 | 594 | pstOffLoad->data = rte_malloc("unsigned char *", len, 0); 595 | if (pstOffLoad->data == NULL) { 596 | rte_free(pstOffLoad); 597 | return -1; 598 | } 599 | 600 | rte_memcpy(pstOffLoad->data, buf, len); 601 | 602 | puts("rte_ring_mp_enqueue before !"); 603 | rte_ring_mp_enqueue(pstHostInfo->sndbuf, pstOffLoad); 604 | puts("rte_ring_mp_enqueue after !"); 605 | 606 | return len; 607 | } 608 | 609 | int nclose(int fd) 610 | { 611 | void *info = NULL; 612 | 613 | info = (struct localhost *)get_hostinfo_fromfd(fd); 614 | if(info == NULL) 615 | return -1; 616 | 617 | struct localhost *pstHostInfo = (struct localhost *)info; 618 | if(pstHostInfo->protocol == IPPROTO_UDP) 619 | { 620 | LL_REMOVE(pstHostInfo, g_pstHost); 621 | 622 | if (pstHostInfo->rcvbuf) 623 | rte_ring_free(pstHostInfo->rcvbuf); 624 | if (pstHostInfo->sndbuf) 625 | rte_ring_free(pstHostInfo->sndbuf); 626 | 627 | rte_free(pstHostInfo); 628 | 629 | set_fd_frombitmap(fd); 630 | } 631 | else if(pstHostInfo->protocol == IPPROTO_TCP) 632 | { 633 | struct tcp_stream *pstStream = (struct tcp_stream*)info; 634 | if (pstStream->status != TCP_STATUS_LISTEN) 635 | { 636 | struct tcp_fragment *pstFragment = rte_malloc("tcp_fragment", sizeof(struct tcp_fragment), 0); 637 | if (pstFragment == NULL) 638 | return -1; 639 | 640 | memset(pstFragment, 0x00, sizeof(struct tcp_fragment)); 641 | pstFragment->data = NULL; 642 | pstFragment->length = 0; 643 | pstFragment->sport = pstStream->dport; 644 | pstFragment->dport = pstStream->sport; 645 | 646 | pstFragment->seqnum = pstStream->snd_nxt; 647 | pstFragment->acknum = pstStream->rcv_nxt; 648 | 649 | pstFragment->tcp_flags = RTE_TCP_FIN_FLAG | RTE_TCP_ACK_FLAG; // 发送FIN 650 | pstFragment->windows = D_TCP_INITIAL_WINDOW; 651 | pstFragment->hdrlen_off = 0x50; 652 | 653 | rte_ring_mp_enqueue(pstStream->sndbuf, pstFragment); 654 | pstStream->status = TCP_STATUS_LAST_ACK; 655 | 656 | set_fd_frombitmap(fd); 657 | } 658 | else 659 | { 660 | LL_REMOVE(pstStream, g_pstTcpTbl->tcb_set); 661 | rte_free(pstStream); 662 | } 663 | } 664 | 665 | return 0; 666 | } 667 | 668 | #if ENABLE_SINGLE_EPOLL 669 | 670 | int epoll_event_callback(struct eventpoll *ep, int sockid, uint32_t event) 671 | { 672 | struct epitem tmp; 673 | tmp.sockfd = sockid; 674 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 675 | if (!epi) 676 | { 677 | printf("rbtree not exist\n"); 678 | return -1; 679 | } 680 | if (epi->rdy) 681 | { 682 | epi->event.events |= event; 683 | return 1; 684 | } 685 | 686 | printf("epoll_event_callback --> %d\n", epi->sockfd); 687 | 688 | pthread_spin_lock(&ep->lock); 689 | epi->rdy = 1; 690 | LIST_INSERT_HEAD(&ep->rdlist, epi, rdlink); 691 | ep->rdnum ++; 692 | pthread_spin_unlock(&ep->lock); 693 | 694 | pthread_mutex_lock(&ep->cdmtx); 695 | 696 | pthread_cond_signal(&ep->cond); 697 | pthread_mutex_unlock(&ep->cdmtx); 698 | } 699 | 700 | int nepoll_create(int size) 701 | { 702 | if (size <= 0) return -1; 703 | // epfd --> struct eventpoll 704 | int epfd = get_fd_frombitmap(); //tcp, udp 705 | 706 | struct eventpoll *ep = (struct eventpoll*)rte_malloc("eventpoll", sizeof(struct eventpoll), 0); 707 | if (!ep) 708 | { 709 | set_fd_frombitmap(epfd); 710 | return -1; 711 | } 712 | 713 | g_pstTcpTbl->ep = ep; 714 | 715 | ep->fd = epfd; 716 | ep->rbcnt = 0; 717 | RB_INIT(&ep->rbr); 718 | LIST_INIT(&ep->rdlist); 719 | 720 | if (pthread_mutex_init(&ep->mtx, NULL)) 721 | { 722 | rte_free(ep); 723 | set_fd_frombitmap(epfd); 724 | 725 | return -2; 726 | } 727 | 728 | if (pthread_mutex_init(&ep->cdmtx, NULL)) 729 | { 730 | pthread_mutex_destroy(&ep->mtx); 731 | rte_free(ep); 732 | set_fd_frombitmap(epfd); 733 | return -2; 734 | } 735 | 736 | if (pthread_cond_init(&ep->cond, NULL)) 737 | { 738 | pthread_mutex_destroy(&ep->cdmtx); 739 | pthread_mutex_destroy(&ep->mtx); 740 | rte_free(ep); 741 | set_fd_frombitmap(epfd); 742 | return -2; 743 | } 744 | 745 | if (pthread_spin_init(&ep->lock, PTHREAD_PROCESS_SHARED)) 746 | { 747 | pthread_cond_destroy(&ep->cond); 748 | pthread_mutex_destroy(&ep->cdmtx); 749 | pthread_mutex_destroy(&ep->mtx); 750 | rte_free(ep); 751 | 752 | set_fd_frombitmap(epfd); 753 | return -2; 754 | } 755 | 756 | return epfd; 757 | } 758 | 759 | int nepoll_ctl(int epfd, int op, int sockid, struct epoll_event *event) 760 | { 761 | struct eventpoll *ep = (struct eventpoll*)get_hostinfo_fromfd(epfd); 762 | if (!ep || (!event && op != EPOLL_CTL_DEL)) 763 | { 764 | errno = -EINVAL; 765 | return -1; 766 | } 767 | 768 | if (op == EPOLL_CTL_ADD) 769 | { 770 | pthread_mutex_lock(&ep->mtx); 771 | 772 | struct epitem tmp; 773 | tmp.sockfd = sockid; 774 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 775 | if (epi) 776 | { 777 | pthread_mutex_unlock(&ep->mtx); 778 | return -1; 779 | } 780 | 781 | epi = (struct epitem*)rte_malloc("epitem", sizeof(struct epitem), 0); 782 | if (!epi) 783 | { 784 | pthread_mutex_unlock(&ep->mtx); 785 | rte_errno = -ENOMEM; 786 | return -1; 787 | } 788 | 789 | epi->sockfd = sockid; 790 | memcpy(&epi->event, event, sizeof(struct epoll_event)); 791 | 792 | epi = RB_INSERT(_epoll_rb_socket, &ep->rbr, epi); 793 | 794 | ep->rbcnt ++; 795 | 796 | pthread_mutex_unlock(&ep->mtx); 797 | } 798 | else if(op == EPOLL_CTL_DEL) 799 | { 800 | pthread_mutex_lock(&ep->mtx); 801 | 802 | struct epitem tmp; 803 | tmp.sockfd = sockid; 804 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 805 | if (!epi) 806 | { 807 | pthread_mutex_unlock(&ep->mtx); 808 | return -1; 809 | } 810 | 811 | epi = RB_REMOVE(_epoll_rb_socket, &ep->rbr, epi); 812 | if (!epi) 813 | { 814 | pthread_mutex_unlock(&ep->mtx); 815 | return -1; 816 | } 817 | 818 | ep->rbcnt --; 819 | rte_free(epi); 820 | 821 | pthread_mutex_unlock(&ep->mtx); 822 | } 823 | else if (op == EPOLL_CTL_MOD) 824 | { 825 | struct epitem tmp; 826 | tmp.sockfd = sockid; 827 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 828 | if (epi) 829 | { 830 | epi->event.events = event->events; 831 | epi->event.events |= EPOLLERR | EPOLLHUP; 832 | } 833 | else 834 | { 835 | rte_errno = -ENOENT; 836 | return -1; 837 | } 838 | } 839 | 840 | return 0; 841 | } 842 | 843 | int nepoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) 844 | { 845 | struct eventpoll *ep = (struct eventpoll*)get_hostinfo_fromfd(epfd);; 846 | if (!ep || !events || maxevents <= 0) 847 | { 848 | rte_errno = -EINVAL; 849 | return -1; 850 | } 851 | 852 | if (pthread_mutex_lock(&ep->cdmtx)) 853 | { 854 | if (rte_errno == EDEADLK) 855 | printf("epoll lock blocked\n"); 856 | } 857 | 858 | while (ep->rdnum == 0 && timeout != 0) 859 | { 860 | ep->waiting = 1; 861 | if (timeout > 0) 862 | { 863 | struct timespec deadline; 864 | 865 | clock_gettime(CLOCK_REALTIME, &deadline); 866 | if (timeout >= 1000) 867 | { 868 | int sec; 869 | sec = timeout / 1000; 870 | deadline.tv_sec += sec; 871 | timeout -= sec * 1000; 872 | } 873 | 874 | deadline.tv_nsec += timeout * 1000000; 875 | 876 | if (deadline.tv_nsec >= 1000000000) 877 | { 878 | deadline.tv_sec++; 879 | deadline.tv_nsec -= 1000000000; 880 | } 881 | 882 | int ret = pthread_cond_timedwait(&ep->cond, &ep->cdmtx, &deadline); 883 | if (ret && ret != ETIMEDOUT) 884 | { 885 | printf("pthread_cond_timewait\n"); 886 | 887 | pthread_mutex_unlock(&ep->cdmtx); 888 | 889 | return -1; 890 | } 891 | timeout = 0; 892 | } 893 | else if (timeout < 0) 894 | { 895 | int ret = pthread_cond_wait(&ep->cond, &ep->cdmtx); 896 | if (ret) 897 | { 898 | printf("pthread_cond_wait\n"); 899 | pthread_mutex_unlock(&ep->cdmtx); 900 | 901 | return -1; 902 | } 903 | } 904 | ep->waiting = 0; 905 | } 906 | 907 | pthread_mutex_unlock(&ep->cdmtx); 908 | 909 | pthread_spin_lock(&ep->lock); 910 | int cnt = 0; 911 | int num = (ep->rdnum > maxevents ? maxevents : ep->rdnum); 912 | int i = 0; 913 | 914 | while (num != 0 && !LIST_EMPTY(&ep->rdlist)) // EPOLLET 915 | { 916 | struct epitem *epi = LIST_FIRST(&ep->rdlist); 917 | LIST_REMOVE(epi, rdlink); 918 | epi->rdy = 0; 919 | 920 | memcpy(&events[i++], &epi->event, sizeof(struct epoll_event)); 921 | 922 | num --; 923 | cnt ++; 924 | ep->rdnum --; 925 | } 926 | pthread_spin_unlock(&ep->lock); 927 | 928 | return cnt; 929 | } 930 | 931 | 932 | #endif -------------------------------------------------------------------------------- /nty_tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) [2018] [WangBoJing] 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | * 25 | * 26 | **** ***** ************ 27 | *** * ** ** * 28 | *** * * * ** ** 29 | * ** * * * ** * 30 | * ** * * * ** * 31 | * ** * ** ** 32 | * ** * *** ** 33 | * ** * *********** ***** ***** ** ***** * **** 34 | * ** * ** ** ** ** *** * **** * ** 35 | * ** * ** ** * ** ** ** *** ** 36 | * ** * ** * * ** ** ** ** * 37 | * ** * ** ** * ** ** ** ** ** 38 | * ** * ** * * ** ** ** ** 39 | * ** * ** ** * ** ** ** ** 40 | * ** * ** ** * ** ** ** ** 41 | * ** * ** * * ** ** ** ** 42 | * ** * ** ** * ** ** ** ** 43 | * *** ** * * ** ** * ** ** 44 | * *** ** * ** ** ** * ** ** 45 | * ** ** * ** ** ** * *** ** 46 | * ** ** * * ** ** * **** ** 47 | ***** * **** * ****** ***** ** **** 48 | * ** 49 | * ** 50 | ***** ** 51 | **** ****** 52 | 53 | * 54 | */ 55 | 56 | 57 | 58 | #ifndef __NTY_TREE_H__ 59 | #define __NTY_TREE_H__ 60 | 61 | 62 | #define SPLAY_HEAD(name, type) \ 63 | struct name { \ 64 | struct type *sph_root; /* root of the tree */ \ 65 | } 66 | 67 | #define SPLAY_INITIALIZER(root) \ 68 | { NULL } 69 | 70 | #define SPLAY_INIT(root) do { \ 71 | (root)->sph_root = NULL; \ 72 | } while (/*CONSTCOND*/ 0) 73 | 74 | #define SPLAY_ENTRY(type) \ 75 | struct { \ 76 | struct type *spe_left; /* left element */ \ 77 | struct type *spe_right; /* right element */ \ 78 | } 79 | 80 | #define SPLAY_LEFT(elm, field) (elm)->field.spe_left 81 | #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right 82 | #define SPLAY_ROOT(head) (head)->sph_root 83 | #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) 84 | 85 | /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ 86 | #define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ 87 | SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ 88 | SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 89 | (head)->sph_root = tmp; \ 90 | } while (/*CONSTCOND*/ 0) 91 | 92 | #define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ 93 | SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ 94 | SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 95 | (head)->sph_root = tmp; \ 96 | } while (/*CONSTCOND*/ 0) 97 | 98 | #define SPLAY_LINKLEFT(head, tmp, field) do { \ 99 | SPLAY_LEFT(tmp, field) = (head)->sph_root; \ 100 | tmp = (head)->sph_root; \ 101 | (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ 102 | } while (/*CONSTCOND*/ 0) 103 | 104 | #define SPLAY_LINKRIGHT(head, tmp, field) do { \ 105 | SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ 106 | tmp = (head)->sph_root; \ 107 | (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ 108 | } while (/*CONSTCOND*/ 0) 109 | 110 | #define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ 111 | SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ 112 | SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ 113 | SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ 114 | SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ 115 | } while (/*CONSTCOND*/ 0) 116 | 117 | 118 | 119 | #define SPLAY_PROTOTYPE(name, type, field, cmp) \ 120 | void name##_SPLAY(struct name *, struct type *); \ 121 | void name##_SPLAY_MINMAX(struct name *, int); \ 122 | struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ 123 | struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ 124 | \ 125 | /* Finds the node with the same key as elm */ \ 126 | static __inline struct type * \ 127 | name##_SPLAY_FIND(struct name *head, struct type *elm) { \ \ 128 | if (SPLAY_EMPTY(head)) \ 129 | return(NULL); \ 130 | name##_SPLAY(head, elm); \ 131 | if ((cmp)(elm, (head)->sph_root) == 0) \ 132 | return (head->sph_root); \ 133 | return (NULL); \ 134 | } \ 135 | \ 136 | static __inline struct type * \ 137 | name##_SPLAY_NEXT(struct name *head, struct type *elm) { \ 138 | name##_SPLAY(head, elm); \ 139 | if (SPLAY_RIGHT(elm, field) != NULL) { \ 140 | elm = SPLAY_RIGHT(elm, field); \ 141 | while (SPLAY_LEFT(elm, field) != NULL) { \ 142 | elm = SPLAY_LEFT(elm, field); \ 143 | } \ 144 | } else \ 145 | elm = NULL; \ 146 | return (elm); \ 147 | } \ 148 | \ 149 | static __inline struct type * \ 150 | name##_SPLAY_MIN_MAX(struct name *head, int val) { \ 151 | name##_SPLAY_MINMAX(head, val); \ 152 | return (SPLAY_ROOT(head)); \ 153 | } 154 | 155 | /* Main splay operation. 156 | * Moves node close to the key of elm to top 157 | */ 158 | #define SPLAY_GENERATE(name, type, field, cmp) \ 159 | struct type * \ 160 | name##_SPLAY_INSERT(struct name *head, struct type *elm) { \ 161 | if (SPLAY_EMPTY(head)) { \ 162 | SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ 163 | } else { \ 164 | int __comp; \ 165 | name##_SPLAY(head, elm); \ 166 | __comp = (cmp)(elm, (head)->sph_root); \ 167 | if(__comp < 0) { \ 168 | SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ 169 | SPLAY_RIGHT(elm, field) = (head)->sph_root; \ 170 | SPLAY_LEFT((head)->sph_root, field) = NULL; \ 171 | } else if (__comp > 0) { \ 172 | SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ 173 | SPLAY_LEFT(elm, field) = (head)->sph_root; \ 174 | SPLAY_RIGHT((head)->sph_root, field) = NULL; \ 175 | } else \ 176 | return ((head)->sph_root); \ 177 | } \ 178 | (head)->sph_root = (elm); \ 179 | return (NULL); \ 180 | } \ 181 | \ 182 | struct type * \ 183 | name##_SPLAY_REMOVE(struct name *head, struct type *elm) { \ 184 | struct type *__tmp; \ 185 | if (SPLAY_EMPTY(head)) \ 186 | return (NULL); \ 187 | name##_SPLAY(head, elm); \ 188 | if ((cmp)(elm, (head)->sph_root) == 0) { \ 189 | if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ 190 | (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ 191 | } else { \ 192 | __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 193 | (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ 194 | name##_SPLAY(head, elm); \ 195 | SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ 196 | } \ 197 | return (elm); \ 198 | } \ 199 | return (NULL); \ 200 | } \ 201 | \ 202 | void \ 203 | name##_SPLAY(struct name *head, struct type *elm) { \ 204 | struct type __node, *__left, *__right, *__tmp; \ 205 | int __comp; \ 206 | \ 207 | SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 208 | __left = __right = &__node; \ 209 | \ 210 | while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) {\ 211 | if (__comp < 0) { \ 212 | __tmp = SPLAY_LEFT((head)->sph_root, field); \ 213 | if (__tmp == NULL) \ 214 | break; \ 215 | if ((cmp)(elm, __tmp) < 0){ \ 216 | SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 217 | if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 218 | break; \ 219 | } \ 220 | SPLAY_LINKLEFT(head, __right, field); \ 221 | } else if (__comp > 0) { \ 222 | __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 223 | if (__tmp == NULL) \ 224 | break; \ 225 | if ((cmp)(elm, __tmp) > 0){ \ 226 | SPLAY_ROTATE_LEFT(head, __tmp, field); \ 227 | if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 228 | break; \ 229 | } \ 230 | SPLAY_LINKRIGHT(head, __left, field); \ 231 | } \ 232 | } \ 233 | SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 234 | } \ 235 | \ 236 | void name##_SPLAY_MINMAX(struct name *head, int __comp) \ 237 | { \ 238 | struct type __node, *__left, *__right, *__tmp; \ 239 | \ 240 | SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ 241 | __left = __right = &__node; \ 242 | \ 243 | while (1) { \ 244 | if (__comp < 0) { \ 245 | __tmp = SPLAY_LEFT((head)->sph_root, field); \ 246 | if (__tmp == NULL) \ 247 | break; \ 248 | if (__comp < 0){ \ 249 | SPLAY_ROTATE_RIGHT(head, __tmp, field); \ 250 | if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ 251 | break; \ 252 | } \ 253 | SPLAY_LINKLEFT(head, __right, field); \ 254 | } else if (__comp > 0) { \ 255 | __tmp = SPLAY_RIGHT((head)->sph_root, field); \ 256 | if (__tmp == NULL) \ 257 | break; \ 258 | if (__comp > 0) { \ 259 | SPLAY_ROTATE_LEFT(head, __tmp, field); \ 260 | if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ 261 | break; \ 262 | } \ 263 | SPLAY_LINKRIGHT(head, __left, field); \ 264 | } \ 265 | } \ 266 | SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ 267 | } 268 | 269 | #define SPLAY_NEGINF -1 270 | #define SPLAY_INF 1 271 | 272 | #define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) 273 | #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) 274 | #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) 275 | #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) 276 | #define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ 277 | : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) 278 | #define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ 279 | : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) 280 | 281 | #define SPLAY_FOREACH(x, name, head) \ 282 | for ((x) = SPLAY_MIN(name, head); \ 283 | (x) != NULL; \ 284 | (x) = SPLAY_NEXT(name, head, x)) 285 | 286 | 287 | 288 | 289 | /* Macros that define a red-black tree */ 290 | #define RB_HEAD(name, type) \ 291 | struct name { \ 292 | struct type *rbh_root; /* root of the tree */ \ 293 | } 294 | 295 | #define RB_INITIALIZER(root) \ 296 | { NULL } 297 | 298 | #define RB_INIT(root) do { \ 299 | (root)->rbh_root = NULL; \ 300 | } while (0) 301 | 302 | 303 | #define RB_BLACK 0 304 | #define RB_RED 1 305 | 306 | #define RB_ENTRY(type) \ 307 | struct { \ 308 | struct type *rbe_left; /* left element */ \ 309 | struct type *rbe_right; /* right element */ \ 310 | struct type *rbe_parent; /* parent element */ \ 311 | int rbe_color; /* node color */ \ 312 | } 313 | 314 | #define RB_LEFT(elm, field) (elm)->field.rbe_left 315 | #define RB_RIGHT(elm, field) (elm)->field.rbe_right 316 | #define RB_PARENT(elm, field) (elm)->field.rbe_parent 317 | #define RB_COLOR(elm, field) (elm)->field.rbe_color 318 | #define RB_ROOT(head) (head)->rbh_root 319 | #define RB_EMPTY(head) (RB_ROOT(head) == NULL) 320 | 321 | #define RB_SET(elm, parent, field) do { \ 322 | RB_PARENT(elm, field) = parent; \ 323 | RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ 324 | RB_COLOR(elm, field) = RB_RED; \ 325 | } while (0) 326 | 327 | #define RB_SET_BLACKRED(black, red, field) do { \ 328 | RB_COLOR(black, field) = RB_BLACK; \ 329 | RB_COLOR(red, field) = RB_RED; \ 330 | } while (0) 331 | 332 | #ifndef RB_AUGMENT 333 | #define RB_AUGMENT(x) do {} while (0) 334 | #endif 335 | 336 | 337 | 338 | #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ 339 | (tmp) = RB_RIGHT(elm, field); \ 340 | if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ 341 | RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ 342 | } \ 343 | RB_AUGMENT(elm); \ 344 | if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ 345 | if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 346 | RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 347 | else \ 348 | RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 349 | } else \ 350 | (head)->rbh_root = (tmp); \ 351 | RB_LEFT(tmp, field) = (elm); \ 352 | RB_PARENT(elm, field) = (tmp); \ 353 | RB_AUGMENT(tmp); \ 354 | if ((RB_PARENT(tmp, field))) \ 355 | RB_AUGMENT(RB_PARENT(tmp, field)); \ 356 | } while (0) 357 | 358 | 359 | #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ 360 | (tmp) = RB_LEFT(elm, field); \ 361 | if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ 362 | RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ 363 | } \ 364 | RB_AUGMENT(elm); \ 365 | if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ 366 | if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ 367 | RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ 368 | else \ 369 | RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ 370 | } else \ 371 | (head)->rbh_root = (tmp); \ 372 | RB_RIGHT(tmp, field) = (elm); \ 373 | RB_PARENT(elm, field) = (tmp); \ 374 | RB_AUGMENT(tmp); \ 375 | if ((RB_PARENT(tmp, field))) \ 376 | RB_AUGMENT(RB_PARENT(tmp, field)); \ 377 | } while (0) 378 | 379 | 380 | #define RB_PROTOTYPE(name, type, field, cmp) \ 381 | RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) 382 | #define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ 383 | RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) 384 | #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ 385 | attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ 386 | attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ 387 | attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ 388 | attr struct type *name##_RB_INSERT(struct name *, struct type *); \ 389 | attr struct type *name##_RB_FIND(struct name *, struct type *); \ 390 | attr struct type *name##_RB_NFIND(struct name *, struct type *); \ 391 | attr struct type *name##_RB_NEXT(struct type *); \ 392 | attr struct type *name##_RB_PREV(struct type *); \ 393 | attr struct type *name##_RB_MINMAX(struct name *, int); \ 394 | 395 | /* Main rb operation. 396 | * Moves node close to the key of elm to top 397 | */ 398 | #define RB_GENERATE(name, type, field, cmp) \ 399 | RB_GENERATE_INTERNAL(name, type, field, cmp,) 400 | #define RB_GENERATE_STATIC(name, type, field, cmp) \ 401 | RB_GENERATE_INTERNAL(name, type, field, cmp, static) 402 | #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ 403 | attr void \ 404 | name##_RB_INSERT_COLOR(struct name *head, struct type *elm) { \ 405 | struct type *parent, *gparent, *tmp; \ 406 | while ((parent = RB_PARENT(elm, field)) != NULL && \ 407 | RB_COLOR(parent, field) == RB_RED) { \ 408 | gparent = RB_PARENT(parent, field); \ 409 | if (parent == RB_LEFT(gparent, field)) { \ 410 | tmp = RB_RIGHT(gparent, field); \ 411 | if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 412 | RB_COLOR(tmp, field) = RB_BLACK; \ 413 | RB_SET_BLACKRED(parent, gparent, field); \ 414 | elm = gparent; \ 415 | continue; \ 416 | } \ 417 | if (RB_RIGHT(parent, field) == elm) { \ 418 | RB_ROTATE_LEFT(head, parent, tmp, field); \ 419 | tmp = parent; \ 420 | parent = elm; \ 421 | elm = tmp; \ 422 | } \ 423 | RB_SET_BLACKRED(parent, gparent, field); \ 424 | RB_ROTATE_RIGHT(head, gparent, tmp, field); \ 425 | } else { \ 426 | tmp = RB_LEFT(gparent, field); \ 427 | if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ 428 | RB_COLOR(tmp, field) = RB_BLACK; \ 429 | RB_SET_BLACKRED(parent, gparent, field); \ 430 | elm = gparent; \ 431 | continue; \ 432 | } \ 433 | if (RB_LEFT(parent, field) == elm) { \ 434 | RB_ROTATE_RIGHT(head, parent, tmp, field); \ 435 | tmp = parent; \ 436 | parent = elm; \ 437 | elm = tmp; \ 438 | } \ 439 | RB_SET_BLACKRED(parent, gparent, field); \ 440 | RB_ROTATE_LEFT(head, gparent, tmp, field); \ 441 | } \ 442 | } \ 443 | RB_COLOR(head->rbh_root, field) = RB_BLACK; \ 444 | } \ 445 | \ 446 | attr void \ 447 | name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ 448 | { \ 449 | struct type *tmp; \ 450 | while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ 451 | elm != RB_ROOT(head)) { \ 452 | if (RB_LEFT(parent, field) == elm) { \ 453 | tmp = RB_RIGHT(parent, field); \ 454 | if (RB_COLOR(tmp, field) == RB_RED) { \ 455 | RB_SET_BLACKRED(tmp, parent, field); \ 456 | RB_ROTATE_LEFT(head, parent, tmp, field); \ 457 | tmp = RB_RIGHT(parent, field); \ 458 | } \ 459 | if ((RB_LEFT(tmp, field) == NULL || \ 460 | RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \ 461 | (RB_RIGHT(tmp, field) == NULL || \ 462 | RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \ 463 | RB_COLOR(tmp, field) = RB_RED; \ 464 | elm = parent; \ 465 | parent = RB_PARENT(elm, field); \ 466 | } else { \ 467 | if (RB_RIGHT(tmp, field) == NULL || \ 468 | RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) { \ 469 | struct type *oleft; \ 470 | if ((oleft = RB_LEFT(tmp, field)) \ 471 | != NULL) \ 472 | RB_COLOR(oleft, field) = RB_BLACK; \ 473 | RB_COLOR(tmp, field) = RB_RED; \ 474 | RB_ROTATE_RIGHT(head, tmp, oleft, field); \ 475 | tmp = RB_RIGHT(parent, field); \ 476 | } \ 477 | RB_COLOR(tmp, field) = RB_COLOR(parent, field); \ 478 | RB_COLOR(parent, field) = RB_BLACK; \ 479 | if (RB_RIGHT(tmp, field)) \ 480 | RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \ 481 | RB_ROTATE_LEFT(head, parent, tmp, field); \ 482 | elm = RB_ROOT(head); \ 483 | break; \ 484 | } \ 485 | } else { \ 486 | tmp = RB_LEFT(parent, field); \ 487 | if (RB_COLOR(tmp, field) == RB_RED) { \ 488 | RB_SET_BLACKRED(tmp, parent, field); \ 489 | RB_ROTATE_RIGHT(head, parent, tmp, field); \ 490 | tmp = RB_LEFT(parent, field); \ 491 | } \ 492 | if ((RB_LEFT(tmp, field) == NULL || \ 493 | RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \ 494 | (RB_RIGHT(tmp, field) == NULL || \ 495 | RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \ 496 | RB_COLOR(tmp, field) = RB_RED; \ 497 | elm = parent; \ 498 | parent = RB_PARENT(elm, field); \ 499 | } else { \ 500 | if (RB_LEFT(tmp, field) == NULL || \ 501 | RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) { \ 502 | struct type *oright; \ 503 | if ((oright = RB_RIGHT(tmp, field)) \ 504 | != NULL) \ 505 | RB_COLOR(oright, field) = RB_BLACK; \ 506 | RB_COLOR(tmp, field) = RB_RED; \ 507 | RB_ROTATE_LEFT(head, tmp, oright, field); \ 508 | tmp = RB_LEFT(parent, field); \ 509 | } \ 510 | RB_COLOR(tmp, field) = RB_COLOR(parent, field); \ 511 | RB_COLOR(parent, field) = RB_BLACK; \ 512 | if (RB_LEFT(tmp, field)) \ 513 | RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \ 514 | RB_ROTATE_RIGHT(head, parent, tmp, field); \ 515 | elm = RB_ROOT(head); \ 516 | break; \ 517 | } \ 518 | } \ 519 | } \ 520 | if (elm) \ 521 | RB_COLOR(elm, field) = RB_BLACK; \ 522 | } \ 523 | \ 524 | attr struct type * \ 525 | name##_RB_REMOVE(struct name *head, struct type *elm) \ 526 | { \ 527 | struct type *child, *parent, *old = elm; \ 528 | int color; \ 529 | if (RB_LEFT(elm, field) == NULL) \ 530 | child = RB_RIGHT(elm, field); \ 531 | else if (RB_RIGHT(elm, field) == NULL) \ 532 | child = RB_LEFT(elm, field); \ 533 | else { \ 534 | struct type *left; \ 535 | elm = RB_RIGHT(elm, field); \ 536 | while ((left = RB_LEFT(elm, field)) != NULL) \ 537 | elm = left; \ 538 | child = RB_RIGHT(elm, field); \ 539 | parent = RB_PARENT(elm, field); \ 540 | color = RB_COLOR(elm, field); \ 541 | if (child) \ 542 | RB_PARENT(child, field) = parent; \ 543 | if (parent) { \ 544 | if (RB_LEFT(parent, field) == elm) \ 545 | RB_LEFT(parent, field) = child; \ 546 | else \ 547 | RB_RIGHT(parent, field) = child; \ 548 | RB_AUGMENT(parent); \ 549 | } else \ 550 | RB_ROOT(head) = child; \ 551 | if (RB_PARENT(elm, field) == old) \ 552 | parent = elm; \ 553 | (elm)->field = (old)->field; \ 554 | if (RB_PARENT(old, field)) { \ 555 | if (RB_LEFT(RB_PARENT(old, field), field) == old) \ 556 | RB_LEFT(RB_PARENT(old, field), field) = elm; \ 557 | else \ 558 | RB_RIGHT(RB_PARENT(old, field), field) = elm; \ 559 | RB_AUGMENT(RB_PARENT(old, field)); \ 560 | } else \ 561 | RB_ROOT(head) = elm; \ 562 | RB_PARENT(RB_LEFT(old, field), field) = elm; \ 563 | if (RB_RIGHT(old, field)) \ 564 | RB_PARENT(RB_RIGHT(old, field), field) = elm; \ 565 | if (parent) { \ 566 | left = parent; \ 567 | do { \ 568 | RB_AUGMENT(left); \ 569 | } while ((left = RB_PARENT(left, field)) != NULL); \ 570 | } \ 571 | goto color; \ 572 | } \ 573 | parent = RB_PARENT(elm, field); \ 574 | color = RB_COLOR(elm, field); \ 575 | if (child) \ 576 | RB_PARENT(child, field) = parent; \ 577 | if (parent) { \ 578 | if (RB_LEFT(parent, field) == elm) \ 579 | RB_LEFT(parent, field) = child; \ 580 | else \ 581 | RB_RIGHT(parent, field) = child; \ 582 | RB_AUGMENT(parent); \ 583 | } else \ 584 | RB_ROOT(head) = child; \ 585 | color: \ 586 | if (color == RB_BLACK) \ 587 | name##_RB_REMOVE_COLOR(head, parent, child); \ 588 | return (old); \ 589 | } \ 590 | \ 591 | /* Inserts a node into the RB tree */ \ 592 | attr struct type * \ 593 | name##_RB_INSERT(struct name *head, struct type *elm) { \ 594 | struct type *tmp; \ 595 | struct type *parent = NULL; \ 596 | int comp = 0; \ 597 | tmp = RB_ROOT(head); \ 598 | while (tmp) { \ 599 | parent = tmp; \ 600 | comp = (cmp)(elm, parent); \ 601 | if (comp < 0) \ 602 | tmp = RB_LEFT(tmp, field); \ 603 | else if (comp > 0) \ 604 | tmp = RB_RIGHT(tmp, field); \ 605 | else \ 606 | return (tmp); \ 607 | } \ 608 | RB_SET(elm, parent, field); \ 609 | if (parent != NULL) { \ 610 | if (comp < 0) \ 611 | RB_LEFT(parent, field) = elm; \ 612 | else \ 613 | RB_RIGHT(parent, field) = elm; \ 614 | RB_AUGMENT(parent); \ 615 | } else \ 616 | RB_ROOT(head) = elm; \ 617 | name##_RB_INSERT_COLOR(head, elm); \ 618 | return (NULL); \ 619 | } \ 620 | \ 621 | /* Finds the node with the same key as elm */ \ 622 | attr struct type * \ 623 | name##_RB_FIND(struct name *head, struct type *elm) { \ 624 | struct type *tmp = RB_ROOT(head); \ 625 | int comp; \ 626 | while (tmp) { \ 627 | comp = cmp(elm, tmp); \ 628 | if (comp < 0) \ 629 | tmp = RB_LEFT(tmp, field); \ 630 | else if (comp > 0) \ 631 | tmp = RB_RIGHT(tmp, field); \ 632 | else \ 633 | return (tmp); \ 634 | } \ 635 | return (NULL); \ 636 | } \ 637 | \ 638 | /* Finds the first node greater than or equal to the search key */ \ 639 | attr struct type * \ 640 | name##_RB_NFIND(struct name *head, struct type *elm) \ 641 | { \ 642 | struct type *tmp = RB_ROOT(head); \ 643 | struct type *res = NULL; \ 644 | int comp; \ 645 | while (tmp) { \ 646 | comp = cmp(elm, tmp); \ 647 | if (comp < 0) { \ 648 | res = tmp; \ 649 | tmp = RB_LEFT(tmp, field); \ 650 | } \ 651 | else if (comp > 0) \ 652 | tmp = RB_RIGHT(tmp, field); \ 653 | else \ 654 | return (tmp); \ 655 | } \ 656 | return (res); \ 657 | } \ 658 | \ 659 | /* ARGSUSED */ \ 660 | attr struct type * \ 661 | name##_RB_NEXT(struct type *elm) \ 662 | { \ 663 | if (RB_RIGHT(elm, field)) { \ 664 | elm = RB_RIGHT(elm, field); \ 665 | while (RB_LEFT(elm, field)) \ 666 | elm = RB_LEFT(elm, field); \ 667 | } else { \ 668 | if (RB_PARENT(elm, field) && \ 669 | (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ 670 | elm = RB_PARENT(elm, field); \ 671 | else { \ 672 | while (RB_PARENT(elm, field) && \ 673 | (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ 674 | elm = RB_PARENT(elm, field); \ 675 | elm = RB_PARENT(elm, field); \ 676 | } \ 677 | } \ 678 | return (elm); \ 679 | } \ 680 | \ 681 | /* ARGSUSED */ \ 682 | attr struct type * \ 683 | name##_RB_PREV(struct type *elm) \ 684 | { \ 685 | if (RB_LEFT(elm, field)) { \ 686 | elm = RB_LEFT(elm, field); \ 687 | while (RB_RIGHT(elm, field)) \ 688 | elm = RB_RIGHT(elm, field); \ 689 | } else { \ 690 | if (RB_PARENT(elm, field) && \ 691 | (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ 692 | elm = RB_PARENT(elm, field); \ 693 | else { \ 694 | while (RB_PARENT(elm, field) && \ 695 | (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ 696 | elm = RB_PARENT(elm, field); \ 697 | elm = RB_PARENT(elm, field); \ 698 | } \ 699 | } \ 700 | return (elm); \ 701 | } \ 702 | \ 703 | attr struct type * \ 704 | name##_RB_MINMAX(struct name *head, int val) \ 705 | { \ 706 | struct type *tmp = RB_ROOT(head); \ 707 | struct type *parent = NULL; \ 708 | while (tmp) { \ 709 | parent = tmp; \ 710 | if (val < 0) \ 711 | tmp = RB_LEFT(tmp, field); \ 712 | else \ 713 | tmp = RB_RIGHT(tmp, field); \ 714 | } \ 715 | return (parent); \ 716 | } 717 | 718 | #define RB_NEGINF -1 719 | #define RB_INF 1 720 | 721 | #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) 722 | #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) 723 | #define RB_FIND(name, x, y) name##_RB_FIND(x, y) 724 | #define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) 725 | #define RB_NEXT(name, x, y) name##_RB_NEXT(y) 726 | #define RB_PREV(name, x, y) name##_RB_PREV(y) 727 | #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) 728 | #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) 729 | 730 | #define RB_FOREACH(x, name, head) \ 731 | for ((x) = RB_MIN(name, head); \ 732 | (x) != NULL; \ 733 | (x) = name##_RB_NEXT(x)) 734 | 735 | #define RB_FOREACH_FROM(x, name, y) \ 736 | for ((x) = (y); \ 737 | ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ 738 | (x) = (y)) 739 | 740 | #define RB_FOREACH_SAFE(x, name, head, y) \ 741 | for ((x) = RB_MIN(name, head); \ 742 | ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ 743 | (x) = (y)) 744 | 745 | #define RB_FOREACH_REVERSE(x, name, head) \ 746 | for ((x) = RB_MAX(name, head); \ 747 | (x) != NULL; \ 748 | (x) = name##_RB_PREV(x)) 749 | 750 | #define RB_FOREACH_REVERSE_FROM(x, name, y) \ 751 | for ((x) = (y); \ 752 | ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ 753 | (x) = (y)) 754 | 755 | #define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ 756 | for ((x) = RB_MAX(name, head); \ 757 | ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ 758 | (x) = (y)) 759 | 760 | 761 | 762 | #endif 763 | 764 | 765 | 766 | 767 | 768 | -------------------------------------------------------------------------------- /.vscode/test.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | #define ENABLE_SEND 1 20 | #define ENABLE_ARP 1 21 | #define ENABLE_ICMP 1 22 | #define ENABLE_ARP_REPLY 1 23 | 24 | #define ENABLE_DEBUG 1 25 | 26 | #define ENABLE_TIMER 1 27 | 28 | #define ENABLE_RINGBUFFER 1 29 | #define ENABLE_MULTHREAD 1 30 | 31 | #define ENABLE_UDP_APP 1 32 | 33 | #define ENABLE_TCP_APP 1 34 | 35 | #define ENABLE_KNI_APP 1 36 | 37 | #define ENABLE_DDOS_DETECT 1 38 | 39 | #define ENABLE_SINGLE_EPOLL 1 40 | 41 | 42 | #define NUM_MBUFS (4096-1) 43 | 44 | #define BURST_SIZE 32 45 | #define RING_SIZE 1024 46 | #define MAX_PACKET_SIZE 2048 47 | #define TIMER_RESOLUTION_CYCLES 120000000000ULL // 10ms * 1000 = 10s * 6 48 | 49 | 50 | #if ENABLE_SINGLE_EPOLL 51 | 52 | #include 53 | #include "nty_tree.h" 54 | 55 | enum EPOLL_EVENTS { 56 | EPOLLNONE = 0x0000, 57 | EPOLLIN = 0x0001, 58 | EPOLLPRI = 0x0002, 59 | EPOLLOUT = 0x0004, 60 | EPOLLRDNORM = 0x0040, 61 | EPOLLRDBAND = 0x0080, 62 | EPOLLWRNORM = 0x0100, 63 | EPOLLWRBAND = 0x0200, 64 | EPOLLMSG = 0x0400, 65 | EPOLLERR = 0x0008, 66 | EPOLLHUP = 0x0010, 67 | EPOLLRDHUP = 0x2000, 68 | EPOLLONESHOT = (1 << 30), 69 | EPOLLET = (1 << 31) 70 | 71 | }; 72 | 73 | #define EPOLL_CTL_ADD 1 74 | #define EPOLL_CTL_DEL 2 75 | #define EPOLL_CTL_MOD 3 76 | 77 | typedef union epoll_data { 78 | void *ptr; 79 | int fd; 80 | uint32_t u32; 81 | uint64_t u64; 82 | } epoll_data_t; 83 | 84 | struct epoll_event { 85 | uint32_t events; 86 | epoll_data_t data; 87 | }; 88 | 89 | 90 | 91 | struct epitem { 92 | RB_ENTRY(epitem) rbn; 93 | LIST_ENTRY(epitem) rdlink; 94 | int rdy; //exist in list 95 | 96 | int sockfd; 97 | struct epoll_event event; 98 | }; 99 | 100 | static int sockfd_cmp(struct epitem *ep1, struct epitem *ep2) { 101 | if (ep1->sockfd < ep2->sockfd) return -1; 102 | else if (ep1->sockfd == ep2->sockfd) return 0; 103 | return 1; 104 | } 105 | 106 | 107 | RB_HEAD(_epoll_rb_socket, epitem); 108 | RB_GENERATE_STATIC(_epoll_rb_socket, epitem, rbn, sockfd_cmp); 109 | 110 | typedef struct _epoll_rb_socket ep_rb_tree; 111 | 112 | // 113 | struct eventpoll { 114 | int fd; 115 | 116 | ep_rb_tree rbr; 117 | int rbcnt; 118 | 119 | LIST_HEAD( ,epitem) rdlist; 120 | int rdnum; 121 | 122 | int waiting; 123 | 124 | pthread_mutex_t mtx; //rbtree update 125 | pthread_spinlock_t lock; //rdlist update 126 | 127 | pthread_cond_t cond; //block for event 128 | pthread_mutex_t cdmtx; //mutex for cond 129 | 130 | }; 131 | 132 | int epoll_event_callback(struct eventpoll *ep, int sockid, uint32_t event); 133 | int nepoll_create(int size); 134 | int nepoll_ctl(int epfd, int op, int sockid, struct epoll_event *event); 135 | int nepoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); 136 | 137 | 138 | 139 | 140 | 141 | #endif 142 | 143 | 144 | #if ENABLE_ARP 145 | 146 | #define ARP_ENTRY_STATUS_DYNAMIC 0 147 | #define ARP_ENTRY_STATUS_STATIC 1 148 | 149 | 150 | #define LL_ADD(item, list) do { \ 151 | item->prev = NULL; \ 152 | item->next = list; \ 153 | if (list != NULL) list->prev = item; \ 154 | list = item; \ 155 | } while(0) 156 | 157 | 158 | #define LL_REMOVE(item, list) do { \ 159 | if (item->prev != NULL) item->prev->next = item->next; \ 160 | if (item->next != NULL) item->next->prev = item->prev; \ 161 | if (list == item) list = item->next; \ 162 | item->prev = item->next = NULL; \ 163 | } while(0) 164 | 165 | 166 | struct arp_entry { 167 | 168 | uint32_t ip; 169 | uint8_t hwaddr[RTE_ETHER_ADDR_LEN]; 170 | 171 | uint8_t type; 172 | // 173 | 174 | struct arp_entry *next; 175 | struct arp_entry *prev; 176 | 177 | 178 | }; 179 | 180 | struct arp_table { 181 | 182 | struct arp_entry *entries; 183 | int count; 184 | 185 | pthread_spinlock_t spinlock; 186 | }; 187 | 188 | 189 | 190 | static struct arp_table *arpt = NULL; 191 | 192 | static struct arp_table *arp_table_instance(void) { 193 | 194 | if (arpt == NULL) { 195 | 196 | arpt = rte_malloc("arp table", sizeof(struct arp_table), 0); 197 | if (arpt == NULL) { 198 | rte_exit(EXIT_FAILURE, "rte_malloc arp table failed\n"); 199 | } 200 | memset(arpt, 0, sizeof(struct arp_table)); 201 | 202 | pthread_spin_init(&arpt->spinlock, PTHREAD_PROCESS_SHARED); 203 | } 204 | 205 | return arpt; 206 | 207 | } 208 | 209 | 210 | static uint8_t* ng_get_dst_macaddr(uint32_t dip) { 211 | 212 | struct arp_entry *iter; 213 | struct arp_table *table = arp_table_instance(); 214 | 215 | int count = table->count; 216 | 217 | for (iter = table->entries; count-- != 0 && iter != NULL;iter = iter->next) { 218 | if (dip == iter->ip) { 219 | return iter->hwaddr; 220 | } 221 | } 222 | 223 | return NULL; 224 | } 225 | 226 | static int ng_arp_entry_insert(uint32_t ip, uint8_t *mac) { 227 | 228 | struct arp_table *table = arp_table_instance(); 229 | 230 | uint8_t *hwaddr = ng_get_dst_macaddr(ip); 231 | if (hwaddr == NULL) { 232 | 233 | struct arp_entry *entry = rte_malloc("arp_entry",sizeof(struct arp_entry), 0); 234 | if (entry) { 235 | memset(entry, 0, sizeof(struct arp_entry)); 236 | 237 | entry->ip = ip; 238 | rte_memcpy(entry->hwaddr, mac, RTE_ETHER_ADDR_LEN); 239 | entry->type = 0; 240 | 241 | pthread_spin_lock(&table->spinlock); 242 | LL_ADD(entry, table->entries); 243 | table->count ++; 244 | pthread_spin_unlock(&table->spinlock); 245 | 246 | } 247 | 248 | return 1; // 249 | } 250 | 251 | return 0; 252 | } 253 | 254 | #endif 255 | 256 | #if ENABLE_SEND 257 | 258 | #define MAKE_IPV4_ADDR(a, b, c, d) (a + (b<<8) + (c<<16) + (d<<24)) 259 | 260 | static uint32_t gLocalIp = MAKE_IPV4_ADDR(192, 168, 0, 119); 261 | 262 | static uint8_t gSrcMac[RTE_ETHER_ADDR_LEN]; 263 | 264 | #endif 265 | 266 | #if ENABLE_KNI_APP 267 | 268 | struct rte_kni *global_kni = NULL; 269 | 270 | 271 | #endif 272 | 273 | #if ENABLE_ARP_REPLY 274 | 275 | static uint8_t gDefaultArpMac[RTE_ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 276 | 277 | #endif 278 | 279 | #if ENABLE_RINGBUFFER 280 | 281 | struct inout_ring { 282 | 283 | struct rte_ring *in; 284 | struct rte_ring *out; 285 | }; 286 | 287 | static struct inout_ring *rInst = NULL; 288 | 289 | static struct inout_ring *ringInstance(void) { 290 | 291 | if (rInst == NULL) { 292 | 293 | rInst = rte_malloc("in/out ring", sizeof(struct inout_ring), 0); 294 | memset(rInst, 0, sizeof(struct inout_ring)); 295 | } 296 | 297 | return rInst; 298 | } 299 | 300 | #endif 301 | 302 | #if ENABLE_UDP_APP 303 | 304 | static int udp_process(struct rte_mbuf *udpmbuf); 305 | static int udp_out(struct rte_mempool *mbuf_pool); 306 | 307 | 308 | #endif 309 | 310 | #if ENABLE_TCP_APP 311 | 312 | static int ng_tcp_process(struct rte_mbuf *tcpmbuf); 313 | static int ng_tcp_out(struct rte_mempool *mbuf_pool); 314 | 315 | 316 | #define TCP_OPTION_LENGTH 10 317 | 318 | #define TCP_MAX_SEQ 4294967295 319 | 320 | #define TCP_INITIAL_WINDOW 14600 321 | 322 | typedef enum _NG_TCP_STATUS { 323 | 324 | NG_TCP_STATUS_CLOSED = 0, 325 | NG_TCP_STATUS_LISTEN, 326 | NG_TCP_STATUS_SYN_RCVD, 327 | NG_TCP_STATUS_SYN_SENT, 328 | NG_TCP_STATUS_ESTABLISHED, 329 | 330 | NG_TCP_STATUS_FIN_WAIT_1, 331 | NG_TCP_STATUS_FIN_WAIT_2, 332 | NG_TCP_STATUS_CLOSING, 333 | NG_TCP_STATUS_TIME_WAIT, 334 | 335 | NG_TCP_STATUS_CLOSE_WAIT, 336 | NG_TCP_STATUS_LAST_ACK 337 | 338 | } NG_TCP_STATUS; 339 | 340 | 341 | struct ng_tcp_stream { // tcb control block 342 | 343 | int fd; // 344 | 345 | uint32_t dip; 346 | uint8_t localmac[RTE_ETHER_ADDR_LEN]; 347 | uint16_t dport; 348 | 349 | uint8_t protocol; 350 | 351 | uint16_t sport; 352 | uint32_t sip; 353 | 354 | uint32_t snd_nxt; // seqnum 355 | uint32_t rcv_nxt; // acknum 356 | 357 | NG_TCP_STATUS status; 358 | #if 0 359 | union { 360 | 361 | struct { 362 | struct ng_tcp_stream *syn_set; // 363 | struct ng_tcp_stream *accept_set; // 364 | }; 365 | 366 | struct { 367 | struct rte_ring *sndbuf; 368 | struct rte_ring *rcvbuf; 369 | }; 370 | }; 371 | #else 372 | struct rte_ring *sndbuf; 373 | struct rte_ring *rcvbuf; 374 | #endif 375 | struct ng_tcp_stream *prev; 376 | struct ng_tcp_stream *next; 377 | 378 | pthread_cond_t cond; 379 | pthread_mutex_t mutex; 380 | 381 | }; 382 | 383 | struct ng_tcp_table { 384 | int count; 385 | //struct ng_tcp_stream *listener_set; // 386 | #if ENABLE_SINGLE_EPOLL 387 | struct eventpoll *ep; // single epoll 388 | #endif 389 | struct ng_tcp_stream *tcb_set; 390 | }; 391 | 392 | struct ng_tcp_fragment { 393 | 394 | uint16_t sport; 395 | uint16_t dport; 396 | uint32_t seqnum; 397 | uint32_t acknum; 398 | uint8_t hdrlen_off; 399 | uint8_t tcp_flags; 400 | uint16_t windows; 401 | uint16_t cksum; 402 | uint16_t tcp_urp; 403 | 404 | int optlen; 405 | uint32_t option[TCP_OPTION_LENGTH]; 406 | 407 | unsigned char *data; 408 | uint32_t length; 409 | 410 | }; 411 | 412 | 413 | struct ng_tcp_table *tInst = NULL; 414 | 415 | static struct ng_tcp_table *tcpInstance(void) { 416 | 417 | if (tInst == NULL) { 418 | 419 | tInst = rte_malloc("ng_tcp_table", sizeof(struct ng_tcp_table), 0); 420 | memset(tInst, 0, sizeof(struct ng_tcp_table)); 421 | 422 | } 423 | return tInst; 424 | } 425 | 426 | 427 | 428 | 429 | #endif 430 | 431 | 432 | int gDpdkPortId = 0; 433 | 434 | 435 | 436 | static const struct rte_eth_conf port_conf_default = { 437 | .rxmode = {.max_rx_pkt_len = RTE_ETHER_MAX_LEN } 438 | }; 439 | 440 | static void ng_init_port(struct rte_mempool *mbuf_pool) { 441 | 442 | uint16_t nb_sys_ports= rte_eth_dev_count_avail(); // 443 | if (nb_sys_ports == 0) { 444 | rte_exit(EXIT_FAILURE, "No Supported eth found\n"); 445 | } 446 | 447 | struct rte_eth_dev_info dev_info; 448 | rte_eth_dev_info_get(gDpdkPortId, &dev_info); // 449 | 450 | const int num_rx_queues = 1; 451 | const int num_tx_queues = 1; 452 | struct rte_eth_conf port_conf = port_conf_default; 453 | rte_eth_dev_configure(gDpdkPortId, num_rx_queues, num_tx_queues, &port_conf); 454 | 455 | 456 | if (rte_eth_rx_queue_setup(gDpdkPortId, 0 , 1024, 457 | rte_eth_dev_socket_id(gDpdkPortId),NULL, mbuf_pool) < 0) { 458 | 459 | rte_exit(EXIT_FAILURE, "Could not setup RX queue\n"); 460 | 461 | } 462 | 463 | #if ENABLE_SEND 464 | struct rte_eth_txconf txq_conf = dev_info.default_txconf; 465 | txq_conf.offloads = port_conf.rxmode.offloads; 466 | if (rte_eth_tx_queue_setup(gDpdkPortId, 0 , 1024, 467 | rte_eth_dev_socket_id(gDpdkPortId), &txq_conf) < 0) { 468 | 469 | rte_exit(EXIT_FAILURE, "Could not setup TX queue\n"); 470 | 471 | } 472 | #endif 473 | 474 | if (rte_eth_dev_start(gDpdkPortId) < 0 ) { 475 | rte_exit(EXIT_FAILURE, "Could not start\n"); 476 | } 477 | 478 | #if ENABLE_KNI_APP 479 | rte_eth_promiscuous_enable(gDpdkPortId); 480 | #endif 481 | } 482 | 483 | /* 484 | static int ng_encode_udp_pkt(uint8_t *msg, unsigned char *data, uint16_t total_len) { 485 | 486 | // encode 487 | 488 | // 1 ethhdr 489 | struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg; 490 | rte_memcpy(eth->s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN); 491 | rte_memcpy(eth->d_addr.addr_bytes, gDstMac, RTE_ETHER_ADDR_LEN); 492 | eth->ether_type = htons(RTE_ETHER_TYPE_IPV4); 493 | 494 | 495 | // 2 iphdr 496 | struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(msg + sizeof(struct rte_ether_hdr)); 497 | ip->version_ihl = 0x45; 498 | ip->type_of_service = 0; 499 | ip->total_length = htons(total_len - sizeof(struct rte_ether_hdr)); 500 | ip->packet_id = 0; 501 | ip->fragment_offset = 0; 502 | ip->time_to_live = 64; // ttl = 64 503 | ip->next_proto_id = IPPROTO_UDP; 504 | ip->src_addr = gSrcIp; 505 | ip->dst_addr = gDstIp; 506 | 507 | ip->hdr_checksum = 0; 508 | ip->hdr_checksum = rte_ipv4_cksum(ip); 509 | 510 | // 3 udphdr 511 | 512 | struct rte_udp_hdr *udp = (struct rte_udp_hdr *)(msg + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); 513 | udp->src_port = gSrcPort; 514 | udp->dst_port = gDstPort; 515 | uint16_t udplen = total_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr); 516 | udp->dgram_len = htons(udplen); 517 | 518 | rte_memcpy((uint8_t*)(udp+1), data, udplen); 519 | 520 | udp->dgram_cksum = 0; 521 | udp->dgram_cksum = rte_ipv4_udptcp_cksum(ip, udp); 522 | 523 | struct in_addr addr; 524 | addr.s_addr = gSrcIp; 525 | printf(" --> src: %s:%d, ", inet_ntoa(addr), ntohs(gSrcPort)); 526 | 527 | addr.s_addr = gDstIp; 528 | printf("dst: %s:%d\n", inet_ntoa(addr), ntohs(gDstPort)); 529 | 530 | return 0; 531 | } 532 | 533 | 534 | static struct rte_mbuf * ng_send_udp(struct rte_mempool *mbuf_pool, uint8_t *data, uint16_t length) { 535 | 536 | // mempool --> mbuf 537 | 538 | const unsigned total_len = length + 42; 539 | 540 | struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool); 541 | if (!mbuf) { 542 | rte_exit(EXIT_FAILURE, "rte_pktmbuf_alloc\n"); 543 | } 544 | mbuf->pkt_len = total_len; 545 | mbuf->data_len = total_len; 546 | 547 | uint8_t *pktdata = rte_pktmbuf_mtod(mbuf, uint8_t*); 548 | 549 | ng_encode_udp_pkt(pktdata, data, total_len); 550 | 551 | return mbuf; 552 | 553 | } 554 | 555 | */ 556 | 557 | #if ENABLE_ARP 558 | 559 | 560 | static int ng_encode_arp_pkt(uint8_t *msg, uint16_t opcode, uint8_t *dst_mac, uint32_t sip, uint32_t dip) { 561 | 562 | // 1 ethhdr 563 | struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg; 564 | rte_memcpy(eth->s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN); 565 | if (!strncmp((const char *)dst_mac, (const char *)gDefaultArpMac, RTE_ETHER_ADDR_LEN)) { 566 | uint8_t mac[RTE_ETHER_ADDR_LEN] = {0x0}; 567 | rte_memcpy(eth->d_addr.addr_bytes, mac, RTE_ETHER_ADDR_LEN); 568 | } else { 569 | rte_memcpy(eth->d_addr.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN); 570 | } 571 | eth->ether_type = htons(RTE_ETHER_TYPE_ARP); 572 | 573 | // 2 arp 574 | struct rte_arp_hdr *arp = (struct rte_arp_hdr *)(eth + 1); 575 | arp->arp_hardware = htons(1); 576 | arp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4); 577 | arp->arp_hlen = RTE_ETHER_ADDR_LEN; 578 | arp->arp_plen = sizeof(uint32_t); 579 | arp->arp_opcode = htons(opcode); 580 | 581 | rte_memcpy(arp->arp_data.arp_sha.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN); 582 | rte_memcpy( arp->arp_data.arp_tha.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN); 583 | 584 | arp->arp_data.arp_sip = sip; 585 | arp->arp_data.arp_tip = dip; 586 | 587 | return 0; 588 | 589 | } 590 | 591 | static struct rte_mbuf *ng_send_arp(struct rte_mempool *mbuf_pool, uint16_t opcode, uint8_t *dst_mac, uint32_t sip, uint32_t dip) { 592 | 593 | const unsigned total_length = sizeof(struct rte_ether_hdr) + sizeof(struct rte_arp_hdr); 594 | 595 | struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool); 596 | if (!mbuf) { 597 | rte_exit(EXIT_FAILURE, "ng_send_arp rte_pktmbuf_alloc\n"); 598 | } 599 | 600 | mbuf->pkt_len = total_length; 601 | mbuf->data_len = total_length; 602 | 603 | uint8_t *pkt_data = rte_pktmbuf_mtod(mbuf, uint8_t *); 604 | ng_encode_arp_pkt(pkt_data, opcode, dst_mac, sip, dip); 605 | 606 | return mbuf; 607 | } 608 | 609 | #endif 610 | 611 | 612 | #if 0 //ENABLE_ICMP 613 | 614 | 615 | static uint16_t ng_checksum(uint16_t *addr, int count) { 616 | 617 | register long sum = 0; 618 | 619 | while (count > 1) { 620 | 621 | sum += *(unsigned short*)addr++; 622 | count -= 2; 623 | 624 | } 625 | 626 | if (count > 0) { 627 | sum += *(unsigned char *)addr; 628 | } 629 | 630 | while (sum >> 16) { 631 | sum = (sum & 0xffff) + (sum >> 16); 632 | } 633 | 634 | return ~sum; 635 | } 636 | 637 | static int ng_encode_icmp_pkt(uint8_t *msg, uint8_t *dst_mac, 638 | uint32_t sip, uint32_t dip, uint16_t id, uint16_t seqnb) { 639 | 640 | // 1 ether 641 | struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg; 642 | rte_memcpy(eth->s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN); 643 | rte_memcpy(eth->d_addr.addr_bytes, dst_mac, RTE_ETHER_ADDR_LEN); 644 | eth->ether_type = htons(RTE_ETHER_TYPE_IPV4); 645 | 646 | // 2 ip 647 | struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(msg + sizeof(struct rte_ether_hdr)); 648 | ip->version_ihl = 0x45; 649 | ip->type_of_service = 0; 650 | ip->total_length = htons(sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_icmp_hdr)); 651 | ip->packet_id = 0; 652 | ip->fragment_offset = 0; 653 | ip->time_to_live = 64; // ttl = 64 654 | ip->next_proto_id = IPPROTO_ICMP; 655 | ip->src_addr = sip; 656 | ip->dst_addr = dip; 657 | 658 | ip->hdr_checksum = 0; 659 | ip->hdr_checksum = rte_ipv4_cksum(ip); 660 | 661 | // 3 icmp 662 | struct rte_icmp_hdr *icmp = (struct rte_icmp_hdr *)(msg + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); 663 | icmp->icmp_type = RTE_IP_ICMP_ECHO_REPLY; 664 | icmp->icmp_code = 0; 665 | icmp->icmp_ident = id; 666 | icmp->icmp_seq_nb = seqnb; 667 | 668 | icmp->icmp_cksum = 0; 669 | icmp->icmp_cksum = ng_checksum((uint16_t*)icmp, sizeof(struct rte_icmp_hdr)); 670 | 671 | return 0; 672 | } 673 | 674 | 675 | static struct rte_mbuf *ng_send_icmp(struct rte_mempool *mbuf_pool, uint8_t *dst_mac, 676 | uint32_t sip, uint32_t dip, uint16_t id, uint16_t seqnb) { 677 | 678 | const unsigned total_length = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_icmp_hdr); 679 | 680 | struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool); 681 | if (!mbuf) { 682 | rte_exit(EXIT_FAILURE, "rte_pktmbuf_alloc\n"); 683 | } 684 | 685 | 686 | mbuf->pkt_len = total_length; 687 | mbuf->data_len = total_length; 688 | 689 | uint8_t *pkt_data = rte_pktmbuf_mtod(mbuf, uint8_t *); 690 | ng_encode_icmp_pkt(pkt_data, dst_mac, sip, dip, id, seqnb); 691 | 692 | return mbuf; 693 | 694 | } 695 | 696 | 697 | #endif 698 | 699 | static void 700 | print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 701 | { 702 | char buf[RTE_ETHER_ADDR_FMT_SIZE]; 703 | rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 704 | printf("%s%s", name, buf); 705 | } 706 | 707 | 708 | #if ENABLE_TIMER 709 | 710 | static void 711 | arp_request_timer_cb(__attribute__((unused)) struct rte_timer *tim, 712 | void *arg) { 713 | 714 | struct rte_mempool *mbuf_pool = (struct rte_mempool *)arg; 715 | struct inout_ring *ring = ringInstance(); 716 | 717 | #if 0 718 | struct rte_mbuf *arpbuf = ng_send_arp(mbuf_pool, RTE_ARP_OP_REQUEST, ahdr->arp_data.arp_sha.addr_bytes, 719 | ahdr->arp_data.arp_tip, ahdr->arp_data.arp_sip); 720 | 721 | rte_eth_tx_burst(gDpdkPortId, 0, &arpbuf, 1); 722 | rte_pktmbuf_free(arpbuf); 723 | 724 | #endif 725 | 726 | int i = 0; 727 | for (i = 1;i <= 254;i ++) { 728 | 729 | uint32_t dstip = (gLocalIp & 0x00FFFFFF) | (0xFF000000 & (i << 24)); 730 | /* 731 | struct in_addr addr; 732 | addr.s_addr = dstip; 733 | printf("arp ---> src: %s \n", inet_ntoa(addr)); 734 | */ 735 | struct rte_mbuf *arpbuf = NULL; 736 | uint8_t *dstmac = ng_get_dst_macaddr(dstip); 737 | if (dstmac == NULL) { 738 | 739 | arpbuf = ng_send_arp(mbuf_pool, RTE_ARP_OP_REQUEST, gDefaultArpMac, gLocalIp, dstip); 740 | 741 | } else { 742 | 743 | arpbuf = ng_send_arp(mbuf_pool, RTE_ARP_OP_REQUEST, dstmac, gLocalIp, dstip); 744 | } 745 | 746 | //rte_eth_tx_burst(gDpdkPortId, 0, &arpbuf, 1); 747 | //rte_pktmbuf_free(arpbuf); 748 | rte_ring_mp_enqueue_burst(ring->out, (void**)&arpbuf, 1, NULL); 749 | 750 | } 751 | 752 | } 753 | 754 | 755 | #endif 756 | 757 | #if ENABLE_MULTHREAD 758 | 759 | 760 | 761 | static int pkt_process(void *arg) { 762 | 763 | struct rte_mempool *mbuf_pool = (struct rte_mempool *)arg; 764 | struct inout_ring *ring = ringInstance(); 765 | 766 | while (1) { 767 | 768 | struct rte_mbuf *mbufs[BURST_SIZE]; 769 | unsigned num_recvd = rte_ring_mc_dequeue_burst(ring->in, (void**)mbufs, BURST_SIZE, NULL); 770 | 771 | unsigned i = 0; 772 | for (i = 0;i < num_recvd;i ++) { 773 | 774 | struct rte_ether_hdr *ehdr = rte_pktmbuf_mtod(mbufs[i], struct rte_ether_hdr*); 775 | 776 | if (ehdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { 777 | 778 | struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(mbufs[i], struct rte_ipv4_hdr *, 779 | sizeof(struct rte_ether_hdr)); 780 | 781 | 782 | #if 1 // arp table 783 | 784 | ng_arp_entry_insert(iphdr->src_addr, ehdr->s_addr.addr_bytes); 785 | 786 | #endif 787 | 788 | if (iphdr->next_proto_id == IPPROTO_UDP) { 789 | 790 | udp_process(mbufs[i]); 791 | // 53 --> 792 | // 793 | 794 | } else if (iphdr->next_proto_id == IPPROTO_TCP) { 795 | 796 | ng_tcp_process(mbufs[i]); 797 | 798 | } else { 799 | 800 | rte_kni_tx_burst(global_kni, mbufs, num_recvd); 801 | 802 | printf("tcp/udp --> rte_kni_handle_request\n"); 803 | 804 | } 805 | 806 | 807 | } else { 808 | // ifconfig vEth0 192.168.0.119 up 809 | 810 | rte_kni_tx_burst(global_kni, mbufs, num_recvd); 811 | 812 | printf("ip --> rte_kni_handle_request\n"); 813 | 814 | } 815 | 816 | 817 | } 818 | 819 | rte_kni_handle_request(global_kni); 820 | 821 | #if ENABLE_UDP_APP 822 | 823 | udp_out(mbuf_pool); 824 | 825 | #endif 826 | 827 | 828 | #if ENABLE_TCP_APP 829 | 830 | ng_tcp_out(mbuf_pool); 831 | 832 | #endif 833 | 834 | } 835 | 836 | return 0; 837 | } 838 | 839 | 840 | #endif 841 | 842 | 843 | #if ENABLE_UDP_APP 844 | 845 | 846 | 847 | struct localhost { // 848 | 849 | int fd; 850 | 851 | //unsigned int status; // 852 | uint32_t localip; // ip --> mac 853 | uint8_t localmac[RTE_ETHER_ADDR_LEN]; 854 | uint16_t localport; 855 | 856 | uint8_t protocol; 857 | 858 | struct rte_ring *sndbuf; 859 | struct rte_ring *rcvbuf; 860 | 861 | struct localhost *prev; // 862 | struct localhost *next; 863 | 864 | pthread_cond_t cond; 865 | pthread_mutex_t mutex; 866 | 867 | }; 868 | 869 | static struct localhost *lhost = NULL; 870 | 871 | #define DEFAULT_FD_NUM 3 872 | 873 | #define MAX_FD_COUNT 1024 874 | 875 | static unsigned char fd_table[MAX_FD_COUNT] = {0}; 876 | 877 | static int get_fd_frombitmap(void) { 878 | 879 | int fd = DEFAULT_FD_NUM; 880 | for ( ;fd < MAX_FD_COUNT;fd ++) { 881 | if ((fd_table[fd/8] & (0x1 << (fd % 8))) == 0) { 882 | fd_table[fd/8] |= (0x1 << (fd % 8)); 883 | return fd; 884 | } 885 | } 886 | 887 | return -1; 888 | 889 | } 890 | 891 | static int set_fd_frombitmap(int fd) { 892 | 893 | if (fd >= MAX_FD_COUNT) return -1; 894 | 895 | fd_table[fd/8] &= ~(0x1 << (fd % 8)); 896 | 897 | return 0; 898 | } 899 | 900 | static struct ng_tcp_stream *get_accept_tcb(uint16_t dport) { 901 | 902 | struct ng_tcp_stream *apt; 903 | struct ng_tcp_table *table = tcpInstance(); 904 | for (apt = table->tcb_set;apt != NULL;apt = apt->next) { 905 | if (dport == apt->dport && apt->fd == -1) { 906 | return apt; 907 | } 908 | } 909 | 910 | return NULL; 911 | } 912 | 913 | //fd --> udp, tcp, epoll 914 | 915 | static void* get_hostinfo_fromfd(int sockfd) { 916 | 917 | struct localhost *host; 918 | 919 | for (host = lhost; host != NULL;host = host->next) { 920 | 921 | if (sockfd == host->fd) { 922 | return host; 923 | } 924 | 925 | } 926 | 927 | #if ENABLE_TCP_APP 928 | 929 | struct ng_tcp_stream *stream = NULL; 930 | struct ng_tcp_table *table = tcpInstance(); 931 | for (stream = table->tcb_set;stream != NULL;stream = stream->next) { 932 | if (sockfd == stream->fd) { 933 | return stream; 934 | } 935 | } 936 | 937 | #endif 938 | 939 | #if ENABLE_SINGLE_EPOLL 940 | 941 | struct eventpoll *ep = table->ep; 942 | if (ep != NULL) { 943 | if (ep->fd == sockfd) { 944 | return ep; 945 | } 946 | } 947 | 948 | #endif 949 | 950 | return NULL; 951 | 952 | } 953 | 954 | static struct localhost * get_hostinfo_fromip_port(uint32_t dip, uint16_t port, uint8_t proto) { 955 | 956 | struct localhost *host; 957 | 958 | for (host = lhost; host != NULL;host = host->next) { 959 | 960 | if (dip == host->localip && port == host->localport && proto == host->protocol) { 961 | return host; 962 | } 963 | 964 | } 965 | 966 | 967 | return NULL; 968 | 969 | } 970 | 971 | // arp 972 | struct offload { // 973 | 974 | uint32_t sip; 975 | uint32_t dip; 976 | 977 | uint16_t sport; 978 | uint16_t dport; // 979 | 980 | int protocol; 981 | 982 | unsigned char *data; 983 | uint16_t length; 984 | 985 | }; 986 | 987 | 988 | static int udp_process(struct rte_mbuf *udpmbuf) { 989 | 990 | struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(udpmbuf, struct rte_ipv4_hdr *, 991 | sizeof(struct rte_ether_hdr)); 992 | struct rte_udp_hdr *udphdr = (struct rte_udp_hdr *)(iphdr + 1); 993 | 994 | 995 | struct in_addr addr; 996 | addr.s_addr = iphdr->src_addr; 997 | printf("udp_process ---> src: %s:%d \n", inet_ntoa(addr), ntohs(udphdr->src_port)); 998 | 999 | struct localhost *host = get_hostinfo_fromip_port(iphdr->dst_addr, udphdr->dst_port, iphdr->next_proto_id); 1000 | if (host == NULL) { 1001 | rte_pktmbuf_free(udpmbuf); 1002 | return -3; 1003 | } 1004 | 1005 | 1006 | struct offload *ol = rte_malloc("offload", sizeof(struct offload), 0); 1007 | if (ol == NULL) { 1008 | rte_pktmbuf_free(udpmbuf); 1009 | return -1; 1010 | } 1011 | 1012 | ol->dip = iphdr->dst_addr; 1013 | ol->sip = iphdr->src_addr; 1014 | ol->sport = udphdr->src_port; 1015 | ol->dport = udphdr->dst_port; 1016 | 1017 | 1018 | ol->protocol = IPPROTO_UDP; 1019 | ol->length = ntohs(udphdr->dgram_len); 1020 | 1021 | ol->data = rte_malloc("unsigned char*", ol->length - sizeof(struct rte_udp_hdr), 0); 1022 | if (ol->data == NULL) { 1023 | 1024 | rte_pktmbuf_free(udpmbuf); 1025 | rte_free(ol); 1026 | 1027 | return -2; 1028 | 1029 | } 1030 | rte_memcpy(ol->data, (unsigned char *)(udphdr+1), ol->length - sizeof(struct rte_udp_hdr)); 1031 | 1032 | rte_ring_mp_enqueue(host->rcvbuf, ol); // recv buffer 1033 | 1034 | pthread_mutex_lock(&host->mutex); 1035 | pthread_cond_signal(&host->cond); 1036 | pthread_mutex_unlock(&host->mutex); 1037 | 1038 | rte_pktmbuf_free(udpmbuf); 1039 | 1040 | return 0; 1041 | } 1042 | 1043 | 1044 | static int ng_encode_udp_apppkt(uint8_t *msg, uint32_t sip, uint32_t dip, 1045 | uint16_t sport, uint16_t dport, uint8_t *srcmac, uint8_t *dstmac, 1046 | unsigned char *data, uint16_t total_len) { 1047 | 1048 | // encode 1049 | 1050 | // 1 ethhdr 1051 | struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg; 1052 | rte_memcpy(eth->s_addr.addr_bytes, srcmac, RTE_ETHER_ADDR_LEN); 1053 | rte_memcpy(eth->d_addr.addr_bytes, dstmac, RTE_ETHER_ADDR_LEN); 1054 | eth->ether_type = htons(RTE_ETHER_TYPE_IPV4); 1055 | 1056 | 1057 | // 2 iphdr 1058 | struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(msg + sizeof(struct rte_ether_hdr)); 1059 | ip->version_ihl = 0x45; 1060 | ip->type_of_service = 0; 1061 | ip->total_length = htons(total_len - sizeof(struct rte_ether_hdr)); 1062 | ip->packet_id = 0; 1063 | ip->fragment_offset = 0; 1064 | ip->time_to_live = 64; // ttl = 64 1065 | ip->next_proto_id = IPPROTO_UDP; 1066 | ip->src_addr = sip; 1067 | ip->dst_addr = dip; 1068 | 1069 | ip->hdr_checksum = 0; 1070 | ip->hdr_checksum = rte_ipv4_cksum(ip); 1071 | 1072 | // 3 udphdr 1073 | 1074 | struct rte_udp_hdr *udp = (struct rte_udp_hdr *)(msg + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); 1075 | udp->src_port = sport; 1076 | udp->dst_port = dport; 1077 | uint16_t udplen = total_len - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr); 1078 | udp->dgram_len = htons(udplen); 1079 | 1080 | rte_memcpy((uint8_t*)(udp+1), data, udplen); 1081 | 1082 | udp->dgram_cksum = 0; 1083 | udp->dgram_cksum = rte_ipv4_udptcp_cksum(ip, udp); 1084 | 1085 | return 0; 1086 | } 1087 | 1088 | 1089 | static struct rte_mbuf * ng_udp_pkt(struct rte_mempool *mbuf_pool, uint32_t sip, uint32_t dip, 1090 | uint16_t sport, uint16_t dport, uint8_t *srcmac, uint8_t *dstmac, 1091 | uint8_t *data, uint16_t length) { 1092 | 1093 | // mempool --> mbuf 1094 | 1095 | const unsigned total_len = length + 42; 1096 | 1097 | struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool); 1098 | if (!mbuf) { 1099 | rte_exit(EXIT_FAILURE, "rte_pktmbuf_alloc\n"); 1100 | } 1101 | mbuf->pkt_len = total_len; 1102 | mbuf->data_len = total_len; 1103 | 1104 | uint8_t *pktdata = rte_pktmbuf_mtod(mbuf, uint8_t*); 1105 | 1106 | ng_encode_udp_apppkt(pktdata, sip, dip, sport, dport, srcmac, dstmac, 1107 | data, total_len); 1108 | 1109 | return mbuf; 1110 | 1111 | } 1112 | 1113 | 1114 | // offload --> mbuf 1115 | static int udp_out(struct rte_mempool *mbuf_pool) { 1116 | 1117 | struct localhost *host; 1118 | for (host = lhost; host != NULL; host = host->next) { 1119 | 1120 | struct offload *ol; 1121 | int nb_snd = rte_ring_mc_dequeue(host->sndbuf, (void **)&ol); 1122 | if (nb_snd < 0) continue; 1123 | 1124 | struct in_addr addr; 1125 | addr.s_addr = ol->dip; 1126 | printf("udp_out ---> src: %s:%d \n", inet_ntoa(addr), ntohs(ol->dport)); 1127 | 1128 | uint8_t *dstmac = ng_get_dst_macaddr(ol->dip); // 1129 | if (dstmac == NULL) { 1130 | 1131 | struct rte_mbuf *arpbuf = ng_send_arp(mbuf_pool, RTE_ARP_OP_REQUEST, gDefaultArpMac, 1132 | ol->sip, ol->dip); 1133 | 1134 | struct inout_ring *ring = ringInstance(); 1135 | rte_ring_mp_enqueue_burst(ring->out, (void **)&arpbuf, 1, NULL); 1136 | 1137 | rte_ring_mp_enqueue(host->sndbuf, ol); 1138 | 1139 | } else { 1140 | 1141 | struct rte_mbuf *udpbuf = ng_udp_pkt(mbuf_pool, ol->sip, ol->dip, ol->sport, ol->dport, 1142 | host->localmac, dstmac, ol->data, ol->length); 1143 | 1144 | 1145 | struct inout_ring *ring = ringInstance(); 1146 | rte_ring_mp_enqueue_burst(ring->out, (void **)&udpbuf, 1, NULL); 1147 | 1148 | } 1149 | 1150 | 1151 | } 1152 | 1153 | return 0; 1154 | } 1155 | 1156 | // hook 1157 | 1158 | static int nsocket(__attribute__((unused)) int domain, int type, __attribute__((unused)) int protocol) { 1159 | 1160 | int fd = get_fd_frombitmap(); // 1161 | 1162 | if (type == SOCK_DGRAM) { 1163 | 1164 | struct localhost *host = rte_malloc("localhost", sizeof(struct localhost), 0); 1165 | if (host == NULL) { 1166 | return -1; 1167 | } 1168 | memset(host, 0, sizeof(struct localhost)); 1169 | 1170 | host->fd = fd; 1171 | 1172 | host->protocol = IPPROTO_UDP; 1173 | 1174 | host->rcvbuf = rte_ring_create("recv buffer", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 1175 | if (host->rcvbuf == NULL) { 1176 | 1177 | rte_free(host); 1178 | return -1; 1179 | } 1180 | 1181 | 1182 | host->sndbuf = rte_ring_create("send buffer", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 1183 | if (host->sndbuf == NULL) { 1184 | 1185 | rte_ring_free(host->rcvbuf); 1186 | 1187 | rte_free(host); 1188 | return -1; 1189 | } 1190 | 1191 | pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER; 1192 | rte_memcpy(&host->cond, &blank_cond, sizeof(pthread_cond_t)); 1193 | 1194 | pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER; 1195 | rte_memcpy(&host->mutex, &blank_mutex, sizeof(pthread_mutex_t)); 1196 | 1197 | LL_ADD(host, lhost); 1198 | 1199 | } else if (type == SOCK_STREAM) { 1200 | 1201 | 1202 | struct ng_tcp_stream *stream = rte_malloc("ng_tcp_stream", sizeof(struct ng_tcp_stream), 0); 1203 | if (stream == NULL) { 1204 | return -1; 1205 | } 1206 | memset(stream, 0, sizeof(struct ng_tcp_stream)); 1207 | 1208 | stream->fd = fd; 1209 | stream->protocol = IPPROTO_TCP; 1210 | stream->next = stream->prev = NULL; 1211 | 1212 | stream->rcvbuf = rte_ring_create("tcp recv buffer", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 1213 | if (stream->rcvbuf == NULL) { 1214 | 1215 | rte_free(stream); 1216 | return -1; 1217 | } 1218 | 1219 | 1220 | stream->sndbuf = rte_ring_create("tcp send buffer", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 1221 | if (stream->sndbuf == NULL) { 1222 | 1223 | rte_ring_free(stream->rcvbuf); 1224 | 1225 | rte_free(stream); 1226 | return -1; 1227 | } 1228 | 1229 | pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER; 1230 | rte_memcpy(&stream->cond, &blank_cond, sizeof(pthread_cond_t)); 1231 | 1232 | pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER; 1233 | rte_memcpy(&stream->mutex, &blank_mutex, sizeof(pthread_mutex_t)); 1234 | 1235 | struct ng_tcp_table *table = tcpInstance(); 1236 | LL_ADD(stream, table->tcb_set); //hash 1237 | // get_stream_from_fd(); 1238 | } 1239 | 1240 | return fd; 1241 | } 1242 | 1243 | static int nbind(int sockfd, const struct sockaddr *addr, 1244 | __attribute__((unused)) socklen_t addrlen) { 1245 | 1246 | void *hostinfo = get_hostinfo_fromfd(sockfd); 1247 | if (hostinfo == NULL) return -1; 1248 | 1249 | struct localhost *host = (struct localhost *)hostinfo; 1250 | if (host->protocol == IPPROTO_UDP) { 1251 | 1252 | const struct sockaddr_in *laddr = (const struct sockaddr_in *)addr; 1253 | host->localport = laddr->sin_port; 1254 | rte_memcpy(&host->localip, &laddr->sin_addr.s_addr, sizeof(uint32_t)); 1255 | rte_memcpy(host->localmac, gSrcMac, RTE_ETHER_ADDR_LEN); 1256 | 1257 | } else if (host->protocol == IPPROTO_TCP) { 1258 | 1259 | struct ng_tcp_stream *stream = (struct ng_tcp_stream *)hostinfo; 1260 | 1261 | const struct sockaddr_in *laddr = (const struct sockaddr_in *)addr; 1262 | stream->dport = laddr->sin_port; 1263 | rte_memcpy(&stream->dip, &laddr->sin_addr.s_addr, sizeof(uint32_t)); 1264 | rte_memcpy(stream->localmac, gSrcMac, RTE_ETHER_ADDR_LEN); 1265 | 1266 | stream->status = NG_TCP_STATUS_CLOSED; 1267 | 1268 | } 1269 | 1270 | return 0; 1271 | 1272 | } 1273 | 1274 | 1275 | static int nlisten(int sockfd, __attribute__((unused)) int backlog) { // 1276 | 1277 | void *hostinfo = get_hostinfo_fromfd(sockfd); 1278 | if (hostinfo == NULL) return -1; 1279 | 1280 | 1281 | struct ng_tcp_stream *stream = (struct ng_tcp_stream *)hostinfo; 1282 | if (stream->protocol == IPPROTO_TCP) { 1283 | stream->status = NG_TCP_STATUS_LISTEN; 1284 | } 1285 | 1286 | return 0; 1287 | } 1288 | 1289 | 1290 | static int naccept(int sockfd, struct sockaddr *addr, __attribute__((unused)) socklen_t *addrlen) { 1291 | 1292 | void *hostinfo = get_hostinfo_fromfd(sockfd); 1293 | if (hostinfo == NULL) return -1; 1294 | 1295 | struct ng_tcp_stream *stream = (struct ng_tcp_stream *)hostinfo; 1296 | if (stream->protocol == IPPROTO_TCP) { 1297 | 1298 | struct ng_tcp_stream *apt = NULL; 1299 | 1300 | pthread_mutex_lock(&stream->mutex); 1301 | while((apt = get_accept_tcb(stream->dport)) == NULL) { 1302 | pthread_cond_wait(&stream->cond, &stream->mutex); 1303 | } 1304 | pthread_mutex_unlock(&stream->mutex); 1305 | 1306 | apt->fd = get_fd_frombitmap(); 1307 | 1308 | struct sockaddr_in *saddr = (struct sockaddr_in *)addr; 1309 | saddr->sin_port = apt->sport; 1310 | rte_memcpy(&saddr->sin_addr.s_addr, &apt->sip, sizeof(uint32_t)); 1311 | 1312 | return apt->fd; 1313 | } 1314 | 1315 | return -1; 1316 | } 1317 | 1318 | 1319 | static ssize_t nsend(int sockfd, const void *buf, size_t len,__attribute__((unused)) int flags) { 1320 | 1321 | ssize_t length = 0; 1322 | 1323 | void *hostinfo = get_hostinfo_fromfd(sockfd); 1324 | if (hostinfo == NULL) return -1; 1325 | 1326 | struct ng_tcp_stream *stream = (struct ng_tcp_stream *)hostinfo; 1327 | if (stream->protocol == IPPROTO_TCP) { 1328 | 1329 | struct ng_tcp_fragment *fragment = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1330 | if (fragment == NULL) { 1331 | return -2; 1332 | } 1333 | 1334 | memset(fragment, 0, sizeof(struct ng_tcp_fragment)); 1335 | 1336 | fragment->dport = stream->sport; 1337 | fragment->sport = stream->dport; 1338 | 1339 | fragment->acknum = stream->rcv_nxt; 1340 | fragment->seqnum = stream->snd_nxt; 1341 | 1342 | fragment->tcp_flags = RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG; 1343 | fragment->windows = TCP_INITIAL_WINDOW; 1344 | fragment->hdrlen_off = 0x50; 1345 | 1346 | 1347 | fragment->data = rte_malloc("unsigned char *", len+1, 0); 1348 | if (fragment->data == NULL) { 1349 | rte_free(fragment); 1350 | return -1; 1351 | } 1352 | memset(fragment->data, 0, len+1); 1353 | 1354 | rte_memcpy(fragment->data, buf, len); 1355 | fragment->length = len; 1356 | length = fragment->length; 1357 | 1358 | // int nb_snd = 0; 1359 | rte_ring_mp_enqueue(stream->sndbuf, fragment); 1360 | 1361 | } 1362 | 1363 | 1364 | return length; 1365 | } 1366 | 1367 | // recv 32 1368 | // recv 1369 | static ssize_t nrecv(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags) { 1370 | 1371 | ssize_t length = 0; 1372 | 1373 | void *hostinfo = get_hostinfo_fromfd(sockfd); 1374 | if (hostinfo == NULL) return -1; 1375 | 1376 | struct ng_tcp_stream *stream = (struct ng_tcp_stream *)hostinfo; 1377 | if (stream->protocol == IPPROTO_TCP) { 1378 | 1379 | struct ng_tcp_fragment *fragment = NULL; 1380 | int nb_rcv = 0; 1381 | 1382 | printf("rte_ring_mc_dequeue before\n"); 1383 | pthread_mutex_lock(&stream->mutex); 1384 | while ((nb_rcv = rte_ring_mc_dequeue(stream->rcvbuf, (void **)&fragment)) < 0) { 1385 | pthread_cond_wait(&stream->cond, &stream->mutex); 1386 | } 1387 | pthread_mutex_unlock(&stream->mutex); 1388 | printf("rte_ring_mc_dequeue after\n"); 1389 | 1390 | if (fragment->length > len) { 1391 | 1392 | rte_memcpy(buf, fragment->data, len); 1393 | 1394 | uint32_t i = 0; 1395 | for(i = 0;i < fragment->length-len;i ++) { 1396 | fragment->data[i] = fragment->data[len+i]; 1397 | } 1398 | fragment->length = fragment->length-len; 1399 | length = fragment->length; 1400 | 1401 | rte_ring_mp_enqueue(stream->rcvbuf, fragment); 1402 | 1403 | } else if (fragment->length == 0) { 1404 | 1405 | rte_free(fragment); 1406 | return 0; 1407 | 1408 | } else { 1409 | 1410 | rte_memcpy(buf, fragment->data, fragment->length); 1411 | length = fragment->length; 1412 | 1413 | rte_free(fragment->data); 1414 | fragment->data = NULL; 1415 | 1416 | rte_free(fragment); 1417 | 1418 | } 1419 | 1420 | } 1421 | 1422 | return length; 1423 | } 1424 | 1425 | 1426 | static ssize_t nrecvfrom(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags, 1427 | struct sockaddr *src_addr, __attribute__((unused)) socklen_t *addrlen) { 1428 | 1429 | struct localhost *host = get_hostinfo_fromfd(sockfd); 1430 | if (host == NULL) return -1; 1431 | 1432 | struct offload *ol = NULL; 1433 | unsigned char *ptr = NULL; 1434 | 1435 | struct sockaddr_in *saddr = (struct sockaddr_in *)src_addr; 1436 | 1437 | int nb = -1; 1438 | pthread_mutex_lock(&host->mutex); 1439 | while ((nb = rte_ring_mc_dequeue(host->rcvbuf, (void **)&ol)) < 0) { 1440 | pthread_cond_wait(&host->cond, &host->mutex); 1441 | } 1442 | pthread_mutex_unlock(&host->mutex); 1443 | 1444 | 1445 | saddr->sin_port = ol->sport; 1446 | rte_memcpy(&saddr->sin_addr.s_addr, &ol->sip, sizeof(uint32_t)); 1447 | 1448 | if (len < ol->length) { 1449 | 1450 | rte_memcpy(buf, ol->data, len); 1451 | 1452 | ptr = rte_malloc("unsigned char *", ol->length-len, 0); 1453 | rte_memcpy(ptr, ol->data+len, ol->length-len); 1454 | 1455 | ol->length -= len; 1456 | rte_free(ol->data); 1457 | ol->data = ptr; 1458 | 1459 | rte_ring_mp_enqueue(host->rcvbuf, ol); 1460 | 1461 | return len; 1462 | 1463 | } else { 1464 | 1465 | int length = ol->length; 1466 | rte_memcpy(buf, ol->data, ol->length); 1467 | 1468 | rte_free(ol->data); 1469 | rte_free(ol); 1470 | 1471 | return length; 1472 | } 1473 | 1474 | 1475 | 1476 | } 1477 | 1478 | static ssize_t nsendto(int sockfd, const void *buf, size_t len, __attribute__((unused)) int flags, 1479 | const struct sockaddr *dest_addr, __attribute__((unused)) socklen_t addrlen) { 1480 | 1481 | 1482 | struct localhost *host = get_hostinfo_fromfd(sockfd); 1483 | if (host == NULL) return -1; 1484 | 1485 | const struct sockaddr_in *daddr = (const struct sockaddr_in *)dest_addr; 1486 | 1487 | struct offload *ol = rte_malloc("offload", sizeof(struct offload), 0); 1488 | if (ol == NULL) return -1; 1489 | 1490 | ol->dip = daddr->sin_addr.s_addr; 1491 | ol->dport = daddr->sin_port; 1492 | ol->sip = host->localip; 1493 | ol->sport = host->localport; 1494 | ol->length = len; 1495 | 1496 | struct in_addr addr; 1497 | addr.s_addr = ol->dip; 1498 | printf("nsendto ---> src: %s:%d \n", inet_ntoa(addr), ntohs(ol->dport)); 1499 | 1500 | 1501 | ol->data = rte_malloc("unsigned char *", len, 0); 1502 | if (ol->data == NULL) { 1503 | rte_free(ol); 1504 | return -1; 1505 | } 1506 | 1507 | rte_memcpy(ol->data, buf, len); 1508 | 1509 | rte_ring_mp_enqueue(host->sndbuf, ol); 1510 | 1511 | return len; 1512 | } 1513 | 1514 | static int nclose(int fd) { 1515 | 1516 | 1517 | void *hostinfo = get_hostinfo_fromfd(fd); 1518 | if (hostinfo == NULL) return -1; 1519 | 1520 | struct localhost *host = (struct localhost*)hostinfo; 1521 | if (host->protocol == IPPROTO_UDP) { 1522 | 1523 | LL_REMOVE(host, lhost); 1524 | 1525 | if (host->rcvbuf) { 1526 | rte_ring_free(host->rcvbuf); 1527 | } 1528 | if (host->sndbuf) { 1529 | rte_ring_free(host->sndbuf); 1530 | } 1531 | 1532 | rte_free(host); 1533 | 1534 | set_fd_frombitmap(fd); 1535 | 1536 | } else if (host->protocol == IPPROTO_TCP) { 1537 | 1538 | struct ng_tcp_stream *stream = (struct ng_tcp_stream*)hostinfo; 1539 | 1540 | if (stream->status != NG_TCP_STATUS_LISTEN) { 1541 | 1542 | struct ng_tcp_fragment *fragment = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1543 | if (fragment == NULL) return -1; 1544 | 1545 | printf("nclose --> enter last ack\n"); 1546 | fragment->data = NULL; 1547 | fragment->length = 0; 1548 | fragment->sport = stream->dport; 1549 | fragment->dport = stream->sport; 1550 | 1551 | fragment->seqnum = stream->snd_nxt; 1552 | fragment->acknum = stream->rcv_nxt; 1553 | 1554 | fragment->tcp_flags = RTE_TCP_FIN_FLAG | RTE_TCP_ACK_FLAG; 1555 | fragment->windows = TCP_INITIAL_WINDOW; 1556 | fragment->hdrlen_off = 0x50; 1557 | 1558 | rte_ring_mp_enqueue(stream->sndbuf, fragment); 1559 | stream->status = NG_TCP_STATUS_LAST_ACK; 1560 | 1561 | 1562 | set_fd_frombitmap(fd); 1563 | 1564 | } else { // nsocket 1565 | 1566 | struct ng_tcp_table *table = tcpInstance(); 1567 | LL_REMOVE(stream, table->tcb_set); 1568 | 1569 | rte_free(stream); 1570 | 1571 | } 1572 | } 1573 | 1574 | return 0; 1575 | } 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | 1583 | #define UDP_APP_RECV_BUFFER_SIZE 128 1584 | 1585 | // 1586 | static int udp_server_entry(__attribute__((unused)) void *arg) { 1587 | 1588 | int connfd = nsocket(AF_INET, SOCK_DGRAM, 0); 1589 | if (connfd == -1) { 1590 | printf("sockfd failed\n"); 1591 | return -1; 1592 | } 1593 | 1594 | struct sockaddr_in localaddr, clientaddr; // struct sockaddr 1595 | memset(&localaddr, 0, sizeof(struct sockaddr_in)); 1596 | 1597 | localaddr.sin_port = htons(8889); 1598 | localaddr.sin_family = AF_INET; 1599 | localaddr.sin_addr.s_addr = inet_addr("192.168.0.119"); // 0.0.0.0 1600 | 1601 | 1602 | nbind(connfd, (struct sockaddr*)&localaddr, sizeof(localaddr)); 1603 | 1604 | char buffer[UDP_APP_RECV_BUFFER_SIZE] = {0}; 1605 | socklen_t addrlen = sizeof(clientaddr); 1606 | while (1) { 1607 | 1608 | if (nrecvfrom(connfd, buffer, UDP_APP_RECV_BUFFER_SIZE, 0, 1609 | (struct sockaddr*)&clientaddr, &addrlen) < 0) { 1610 | 1611 | continue; 1612 | 1613 | } else { 1614 | 1615 | printf("recv from %s:%d, data:%s\n", inet_ntoa(clientaddr.sin_addr), 1616 | ntohs(clientaddr.sin_port), buffer); 1617 | nsendto(connfd, buffer, strlen(buffer), 0, 1618 | (struct sockaddr*)&clientaddr, sizeof(clientaddr)); 1619 | } 1620 | 1621 | } 1622 | 1623 | nclose(connfd); 1624 | 1625 | } 1626 | 1627 | 1628 | 1629 | 1630 | #endif 1631 | 1632 | 1633 | #if ENABLE_TCP_APP // ngtcp 1634 | 1635 | 1636 | // --> tcb 1637 | // 1638 | static struct ng_tcp_stream * ng_tcp_stream_search(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport) { // proto 1639 | 1640 | struct ng_tcp_table *table = tcpInstance(); 1641 | 1642 | struct ng_tcp_stream *iter; 1643 | for (iter = table->tcb_set;iter != NULL; iter = iter->next) { // established 1644 | 1645 | if (iter->sip == sip && iter->dip == dip && 1646 | iter->sport == sport && iter->dport == dport) { 1647 | return iter; 1648 | } 1649 | 1650 | } 1651 | 1652 | for (iter = table->tcb_set;iter != NULL; iter = iter->next) { 1653 | 1654 | if (iter->dport == dport && iter->status == NG_TCP_STATUS_LISTEN) { // listen 1655 | return iter; 1656 | } 1657 | 1658 | } 1659 | 1660 | return NULL; 1661 | } 1662 | 1663 | static struct ng_tcp_stream * ng_tcp_stream_create(uint32_t sip, uint32_t dip, uint16_t sport, uint16_t dport) { // proto 1664 | 1665 | // tcp --> status 1666 | struct ng_tcp_stream *stream = rte_malloc("ng_tcp_stream", sizeof(struct ng_tcp_stream), 0); 1667 | if (stream == NULL) return NULL; 1668 | 1669 | stream->sip = sip; 1670 | stream->dip = dip; 1671 | stream->sport = sport; 1672 | stream->dport = dport; 1673 | stream->protocol = IPPROTO_TCP; 1674 | stream->fd = -1; //unused 1675 | 1676 | // 1677 | stream->status = NG_TCP_STATUS_LISTEN; 1678 | 1679 | printf("ng_tcp_stream_create\n"); 1680 | // 1681 | char sbufname[32] = {0}; 1682 | sprintf(sbufname, "sndbuf%x%d", sip, sport); 1683 | stream->sndbuf = rte_ring_create(sbufname, RING_SIZE, rte_socket_id(), 0); 1684 | 1685 | char rbufname[32] = {0}; 1686 | sprintf(rbufname, "bufname%x%d", sip, sport); 1687 | stream->rcvbuf = rte_ring_create(rbufname, RING_SIZE, rte_socket_id(), 0); 1688 | 1689 | // seq num 1690 | uint32_t next_seed = time(NULL); 1691 | stream->snd_nxt = rand_r(&next_seed) % TCP_MAX_SEQ; 1692 | rte_memcpy(stream->localmac, gSrcMac, RTE_ETHER_ADDR_LEN); 1693 | 1694 | pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER; 1695 | rte_memcpy(&stream->cond, &blank_cond, sizeof(pthread_cond_t)); 1696 | 1697 | pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER; 1698 | rte_memcpy(&stream->mutex, &blank_mutex, sizeof(pthread_mutex_t)); 1699 | 1700 | //struct ng_tcp_table *table = tcpInstance(); 1701 | //LL_ADD(stream, table->tcb_set); 1702 | 1703 | return stream; 1704 | } 1705 | 1706 | 1707 | 1708 | static int ng_tcp_handle_listen(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr, struct rte_ipv4_hdr *iphdr) { 1709 | 1710 | if (tcphdr->tcp_flags & RTE_TCP_SYN_FLAG) { 1711 | //stream --> listenfd 1712 | if (stream->status == NG_TCP_STATUS_LISTEN) { 1713 | 1714 | struct ng_tcp_table *table = tcpInstance(); 1715 | struct ng_tcp_stream *syn = ng_tcp_stream_create(iphdr->src_addr, iphdr->dst_addr, tcphdr->src_port, tcphdr->dst_port); 1716 | LL_ADD(syn, table->tcb_set); 1717 | 1718 | 1719 | struct ng_tcp_fragment *fragment = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1720 | if (fragment == NULL) return -1; 1721 | memset(fragment, 0, sizeof(struct ng_tcp_fragment)); 1722 | 1723 | fragment->sport = tcphdr->dst_port; 1724 | fragment->dport = tcphdr->src_port; 1725 | 1726 | struct in_addr addr; 1727 | addr.s_addr = syn->sip; 1728 | printf("tcp ---> src: %s:%d ", inet_ntoa(addr), ntohs(tcphdr->src_port)); 1729 | 1730 | 1731 | addr.s_addr = syn->dip; 1732 | printf(" ---> dst: %s:%d \n", inet_ntoa(addr), ntohs(tcphdr->dst_port)); 1733 | 1734 | fragment->seqnum = syn->snd_nxt; 1735 | fragment->acknum = ntohl(tcphdr->sent_seq) + 1; 1736 | syn->rcv_nxt = fragment->acknum; 1737 | 1738 | fragment->tcp_flags = (RTE_TCP_SYN_FLAG | RTE_TCP_ACK_FLAG); 1739 | fragment->windows = TCP_INITIAL_WINDOW; 1740 | fragment->hdrlen_off = 0x50; 1741 | 1742 | fragment->data = NULL; 1743 | fragment->length = 0; 1744 | 1745 | rte_ring_mp_enqueue(syn->sndbuf, fragment); 1746 | 1747 | syn->status = NG_TCP_STATUS_SYN_RCVD; 1748 | } 1749 | 1750 | } 1751 | 1752 | return 0; 1753 | } 1754 | 1755 | 1756 | static int ng_tcp_handle_syn_rcvd(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr) { 1757 | 1758 | if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) { 1759 | 1760 | if (stream->status == NG_TCP_STATUS_SYN_RCVD) { 1761 | 1762 | uint32_t acknum = ntohl(tcphdr->recv_ack); 1763 | if (acknum == stream->snd_nxt + 1) { 1764 | // 1765 | } 1766 | 1767 | stream->status = NG_TCP_STATUS_ESTABLISHED; 1768 | 1769 | // accept 1770 | struct ng_tcp_stream *listener = ng_tcp_stream_search(0, 0, 0, stream->dport); 1771 | if (listener == NULL) { 1772 | rte_exit(EXIT_FAILURE, "ng_tcp_stream_search failed\n"); 1773 | } 1774 | 1775 | pthread_mutex_lock(&listener->mutex); 1776 | pthread_cond_signal(&listener->cond); 1777 | pthread_mutex_unlock(&listener->mutex); 1778 | 1779 | #if ENABLE_SINGLE_EPOLL 1780 | 1781 | struct ng_tcp_table *table = tcpInstance(); 1782 | epoll_event_callback(table->ep, listener->fd, EPOLLIN); 1783 | 1784 | #endif 1785 | 1786 | } 1787 | 1788 | } 1789 | return 0; 1790 | } 1791 | 1792 | static int ng_tcp_enqueue_recvbuffer(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr, int tcplen) { 1793 | 1794 | // recv buffer 1795 | struct ng_tcp_fragment *rfragment = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1796 | if (rfragment == NULL) return -1; 1797 | memset(rfragment, 0, sizeof(struct ng_tcp_fragment)); 1798 | 1799 | rfragment->dport = ntohs(tcphdr->dst_port); 1800 | rfragment->sport = ntohs(tcphdr->src_port); 1801 | 1802 | uint8_t hdrlen = tcphdr->data_off >> 4; 1803 | int payloadlen = tcplen - hdrlen * 4; // 1804 | if (payloadlen > 0) { 1805 | 1806 | uint8_t *payload = (uint8_t*)tcphdr + hdrlen * 4; 1807 | 1808 | rfragment->data = rte_malloc("unsigned char *", payloadlen+1, 0); 1809 | if (rfragment->data == NULL) { 1810 | rte_free(rfragment); 1811 | return -1; 1812 | } 1813 | memset(rfragment->data, 0, payloadlen+1); 1814 | 1815 | rte_memcpy(rfragment->data, payload, payloadlen); 1816 | rfragment->length = payloadlen; 1817 | 1818 | } else if (payloadlen == 0) { 1819 | 1820 | rfragment->length = 0; 1821 | rfragment->data = NULL; 1822 | 1823 | } 1824 | rte_ring_mp_enqueue(stream->rcvbuf, rfragment); 1825 | 1826 | pthread_mutex_lock(&stream->mutex); 1827 | pthread_cond_signal(&stream->cond); 1828 | pthread_mutex_unlock(&stream->mutex); 1829 | 1830 | return 0; 1831 | } 1832 | 1833 | static int ng_tcp_send_ackpkt(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr) { 1834 | 1835 | struct ng_tcp_fragment *ackfrag = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1836 | if (ackfrag == NULL) return -1; 1837 | memset(ackfrag, 0, sizeof(struct ng_tcp_fragment)); 1838 | 1839 | ackfrag->dport = tcphdr->src_port; 1840 | ackfrag->sport = tcphdr->dst_port; 1841 | 1842 | // remote 1843 | 1844 | printf("ng_tcp_send_ackpkt: %d, %d\n", stream->rcv_nxt, ntohs(tcphdr->sent_seq)); 1845 | 1846 | 1847 | ackfrag->acknum = stream->rcv_nxt; 1848 | ackfrag->seqnum = stream->snd_nxt; 1849 | 1850 | ackfrag->tcp_flags = RTE_TCP_ACK_FLAG; 1851 | ackfrag->windows = TCP_INITIAL_WINDOW; 1852 | ackfrag->hdrlen_off = 0x50; 1853 | ackfrag->data = NULL; 1854 | ackfrag->length = 0; 1855 | 1856 | rte_ring_mp_enqueue(stream->sndbuf, ackfrag); 1857 | 1858 | return 0; 1859 | } 1860 | 1861 | static int ng_tcp_handle_established(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr, int tcplen) { 1862 | 1863 | if (tcphdr->tcp_flags & RTE_TCP_SYN_FLAG) { 1864 | // 1865 | } 1866 | if (tcphdr->tcp_flags & RTE_TCP_PSH_FLAG) { // 1867 | 1868 | // recv buffer 1869 | #if 0 1870 | struct ng_tcp_fragment *rfragment = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1871 | if (rfragment == NULL) return -1; 1872 | memset(rfragment, 0, sizeof(struct ng_tcp_fragment)); 1873 | 1874 | rfragment->dport = ntohs(tcphdr->dst_port); 1875 | rfragment->sport = ntohs(tcphdr->src_port); 1876 | 1877 | uint8_t hdrlen = tcphdr->data_off >> 4; 1878 | int payloadlen = tcplen - hdrlen * 4; 1879 | if (payloadlen > 0) { 1880 | 1881 | uint8_t *payload = (uint8_t*)tcphdr + hdrlen * 4; 1882 | 1883 | rfragment->data = rte_malloc("unsigned char *", payloadlen+1, 0); 1884 | if (rfragment->data == NULL) { 1885 | rte_free(rfragment); 1886 | return -1; 1887 | } 1888 | memset(rfragment->data, 0, payloadlen+1); 1889 | 1890 | rte_memcpy(rfragment->data, payload, payloadlen); 1891 | rfragment->length = payloadlen; 1892 | 1893 | printf("tcp : %s\n", rfragment->data); 1894 | } 1895 | rte_ring_mp_enqueue(stream->rcvbuf, rfragment); 1896 | #else 1897 | 1898 | ng_tcp_enqueue_recvbuffer(stream, tcphdr, tcplen); 1899 | 1900 | #if ENABLE_SINGLE_EPOLL 1901 | 1902 | struct ng_tcp_table *table = tcpInstance(); 1903 | epoll_event_callback(table->ep, stream->fd, EPOLLIN); 1904 | 1905 | #endif 1906 | 1907 | 1908 | #endif 1909 | 1910 | 1911 | #if 0 1912 | // ack pkt 1913 | struct ng_tcp_fragment *ackfrag = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1914 | if (ackfrag == NULL) return -1; 1915 | memset(ackfrag, 0, sizeof(struct ng_tcp_fragment)); 1916 | 1917 | ackfrag->dport = tcphdr->src_port; 1918 | ackfrag->sport = tcphdr->dst_port; 1919 | 1920 | // remote 1921 | 1922 | printf("ng_tcp_handle_established: %d, %d\n", stream->rcv_nxt, ntohs(tcphdr->sent_seq)); 1923 | 1924 | 1925 | stream->rcv_nxt = stream->rcv_nxt + payloadlen; 1926 | // local 1927 | stream->snd_nxt = ntohl(tcphdr->recv_ack); 1928 | //ackfrag-> 1929 | 1930 | ackfrag->acknum = stream->rcv_nxt; 1931 | ackfrag->seqnum = stream->snd_nxt; 1932 | 1933 | ackfrag->tcp_flags = RTE_TCP_ACK_FLAG; 1934 | ackfrag->windows = TCP_INITIAL_WINDOW; 1935 | ackfrag->hdrlen_off = 0x50; 1936 | ackfrag->data = NULL; 1937 | ackfrag->length = 0; 1938 | 1939 | rte_ring_mp_enqueue(stream->sndbuf, ackfrag); 1940 | 1941 | #else 1942 | 1943 | uint8_t hdrlen = tcphdr->data_off >> 4; 1944 | int payloadlen = tcplen - hdrlen * 4; 1945 | 1946 | stream->rcv_nxt = stream->rcv_nxt + payloadlen; 1947 | stream->snd_nxt = ntohl(tcphdr->recv_ack); 1948 | 1949 | ng_tcp_send_ackpkt(stream, tcphdr); 1950 | 1951 | #endif 1952 | // echo pkt 1953 | #if 0 1954 | struct ng_tcp_fragment *echofrag = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1955 | if (echofrag == NULL) return -1; 1956 | memset(echofrag, 0, sizeof(struct ng_tcp_fragment)); 1957 | 1958 | echofrag->dport = tcphdr->src_port; 1959 | echofrag->sport = tcphdr->dst_port; 1960 | 1961 | echofrag->acknum = stream->rcv_nxt; 1962 | echofrag->seqnum = stream->snd_nxt; 1963 | 1964 | echofrag->tcp_flags = RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG; 1965 | echofrag->windows = TCP_INITIAL_WINDOW; 1966 | echofrag->hdrlen_off = 0x50; 1967 | 1968 | uint8_t *payload = (uint8_t*)tcphdr + hdrlen * 4; 1969 | 1970 | echofrag->data = rte_malloc("unsigned char *", payloadlen, 0); 1971 | if (echofrag->data == NULL) { 1972 | rte_free(echofrag); 1973 | return -1; 1974 | } 1975 | memset(echofrag->data, 0, payloadlen); 1976 | 1977 | rte_memcpy(echofrag->data, payload, payloadlen); 1978 | echofrag->length = payloadlen; 1979 | 1980 | rte_ring_mp_enqueue(stream->sndbuf, echofrag); 1981 | #endif 1982 | 1983 | } 1984 | if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) { 1985 | 1986 | } 1987 | if (tcphdr->tcp_flags & RTE_TCP_FIN_FLAG) { 1988 | 1989 | stream->status = NG_TCP_STATUS_CLOSE_WAIT; 1990 | 1991 | #if 0 1992 | 1993 | struct ng_tcp_fragment *rfragment = rte_malloc("ng_tcp_fragment", sizeof(struct ng_tcp_fragment), 0); 1994 | if (rfragment == NULL) return -1; 1995 | memset(rfragment, 0, sizeof(struct ng_tcp_fragment)); 1996 | 1997 | rfragment->dport = ntohs(tcphdr->dst_port); 1998 | rfragment->sport = ntohs(tcphdr->src_port); 1999 | 2000 | uint8_t hdrlen = tcphdr->data_off >> 4; 2001 | int payloadlen = tcplen - hdrlen * 4; 2002 | 2003 | rfragment->length = 0; 2004 | rfragment->data = NULL; 2005 | 2006 | rte_ring_mp_enqueue(stream->rcvbuf, rfragment); 2007 | 2008 | #else 2009 | 2010 | ng_tcp_enqueue_recvbuffer(stream, tcphdr, tcphdr->data_off >> 4); 2011 | 2012 | #if ENABLE_SINGLE_EPOLL 2013 | 2014 | struct ng_tcp_table *table = tcpInstance(); 2015 | epoll_event_callback(table->ep, stream->fd, EPOLLIN); 2016 | 2017 | #endif 2018 | 2019 | 2020 | #endif 2021 | // send ack ptk 2022 | stream->rcv_nxt = stream->rcv_nxt + 1; 2023 | stream->snd_nxt = ntohl(tcphdr->recv_ack); 2024 | 2025 | ng_tcp_send_ackpkt(stream, tcphdr); 2026 | 2027 | } 2028 | 2029 | return 0; 2030 | } 2031 | 2032 | static int ng_tcp_handle_close_wait(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr) { 2033 | 2034 | if (tcphdr->tcp_flags & RTE_TCP_FIN_FLAG) { // 2035 | 2036 | if (stream->status == NG_TCP_STATUS_CLOSE_WAIT) { 2037 | 2038 | 2039 | 2040 | } 2041 | 2042 | } 2043 | 2044 | 2045 | return 0; 2046 | 2047 | } 2048 | 2049 | static int ng_tcp_handle_last_ack(struct ng_tcp_stream *stream, struct rte_tcp_hdr *tcphdr) { 2050 | 2051 | if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) { 2052 | 2053 | if (stream->status == NG_TCP_STATUS_LAST_ACK) { 2054 | 2055 | stream->status = NG_TCP_STATUS_CLOSED; 2056 | 2057 | printf("ng_tcp_handle_last_ack\n"); 2058 | struct ng_tcp_table *table = tcpInstance(); 2059 | LL_REMOVE(stream, table->tcb_set); 2060 | 2061 | rte_ring_free(stream->sndbuf); 2062 | rte_ring_free(stream->rcvbuf); 2063 | 2064 | rte_free(stream); 2065 | 2066 | } 2067 | 2068 | } 2069 | 2070 | return 0; 2071 | } 2072 | 2073 | // --> tcp 2074 | static int ng_tcp_process(struct rte_mbuf *tcpmbuf) { 2075 | 2076 | struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(tcpmbuf, struct rte_ipv4_hdr *, 2077 | sizeof(struct rte_ether_hdr)); 2078 | struct rte_tcp_hdr *tcphdr = (struct rte_tcp_hdr *)(iphdr + 1); 2079 | 2080 | // tcphdr, rte_ipv4_udptcp_cksum 2081 | uint16_t tcpcksum = tcphdr->cksum; 2082 | tcphdr->cksum = 0; 2083 | uint16_t cksum = rte_ipv4_udptcp_cksum(iphdr, tcphdr); 2084 | 2085 | #if 1 // 2086 | if (cksum != tcpcksum) { // 2087 | printf("cksum: %x, tcp cksum: %x\n", cksum, tcpcksum); 2088 | rte_pktmbuf_free(tcpmbuf); 2089 | return -1; 2090 | } 2091 | #endif 2092 | 2093 | struct ng_tcp_stream *stream = ng_tcp_stream_search(iphdr->src_addr, iphdr->dst_addr, 2094 | tcphdr->src_port, tcphdr->dst_port); 2095 | if (stream == NULL) { 2096 | rte_pktmbuf_free(tcpmbuf); 2097 | return -2; 2098 | } 2099 | 2100 | switch (stream->status) { 2101 | 2102 | case NG_TCP_STATUS_CLOSED: //client 2103 | break; 2104 | 2105 | case NG_TCP_STATUS_LISTEN: // server 2106 | ng_tcp_handle_listen(stream, tcphdr, iphdr); 2107 | break; 2108 | 2109 | case NG_TCP_STATUS_SYN_RCVD: // server 2110 | ng_tcp_handle_syn_rcvd(stream, tcphdr); 2111 | break; 2112 | 2113 | case NG_TCP_STATUS_SYN_SENT: // client 2114 | break; 2115 | 2116 | case NG_TCP_STATUS_ESTABLISHED: { // server | client 2117 | 2118 | int tcplen = ntohs(iphdr->total_length) - sizeof(struct rte_ipv4_hdr); 2119 | 2120 | ng_tcp_handle_established(stream, tcphdr, tcplen); 2121 | 2122 | break; 2123 | } 2124 | case NG_TCP_STATUS_FIN_WAIT_1: // ~client 2125 | break; 2126 | 2127 | case NG_TCP_STATUS_FIN_WAIT_2: // ~client 2128 | break; 2129 | 2130 | case NG_TCP_STATUS_CLOSING: // ~client 2131 | break; 2132 | 2133 | case NG_TCP_STATUS_TIME_WAIT: // ~client 2134 | break; 2135 | 2136 | case NG_TCP_STATUS_CLOSE_WAIT: // ~server 2137 | ng_tcp_handle_close_wait(stream, tcphdr); 2138 | break; 2139 | 2140 | case NG_TCP_STATUS_LAST_ACK: // ~server 2141 | ng_tcp_handle_last_ack(stream, tcphdr); 2142 | break; 2143 | 2144 | } 2145 | 2146 | rte_pktmbuf_free(tcpmbuf); 2147 | 2148 | return 0; 2149 | } 2150 | 2151 | 2152 | static int ng_encode_tcp_apppkt(uint8_t *msg, uint32_t sip, uint32_t dip, 2153 | uint8_t *srcmac, uint8_t *dstmac, struct ng_tcp_fragment *fragment) { 2154 | 2155 | // encode 2156 | const unsigned total_len = fragment->length + sizeof(struct rte_ether_hdr) + 2157 | sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr) + 2158 | fragment->optlen * sizeof(uint32_t); 2159 | 2160 | // 1 ethhdr 2161 | struct rte_ether_hdr *eth = (struct rte_ether_hdr *)msg; 2162 | rte_memcpy(eth->s_addr.addr_bytes, srcmac, RTE_ETHER_ADDR_LEN); 2163 | rte_memcpy(eth->d_addr.addr_bytes, dstmac, RTE_ETHER_ADDR_LEN); 2164 | eth->ether_type = htons(RTE_ETHER_TYPE_IPV4); 2165 | 2166 | 2167 | // 2 iphdr 2168 | struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)(msg + sizeof(struct rte_ether_hdr)); 2169 | ip->version_ihl = 0x45; 2170 | ip->type_of_service = 0; 2171 | ip->total_length = htons(total_len - sizeof(struct rte_ether_hdr)); 2172 | ip->packet_id = 0; 2173 | ip->fragment_offset = 0; 2174 | ip->time_to_live = 64; // ttl = 64 2175 | ip->next_proto_id = IPPROTO_TCP; 2176 | ip->src_addr = sip; 2177 | ip->dst_addr = dip; 2178 | 2179 | ip->hdr_checksum = 0; 2180 | ip->hdr_checksum = rte_ipv4_cksum(ip); 2181 | 2182 | // 3 udphdr 2183 | 2184 | struct rte_tcp_hdr *tcp = (struct rte_tcp_hdr *)(msg + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); 2185 | tcp->src_port = fragment->sport; 2186 | tcp->dst_port = fragment->dport; 2187 | tcp->sent_seq = htonl(fragment->seqnum); 2188 | tcp->recv_ack = htonl(fragment->acknum); 2189 | 2190 | tcp->data_off = fragment->hdrlen_off; 2191 | tcp->rx_win = fragment->windows; 2192 | tcp->tcp_urp = fragment->tcp_urp; 2193 | tcp->tcp_flags = fragment->tcp_flags; 2194 | 2195 | if (fragment->data != NULL) { 2196 | uint8_t *payload = (uint8_t*)(tcp+1) + fragment->optlen * sizeof(uint32_t); 2197 | rte_memcpy(payload, fragment->data, fragment->length); 2198 | } 2199 | 2200 | tcp->cksum = 0; 2201 | tcp->cksum = rte_ipv4_udptcp_cksum(ip, tcp); 2202 | 2203 | return 0; 2204 | } 2205 | 2206 | 2207 | static struct rte_mbuf * ng_tcp_pkt(struct rte_mempool *mbuf_pool, uint32_t sip, uint32_t dip, 2208 | uint8_t *srcmac, uint8_t *dstmac, struct ng_tcp_fragment *fragment) { 2209 | 2210 | // mempool --> mbuf 2211 | 2212 | const unsigned total_len = fragment->length + sizeof(struct rte_ether_hdr) + 2213 | sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_tcp_hdr) + 2214 | fragment->optlen * sizeof(uint32_t); 2215 | 2216 | struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mbuf_pool); 2217 | if (!mbuf) { 2218 | rte_exit(EXIT_FAILURE, "ng_tcp_pkt rte_pktmbuf_alloc\n"); 2219 | } 2220 | mbuf->pkt_len = total_len; 2221 | mbuf->data_len = total_len; 2222 | 2223 | uint8_t *pktdata = rte_pktmbuf_mtod(mbuf, uint8_t*); 2224 | 2225 | ng_encode_tcp_apppkt(pktdata, sip, dip, srcmac, dstmac, fragment); 2226 | 2227 | return mbuf; 2228 | 2229 | } 2230 | 2231 | 2232 | // struct localhost , struct tcp_stream 2233 | 2234 | static int ng_tcp_out(struct rte_mempool *mbuf_pool) { 2235 | 2236 | struct ng_tcp_table *table = tcpInstance(); 2237 | 2238 | struct ng_tcp_stream *stream; 2239 | for (stream = table->tcb_set;stream != NULL;stream = stream->next) { 2240 | 2241 | if (stream->sndbuf == NULL) continue; // listener 2242 | 2243 | struct ng_tcp_fragment *fragment = NULL; 2244 | int nb_snd = rte_ring_mc_dequeue(stream->sndbuf, (void**)&fragment); 2245 | if (nb_snd < 0) continue; 2246 | 2247 | uint8_t *dstmac = ng_get_dst_macaddr(stream->sip); // 2248 | if (dstmac == NULL) { 2249 | 2250 | //printf("ng_send_arp\n"); 2251 | struct rte_mbuf *arpbuf = ng_send_arp(mbuf_pool, RTE_ARP_OP_REQUEST, gDefaultArpMac, 2252 | stream->dip, stream->sip); 2253 | 2254 | struct inout_ring *ring = ringInstance(); 2255 | rte_ring_mp_enqueue_burst(ring->out, (void **)&arpbuf, 1, NULL); 2256 | 2257 | rte_ring_mp_enqueue(stream->sndbuf, fragment); 2258 | 2259 | } else { 2260 | 2261 | struct rte_mbuf *tcpbuf = ng_tcp_pkt(mbuf_pool, stream->dip, stream->sip, stream->localmac, dstmac, fragment); 2262 | 2263 | struct inout_ring *ring = ringInstance(); 2264 | rte_ring_mp_enqueue_burst(ring->out, (void **)&tcpbuf, 1, NULL); 2265 | 2266 | if (fragment->data != NULL) 2267 | rte_free(fragment->data); 2268 | 2269 | rte_free(fragment); 2270 | } 2271 | 2272 | } 2273 | 2274 | return 0; 2275 | } 2276 | 2277 | 2278 | 2279 | #if ENABLE_SINGLE_EPOLL 2280 | 2281 | 2282 | // 3 + 1 2283 | 2284 | int epoll_event_callback(struct eventpoll *ep, int sockid, uint32_t event) { 2285 | 2286 | struct epitem tmp; 2287 | tmp.sockfd = sockid; 2288 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 2289 | if (!epi) { 2290 | printf("rbtree not exist\n"); 2291 | return -1; 2292 | } 2293 | if (epi->rdy) { 2294 | epi->event.events |= event; 2295 | return 1; 2296 | } 2297 | 2298 | printf("epoll_event_callback --> %d\n", epi->sockfd); 2299 | 2300 | pthread_spin_lock(&ep->lock); 2301 | epi->rdy = 1; 2302 | LIST_INSERT_HEAD(&ep->rdlist, epi, rdlink); 2303 | ep->rdnum ++; 2304 | pthread_spin_unlock(&ep->lock); 2305 | 2306 | pthread_mutex_lock(&ep->cdmtx); 2307 | 2308 | pthread_cond_signal(&ep->cond); 2309 | pthread_mutex_unlock(&ep->cdmtx); 2310 | 2311 | } 2312 | 2313 | // eventpoll --> tcp_table->ep; 2314 | int nepoll_create(int size) { 2315 | 2316 | if (size <= 0) return -1; 2317 | 2318 | // epfd --> struct eventpoll 2319 | int epfd = get_fd_frombitmap(); //tcp, udp 2320 | 2321 | struct eventpoll *ep = (struct eventpoll*)rte_malloc("eventpoll", sizeof(struct eventpoll), 0); 2322 | if (!ep) { 2323 | set_fd_frombitmap(epfd); 2324 | return -1; 2325 | } 2326 | 2327 | struct ng_tcp_table *table = tcpInstance(); 2328 | table->ep = ep; 2329 | 2330 | ep->fd = epfd; 2331 | ep->rbcnt = 0; 2332 | RB_INIT(&ep->rbr); 2333 | LIST_INIT(&ep->rdlist); 2334 | 2335 | if (pthread_mutex_init(&ep->mtx, NULL)) { 2336 | free(ep); 2337 | set_fd_frombitmap(epfd); 2338 | 2339 | return -2; 2340 | } 2341 | 2342 | if (pthread_mutex_init(&ep->cdmtx, NULL)) { 2343 | pthread_mutex_destroy(&ep->mtx); 2344 | free(ep); 2345 | set_fd_frombitmap(epfd); 2346 | return -2; 2347 | } 2348 | 2349 | if (pthread_cond_init(&ep->cond, NULL)) { 2350 | pthread_mutex_destroy(&ep->cdmtx); 2351 | pthread_mutex_destroy(&ep->mtx); 2352 | free(ep); 2353 | set_fd_frombitmap(epfd); 2354 | return -2; 2355 | } 2356 | 2357 | if (pthread_spin_init(&ep->lock, PTHREAD_PROCESS_SHARED)) { 2358 | pthread_cond_destroy(&ep->cond); 2359 | pthread_mutex_destroy(&ep->cdmtx); 2360 | pthread_mutex_destroy(&ep->mtx); 2361 | free(ep); 2362 | 2363 | set_fd_frombitmap(epfd); 2364 | return -2; 2365 | } 2366 | 2367 | return epfd; 2368 | 2369 | } 2370 | 2371 | 2372 | int nepoll_ctl(int epfd, int op, int sockid, struct epoll_event *event) { 2373 | 2374 | struct eventpoll *ep = (struct eventpoll*)get_hostinfo_fromfd(epfd); 2375 | if (!ep || (!event && op != EPOLL_CTL_DEL)) { 2376 | errno = -EINVAL; 2377 | return -1; 2378 | } 2379 | 2380 | if (op == EPOLL_CTL_ADD) { 2381 | 2382 | pthread_mutex_lock(&ep->mtx); 2383 | 2384 | struct epitem tmp; 2385 | tmp.sockfd = sockid; 2386 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 2387 | if (epi) { 2388 | pthread_mutex_unlock(&ep->mtx); 2389 | return -1; 2390 | } 2391 | 2392 | epi = (struct epitem*)rte_malloc("epitem", sizeof(struct epitem), 0); 2393 | if (!epi) { 2394 | pthread_mutex_unlock(&ep->mtx); 2395 | rte_errno = -ENOMEM; 2396 | return -1; 2397 | } 2398 | 2399 | epi->sockfd = sockid; 2400 | memcpy(&epi->event, event, sizeof(struct epoll_event)); 2401 | 2402 | epi = RB_INSERT(_epoll_rb_socket, &ep->rbr, epi); 2403 | 2404 | ep->rbcnt ++; 2405 | 2406 | pthread_mutex_unlock(&ep->mtx); 2407 | 2408 | } else if (op == EPOLL_CTL_DEL) { 2409 | 2410 | pthread_mutex_lock(&ep->mtx); 2411 | 2412 | struct epitem tmp; 2413 | tmp.sockfd = sockid; 2414 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 2415 | if (!epi) { 2416 | 2417 | pthread_mutex_unlock(&ep->mtx); 2418 | return -1; 2419 | } 2420 | 2421 | epi = RB_REMOVE(_epoll_rb_socket, &ep->rbr, epi); 2422 | if (!epi) { 2423 | 2424 | pthread_mutex_unlock(&ep->mtx); 2425 | return -1; 2426 | } 2427 | 2428 | ep->rbcnt --; 2429 | free(epi); 2430 | 2431 | pthread_mutex_unlock(&ep->mtx); 2432 | 2433 | } else if (op == EPOLL_CTL_MOD) { 2434 | 2435 | struct epitem tmp; 2436 | tmp.sockfd = sockid; 2437 | struct epitem *epi = RB_FIND(_epoll_rb_socket, &ep->rbr, &tmp); 2438 | if (epi) { 2439 | epi->event.events = event->events; 2440 | epi->event.events |= EPOLLERR | EPOLLHUP; 2441 | } else { 2442 | rte_errno = -ENOENT; 2443 | return -1; 2444 | } 2445 | 2446 | } 2447 | 2448 | return 0; 2449 | 2450 | } 2451 | 2452 | 2453 | int nepoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) { 2454 | 2455 | 2456 | 2457 | struct eventpoll *ep = (struct eventpoll*)get_hostinfo_fromfd(epfd);; 2458 | if (!ep || !events || maxevents <= 0) { 2459 | rte_errno = -EINVAL; 2460 | return -1; 2461 | } 2462 | 2463 | if (pthread_mutex_lock(&ep->cdmtx)) { 2464 | if (rte_errno == EDEADLK) { 2465 | printf("epoll lock blocked\n"); 2466 | } 2467 | } 2468 | 2469 | 2470 | while (ep->rdnum == 0 && timeout != 0) { 2471 | 2472 | ep->waiting = 1; 2473 | if (timeout > 0) { 2474 | 2475 | struct timespec deadline; 2476 | 2477 | clock_gettime(CLOCK_REALTIME, &deadline); 2478 | if (timeout >= 1000) { 2479 | int sec; 2480 | sec = timeout / 1000; 2481 | deadline.tv_sec += sec; 2482 | timeout -= sec * 1000; 2483 | } 2484 | 2485 | deadline.tv_nsec += timeout * 1000000; 2486 | 2487 | if (deadline.tv_nsec >= 1000000000) { 2488 | deadline.tv_sec++; 2489 | deadline.tv_nsec -= 1000000000; 2490 | } 2491 | 2492 | int ret = pthread_cond_timedwait(&ep->cond, &ep->cdmtx, &deadline); 2493 | if (ret && ret != ETIMEDOUT) { 2494 | printf("pthread_cond_timewait\n"); 2495 | 2496 | pthread_mutex_unlock(&ep->cdmtx); 2497 | 2498 | return -1; 2499 | } 2500 | timeout = 0; 2501 | } else if (timeout < 0) { 2502 | 2503 | int ret = pthread_cond_wait(&ep->cond, &ep->cdmtx); 2504 | if (ret) { 2505 | printf("pthread_cond_wait\n"); 2506 | pthread_mutex_unlock(&ep->cdmtx); 2507 | 2508 | return -1; 2509 | } 2510 | } 2511 | ep->waiting = 0; 2512 | 2513 | } 2514 | 2515 | pthread_mutex_unlock(&ep->cdmtx); 2516 | 2517 | pthread_spin_lock(&ep->lock); 2518 | 2519 | int cnt = 0; 2520 | int num = (ep->rdnum > maxevents ? maxevents : ep->rdnum); 2521 | int i = 0; 2522 | 2523 | while (num != 0 && !LIST_EMPTY(&ep->rdlist)) { //EPOLLET 2524 | 2525 | struct epitem *epi = LIST_FIRST(&ep->rdlist); 2526 | LIST_REMOVE(epi, rdlink); 2527 | epi->rdy = 0; 2528 | 2529 | memcpy(&events[i++], &epi->event, sizeof(struct epoll_event)); 2530 | 2531 | num --; 2532 | cnt ++; 2533 | ep->rdnum --; 2534 | } 2535 | 2536 | pthread_spin_unlock(&ep->lock); 2537 | 2538 | return cnt; 2539 | } 2540 | 2541 | #endif 2542 | 2543 | 2544 | 2545 | #define BUFFER_SIZE 1024 2546 | 2547 | 2548 | #if ENABLE_SINGLE_EPOLL 2549 | 2550 | static int tcp_server_entry(__attribute__((unused)) void *arg) { 2551 | 2552 | int listenfd = nsocket(AF_INET, SOCK_STREAM, 0); 2553 | if (listenfd == -1) { 2554 | return -1; 2555 | } 2556 | 2557 | struct sockaddr_in servaddr; 2558 | memset(&servaddr, 0, sizeof(struct sockaddr)); 2559 | servaddr.sin_family = AF_INET; 2560 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 2561 | servaddr.sin_port = htons(9999); 2562 | nbind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); 2563 | 2564 | nlisten(listenfd, 10); 2565 | 2566 | int epfd = nepoll_create(1); // event poll 2567 | 2568 | struct epoll_event ev, events[128]; 2569 | ev.events = EPOLLIN; 2570 | ev.data.fd = listenfd; 2571 | nepoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev); 2572 | 2573 | char buff[BUFFER_SIZE] = {0}; 2574 | while(1) { 2575 | 2576 | int nready = nepoll_wait(epfd, events, 128, 5); 2577 | if (nready < 0) continue; 2578 | 2579 | int i = 0; 2580 | for (i = 0;i < nready;i ++) { 2581 | 2582 | if (listenfd == events[i].data.fd) { 2583 | 2584 | 2585 | struct sockaddr_in client; 2586 | socklen_t len = sizeof(client); 2587 | int connfd = naccept(listenfd, (struct sockaddr*)&client, &len); 2588 | 2589 | struct epoll_event ev; 2590 | ev.events = EPOLLIN; 2591 | ev.data.fd = connfd; 2592 | nepoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev); 2593 | 2594 | } else { // clientfd 2595 | 2596 | int connfd = events[i].data.fd; 2597 | 2598 | int n = nrecv(connfd, buff, BUFFER_SIZE, 0); //block 2599 | if (n > 0) { 2600 | printf("recv: %s\n", buff); 2601 | nsend(connfd, buff, n, 0); 2602 | 2603 | } else { 2604 | 2605 | nepoll_ctl(epfd, EPOLL_CTL_DEL, connfd, NULL); 2606 | nclose(connfd); 2607 | 2608 | } 2609 | 2610 | } 2611 | 2612 | } 2613 | } 2614 | 2615 | } 2616 | 2617 | 2618 | #else 2619 | 2620 | 2621 | // hook 2622 | static int tcp_server_entry(__attribute__((unused)) void *arg) { 2623 | 2624 | int listenfd = nsocket(AF_INET, SOCK_STREAM, 0); 2625 | if (listenfd == -1) { 2626 | return -1; 2627 | } 2628 | 2629 | struct sockaddr_in servaddr; 2630 | memset(&servaddr, 0, sizeof(struct sockaddr)); 2631 | servaddr.sin_family = AF_INET; 2632 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 2633 | servaddr.sin_port = htons(9999); 2634 | nbind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); 2635 | 2636 | nlisten(listenfd, 10); 2637 | 2638 | while (1) { 2639 | 2640 | struct sockaddr_in client; 2641 | socklen_t len = sizeof(client); 2642 | int connfd = naccept(listenfd, (struct sockaddr*)&client, &len); 2643 | 2644 | char buff[BUFFER_SIZE] = {0}; 2645 | while (1) { 2646 | 2647 | int n = nrecv(connfd, buff, BUFFER_SIZE, 0); //block 2648 | if (n > 0) { 2649 | printf("recv: %s\n", buff); 2650 | nsend(connfd, buff, n, 0); 2651 | 2652 | } else if (n == 0) { 2653 | 2654 | nclose(connfd); 2655 | break; 2656 | } else { //nonblock 2657 | 2658 | } 2659 | } 2660 | 2661 | } 2662 | nclose(listenfd); 2663 | 2664 | 2665 | } 2666 | 2667 | #endif 2668 | 2669 | 2670 | #endif 2671 | 2672 | 2673 | #if ENABLE_KNI_APP 2674 | // ifconfig vEth0 up/down 2675 | 2676 | 2677 | // config_network_if 2678 | // rte_kni_handle_request 2679 | static int ng_config_network_if(uint16_t port_id, uint8_t if_up) { 2680 | 2681 | if (!rte_eth_dev_is_valid_port(port_id)) { 2682 | return -EINVAL; 2683 | } 2684 | 2685 | int ret = 0; 2686 | if (if_up) { 2687 | 2688 | rte_eth_dev_stop(port_id); 2689 | ret = rte_eth_dev_start(port_id); 2690 | 2691 | } else { 2692 | 2693 | rte_eth_dev_stop(port_id); 2694 | 2695 | } 2696 | 2697 | if (ret < 0) { 2698 | printf("Failed to start port : %d\n", port_id); 2699 | } 2700 | 2701 | return 0; 2702 | } 2703 | 2704 | static struct rte_kni *ng_alloc_kni(struct rte_mempool *mbuf_pool) { 2705 | 2706 | struct rte_kni *kni_hanlder = NULL; 2707 | 2708 | struct rte_kni_conf conf; 2709 | memset(&conf, 0, sizeof(conf)); 2710 | 2711 | snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", gDpdkPortId); 2712 | conf.group_id = gDpdkPortId; 2713 | conf.mbuf_size = MAX_PACKET_SIZE; 2714 | rte_eth_macaddr_get(gDpdkPortId, (struct rte_ether_addr *)conf.mac_addr); 2715 | rte_eth_dev_get_mtu(gDpdkPortId, &conf.mtu); 2716 | 2717 | print_ethaddr("ng_alloc_kni: ", (struct rte_ether_addr *)conf.mac_addr); 2718 | 2719 | /* 2720 | struct rte_eth_dev_info dev_info; 2721 | memset(&dev_info, 0, sizeof(dev_info)); 2722 | rte_eth_dev_info_get(gDpdkPortId, &dev_info); 2723 | */ 2724 | 2725 | 2726 | struct rte_kni_ops ops; 2727 | memset(&ops, 0, sizeof(ops)); 2728 | 2729 | ops.port_id = gDpdkPortId; 2730 | ops.config_network_if = ng_config_network_if; 2731 | 2732 | 2733 | kni_hanlder = rte_kni_alloc(mbuf_pool, &conf, &ops); 2734 | if (!kni_hanlder) { 2735 | rte_exit(EXIT_FAILURE, "Failed to create kni for port : %d\n", gDpdkPortId); 2736 | } 2737 | 2738 | return kni_hanlder; 2739 | } 2740 | 2741 | 2742 | 2743 | #endif 2744 | 2745 | 2746 | #if ENABLE_DDOS_DETECT 2747 | 2748 | 2749 | #define CAPTURE_WINDOWS 256 2750 | 2751 | static double tresh = 1200.0; 2752 | 2753 | static uint32_t p_setbits[CAPTURE_WINDOWS] = {0}; 2754 | static uint32_t p_totbits[CAPTURE_WINDOWS] = {0}; 2755 | static double p_entropy[CAPTURE_WINDOWS] = {0}; 2756 | static int pkt_idx = 0; 2757 | 2758 | /* 2759 | 23651/17408, E(nan) 2760 | 1805328/4456448 Entropy(nan), Total_Entropy(4339971.575790) 2761 | 2762 | 23526/17408, E(nan) 2763 | 1805203/4456448 Entropy(nan), Total_Entropy(4339902.272671) 2764 | 2765 | 17847/17408, E(nan) 2766 | 1799524/4456448 Entropy(nan), Total_Entropy(4336731.547140) 2767 | 2768 | 17670/17408, E(nan) 2769 | 1799347/4456448 Entropy(nan), Total_Entropy(4336632.027009) 2770 | 2771 | 17774/17408, E(nan) 2772 | 1799451/4456448 Entropy(nan), Total_Entropy(4336690.507219) 2773 | 2774 | */ 2775 | static double ddos_entropy(double set_bits, double total_bits) { 2776 | 2777 | return ( - set_bits) * (log2(set_bits) - log2(total_bits)) // 1 2778 | - (total_bits - set_bits) * (log2(total_bits - set_bits) - log2(total_bits)) 2779 | + log2(total_bits); 2780 | 2781 | } 2782 | 2783 | 2784 | static uint32_t count_bit(uint8_t *msg, const uint32_t length) { 2785 | 2786 | #if 0 2787 | uint32_t v; // count bits set in this (32-bit value) 2788 | uint32_t c, set_bits = 0; // store the total here 2789 | static const int S[5] = {1, 2, 4, 8, 16}; // Magic Binary Numbers 2790 | static const int B[5] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF}; 2791 | 2792 | 2793 | uint32_t *ptr = (uint32_t *)msg; 2794 | uint32_t *end = (uint32_t *)msg + length; 2795 | 2796 | 2797 | 2798 | while (ptr < end) { 2799 | 2800 | v = *ptr++; 2801 | 2802 | c = v - ((v >> S[0]) & B[0]); 2803 | c = ((c >> S[1]) & B[1]) + (c & B[1]); 2804 | c = ((c >> S[2]) + c) & B[2]; 2805 | c = ((c >> S[3]) + c) & B[3]; 2806 | c = ((c >> S[4]) + c) & B[4]; 2807 | 2808 | set_bits += c; 2809 | } 2810 | #else 2811 | 2812 | uint64_t v, set_bits = 0; 2813 | const uint64_t *ptr = (uint64_t *) msg; 2814 | const uint64_t *end = (uint64_t *) (msg + length); 2815 | 2816 | do { 2817 | v = *(ptr++); 2818 | v = v - ((v >> 1) & 0x5555555555555555); // reuse input as temporary 2819 | v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333); // temp 2820 | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0F; 2821 | set_bits += (v * 0x0101010101010101) >> (sizeof(v) - 1) * 8; // count 2822 | 2823 | } while(end > ptr); 2824 | 2825 | #endif 2826 | return set_bits; 2827 | 2828 | } 2829 | 2830 | 2831 | 2832 | static int ddos_detect(struct rte_mbuf *pkt) { 2833 | 2834 | static char flag = 0; // 1 ddos, 0 no attack 2835 | 2836 | uint8_t *msg = rte_pktmbuf_mtod(pkt, uint8_t * ); 2837 | uint32_t set_bits = count_bit(msg, pkt->buf_len); 2838 | 2839 | uint32_t tot_bits = pkt->buf_len * 8; 2840 | 2841 | p_setbits[pkt_idx % CAPTURE_WINDOWS] = set_bits; 2842 | p_totbits[pkt_idx % CAPTURE_WINDOWS] = tot_bits; 2843 | p_entropy[pkt_idx % CAPTURE_WINDOWS] = ddos_entropy(set_bits, tot_bits); 2844 | 2845 | //printf("\n %u/%u, E(%f)\n", set_bits, tot_bits, p_entropy[pkt_idx % CAPTURE_WINDOWS]); 2846 | if (pkt_idx >= CAPTURE_WINDOWS) { 2847 | 2848 | int i = 0; 2849 | uint32_t total_set = 0, total_bit = 0; 2850 | double sum_entropy = 0.0; 2851 | 2852 | for (i = 0;i < CAPTURE_WINDOWS;i ++) { 2853 | total_set += p_setbits[i]; // set_bits 2854 | total_bit += p_totbits[i]; // count_bits 2855 | sum_entropy += p_entropy[i]; 2856 | } 2857 | 2858 | double entropy = ddos_entropy(total_set, total_bit); 2859 | 2860 | // nan --> 2861 | //printf("%u/%u Entropy(%f), Total_Entropy(%f)\n", total_set, total_bit, sum_entropy, entropy); 2862 | if (tresh < sum_entropy - entropy) { // ddos attack 2863 | 2864 | if (!flag) { // detect 2865 | // 2866 | rte_exit(EXIT_FAILURE, "ddos attack !!! Entropy(%f) < Total_Entropy(%f)\n", 2867 | entropy, sum_entropy); 2868 | 2869 | } 2870 | 2871 | flag = 1; 2872 | 2873 | } else { 2874 | 2875 | if (flag) { // 2876 | 2877 | printf( "no new !!! Entropy(%f) < Total_Entropy(%f)\n", 2878 | entropy, sum_entropy); 2879 | } 2880 | 2881 | flag = 0; 2882 | 2883 | } 2884 | 2885 | // sum(p_entropy[i]) 2886 | // ddos_entropy(sum(set_bits), sum(tot_bits)); 2887 | 2888 | pkt_idx = (pkt_idx+1) % CAPTURE_WINDOWS + CAPTURE_WINDOWS; 2889 | } else { 2890 | pkt_idx ++; 2891 | } 2892 | 2893 | 2894 | return 0; 2895 | 2896 | } 2897 | 2898 | 2899 | 2900 | #endif 2901 | 2902 | 2903 | int main(int argc, char *argv[]) { 2904 | 2905 | if (rte_eal_init(argc, argv) < 0) { 2906 | rte_exit(EXIT_FAILURE, "Error with EAL init\n"); 2907 | 2908 | } 2909 | 2910 | struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("mbuf pool", NUM_MBUFS, 2911 | 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 2912 | if (mbuf_pool == NULL) { 2913 | rte_exit(EXIT_FAILURE, "Could not create mbuf pool\n"); 2914 | } 2915 | 2916 | #if ENABLE_KNI_APP 2917 | 2918 | if (-1 == rte_kni_init(gDpdkPortId)) { 2919 | rte_exit(EXIT_FAILURE, "kni init failed\n"); 2920 | } 2921 | ng_init_port(mbuf_pool); 2922 | // kni_alloc 2923 | global_kni = ng_alloc_kni(mbuf_pool); 2924 | 2925 | #else 2926 | ng_init_port(mbuf_pool); 2927 | 2928 | #endif 2929 | 2930 | 2931 | rte_eth_macaddr_get(gDpdkPortId, (struct rte_ether_addr *)gSrcMac); 2932 | 2933 | #if ENABLE_TIMER 2934 | 2935 | rte_timer_subsystem_init(); 2936 | 2937 | struct rte_timer arp_timer; 2938 | rte_timer_init(&arp_timer); 2939 | 2940 | uint64_t hz = rte_get_timer_hz(); 2941 | unsigned lcore_id = rte_lcore_id(); 2942 | rte_timer_reset(&arp_timer, hz, PERIODICAL, lcore_id, arp_request_timer_cb, mbuf_pool); 2943 | 2944 | #endif 2945 | 2946 | #if ENABLE_RINGBUFFER 2947 | 2948 | struct inout_ring *ring = ringInstance(); 2949 | if (ring == NULL) { 2950 | rte_exit(EXIT_FAILURE, "ring buffer init failed\n"); 2951 | } 2952 | 2953 | if (ring->in == NULL) { 2954 | ring->in = rte_ring_create("in ring", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 2955 | } 2956 | if (ring->out == NULL) { 2957 | ring->out = rte_ring_create("out ring", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); 2958 | } 2959 | 2960 | #endif 2961 | 2962 | #if ENABLE_MULTHREAD 2963 | 2964 | lcore_id = rte_get_next_lcore(lcore_id, 1, 0); 2965 | rte_eal_remote_launch(pkt_process, mbuf_pool, lcore_id); 2966 | 2967 | #endif 2968 | 2969 | #if ENABLE_UDP_APP 2970 | 2971 | lcore_id = rte_get_next_lcore(lcore_id, 1, 0); 2972 | rte_eal_remote_launch(udp_server_entry, mbuf_pool, lcore_id); 2973 | 2974 | #endif 2975 | 2976 | #if ENABLE_TCP_APP 2977 | 2978 | lcore_id = rte_get_next_lcore(lcore_id, 1, 0); 2979 | rte_eal_remote_launch(tcp_server_entry, mbuf_pool, lcore_id); 2980 | 2981 | #endif 2982 | 2983 | 2984 | while (1) { 2985 | 2986 | // rx 2987 | struct rte_mbuf *rx[BURST_SIZE]; 2988 | unsigned num_recvd = rte_eth_rx_burst(gDpdkPortId, 0, rx, BURST_SIZE); 2989 | if (num_recvd > BURST_SIZE) { 2990 | rte_exit(EXIT_FAILURE, "Error receiving from eth\n"); 2991 | } else if (num_recvd > 0) { 2992 | #if ENABLE_DDOS_DETECT 2993 | 2994 | unsigned i = 0; 2995 | for (i = 0;i < num_recvd;i ++) { 2996 | ddos_detect(rx[i]); 2997 | } 2998 | #endif 2999 | rte_ring_sp_enqueue_burst(ring->in, (void**)rx, num_recvd, NULL); 3000 | } 3001 | 3002 | 3003 | // tx 3004 | struct rte_mbuf *tx[BURST_SIZE]; 3005 | unsigned nb_tx = rte_ring_sc_dequeue_burst(ring->out, (void**)tx, BURST_SIZE, NULL); 3006 | if (nb_tx > 0) { 3007 | 3008 | rte_eth_tx_burst(gDpdkPortId, 0, tx, nb_tx); 3009 | 3010 | unsigned i = 0; 3011 | for (i = 0;i < nb_tx;i ++) { 3012 | rte_pktmbuf_free(tx[i]); 3013 | } 3014 | 3015 | } 3016 | 3017 | 3018 | 3019 | #if ENABLE_TIMER 3020 | 3021 | static uint64_t prev_tsc = 0, cur_tsc; 3022 | uint64_t diff_tsc; 3023 | 3024 | cur_tsc = rte_rdtsc(); 3025 | diff_tsc = cur_tsc - prev_tsc; 3026 | if (diff_tsc > TIMER_RESOLUTION_CYCLES) { 3027 | rte_timer_manage(); 3028 | prev_tsc = cur_tsc; 3029 | } 3030 | 3031 | #endif 3032 | 3033 | 3034 | } 3035 | 3036 | } 3037 | 3038 | 3039 | 3040 | 3041 | --------------------------------------------------------------------------------