1 /* for io_module_func def'ns */ 2 #include "io_module.h" 3 /* for mtcp related def'ns */ 4 #include "mtcp.h" 5 /* for errno */ 6 #include <errno.h> 7 /* for logging */ 8 #include "debug.h" 9 /* for num_devices_* */ 10 #include "config.h" 11 12 #include <string.h> 13 #include <pcap.h> 14 15 /*----------------------------------------------------------------------------*/ 16 struct pcap_private_context { 17 pcap_t *handle[MAX_DEVICES]; 18 char *dev_name[MAX_DEVICES]; 19 20 struct pcap_pkthdr phdr; 21 const u_char *rdata; 22 u_char wdata[ETHERNET_FRAME_LEN]; 23 uint16_t count[MAX_DEVICES]; 24 } g_pcap_ctx; 25 26 #define PCAP_BUFFER_SIZE (1048576 * 16U) 27 /*----------------------------------------------------------------------------*/ 28 void 29 pcap_init_handle(struct mtcp_thread_context *ctxt) 30 { 31 ctxt->io_private_context = &g_pcap_ctx; 32 } 33 /*----------------------------------------------------------------------------*/ 34 int32_t 35 pcap_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx) 36 { 37 if (ifidx < 0 || ifidx >= MAX_DEVICES) 38 return -1; 39 40 struct pcap_private_context *ppc = ctxt->io_private_context; 41 if ((ppc->rdata = pcap_next(ppc->handle[ifidx], &ppc->phdr)) == NULL) 42 return 0; 43 44 if (ppc->phdr.caplen != ppc->phdr.len) 45 TRACE_ERROR("caplen = %u, len: %u\n", 46 ppc->phdr.caplen, 47 ppc->phdr.len); 48 49 /* sanity check */ 50 if (ppc->rdata == NULL) 51 return 0; 52 53 return 1; /* PCAP always receives only one packet */ 54 } 55 /*----------------------------------------------------------------------------*/ 56 uint8_t * 57 pcap_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len) 58 { 59 struct pcap_private_context *ppc = ctxt->io_private_context; 60 if (ppc->rdata == NULL) 61 return NULL; 62 63 *len = ppc->phdr.caplen; 64 return (uint8_t *)ppc->rdata; 65 } 66 /*----------------------------------------------------------------------------*/ 67 int 68 pcap_send_pkts(struct mtcp_thread_context *ctxt, int nif) 69 { 70 int ret = 0; 71 struct pcap_private_context *ppc = ctxt->io_private_context; 72 73 if (ppc->count[nif] > 0) { 74 ret = pcap_inject(ppc->handle[nif], ppc->wdata, ppc->phdr.len); 75 } 76 77 ppc->count[nif] = 0; 78 return (ret != -1) ? 1 : 0; 79 } 80 /*----------------------------------------------------------------------------*/ 81 uint8_t * 82 pcap_get_wptr(struct mtcp_thread_context *ctxt, int ifidx, uint16_t pktsize) 83 { 84 struct pcap_private_context *ppc = ctxt->io_private_context; 85 /* phdr can be reused */ 86 ppc->phdr.caplen = ppc->phdr.len = pktsize; 87 ppc->count[ifidx] = 1; 88 return ppc->wdata; 89 } 90 /*----------------------------------------------------------------------------*/ 91 int 92 pcap_get_nif(struct ifreq *ifr) 93 { 94 int i; 95 96 for (i = 0; i < g_config.mos->netdev_table->num; i++) 97 if (!strcmp(ifr->ifr_name, g_pcap_ctx.dev_name[i])) 98 return i; 99 100 return -1; 101 } 102 /*----------------------------------------------------------------------------*/ 103 int32_t 104 pcap_select(struct mtcp_thread_context *ctxt) 105 { 106 return 0; 107 } 108 /*----------------------------------------------------------------------------*/ 109 void 110 pcap_destroy_handle(struct mtcp_thread_context *ctxt) 111 { 112 int i; 113 struct pcap_private_context *ppc = ctxt->io_private_context; 114 if (!ppc) 115 return; 116 117 for (i = 0; i < g_config.mos->netdev_table->num; i++) { 118 pcap_close(ppc->handle[i]); 119 } 120 121 ctxt->io_private_context = NULL; 122 } 123 /*----------------------------------------------------------------------------*/ 124 void 125 pcap_load_module_upper_half(void) 126 { 127 int i; 128 char errbuf[PCAP_ERRBUF_SIZE]; 129 struct netdev_entry **ent = g_config.mos->netdev_table->ent; 130 131 for (i = 0; i < g_config.mos->netdev_table->num; i++) { 132 #if 0 133 g_pcap_ctx.handle[i] = pcap_open_live(ent[i]->dev_name, BUFSIZ, 1, 134 1, errbuf); 135 if (!g_pcap_ctx.handle[i]) { 136 TRACE_ERROR("Interface '%s' not found\n", ent[i]->dev_name); 137 exit(EXIT_FAILURE); 138 } 139 #endif 140 g_pcap_ctx.handle[i] = pcap_create(ent[i]->dev_name, errbuf); 141 if (!g_pcap_ctx.handle[i]) { 142 TRACE_ERROR("Interface '%s' not found\n", ent[i]->dev_name); 143 exit(EXIT_FAILURE); 144 } 145 g_pcap_ctx.dev_name[i] = ent[i]->dev_name; 146 147 if (pcap_set_buffer_size(g_pcap_ctx.handle[i], PCAP_BUFFER_SIZE) != 0) { 148 TRACE_ERROR("Can't increase buffer size to %u bytes\n", 149 PCAP_BUFFER_SIZE); 150 } 151 152 if (pcap_activate(g_pcap_ctx.handle[i]) < 0) { 153 TRACE_ERROR("Failed to activate pcap handle!\n"); 154 pcap_perror(g_pcap_ctx.handle[i], ""); 155 exit(EXIT_FAILURE); 156 } 157 } 158 159 num_queues = 1; 160 } 161 /*----------------------------------------------------------------------------*/ 162 io_module_func pcap_module_func = { 163 .load_module_upper_half = pcap_load_module_upper_half, 164 .load_module_lower_half = NULL, 165 .init_handle = pcap_init_handle, 166 .link_devices = NULL, 167 .release_pkt = NULL, 168 .send_pkts = pcap_send_pkts, 169 .get_wptr = pcap_get_wptr, 170 .set_wptr = NULL, 171 .recv_pkts = pcap_recv_pkts, 172 .get_rptr = pcap_get_rptr, 173 .select = NULL, 174 .destroy_handle = pcap_destroy_handle, 175 .dev_ioctl = NULL, 176 .get_nif = pcap_get_nif, 177 }; 178 /*----------------------------------------------------------------------------*/ 179