xref: /f-stack/dpdk/drivers/net/pcap/rte_eth_pcap.c (revision 819aafb6)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation.
3  * Copyright(c) 2014 6WIND S.A.
4  * All rights reserved.
5  */
6 
7 #include <time.h>
8 
9 #include <net/if.h>
10 #include <sys/socket.h>
11 #include <sys/ioctl.h>
12 #include <unistd.h>
13 
14 #if defined(RTE_EXEC_ENV_BSDAPP)
15 #include <sys/sysctl.h>
16 #include <net/if_dl.h>
17 #endif
18 
19 #include <pcap.h>
20 
21 #include <rte_cycles.h>
22 #include <rte_ethdev_driver.h>
23 #include <rte_ethdev_vdev.h>
24 #include <rte_kvargs.h>
25 #include <rte_malloc.h>
26 #include <rte_mbuf.h>
27 #include <rte_bus_vdev.h>
28 #include <rte_string_fns.h>
29 
30 #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535
31 #define RTE_ETH_PCAP_SNAPLEN ETHER_MAX_JUMBO_FRAME_LEN
32 #define RTE_ETH_PCAP_PROMISC 1
33 #define RTE_ETH_PCAP_TIMEOUT -1
34 
35 #define ETH_PCAP_RX_PCAP_ARG  "rx_pcap"
36 #define ETH_PCAP_TX_PCAP_ARG  "tx_pcap"
37 #define ETH_PCAP_RX_IFACE_ARG "rx_iface"
38 #define ETH_PCAP_RX_IFACE_IN_ARG "rx_iface_in"
39 #define ETH_PCAP_TX_IFACE_ARG "tx_iface"
40 #define ETH_PCAP_IFACE_ARG    "iface"
41 #define ETH_PCAP_PHY_MAC_ARG  "phy_mac"
42 
43 #define ETH_PCAP_ARG_MAXLEN	64
44 
45 #define RTE_PMD_PCAP_MAX_QUEUES 16
46 
47 static char errbuf[PCAP_ERRBUF_SIZE];
48 static struct timeval start_time;
49 static uint64_t start_cycles;
50 static uint64_t hz;
51 static uint8_t iface_idx;
52 
53 struct queue_stat {
54 	volatile unsigned long pkts;
55 	volatile unsigned long bytes;
56 	volatile unsigned long err_pkts;
57 };
58 
59 struct pcap_rx_queue {
60 	uint16_t port_id;
61 	uint16_t queue_id;
62 	struct rte_mempool *mb_pool;
63 	struct queue_stat rx_stat;
64 	char name[PATH_MAX];
65 	char type[ETH_PCAP_ARG_MAXLEN];
66 };
67 
68 struct pcap_tx_queue {
69 	uint16_t port_id;
70 	uint16_t queue_id;
71 	struct queue_stat tx_stat;
72 	char name[PATH_MAX];
73 	char type[ETH_PCAP_ARG_MAXLEN];
74 };
75 
76 struct pmd_internals {
77 	struct pcap_rx_queue rx_queue[RTE_PMD_PCAP_MAX_QUEUES];
78 	struct pcap_tx_queue tx_queue[RTE_PMD_PCAP_MAX_QUEUES];
79 	char devargs[ETH_PCAP_ARG_MAXLEN];
80 	struct ether_addr eth_addr;
81 	int if_index;
82 	int single_iface;
83 	int phy_mac;
84 };
85 
86 struct pmd_process_private {
87 	pcap_t *rx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
88 	pcap_t *tx_pcap[RTE_PMD_PCAP_MAX_QUEUES];
89 	pcap_dumper_t *tx_dumper[RTE_PMD_PCAP_MAX_QUEUES];
90 };
91 
92 struct pmd_devargs {
93 	unsigned int num_of_queue;
94 	struct devargs_queue {
95 		pcap_dumper_t *dumper;
96 		pcap_t *pcap;
97 		const char *name;
98 		const char *type;
99 	} queue[RTE_PMD_PCAP_MAX_QUEUES];
100 	int phy_mac;
101 };
102 
103 static const char *valid_arguments[] = {
104 	ETH_PCAP_RX_PCAP_ARG,
105 	ETH_PCAP_TX_PCAP_ARG,
106 	ETH_PCAP_RX_IFACE_ARG,
107 	ETH_PCAP_RX_IFACE_IN_ARG,
108 	ETH_PCAP_TX_IFACE_ARG,
109 	ETH_PCAP_IFACE_ARG,
110 	ETH_PCAP_PHY_MAC_ARG,
111 	NULL
112 };
113 
114 static struct rte_eth_link pmd_link = {
115 		.link_speed = ETH_SPEED_NUM_10G,
116 		.link_duplex = ETH_LINK_FULL_DUPLEX,
117 		.link_status = ETH_LINK_DOWN,
118 		.link_autoneg = ETH_LINK_FIXED,
119 };
120 
121 static int eth_pcap_logtype;
122 
123 #define PMD_LOG(level, fmt, args...) \
124 	rte_log(RTE_LOG_ ## level, eth_pcap_logtype, \
125 		"%s(): " fmt "\n", __func__, ##args)
126 
127 static int
128 eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf,
129 		const u_char *data, uint16_t data_len)
130 {
131 	/* Copy the first segment. */
132 	uint16_t len = rte_pktmbuf_tailroom(mbuf);
133 	struct rte_mbuf *m = mbuf;
134 
135 	rte_memcpy(rte_pktmbuf_append(mbuf, len), data, len);
136 	data_len -= len;
137 	data += len;
138 
139 	while (data_len > 0) {
140 		/* Allocate next mbuf and point to that. */
141 		m->next = rte_pktmbuf_alloc(mb_pool);
142 
143 		if (unlikely(!m->next))
144 			return -1;
145 
146 		m = m->next;
147 
148 		/* Headroom is not needed in chained mbufs. */
149 		rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m));
150 		m->pkt_len = 0;
151 		m->data_len = 0;
152 
153 		/* Copy next segment. */
154 		len = RTE_MIN(rte_pktmbuf_tailroom(m), data_len);
155 		rte_memcpy(rte_pktmbuf_append(m, len), data, len);
156 
157 		mbuf->nb_segs++;
158 		data_len -= len;
159 		data += len;
160 	}
161 
162 	return mbuf->nb_segs;
163 }
164 
165 static uint16_t
166 eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
167 {
168 	unsigned int i;
169 	struct pcap_pkthdr header;
170 	struct pmd_process_private *pp;
171 	const u_char *packet;
172 	struct rte_mbuf *mbuf;
173 	struct pcap_rx_queue *pcap_q = queue;
174 	uint16_t num_rx = 0;
175 	uint32_t rx_bytes = 0;
176 	pcap_t *pcap;
177 
178 	pp = rte_eth_devices[pcap_q->port_id].process_private;
179 	pcap = pp->rx_pcap[pcap_q->queue_id];
180 
181 	if (unlikely(pcap == NULL || nb_pkts == 0))
182 		return 0;
183 
184 	/* Reads the given number of packets from the pcap file one by one
185 	 * and copies the packet data into a newly allocated mbuf to return.
186 	 */
187 	for (i = 0; i < nb_pkts; i++) {
188 		/* Get the next PCAP packet */
189 		packet = pcap_next(pcap, &header);
190 		if (unlikely(packet == NULL))
191 			break;
192 
193 		mbuf = rte_pktmbuf_alloc(pcap_q->mb_pool);
194 		if (unlikely(mbuf == NULL))
195 			break;
196 
197 		if (header.caplen <= rte_pktmbuf_tailroom(mbuf)) {
198 			/* pcap packet will fit in the mbuf, can copy it */
199 			rte_memcpy(rte_pktmbuf_mtod(mbuf, void *), packet,
200 					header.caplen);
201 			mbuf->data_len = (uint16_t)header.caplen;
202 		} else {
203 			/* Try read jumbo frame into multi mbufs. */
204 			if (unlikely(eth_pcap_rx_jumbo(pcap_q->mb_pool,
205 						       mbuf,
206 						       packet,
207 						       header.caplen) == -1)) {
208 				rte_pktmbuf_free(mbuf);
209 				break;
210 			}
211 		}
212 
213 		mbuf->pkt_len = (uint16_t)header.caplen;
214 		mbuf->port = pcap_q->port_id;
215 		bufs[num_rx] = mbuf;
216 		num_rx++;
217 		rx_bytes += header.caplen;
218 	}
219 	pcap_q->rx_stat.pkts += num_rx;
220 	pcap_q->rx_stat.bytes += rx_bytes;
221 
222 	return num_rx;
223 }
224 
225 static inline void
226 calculate_timestamp(struct timeval *ts) {
227 	uint64_t cycles;
228 	struct timeval cur_time;
229 
230 	cycles = rte_get_timer_cycles() - start_cycles;
231 	cur_time.tv_sec = cycles / hz;
232 	cur_time.tv_usec = (cycles % hz) * 1e6 / hz;
233 	timeradd(&start_time, &cur_time, ts);
234 }
235 
236 /*
237  * Callback to handle writing packets to a pcap file.
238  */
239 static uint16_t
240 eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
241 {
242 	unsigned int i;
243 	struct rte_mbuf *mbuf;
244 	struct pmd_process_private *pp;
245 	struct pcap_tx_queue *dumper_q = queue;
246 	uint16_t num_tx = 0;
247 	uint32_t tx_bytes = 0;
248 	struct pcap_pkthdr header;
249 	pcap_dumper_t *dumper;
250 	unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
251 	size_t len;
252 
253 	pp = rte_eth_devices[dumper_q->port_id].process_private;
254 	dumper = pp->tx_dumper[dumper_q->queue_id];
255 
256 	if (dumper == NULL || nb_pkts == 0)
257 		return 0;
258 
259 	/* writes the nb_pkts packets to the previously opened pcap file
260 	 * dumper */
261 	for (i = 0; i < nb_pkts; i++) {
262 		mbuf = bufs[i];
263 		len = rte_pktmbuf_pkt_len(mbuf);
264 		if (unlikely(!rte_pktmbuf_is_contiguous(mbuf) &&
265 				len > sizeof(temp_data))) {
266 			PMD_LOG(ERR,
267 				"Dropping multi segment PCAP packet. Size (%zd) > max size (%zd).",
268 				len, sizeof(temp_data));
269 			rte_pktmbuf_free(mbuf);
270 			continue;
271 		}
272 
273 		calculate_timestamp(&header.ts);
274 		header.len = len;
275 		header.caplen = header.len;
276 		/* rte_pktmbuf_read() returns a pointer to the data directly
277 		 * in the mbuf (when the mbuf is contiguous) or, otherwise,
278 		 * a pointer to temp_data after copying into it.
279 		 */
280 		pcap_dump((u_char *)dumper, &header,
281 			rte_pktmbuf_read(mbuf, 0, len, temp_data));
282 
283 		num_tx++;
284 		tx_bytes += len;
285 		rte_pktmbuf_free(mbuf);
286 	}
287 
288 	/*
289 	 * Since there's no place to hook a callback when the forwarding
290 	 * process stops and to make sure the pcap file is actually written,
291 	 * we flush the pcap dumper within each burst.
292 	 */
293 	pcap_dump_flush(dumper);
294 	dumper_q->tx_stat.pkts += num_tx;
295 	dumper_q->tx_stat.bytes += tx_bytes;
296 	dumper_q->tx_stat.err_pkts += nb_pkts - num_tx;
297 
298 	return nb_pkts;
299 }
300 
301 /*
302  * Callback to handle sending packets through a real NIC.
303  */
304 static uint16_t
305 eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
306 {
307 	unsigned int i;
308 	int ret;
309 	struct rte_mbuf *mbuf;
310 	struct pmd_process_private *pp;
311 	struct pcap_tx_queue *tx_queue = queue;
312 	uint16_t num_tx = 0;
313 	uint32_t tx_bytes = 0;
314 	pcap_t *pcap;
315 	unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN];
316 	size_t len;
317 
318 	pp = rte_eth_devices[tx_queue->port_id].process_private;
319 	pcap = pp->tx_pcap[tx_queue->queue_id];
320 
321 	if (unlikely(nb_pkts == 0 || pcap == NULL))
322 		return 0;
323 
324 	for (i = 0; i < nb_pkts; i++) {
325 		mbuf = bufs[i];
326 		len = rte_pktmbuf_pkt_len(mbuf);
327 		if (unlikely(!rte_pktmbuf_is_contiguous(mbuf) &&
328 				len > sizeof(temp_data))) {
329 			PMD_LOG(ERR,
330 				"Dropping multi segment PCAP packet. Size (%zd) > max size (%zd).",
331 				len, sizeof(temp_data));
332 			rte_pktmbuf_free(mbuf);
333 			continue;
334 		}
335 
336 		/* rte_pktmbuf_read() returns a pointer to the data directly
337 		 * in the mbuf (when the mbuf is contiguous) or, otherwise,
338 		 * a pointer to temp_data after copying into it.
339 		 */
340 		ret = pcap_sendpacket(pcap,
341 			rte_pktmbuf_read(mbuf, 0, len, temp_data), len);
342 		if (unlikely(ret != 0))
343 			break;
344 		num_tx++;
345 		tx_bytes += len;
346 		rte_pktmbuf_free(mbuf);
347 	}
348 
349 	tx_queue->tx_stat.pkts += num_tx;
350 	tx_queue->tx_stat.bytes += tx_bytes;
351 	tx_queue->tx_stat.err_pkts += i - num_tx;
352 
353 	return i;
354 }
355 
356 /*
357  * pcap_open_live wrapper function
358  */
359 static inline int
360 open_iface_live(const char *iface, pcap_t **pcap) {
361 	*pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN,
362 			RTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf);
363 
364 	if (*pcap == NULL) {
365 		PMD_LOG(ERR, "Couldn't open %s: %s", iface, errbuf);
366 		return -1;
367 	}
368 
369 	return 0;
370 }
371 
372 static int
373 open_single_iface(const char *iface, pcap_t **pcap)
374 {
375 	if (open_iface_live(iface, pcap) < 0) {
376 		PMD_LOG(ERR, "Couldn't open interface %s", iface);
377 		return -1;
378 	}
379 
380 	return 0;
381 }
382 
383 static int
384 open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper)
385 {
386 	pcap_t *tx_pcap;
387 
388 	/*
389 	 * We need to create a dummy empty pcap_t to use it
390 	 * with pcap_dump_open(). We create big enough an Ethernet
391 	 * pcap holder.
392 	 */
393 	tx_pcap = pcap_open_dead(DLT_EN10MB, RTE_ETH_PCAP_SNAPSHOT_LEN);
394 	if (tx_pcap == NULL) {
395 		PMD_LOG(ERR, "Couldn't create dead pcap");
396 		return -1;
397 	}
398 
399 	/* The dumper is created using the previous pcap_t reference */
400 	*dumper = pcap_dump_open(tx_pcap, pcap_filename);
401 	if (*dumper == NULL) {
402 		pcap_close(tx_pcap);
403 		PMD_LOG(ERR, "Couldn't open %s for writing.",
404 			pcap_filename);
405 		return -1;
406 	}
407 
408 	pcap_close(tx_pcap);
409 	return 0;
410 }
411 
412 static int
413 open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap)
414 {
415 	*pcap = pcap_open_offline(pcap_filename, errbuf);
416 	if (*pcap == NULL) {
417 		PMD_LOG(ERR, "Couldn't open %s: %s", pcap_filename,
418 			errbuf);
419 		return -1;
420 	}
421 
422 	return 0;
423 }
424 
425 static int
426 eth_dev_start(struct rte_eth_dev *dev)
427 {
428 	unsigned int i;
429 	struct pmd_internals *internals = dev->data->dev_private;
430 	struct pmd_process_private *pp = dev->process_private;
431 	struct pcap_tx_queue *tx;
432 	struct pcap_rx_queue *rx;
433 
434 	/* Special iface case. Single pcap is open and shared between tx/rx. */
435 	if (internals->single_iface) {
436 		tx = &internals->tx_queue[0];
437 		rx = &internals->rx_queue[0];
438 
439 		if (!pp->tx_pcap[0] &&
440 			strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) {
441 			if (open_single_iface(tx->name, &pp->tx_pcap[0]) < 0)
442 				return -1;
443 			pp->rx_pcap[0] = pp->tx_pcap[0];
444 		}
445 
446 		goto status_up;
447 	}
448 
449 	/* If not open already, open tx pcaps/dumpers */
450 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
451 		tx = &internals->tx_queue[i];
452 
453 		if (!pp->tx_dumper[i] &&
454 				strcmp(tx->type, ETH_PCAP_TX_PCAP_ARG) == 0) {
455 			if (open_single_tx_pcap(tx->name,
456 				&pp->tx_dumper[i]) < 0)
457 				return -1;
458 		} else if (!pp->tx_pcap[i] &&
459 				strcmp(tx->type, ETH_PCAP_TX_IFACE_ARG) == 0) {
460 			if (open_single_iface(tx->name, &pp->tx_pcap[i]) < 0)
461 				return -1;
462 		}
463 	}
464 
465 	/* If not open already, open rx pcaps */
466 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
467 		rx = &internals->rx_queue[i];
468 
469 		if (pp->rx_pcap[i] != NULL)
470 			continue;
471 
472 		if (strcmp(rx->type, ETH_PCAP_RX_PCAP_ARG) == 0) {
473 			if (open_single_rx_pcap(rx->name, &pp->rx_pcap[i]) < 0)
474 				return -1;
475 		} else if (strcmp(rx->type, ETH_PCAP_RX_IFACE_ARG) == 0) {
476 			if (open_single_iface(rx->name, &pp->rx_pcap[i]) < 0)
477 				return -1;
478 		}
479 	}
480 
481 status_up:
482 	for (i = 0; i < dev->data->nb_rx_queues; i++)
483 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
484 
485 	for (i = 0; i < dev->data->nb_tx_queues; i++)
486 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
487 
488 	dev->data->dev_link.link_status = ETH_LINK_UP;
489 
490 	return 0;
491 }
492 
493 /*
494  * This function gets called when the current port gets stopped.
495  * Is the only place for us to close all the tx streams dumpers.
496  * If not called the dumpers will be flushed within each tx burst.
497  */
498 static void
499 eth_dev_stop(struct rte_eth_dev *dev)
500 {
501 	unsigned int i;
502 	struct pmd_internals *internals = dev->data->dev_private;
503 	struct pmd_process_private *pp = dev->process_private;
504 
505 	/* Special iface case. Single pcap is open and shared between tx/rx. */
506 	if (internals->single_iface) {
507 		pcap_close(pp->tx_pcap[0]);
508 		pp->tx_pcap[0] = NULL;
509 		pp->rx_pcap[0] = NULL;
510 		goto status_down;
511 	}
512 
513 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
514 		if (pp->tx_dumper[i] != NULL) {
515 			pcap_dump_close(pp->tx_dumper[i]);
516 			pp->tx_dumper[i] = NULL;
517 		}
518 
519 		if (pp->tx_pcap[i] != NULL) {
520 			pcap_close(pp->tx_pcap[i]);
521 			pp->tx_pcap[i] = NULL;
522 		}
523 	}
524 
525 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
526 		if (pp->rx_pcap[i] != NULL) {
527 			pcap_close(pp->rx_pcap[i]);
528 			pp->rx_pcap[i] = NULL;
529 		}
530 	}
531 
532 status_down:
533 	for (i = 0; i < dev->data->nb_rx_queues; i++)
534 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
535 
536 	for (i = 0; i < dev->data->nb_tx_queues; i++)
537 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
538 
539 	dev->data->dev_link.link_status = ETH_LINK_DOWN;
540 }
541 
542 static int
543 eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
544 {
545 	return 0;
546 }
547 
548 static void
549 eth_dev_info(struct rte_eth_dev *dev,
550 		struct rte_eth_dev_info *dev_info)
551 {
552 	struct pmd_internals *internals = dev->data->dev_private;
553 
554 	dev_info->if_index = internals->if_index;
555 	dev_info->max_mac_addrs = 1;
556 	dev_info->max_rx_pktlen = (uint32_t) -1;
557 	dev_info->max_rx_queues = dev->data->nb_rx_queues;
558 	dev_info->max_tx_queues = dev->data->nb_tx_queues;
559 	dev_info->min_rx_bufsize = 0;
560 }
561 
562 static int
563 eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
564 {
565 	unsigned int i;
566 	unsigned long rx_packets_total = 0, rx_bytes_total = 0;
567 	unsigned long tx_packets_total = 0, tx_bytes_total = 0;
568 	unsigned long tx_packets_err_total = 0;
569 	const struct pmd_internals *internal = dev->data->dev_private;
570 
571 	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
572 			i < dev->data->nb_rx_queues; i++) {
573 		stats->q_ipackets[i] = internal->rx_queue[i].rx_stat.pkts;
574 		stats->q_ibytes[i] = internal->rx_queue[i].rx_stat.bytes;
575 		rx_packets_total += stats->q_ipackets[i];
576 		rx_bytes_total += stats->q_ibytes[i];
577 	}
578 
579 	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS &&
580 			i < dev->data->nb_tx_queues; i++) {
581 		stats->q_opackets[i] = internal->tx_queue[i].tx_stat.pkts;
582 		stats->q_obytes[i] = internal->tx_queue[i].tx_stat.bytes;
583 		stats->q_errors[i] = internal->tx_queue[i].tx_stat.err_pkts;
584 		tx_packets_total += stats->q_opackets[i];
585 		tx_bytes_total += stats->q_obytes[i];
586 		tx_packets_err_total += stats->q_errors[i];
587 	}
588 
589 	stats->ipackets = rx_packets_total;
590 	stats->ibytes = rx_bytes_total;
591 	stats->opackets = tx_packets_total;
592 	stats->obytes = tx_bytes_total;
593 	stats->oerrors = tx_packets_err_total;
594 
595 	return 0;
596 }
597 
598 static void
599 eth_stats_reset(struct rte_eth_dev *dev)
600 {
601 	unsigned int i;
602 	struct pmd_internals *internal = dev->data->dev_private;
603 
604 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
605 		internal->rx_queue[i].rx_stat.pkts = 0;
606 		internal->rx_queue[i].rx_stat.bytes = 0;
607 	}
608 
609 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
610 		internal->tx_queue[i].tx_stat.pkts = 0;
611 		internal->tx_queue[i].tx_stat.bytes = 0;
612 		internal->tx_queue[i].tx_stat.err_pkts = 0;
613 	}
614 }
615 
616 static void
617 eth_dev_close(struct rte_eth_dev *dev __rte_unused)
618 {
619 }
620 
621 static void
622 eth_queue_release(void *q __rte_unused)
623 {
624 }
625 
626 static int
627 eth_link_update(struct rte_eth_dev *dev __rte_unused,
628 		int wait_to_complete __rte_unused)
629 {
630 	return 0;
631 }
632 
633 static int
634 eth_rx_queue_setup(struct rte_eth_dev *dev,
635 		uint16_t rx_queue_id,
636 		uint16_t nb_rx_desc __rte_unused,
637 		unsigned int socket_id __rte_unused,
638 		const struct rte_eth_rxconf *rx_conf __rte_unused,
639 		struct rte_mempool *mb_pool)
640 {
641 	struct pmd_internals *internals = dev->data->dev_private;
642 	struct pcap_rx_queue *pcap_q = &internals->rx_queue[rx_queue_id];
643 
644 	pcap_q->mb_pool = mb_pool;
645 	pcap_q->port_id = dev->data->port_id;
646 	pcap_q->queue_id = rx_queue_id;
647 	dev->data->rx_queues[rx_queue_id] = pcap_q;
648 
649 	return 0;
650 }
651 
652 static int
653 eth_tx_queue_setup(struct rte_eth_dev *dev,
654 		uint16_t tx_queue_id,
655 		uint16_t nb_tx_desc __rte_unused,
656 		unsigned int socket_id __rte_unused,
657 		const struct rte_eth_txconf *tx_conf __rte_unused)
658 {
659 	struct pmd_internals *internals = dev->data->dev_private;
660 	struct pcap_tx_queue *pcap_q = &internals->tx_queue[tx_queue_id];
661 
662 	pcap_q->port_id = dev->data->port_id;
663 	pcap_q->queue_id = tx_queue_id;
664 	dev->data->tx_queues[tx_queue_id] = pcap_q;
665 
666 	return 0;
667 }
668 
669 static int
670 eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
671 {
672 	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
673 
674 	return 0;
675 }
676 
677 static int
678 eth_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
679 {
680 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
681 
682 	return 0;
683 }
684 
685 static int
686 eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
687 {
688 	dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
689 
690 	return 0;
691 }
692 
693 static int
694 eth_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
695 {
696 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
697 
698 	return 0;
699 }
700 
701 static const struct eth_dev_ops ops = {
702 	.dev_start = eth_dev_start,
703 	.dev_stop = eth_dev_stop,
704 	.dev_close = eth_dev_close,
705 	.dev_configure = eth_dev_configure,
706 	.dev_infos_get = eth_dev_info,
707 	.rx_queue_setup = eth_rx_queue_setup,
708 	.tx_queue_setup = eth_tx_queue_setup,
709 	.rx_queue_start = eth_rx_queue_start,
710 	.tx_queue_start = eth_tx_queue_start,
711 	.rx_queue_stop = eth_rx_queue_stop,
712 	.tx_queue_stop = eth_tx_queue_stop,
713 	.rx_queue_release = eth_queue_release,
714 	.tx_queue_release = eth_queue_release,
715 	.link_update = eth_link_update,
716 	.stats_get = eth_stats_get,
717 	.stats_reset = eth_stats_reset,
718 };
719 
720 static int
721 add_queue(struct pmd_devargs *pmd, const char *name, const char *type,
722 		pcap_t *pcap, pcap_dumper_t *dumper)
723 {
724 	if (pmd->num_of_queue >= RTE_PMD_PCAP_MAX_QUEUES)
725 		return -1;
726 	if (pcap)
727 		pmd->queue[pmd->num_of_queue].pcap = pcap;
728 	if (dumper)
729 		pmd->queue[pmd->num_of_queue].dumper = dumper;
730 	pmd->queue[pmd->num_of_queue].name = name;
731 	pmd->queue[pmd->num_of_queue].type = type;
732 	pmd->num_of_queue++;
733 	return 0;
734 }
735 
736 /*
737  * Function handler that opens the pcap file for reading a stores a
738  * reference of it for use it later on.
739  */
740 static int
741 open_rx_pcap(const char *key, const char *value, void *extra_args)
742 {
743 	const char *pcap_filename = value;
744 	struct pmd_devargs *rx = extra_args;
745 	pcap_t *pcap = NULL;
746 
747 	if (open_single_rx_pcap(pcap_filename, &pcap) < 0)
748 		return -1;
749 
750 	if (add_queue(rx, pcap_filename, key, pcap, NULL) < 0) {
751 		pcap_close(pcap);
752 		return -1;
753 	}
754 
755 	return 0;
756 }
757 
758 /*
759  * Opens a pcap file for writing and stores a reference to it
760  * for use it later on.
761  */
762 static int
763 open_tx_pcap(const char *key, const char *value, void *extra_args)
764 {
765 	const char *pcap_filename = value;
766 	struct pmd_devargs *dumpers = extra_args;
767 	pcap_dumper_t *dumper;
768 
769 	if (open_single_tx_pcap(pcap_filename, &dumper) < 0)
770 		return -1;
771 
772 	if (add_queue(dumpers, pcap_filename, key, NULL, dumper) < 0) {
773 		pcap_dump_close(dumper);
774 		return -1;
775 	}
776 
777 	return 0;
778 }
779 
780 /*
781  * Opens an interface for reading and writing
782  */
783 static inline int
784 open_rx_tx_iface(const char *key, const char *value, void *extra_args)
785 {
786 	const char *iface = value;
787 	struct pmd_devargs *tx = extra_args;
788 	pcap_t *pcap = NULL;
789 
790 	if (open_single_iface(iface, &pcap) < 0)
791 		return -1;
792 
793 	tx->queue[0].pcap = pcap;
794 	tx->queue[0].name = iface;
795 	tx->queue[0].type = key;
796 
797 	return 0;
798 }
799 
800 static inline int
801 set_iface_direction(const char *iface, pcap_t *pcap,
802 		pcap_direction_t direction)
803 {
804 	const char *direction_str = (direction == PCAP_D_IN) ? "IN" : "OUT";
805 	if (pcap_setdirection(pcap, direction) < 0) {
806 		PMD_LOG(ERR, "Setting %s pcap direction %s failed - %s\n",
807 				iface, direction_str, pcap_geterr(pcap));
808 		return -1;
809 	}
810 	PMD_LOG(INFO, "Setting %s pcap direction %s\n",
811 			iface, direction_str);
812 	return 0;
813 }
814 
815 static inline int
816 open_iface(const char *key, const char *value, void *extra_args)
817 {
818 	const char *iface = value;
819 	struct pmd_devargs *pmd = extra_args;
820 	pcap_t *pcap = NULL;
821 
822 	if (open_single_iface(iface, &pcap) < 0)
823 		return -1;
824 	if (add_queue(pmd, iface, key, pcap, NULL) < 0) {
825 		pcap_close(pcap);
826 		return -1;
827 	}
828 
829 	return 0;
830 }
831 
832 /*
833  * Opens a NIC for reading packets from it
834  */
835 static inline int
836 open_rx_iface(const char *key, const char *value, void *extra_args)
837 {
838 	int ret = open_iface(key, value, extra_args);
839 	if (ret < 0)
840 		return ret;
841 	if (strcmp(key, ETH_PCAP_RX_IFACE_IN_ARG) == 0) {
842 		struct pmd_devargs *pmd = extra_args;
843 		unsigned int qid = pmd->num_of_queue - 1;
844 
845 		set_iface_direction(pmd->queue[qid].name,
846 				pmd->queue[qid].pcap,
847 				PCAP_D_IN);
848 	}
849 
850 	return 0;
851 }
852 
853 static inline int
854 rx_iface_args_process(const char *key, const char *value, void *extra_args)
855 {
856 	if (strcmp(key, ETH_PCAP_RX_IFACE_ARG) == 0 ||
857 			strcmp(key, ETH_PCAP_RX_IFACE_IN_ARG) == 0)
858 		return open_rx_iface(key, value, extra_args);
859 
860 	return 0;
861 }
862 
863 /*
864  * Opens a NIC for writing packets to it
865  */
866 static int
867 open_tx_iface(const char *key, const char *value, void *extra_args)
868 {
869 	return open_iface(key, value, extra_args);
870 }
871 
872 static int
873 select_phy_mac(const char *key __rte_unused, const char *value,
874 		void *extra_args)
875 {
876 	if (extra_args) {
877 		const int phy_mac = atoi(value);
878 		int *enable_phy_mac = extra_args;
879 
880 		if (phy_mac)
881 			*enable_phy_mac = 1;
882 	}
883 	return 0;
884 }
885 
886 static int
887 pmd_init_internals(struct rte_vdev_device *vdev,
888 		const unsigned int nb_rx_queues,
889 		const unsigned int nb_tx_queues,
890 		struct pmd_internals **internals,
891 		struct rte_eth_dev **eth_dev)
892 {
893 	struct rte_eth_dev_data *data;
894 	struct pmd_process_private *pp;
895 	unsigned int numa_node = vdev->device.numa_node;
896 
897 	PMD_LOG(INFO, "Creating pcap-backed ethdev on numa socket %d",
898 		numa_node);
899 
900 	pp = (struct pmd_process_private *)
901 		rte_zmalloc(NULL, sizeof(struct pmd_process_private),
902 				RTE_CACHE_LINE_SIZE);
903 
904 	if (pp == NULL) {
905 		PMD_LOG(ERR,
906 			"Failed to allocate memory for process private");
907 		return -1;
908 	}
909 
910 	/* reserve an ethdev entry */
911 	*eth_dev = rte_eth_vdev_allocate(vdev, sizeof(**internals));
912 	if (!(*eth_dev)) {
913 		rte_free(pp);
914 		return -1;
915 	}
916 	(*eth_dev)->process_private = pp;
917 	/* now put it all together
918 	 * - store queue data in internals,
919 	 * - store numa_node info in eth_dev
920 	 * - point eth_dev_data to internals
921 	 * - and point eth_dev structure to new eth_dev_data structure
922 	 */
923 	*internals = (*eth_dev)->data->dev_private;
924 	/*
925 	 * Interface MAC = 02:70:63:61:70:<iface_idx>
926 	 * derived from: 'locally administered':'p':'c':'a':'p':'iface_idx'
927 	 * where the middle 4 characters are converted to hex.
928 	 */
929 	(*internals)->eth_addr = (struct ether_addr) {
930 		.addr_bytes = { 0x02, 0x70, 0x63, 0x61, 0x70, iface_idx++ }
931 	};
932 	(*internals)->phy_mac = 0;
933 	data = (*eth_dev)->data;
934 	data->nb_rx_queues = (uint16_t)nb_rx_queues;
935 	data->nb_tx_queues = (uint16_t)nb_tx_queues;
936 	data->dev_link = pmd_link;
937 	data->mac_addrs = &(*internals)->eth_addr;
938 
939 	/*
940 	 * NOTE: we'll replace the data element, of originally allocated
941 	 * eth_dev so the rings are local per-process
942 	 */
943 	(*eth_dev)->dev_ops = &ops;
944 
945 	strlcpy((*internals)->devargs, rte_vdev_device_args(vdev),
946 			ETH_PCAP_ARG_MAXLEN);
947 
948 	return 0;
949 }
950 
951 static int
952 eth_pcap_update_mac(const char *if_name, struct rte_eth_dev *eth_dev,
953 		const unsigned int numa_node)
954 {
955 #if defined(RTE_EXEC_ENV_LINUXAPP)
956 	void *mac_addrs;
957 	struct ifreq ifr;
958 	int if_fd = socket(AF_INET, SOCK_DGRAM, 0);
959 
960 	if (if_fd == -1)
961 		return -1;
962 
963 	rte_strscpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
964 	if (ioctl(if_fd, SIOCGIFHWADDR, &ifr)) {
965 		close(if_fd);
966 		return -1;
967 	}
968 
969 	mac_addrs = rte_zmalloc_socket(NULL, ETHER_ADDR_LEN, 0, numa_node);
970 	if (!mac_addrs) {
971 		close(if_fd);
972 		return -1;
973 	}
974 
975 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
976 	eth_dev->data->mac_addrs = mac_addrs;
977 	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
978 			ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
979 
980 	close(if_fd);
981 
982 	return 0;
983 
984 #elif defined(RTE_EXEC_ENV_BSDAPP)
985 	void *mac_addrs;
986 	struct if_msghdr *ifm;
987 	struct sockaddr_dl *sdl;
988 	int mib[6];
989 	size_t len = 0;
990 	char *buf;
991 
992 	mib[0] = CTL_NET;
993 	mib[1] = AF_ROUTE;
994 	mib[2] = 0;
995 	mib[3] = AF_LINK;
996 	mib[4] = NET_RT_IFLIST;
997 	mib[5] = if_nametoindex(if_name);
998 
999 	if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
1000 		return -1;
1001 
1002 	if (len == 0)
1003 		return -1;
1004 
1005 	buf = rte_malloc(NULL, len, 0);
1006 	if (!buf)
1007 		return -1;
1008 
1009 	if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
1010 		rte_free(buf);
1011 		return -1;
1012 	}
1013 	ifm = (struct if_msghdr *)buf;
1014 	sdl = (struct sockaddr_dl *)(ifm + 1);
1015 
1016 	mac_addrs = rte_zmalloc_socket(NULL, ETHER_ADDR_LEN, 0, numa_node);
1017 	if (!mac_addrs) {
1018 		rte_free(buf);
1019 		return -1;
1020 	}
1021 
1022 	PMD_LOG(INFO, "Setting phy MAC for %s", if_name);
1023 	eth_dev->data->mac_addrs = mac_addrs;
1024 	rte_memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
1025 			LLADDR(sdl), ETHER_ADDR_LEN);
1026 
1027 	rte_free(buf);
1028 
1029 	return 0;
1030 #else
1031 	return -1;
1032 #endif
1033 }
1034 
1035 static int
1036 eth_from_pcaps_common(struct rte_vdev_device *vdev,
1037 		struct pmd_devargs *rx_queues, const unsigned int nb_rx_queues,
1038 		struct pmd_devargs *tx_queues, const unsigned int nb_tx_queues,
1039 		struct pmd_internals **internals, struct rte_eth_dev **eth_dev)
1040 {
1041 	struct pmd_process_private *pp;
1042 	unsigned int i;
1043 
1044 	/* do some parameter checking */
1045 	if (rx_queues == NULL && nb_rx_queues > 0)
1046 		return -1;
1047 	if (tx_queues == NULL && nb_tx_queues > 0)
1048 		return -1;
1049 
1050 	if (pmd_init_internals(vdev, nb_rx_queues, nb_tx_queues, internals,
1051 			eth_dev) < 0)
1052 		return -1;
1053 
1054 	pp = (*eth_dev)->process_private;
1055 	for (i = 0; i < nb_rx_queues; i++) {
1056 		struct pcap_rx_queue *rx = &(*internals)->rx_queue[i];
1057 		struct devargs_queue *queue = &rx_queues->queue[i];
1058 
1059 		pp->rx_pcap[i] = queue->pcap;
1060 		snprintf(rx->name, sizeof(rx->name), "%s", queue->name);
1061 		snprintf(rx->type, sizeof(rx->type), "%s", queue->type);
1062 	}
1063 
1064 	for (i = 0; i < nb_tx_queues; i++) {
1065 		struct pcap_tx_queue *tx = &(*internals)->tx_queue[i];
1066 		struct devargs_queue *queue = &tx_queues->queue[i];
1067 
1068 		pp->tx_dumper[i] = queue->dumper;
1069 		pp->tx_pcap[i] = queue->pcap;
1070 		snprintf(tx->name, sizeof(tx->name), "%s", queue->name);
1071 		snprintf(tx->type, sizeof(tx->type), "%s", queue->type);
1072 	}
1073 
1074 	return 0;
1075 }
1076 
1077 static int
1078 eth_from_pcaps(struct rte_vdev_device *vdev,
1079 		struct pmd_devargs *rx_queues, const unsigned int nb_rx_queues,
1080 		struct pmd_devargs *tx_queues, const unsigned int nb_tx_queues,
1081 		int single_iface, unsigned int using_dumpers)
1082 {
1083 	struct pmd_internals *internals = NULL;
1084 	struct rte_eth_dev *eth_dev = NULL;
1085 	int ret;
1086 
1087 	ret = eth_from_pcaps_common(vdev, rx_queues, nb_rx_queues,
1088 		tx_queues, nb_tx_queues, &internals, &eth_dev);
1089 
1090 	if (ret < 0)
1091 		return ret;
1092 
1093 	/* store weather we are using a single interface for rx/tx or not */
1094 	internals->single_iface = single_iface;
1095 
1096 	if (single_iface) {
1097 		internals->if_index = if_nametoindex(rx_queues->queue[0].name);
1098 
1099 		/* phy_mac arg is applied only only if "iface" devarg is provided */
1100 		if (rx_queues->phy_mac) {
1101 			int ret = eth_pcap_update_mac(rx_queues->queue[0].name,
1102 					eth_dev, vdev->device.numa_node);
1103 			if (ret == 0)
1104 				internals->phy_mac = 1;
1105 		}
1106 	}
1107 
1108 	eth_dev->rx_pkt_burst = eth_pcap_rx;
1109 
1110 	if (using_dumpers)
1111 		eth_dev->tx_pkt_burst = eth_pcap_tx_dumper;
1112 	else
1113 		eth_dev->tx_pkt_burst = eth_pcap_tx;
1114 
1115 	rte_eth_dev_probing_finish(eth_dev);
1116 	return 0;
1117 }
1118 
1119 static int
1120 pmd_pcap_probe(struct rte_vdev_device *dev)
1121 {
1122 	const char *name;
1123 	unsigned int is_rx_pcap = 0, is_tx_pcap = 0;
1124 	struct rte_kvargs *kvlist;
1125 	struct pmd_devargs pcaps = {0};
1126 	struct pmd_devargs dumpers = {0};
1127 	struct rte_eth_dev *eth_dev =  NULL;
1128 	struct pmd_internals *internal;
1129 	int single_iface = 0;
1130 	int ret;
1131 
1132 	name = rte_vdev_device_name(dev);
1133 	PMD_LOG(INFO, "Initializing pmd_pcap for %s", name);
1134 
1135 	gettimeofday(&start_time, NULL);
1136 	start_cycles = rte_get_timer_cycles();
1137 	hz = rte_get_timer_hz();
1138 
1139 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
1140 		eth_dev = rte_eth_dev_attach_secondary(name);
1141 		if (!eth_dev) {
1142 			PMD_LOG(ERR, "Failed to probe %s", name);
1143 			return -1;
1144 		}
1145 
1146 		internal = eth_dev->data->dev_private;
1147 
1148 		kvlist = rte_kvargs_parse(internal->devargs, valid_arguments);
1149 		if (kvlist == NULL)
1150 			return -1;
1151 	} else {
1152 		kvlist = rte_kvargs_parse(rte_vdev_device_args(dev),
1153 				valid_arguments);
1154 		if (kvlist == NULL)
1155 			return -1;
1156 	}
1157 
1158 	/*
1159 	 * If iface argument is passed we open the NICs and use them for
1160 	 * reading / writing
1161 	 */
1162 	if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) {
1163 
1164 		ret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG,
1165 				&open_rx_tx_iface, &pcaps);
1166 		if (ret < 0)
1167 			goto free_kvlist;
1168 
1169 		dumpers.queue[0] = pcaps.queue[0];
1170 
1171 		ret = rte_kvargs_process(kvlist, ETH_PCAP_PHY_MAC_ARG,
1172 				&select_phy_mac, &pcaps.phy_mac);
1173 		if (ret < 0)
1174 			goto free_kvlist;
1175 
1176 		dumpers.phy_mac = pcaps.phy_mac;
1177 
1178 		single_iface = 1;
1179 		pcaps.num_of_queue = 1;
1180 		dumpers.num_of_queue = 1;
1181 
1182 		goto create_eth;
1183 	}
1184 
1185 	/*
1186 	 * We check whether we want to open a RX stream from a real NIC or a
1187 	 * pcap file
1188 	 */
1189 	is_rx_pcap = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG) ? 1 : 0;
1190 	pcaps.num_of_queue = 0;
1191 
1192 	if (is_rx_pcap) {
1193 		ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG,
1194 				&open_rx_pcap, &pcaps);
1195 	} else {
1196 		ret = rte_kvargs_process(kvlist, NULL,
1197 				&rx_iface_args_process, &pcaps);
1198 	}
1199 
1200 	if (ret < 0)
1201 		goto free_kvlist;
1202 
1203 	/*
1204 	 * We check whether we want to open a TX stream to a real NIC or a
1205 	 * pcap file
1206 	 */
1207 	is_tx_pcap = rte_kvargs_count(kvlist, ETH_PCAP_TX_PCAP_ARG) ? 1 : 0;
1208 	dumpers.num_of_queue = 0;
1209 
1210 	if (is_tx_pcap)
1211 		ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_PCAP_ARG,
1212 				&open_tx_pcap, &dumpers);
1213 	else
1214 		ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_IFACE_ARG,
1215 				&open_tx_iface, &dumpers);
1216 
1217 	if (ret < 0)
1218 		goto free_kvlist;
1219 
1220 create_eth:
1221 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
1222 		struct pmd_process_private *pp;
1223 		unsigned int i;
1224 
1225 		internal = eth_dev->data->dev_private;
1226 			pp = (struct pmd_process_private *)
1227 				rte_zmalloc(NULL,
1228 					sizeof(struct pmd_process_private),
1229 					RTE_CACHE_LINE_SIZE);
1230 
1231 		if (pp == NULL) {
1232 			PMD_LOG(ERR,
1233 				"Failed to allocate memory for process private");
1234 			ret = -1;
1235 			goto free_kvlist;
1236 		}
1237 
1238 		eth_dev->dev_ops = &ops;
1239 		eth_dev->device = &dev->device;
1240 
1241 		/* setup process private */
1242 		for (i = 0; i < pcaps.num_of_queue; i++)
1243 			pp->rx_pcap[i] = pcaps.queue[i].pcap;
1244 
1245 		for (i = 0; i < dumpers.num_of_queue; i++) {
1246 			pp->tx_dumper[i] = dumpers.queue[i].dumper;
1247 			pp->tx_pcap[i] = dumpers.queue[i].pcap;
1248 		}
1249 
1250 		eth_dev->process_private = pp;
1251 		eth_dev->rx_pkt_burst = eth_pcap_rx;
1252 		if (is_tx_pcap)
1253 			eth_dev->tx_pkt_burst = eth_pcap_tx_dumper;
1254 		else
1255 			eth_dev->tx_pkt_burst = eth_pcap_tx;
1256 
1257 		rte_eth_dev_probing_finish(eth_dev);
1258 		goto free_kvlist;
1259 	}
1260 
1261 	ret = eth_from_pcaps(dev, &pcaps, pcaps.num_of_queue, &dumpers,
1262 		dumpers.num_of_queue, single_iface, is_tx_pcap);
1263 
1264 free_kvlist:
1265 	rte_kvargs_free(kvlist);
1266 
1267 	return ret;
1268 }
1269 
1270 static int
1271 pmd_pcap_remove(struct rte_vdev_device *dev)
1272 {
1273 	struct pmd_internals *internals = NULL;
1274 	struct rte_eth_dev *eth_dev = NULL;
1275 
1276 	PMD_LOG(INFO, "Closing pcap ethdev on numa socket %d",
1277 			rte_socket_id());
1278 
1279 	if (!dev)
1280 		return -1;
1281 
1282 	/* reserve an ethdev entry */
1283 	eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
1284 	if (eth_dev == NULL)
1285 		return -1;
1286 
1287 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
1288 		internals = eth_dev->data->dev_private;
1289 		if (internals != NULL && internals->phy_mac == 0)
1290 			/* not dynamically allocated, must not be freed */
1291 			eth_dev->data->mac_addrs = NULL;
1292 	}
1293 
1294 	rte_free(eth_dev->process_private);
1295 	rte_eth_dev_release_port(eth_dev);
1296 
1297 	return 0;
1298 }
1299 
1300 static struct rte_vdev_driver pmd_pcap_drv = {
1301 	.probe = pmd_pcap_probe,
1302 	.remove = pmd_pcap_remove,
1303 };
1304 
1305 RTE_PMD_REGISTER_VDEV(net_pcap, pmd_pcap_drv);
1306 RTE_PMD_REGISTER_ALIAS(net_pcap, eth_pcap);
1307 RTE_PMD_REGISTER_PARAM_STRING(net_pcap,
1308 	ETH_PCAP_RX_PCAP_ARG "=<string> "
1309 	ETH_PCAP_TX_PCAP_ARG "=<string> "
1310 	ETH_PCAP_RX_IFACE_ARG "=<ifc> "
1311 	ETH_PCAP_RX_IFACE_IN_ARG "=<ifc> "
1312 	ETH_PCAP_TX_IFACE_ARG "=<ifc> "
1313 	ETH_PCAP_IFACE_ARG "=<ifc> "
1314 	ETH_PCAP_PHY_MAC_ARG "=<int>");
1315 
1316 RTE_INIT(eth_pcap_init_log)
1317 {
1318 	eth_pcap_logtype = rte_log_register("pmd.net.pcap");
1319 	if (eth_pcap_logtype >= 0)
1320 		rte_log_set_level(eth_pcap_logtype, RTE_LOG_NOTICE);
1321 }
1322