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
pcap_init_handle(struct mtcp_thread_context * ctxt)29 pcap_init_handle(struct mtcp_thread_context *ctxt)
30 {
31 ctxt->io_private_context = &g_pcap_ctx;
32 }
33 /*----------------------------------------------------------------------------*/
34 int32_t
pcap_recv_pkts(struct mtcp_thread_context * ctxt,int ifidx)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 *
pcap_get_rptr(struct mtcp_thread_context * ctxt,int ifidx,int index,uint16_t * len)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
pcap_send_pkts(struct mtcp_thread_context * ctxt,int nif)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 *
pcap_get_wptr(struct mtcp_thread_context * ctxt,int ifidx,uint16_t pktsize)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
pcap_get_nif(struct ifreq * ifr)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
pcap_select(struct mtcp_thread_context * ctxt)104 pcap_select(struct mtcp_thread_context *ctxt)
105 {
106 return 0;
107 }
108 /*----------------------------------------------------------------------------*/
109 void
pcap_destroy_handle(struct mtcp_thread_context * ctxt)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
pcap_load_module_upper_half(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