1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4 
5 #include <netinet/in.h>
6 #ifdef RTE_EXEC_ENV_LINUX
7 #include <linux/if.h>
8 #include <linux/if_tun.h>
9 #endif
10 #include <sys/ioctl.h>
11 
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 
18 #include <rte_string_fns.h>
19 
20 #include "rte_eth_softnic_internals.h"
21 
22 #define TAP_DEV                                            "/dev/net/tun"
23 
24 int
softnic_tap_init(struct pmd_internals * p)25 softnic_tap_init(struct pmd_internals *p)
26 {
27 	TAILQ_INIT(&p->tap_list);
28 
29 	return 0;
30 }
31 
32 void
softnic_tap_free(struct pmd_internals * p)33 softnic_tap_free(struct pmd_internals *p)
34 {
35 	for ( ; ; ) {
36 		struct softnic_tap *tap;
37 
38 		tap = TAILQ_FIRST(&p->tap_list);
39 		if (tap == NULL)
40 			break;
41 
42 		TAILQ_REMOVE(&p->tap_list, tap, node);
43 		free(tap);
44 	}
45 }
46 
47 struct softnic_tap *
softnic_tap_find(struct pmd_internals * p,const char * name)48 softnic_tap_find(struct pmd_internals *p,
49 	const char *name)
50 {
51 	struct softnic_tap *tap;
52 
53 	if (name == NULL)
54 		return NULL;
55 
56 	TAILQ_FOREACH(tap, &p->tap_list, node)
57 		if (strcmp(tap->name, name) == 0)
58 			return tap;
59 
60 	return NULL;
61 }
62 
63 #ifndef RTE_EXEC_ENV_LINUX
64 
65 struct softnic_tap *
softnic_tap_create(struct pmd_internals * p __rte_unused,const char * name __rte_unused)66 softnic_tap_create(struct pmd_internals *p __rte_unused,
67 	const char *name __rte_unused)
68 {
69 	return NULL;
70 }
71 
72 #else
73 
74 struct softnic_tap *
softnic_tap_create(struct pmd_internals * p,const char * name)75 softnic_tap_create(struct pmd_internals *p,
76 	const char *name)
77 {
78 	struct softnic_tap *tap;
79 	struct ifreq ifr;
80 	int fd, status;
81 
82 	/* Check input params */
83 	if (name == NULL ||
84 		softnic_tap_find(p, name))
85 		return NULL;
86 
87 	/* Resource create */
88 	fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
89 	if (fd < 0)
90 		return NULL;
91 
92 	memset(&ifr, 0, sizeof(ifr));
93 	ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
94 	strlcpy(ifr.ifr_name, name, IFNAMSIZ);
95 
96 	status = ioctl(fd, TUNSETIFF, (void *)&ifr);
97 	if (status < 0) {
98 		close(fd);
99 		return NULL;
100 	}
101 
102 	/* Node allocation */
103 	tap = calloc(1, sizeof(struct softnic_tap));
104 	if (tap == NULL) {
105 		close(fd);
106 		return NULL;
107 	}
108 	/* Node fill in */
109 	strlcpy(tap->name, name, sizeof(tap->name));
110 	tap->fd = fd;
111 
112 	/* Node add to list */
113 	TAILQ_INSERT_TAIL(&p->tap_list, tap, node);
114 
115 	return tap;
116 }
117 
118 #endif
119