ZBLOG

AF_XDP的例子

AF_XDP是一种高性能网络数据包处理技术,可用于加速数据包的传输和处理。以下是一个使用AF_XDP的简单例子:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <arpa/inet.h>
  6. #include <linux/if_link.h>
  7. #include <net/if.h>
  8. #include <sys/socket.h>
  9. #include <sys/types.h>
  10. #include <linux/bpf.h>
  11. #include <linux/if_xdp.h>
  12. #define MAX_FRAME_SIZE 2048
  13. static int xdp_sock;
  14. int init_xdp_socket(char* if_name, int queue_id)
  15. {
  16. int err;
  17. struct sockaddr_in addr;
  18. struct xdp_umem_reg umem_reg = {};
  19. struct xdp_desc desc = {};
  20. struct ifreq ifr = {};
  21. void* buffer;
  22. xdp_sock = socket(AF_XDP, SOCK_RAW, 0);
  23. if (xdp_sock < 0) {
  24. printf("failed to create AF_XDP socket\n");
  25. return -1;
  26. }
  27. memset(&ifr, 0, sizeof(ifr));
  28. strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
  29. if (setsockopt(xdp_sock, SOL_SOCKET, SO_ATTACH_BPF, &queue_id, sizeof(queue_id)) < 0) {
  30. printf("failed to attach bpf program to socket\n");
  31. return -1;
  32. }
  33. if (ioctl(xdp_sock, SIOCGIFFLAGS, &ifr) != 0) {
  34. printf("failed to get interface flags\n");
  35. return -1;
  36. }
  37. ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
  38. if (ioctl(xdp_sock, SIOCSIFFLAGS, &ifr) != 0) {
  39. printf("failed to set interface flags\n");
  40. return -1;
  41. }
  42. memset(&addr, 0, sizeof(addr));
  43. addr.sin_family = AF_INET;
  44. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  45. if (bind(xdp_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
  46. printf("failed to bind socket\n");
  47. return -1;
  48. }
  49. // Allocate and register umem
  50. int umem_fd = -1;
  51. if ((umem_fd = open("/dev/xdp_umem", O_RDWR)) < 0) {
  52. printf("failed to open xdp_umem device\n");
  53. return -1;
  54. }
  55. buffer = mmap(NULL, MAX_FRAME_SIZE * XDP_UMEM_PGSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
  56. if (buffer == MAP_FAILED) {
  57. printf("failed to allocate memory for umem\n");
  58. return -1;
  59. }
  60. umem_reg.addr = (uint64_t)buffer;
  61. umem_reg.len = MAX_FRAME_SIZE * XDP_UMEM_PGSIZE;
  62. umem_reg.chunk_size = MAX_FRAME_SIZE;
  63. umem_reg.headroom = 0;
  64. if (ioctl(umem_fd, XDP_UMEM_REG, &umem_reg) < 0) {
  65. printf("failed to register umem\n");
  66. return -1;
  67. }
  68. memset(&desc, 0, sizeof(desc));
  69. desc.addr = umem_reg.addr;
  70. desc.len = MAX_FRAME_SIZE;
  71. desc.options |= XDP_DESC_OPTIONS_SKB;
  72. desc.skb = buffer;
  73. if (setsockopt(xdp_sock, SOL_XDP, XDP_UMEM_REG, &desc, sizeof(desc)) < 0) {
  74. printf("failed to set xdp umem reg\n");
  75. return -1;
  76. }
  77. // Attach program to queue
  78. struct bpf_prog_info info = {};
  79. err = bpf_prog_query(BPF_PROG_TYPE_XDP, "xdp_program", 0, &info, sizeof(info));
  80. if (err != 0) {
  81. printf("failed to query xdp_program\n");
  82. return -1;
  83. }
  84. struct xdp_link_info link_info = {};
  85. link_info.umem_id = umem_reg.mem_umem_id;
  86. link_info.reg_mem_chunk_size = MAX_FRAME_SIZE;
  87. link_info.rx_queue_index = queue_id;
  88. if (setsockopt(xdp_sock, SOL_XDP, XDP_ATTACH, &link_info, sizeof(link_info)) < 0) {
  89. printf("failed to attach bpf program to queue\n");
  90. return -1;
  91. }
  92. return xdp_sock;
  93. }
  94. void handle_packet(struct xdp_buff* xdp)
  95. {
  96. uint32_t* data = (uint32_t*)(xdp->data);
  97. printf("Received packet with data: %u\n", *data);
  98. }
  99. int main(int argc, char** argv)
  100. {
  101. int queue_id = 0; // the queue id we want to bind to
  102. char* if_name = "eth0"; // the interface name we want to use
  103. int sock = init_xdp_socket(if_name, queue_id);
  104. if (sock < 0) {
  105. printf("failed to initialize xdp socket\n");
  106. return -1;
  107. }
  108. while (1) {
  109. struct xdp_buff xdp;
  110. ssize_t len = recvfrom(sock, &xdp, sizeof(xdp), 0, NULL, NULL);
  111. if (len < 0) {
  112. printf("failed to receive packet\n");
  113. continue;
  114. }
  115. handle_packet(&xdp);
  116. }
  117. return 0;
  118. }

这个例子演示了如何使用AF_XDP收发数据包。它创建了一个套接字,并将其绑定到指定的队列和接口上。然后,它使用XDP_UMEM_REG来分配和注册用户内存(umem),并将其附加到套接字上。最后,它将BPF程序附加到队列上以处理传入的数据包。在循环中,它使用recvfrom从套接字接收数据包,并调用handle_packet函数来处理数据包。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:http://sdn.0voice.com/?id=473

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?