sendpacket.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2025 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #pragma once
  20. #include "defines.h"
  21. #include "config.h"
  22. #include <sys/socket.h>
  23. #ifdef __NetBSD__
  24. #include <net/if_ether.h>
  25. #elif ! defined(__HAIKU__)
  26. #include <net/if.h>
  27. #include <netinet/if_ether.h>
  28. #endif
  29. #if defined HAVE_NETMAP
  30. #include "common/netmap.h"
  31. #include <net/netmap.h>
  32. #endif
  33. #ifdef HAVE_PF_PACKET
  34. #include <netpacket/packet.h>
  35. #endif
  36. #ifdef HAVE_TX_RING
  37. #include "txring.h"
  38. #endif
  39. #ifdef HAVE_LIBDNET
  40. /* need to undef these which are pulled in via defines.h, prior to importing dnet.h */
  41. #undef icmp_id
  42. #undef icmp_seq
  43. #undef icmp_data
  44. #undef icmp_mask
  45. #ifdef HAVE_DNET_H
  46. #include <dnet.h>
  47. #endif
  48. #ifdef HAVE_DUMBNET_H
  49. #include <dumbnet.h>
  50. #endif
  51. #endif
  52. typedef enum sendpacket_type_e {
  53. SP_TYPE_NONE,
  54. SP_TYPE_LIBNET,
  55. SP_TYPE_LIBDNET,
  56. SP_TYPE_LIBPCAP,
  57. SP_TYPE_BPF,
  58. SP_TYPE_PF_PACKET,
  59. SP_TYPE_TX_RING,
  60. SP_TYPE_KHIAL,
  61. SP_TYPE_NETMAP,
  62. SP_TYPE_TUNTAP,
  63. SP_TYPE_LIBPCAP_DUMP,
  64. SP_TYPE_LIBXDP
  65. } sendpacket_type_t;
  66. /* these are the file_operations ioctls */
  67. #define KHIAL_SET_DIRECTION (0x1)
  68. #define KHIAL_GET_DIRECTION (0x2)
  69. /* these are the directions */
  70. typedef enum khial_direction_e {
  71. KHIAL_DIRECTION_RX = 0,
  72. KHIAL_DIRECTION_TX,
  73. } khial_direction_t;
  74. typedef struct pcap_dump_s{
  75. pcap_t *pcap;
  76. pcap_dumper_t* dump;
  77. } pcap_dump_t;
  78. union sendpacket_handle {
  79. pcap_t *pcap;
  80. pcap_dump_t dump;
  81. int fd;
  82. #ifdef HAVE_LIBDNET
  83. eth_t *ldnet;
  84. #endif
  85. };
  86. #define SENDPACKET_ERRBUF_SIZE 1024
  87. #define MAX_IFNAMELEN 64
  88. #ifdef HAVE_LIBXDP
  89. #include <errno.h>
  90. #include <stdlib.h>
  91. #include <linux/if_xdp.h>
  92. #include <xdp/xsk.h>
  93. struct xsk_ring_stats {
  94. unsigned long rx_npkts;
  95. unsigned long tx_npkts;
  96. unsigned long rx_dropped_npkts;
  97. unsigned long rx_invalid_npkts;
  98. unsigned long tx_invalid_npkts;
  99. unsigned long rx_full_npkts;
  100. unsigned long rx_fill_empty_npkts;
  101. unsigned long tx_empty_npkts;
  102. unsigned long prev_rx_npkts;
  103. unsigned long prev_tx_npkts;
  104. unsigned long prev_rx_dropped_npkts;
  105. unsigned long prev_rx_invalid_npkts;
  106. unsigned long prev_tx_invalid_npkts;
  107. unsigned long prev_rx_full_npkts;
  108. unsigned long prev_rx_fill_empty_npkts;
  109. unsigned long prev_tx_empty_npkts;
  110. };
  111. struct xsk_driver_stats {
  112. unsigned long intrs;
  113. unsigned long prev_intrs;
  114. };
  115. struct xsk_app_stats {
  116. unsigned long rx_empty_polls;
  117. unsigned long fill_fail_polls;
  118. unsigned long copy_tx_sendtos;
  119. unsigned long tx_wakeup_sendtos;
  120. unsigned long opt_polls;
  121. unsigned long prev_rx_empty_polls;
  122. unsigned long prev_fill_fail_polls;
  123. unsigned long prev_copy_tx_sendtos;
  124. unsigned long prev_tx_wakeup_sendtos;
  125. unsigned long prev_opt_polls;
  126. };
  127. struct xsk_umem_info {
  128. struct xsk_ring_prod fq;
  129. struct xsk_ring_cons cq;
  130. struct xsk_umem *umem;
  131. void *buffer;
  132. };
  133. struct xsk_socket {
  134. struct xsk_ring_cons *rx;
  135. struct xsk_ring_prod *tx;
  136. struct xsk_ctx *ctx;
  137. struct xsk_socket_config config;
  138. int fd;
  139. };
  140. struct xsk_socket_info {
  141. struct xsk_ring_cons rx;
  142. struct xsk_ring_prod tx;
  143. struct xsk_umem_info *umem;
  144. struct xsk_socket *xsk;
  145. struct xsk_ring_stats ring_stats;
  146. struct xsk_app_stats app_stats;
  147. struct xsk_driver_stats drv_stats;
  148. u_int32_t outstanding_tx;
  149. };
  150. #endif /* HAVE_LIBXDP */
  151. struct sendpacket_s {
  152. tcpr_dir_t cache_dir;
  153. int open;
  154. char device[MAX_IFNAMELEN];
  155. char errbuf[SENDPACKET_ERRBUF_SIZE];
  156. COUNTER retry_enobufs;
  157. COUNTER retry_eagain;
  158. COUNTER failed;
  159. COUNTER trunc_packets;
  160. COUNTER sent;
  161. COUNTER bytes_sent;
  162. COUNTER attempt;
  163. COUNTER flow_non_flow_packets;
  164. COUNTER flows;
  165. COUNTER flow_packets;
  166. COUNTER flows_unique;
  167. COUNTER flows_expired;
  168. COUNTER flows_invalid_packets;
  169. sendpacket_type_t handle_type;
  170. union sendpacket_handle handle;
  171. struct tcpr_ether_addr ether;
  172. #if defined HAVE_NETMAP
  173. int first_packet;
  174. int netmap_delay;
  175. #endif
  176. #ifdef HAVE_NETMAP
  177. struct netmap_if *nm_if;
  178. nmreq_t nmr;
  179. void *mmap_addr;
  180. int mmap_size;
  181. uint32_t if_flags;
  182. uint32_t is_vale;
  183. int netmap_version;
  184. uint16_t first_tx_ring, last_tx_ring, cur_tx_ring;
  185. #ifdef linux
  186. uint32_t data;
  187. uint32_t gso;
  188. uint32_t tso;
  189. uint32_t rxcsum;
  190. uint32_t txcsum;
  191. #endif /* linux */
  192. #endif /* HAVE_NETMAP */
  193. #ifdef HAVE_PF_PACKET
  194. struct sockaddr_ll sa;
  195. #ifdef HAVE_TX_RING
  196. txring_t *tx_ring;
  197. #endif
  198. #endif
  199. #ifdef HAVE_LIBXDP
  200. struct xsk_socket_info *xsk_info;
  201. struct xsk_umem_info *umem_info;
  202. unsigned int batch_size;
  203. unsigned int pckt_count;
  204. int frame_size;
  205. unsigned int tx_idx;
  206. int tx_size;
  207. #endif
  208. bool abort;
  209. };
  210. typedef struct sendpacket_s sendpacket_t;
  211. #ifdef HAVE_LIBXDP
  212. struct xsk_umem_info *
  213. create_umem_area(int nb_of_frames, int frame_size, int nb_of_completion_queue_descs, int nb_of_fill_queue_descs);
  214. struct xsk_socket_info *create_xsk_socket(struct xsk_umem_info *umem,
  215. int nb_of_tx_queue_desc,
  216. int nb_of_rx_queue_desc,
  217. const char *device,
  218. u_int32_t queue_id,
  219. char *errbuf);
  220. static inline void
  221. gen_eth_frame(struct xsk_umem_info *umem, u_int64_t addr, u_char *pkt_data, COUNTER pkt_size)
  222. {
  223. memcpy(xsk_umem__get_data(umem->buffer, addr), pkt_data, pkt_size);
  224. }
  225. static inline void
  226. kick_tx(struct xsk_socket_info *xsk)
  227. {
  228. int ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
  229. if (ret >= 0 || errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || errno == ENETDOWN) {
  230. return;
  231. }
  232. if (errno == EINVAL) {
  233. printf("%s\n", "Send error: XDP is either not supported by this underlying network driver, or it has a bug.\n"
  234. "Try upgrading to a newer kernel version and/or network driver and try again.");
  235. exit(0);
  236. } else {
  237. printf("%s %s\n", "XDP packet sending exited with error!", strerror(errno));
  238. exit(1);
  239. }
  240. }
  241. static inline void
  242. complete_tx_only(sendpacket_t *sp)
  243. {
  244. u_int32_t completion_idx = 0;
  245. if (sp->xsk_info->outstanding_tx == 0) {
  246. return;
  247. }
  248. if (xsk_ring_prod__needs_wakeup(&(sp->xsk_info->tx))) {
  249. sp->xsk_info->app_stats.tx_wakeup_sendtos++;
  250. kick_tx(sp->xsk_info);
  251. }
  252. unsigned int rcvd = xsk_ring_cons__peek(&sp->xsk_info->umem->cq, sp->pckt_count, &completion_idx);
  253. if (rcvd > 0) {
  254. xsk_ring_cons__release(&sp->xsk_info->umem->cq, rcvd);
  255. sp->xsk_info->outstanding_tx -= rcvd;
  256. }
  257. }
  258. #endif /* HAVE_LIBXDP */
  259. int sendpacket(sendpacket_t *, const u_char *, size_t, struct pcap_pkthdr *);
  260. void sendpacket_close(sendpacket_t *);
  261. char *sendpacket_geterr(sendpacket_t *);
  262. size_t sendpacket_getstat(sendpacket_t *, char *, size_t);
  263. sendpacket_t *sendpacket_open(const char *, char *, tcpr_dir_t, sendpacket_type_t, void *arg);
  264. struct tcpr_ether_addr *sendpacket_get_hwaddr(sendpacket_t *);
  265. int sendpacket_get_dlt(sendpacket_t *);
  266. const char *sendpacket_get_method(sendpacket_t *);
  267. void sendpacket_abort(sendpacket_t *);