Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2016-2017 Intel Corporation
3 : : */
4 : :
5 : : #include <rte_atomic.h>
6 : : #include <rte_branch_prediction.h>
7 : : #include <rte_byteorder.h>
8 : : #include <rte_common.h>
9 : : #include <rte_mbuf.h>
10 : : #include <ethdev_driver.h>
11 : : #include <ethdev_vdev.h>
12 : : #include <rte_malloc.h>
13 : : #include <bus_vdev_driver.h>
14 : : #include <rte_kvargs.h>
15 : : #include <rte_net.h>
16 : : #include <rte_debug.h>
17 : : #include <rte_ip.h>
18 : : #include <rte_ethdev.h>
19 : : #include <rte_errno.h>
20 : : #include <rte_cycles.h>
21 : :
22 : : #include <assert.h>
23 : : #include <sys/types.h>
24 : : #include <sys/stat.h>
25 : : #include <sys/ioctl.h>
26 : : #include <sys/mman.h>
27 : : #include <errno.h>
28 : : #include <signal.h>
29 : : #include <stdbool.h>
30 : : #include <stdint.h>
31 : : #include <stdlib.h>
32 : : #include <sys/uio.h>
33 : : #include <unistd.h>
34 : : #include <net/if.h>
35 : : #include <linux/if_tun.h>
36 : : #include <linux/sched.h>
37 : : #include <fcntl.h>
38 : :
39 : : #include <tap_rss.h>
40 : : #include <rte_eth_tap.h>
41 : : #include <tap_flow.h>
42 : : #include <tap_netlink.h>
43 : : #include <tap_tcmsgs.h>
44 : :
45 : : /* Linux based path to the TUN device */
46 : : #define TUN_TAP_DEV_PATH "/dev/net/tun"
47 : : #define DEFAULT_TAP_NAME "dtap"
48 : : #define DEFAULT_TUN_NAME "dtun"
49 : :
50 : : #define ETH_TAP_IFACE_ARG "iface"
51 : : #define ETH_TAP_REMOTE_ARG "remote"
52 : : #define ETH_TAP_MAC_ARG "mac"
53 : : #define ETH_TAP_MAC_FIXED "fixed"
54 : : #define ETH_TAP_PERSIST_ARG "persist"
55 : :
56 : : #define ETH_TAP_USR_MAC_FMT "xx:xx:xx:xx:xx:xx"
57 : : #define ETH_TAP_CMP_MAC_FMT "0123456789ABCDEFabcdef"
58 : : #define ETH_TAP_MAC_ARG_FMT ETH_TAP_MAC_FIXED "|" ETH_TAP_USR_MAC_FMT
59 : :
60 : : #define TAP_GSO_MBUFS_PER_CORE 128
61 : : #define TAP_GSO_MBUF_SEG_SIZE 128
62 : : #define TAP_GSO_MBUF_CACHE_SIZE 4
63 : : #define TAP_GSO_MBUFS_NUM \
64 : : (TAP_GSO_MBUFS_PER_CORE * TAP_GSO_MBUF_CACHE_SIZE)
65 : :
66 : : /* IPC key for queue fds sync */
67 : : #define TAP_MP_KEY "tap_mp_sync_queues"
68 : : #define TAP_MP_REQ_START_RXTX "tap_mp_req_start_rxtx"
69 : :
70 : : static_assert(RTE_PMD_TAP_MAX_QUEUES <= RTE_MP_MAX_FD_NUM, "TAP max queues exceeds MP fd limit");
71 : :
72 : : #define TAP_IOV_DEFAULT_MAX 1024
73 : :
74 : : #define TAP_RX_OFFLOAD (RTE_ETH_RX_OFFLOAD_SCATTER | \
75 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | \
76 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM | \
77 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
78 : :
79 : : #define TAP_TX_OFFLOAD (RTE_ETH_TX_OFFLOAD_MULTI_SEGS | \
80 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM | \
81 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM | \
82 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM | \
83 : : RTE_ETH_TX_OFFLOAD_TCP_TSO)
84 : :
85 : : static int tap_devices_count;
86 : :
87 : : static const char *tuntap_types[ETH_TUNTAP_TYPE_MAX] = {
88 : : "UNKNOWN", "TUN", "TAP"
89 : : };
90 : :
91 : : static const char *valid_arguments[] = {
92 : : ETH_TAP_IFACE_ARG,
93 : : ETH_TAP_REMOTE_ARG,
94 : : ETH_TAP_MAC_ARG,
95 : : ETH_TAP_PERSIST_ARG,
96 : : NULL
97 : : };
98 : :
99 : : static volatile uint32_t tap_trigger; /* Rx trigger */
100 : :
101 : : static struct rte_eth_link pmd_link = {
102 : : .link_speed = RTE_ETH_SPEED_NUM_10G,
103 : : .link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
104 : : .link_status = RTE_ETH_LINK_DOWN,
105 : : .link_autoneg = RTE_ETH_LINK_FIXED,
106 : : };
107 : :
108 : : static void
109 : 0 : tap_trigger_cb(int sig __rte_unused)
110 : : {
111 : : /* Valid trigger values are nonzero */
112 : 0 : tap_trigger = (tap_trigger + 1) | 0x80000000;
113 : 0 : }
114 : :
115 : : /* Message header to synchronize queues via IPC */
116 : : struct ipc_queues {
117 : : char port_name[RTE_DEV_NAME_MAX_LEN];
118 : : int q_count;
119 : : /*
120 : : * The file descriptors are in the dedicated part
121 : : * of the Unix message to be translated by the kernel.
122 : : */
123 : : };
124 : :
125 : : static int tap_intr_handle_set(struct rte_eth_dev *dev, int set);
126 : :
127 : : /**
128 : : * Tun/Tap allocation routine
129 : : *
130 : : * @param[in] pmd
131 : : * Pointer to private structure.
132 : : *
133 : : * @param[in] is_keepalive
134 : : * Keepalive flag
135 : : *
136 : : * @param[in] persistent
137 : : * Mark device as persistent
138 : : *
139 : : * @return
140 : : * -1 on failure, fd on success
141 : : */
142 : : static int
143 [ # # ]: 0 : tun_alloc(struct pmd_internals *pmd, int is_keepalive, int persistent)
144 : : {
145 : : struct ifreq ifr;
146 : : #ifdef IFF_MULTI_QUEUE
147 : : unsigned int features;
148 : : #endif
149 : : int fd, signo, flags;
150 : :
151 : : memset(&ifr, 0, sizeof(struct ifreq));
152 : :
153 : : /*
154 : : * Do not set IFF_NO_PI as packet information header will be needed
155 : : * to check if a received packet has been truncated.
156 : : */
157 [ # # ]: 0 : ifr.ifr_flags = (pmd->type == ETH_TUNTAP_TYPE_TAP) ?
158 : : IFF_TAP : IFF_TUN | IFF_POINTOPOINT;
159 : 0 : strlcpy(ifr.ifr_name, pmd->name, IFNAMSIZ);
160 : :
161 : : fd = open(TUN_TAP_DEV_PATH, O_RDWR);
162 [ # # ]: 0 : if (fd < 0) {
163 : 0 : TAP_LOG(ERR, "Unable to open %s interface", TUN_TAP_DEV_PATH);
164 : 0 : goto error;
165 : : }
166 : :
167 : : #ifdef IFF_MULTI_QUEUE
168 : : /* Grab the TUN features to verify we can work multi-queue */
169 [ # # ]: 0 : if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
170 : 0 : TAP_LOG(ERR, "unable to get TUN/TAP features");
171 : 0 : goto error;
172 : : }
173 : 0 : TAP_LOG(DEBUG, "%s Features %08x", TUN_TAP_DEV_PATH, features);
174 : :
175 [ # # ]: 0 : if (features & IFF_MULTI_QUEUE) {
176 : 0 : TAP_LOG(DEBUG, " Multi-queue support for %d queues",
177 : : RTE_PMD_TAP_MAX_QUEUES);
178 : 0 : ifr.ifr_flags |= IFF_MULTI_QUEUE;
179 : : } else
180 : : #endif
181 : : {
182 : 0 : ifr.ifr_flags |= IFF_ONE_QUEUE;
183 : 0 : TAP_LOG(DEBUG, " Single queue only support");
184 : : }
185 : :
186 : : /* Set the TUN/TAP configuration and set the name if needed */
187 [ # # ]: 0 : if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
188 : 0 : TAP_LOG(WARNING, "Unable to set TUNSETIFF for %s: %s",
189 : : ifr.ifr_name, strerror(errno));
190 : 0 : goto error;
191 : : }
192 : :
193 : : /* Keep the device after application exit */
194 [ # # # # ]: 0 : if (persistent && ioctl(fd, TUNSETPERSIST, 1) < 0) {
195 : 0 : TAP_LOG(WARNING,
196 : : "Unable to set persist %s: %s",
197 : : ifr.ifr_name, strerror(errno));
198 : 0 : goto error;
199 : : }
200 : :
201 : : /*
202 : : * Name passed to kernel might be wildcard like dtun%d
203 : : * and need to find the resulting device.
204 : : */
205 : 0 : TAP_LOG(DEBUG, "Device name is '%s'", ifr.ifr_name);
206 : : strlcpy(pmd->name, ifr.ifr_name, RTE_ETH_NAME_MAX_LEN);
207 : :
208 [ # # ]: 0 : if (is_keepalive) {
209 : : /*
210 : : * Detach the TUN/TAP keep-alive queue
211 : : * to avoid traffic through it
212 : : */
213 : 0 : ifr.ifr_flags = IFF_DETACH_QUEUE;
214 [ # # ]: 0 : if (ioctl(fd, TUNSETQUEUE, (void *)&ifr) < 0) {
215 : 0 : TAP_LOG(WARNING,
216 : : "Unable to detach keep-alive queue for %s: %s",
217 : : ifr.ifr_name, strerror(errno));
218 : 0 : goto error;
219 : : }
220 : : }
221 : :
222 : 0 : flags = fcntl(fd, F_GETFL);
223 [ # # ]: 0 : if (flags == -1) {
224 : 0 : TAP_LOG(WARNING, "Unable to get %s current flags: %s",
225 : : ifr.ifr_name, strerror(errno));
226 : 0 : goto error;
227 : : }
228 : :
229 : : /* Always set the file descriptor to non-blocking */
230 : 0 : flags |= O_NONBLOCK;
231 [ # # ]: 0 : if (fcntl(fd, F_SETFL, flags) < 0) {
232 : 0 : TAP_LOG(WARNING,
233 : : "Unable to set %s to nonblocking: %s",
234 : : ifr.ifr_name, strerror(errno));
235 : 0 : goto error;
236 : : }
237 : :
238 : : /* Find a free realtime signal */
239 [ # # ]: 0 : for (signo = SIGRTMIN + 1; signo < SIGRTMAX; signo++) {
240 : : struct sigaction sa;
241 : :
242 [ # # ]: 0 : if (sigaction(signo, NULL, &sa) == -1) {
243 : 0 : TAP_LOG(WARNING,
244 : : "Unable to get current rt-signal %d handler",
245 : : signo);
246 : 0 : goto error;
247 : : }
248 : :
249 : : /* Already have the handler we want on this signal */
250 [ # # ]: 0 : if (sa.sa_handler == tap_trigger_cb)
251 : : break;
252 : :
253 : : /* Is handler in use by application */
254 [ # # ]: 0 : if (sa.sa_handler != SIG_DFL) {
255 : 0 : TAP_LOG(DEBUG,
256 : : "Skipping used rt-signal %d", signo);
257 : 0 : continue;
258 : : }
259 : :
260 : 0 : sa = (struct sigaction) {
261 : : .sa_flags = SA_RESTART,
262 : : .sa_handler = tap_trigger_cb,
263 : : };
264 : :
265 [ # # ]: 0 : if (sigaction(signo, &sa, NULL) == -1) {
266 : 0 : TAP_LOG(WARNING,
267 : : "Unable to set rt-signal %d handler", signo);
268 : 0 : goto error;
269 : : }
270 : :
271 : : /* Found a good signal to use */
272 : 0 : TAP_LOG(DEBUG,
273 : : "Using rt-signal %d", signo);
274 : 0 : break;
275 : : }
276 : :
277 [ # # ]: 0 : if (signo == SIGRTMAX) {
278 : 0 : TAP_LOG(WARNING, "All rt-signals are in use");
279 : :
280 : : /* Disable trigger globally in case of error */
281 : 0 : tap_trigger = 0;
282 : 0 : TAP_LOG(NOTICE, "No Rx trigger signal available");
283 : : } else {
284 : : /* Enable signal on file descriptor */
285 [ # # ]: 0 : if (fcntl(fd, F_SETSIG, signo) < 0) {
286 : 0 : TAP_LOG(WARNING, "Unable to set signo %d for fd %d: %s",
287 : : signo, fd, strerror(errno));
288 : 0 : goto error;
289 : : }
290 [ # # ]: 0 : if (fcntl(fd, F_SETFL, flags | O_ASYNC) < 0) {
291 : 0 : TAP_LOG(WARNING, "Unable to set fcntl flags: %s",
292 : : strerror(errno));
293 : 0 : goto error;
294 : : }
295 : :
296 [ # # ]: 0 : if (fcntl(fd, F_SETOWN, getpid()) < 0) {
297 : 0 : TAP_LOG(WARNING, "Unable to set fcntl owner: %s",
298 : : strerror(errno));
299 : 0 : goto error;
300 : : }
301 : : }
302 : : return fd;
303 : :
304 : 0 : error:
305 [ # # ]: 0 : if (fd >= 0)
306 : 0 : close(fd);
307 : : return -1;
308 : : }
309 : :
310 : : static void
311 : 0 : tap_verify_csum(struct rte_mbuf *mbuf)
312 : : {
313 : 0 : uint32_t l2 = mbuf->packet_type & RTE_PTYPE_L2_MASK;
314 : 0 : uint32_t l3 = mbuf->packet_type & RTE_PTYPE_L3_MASK;
315 : 0 : uint32_t l4 = mbuf->packet_type & RTE_PTYPE_L4_MASK;
316 : : unsigned int l2_len = sizeof(struct rte_ether_hdr);
317 : : unsigned int l3_len;
318 : : uint16_t cksum = 0;
319 : : void *l3_hdr;
320 : : void *l4_hdr;
321 : : struct rte_udp_hdr *udp_hdr;
322 : :
323 [ # # ]: 0 : if (l2 == RTE_PTYPE_L2_ETHER_VLAN)
324 : : l2_len += 4;
325 [ # # ]: 0 : else if (l2 == RTE_PTYPE_L2_ETHER_QINQ)
326 : : l2_len += 8;
327 : : /* Don't verify checksum for packets with discontinuous L2 header */
328 [ # # ]: 0 : if (unlikely(l2_len + sizeof(struct rte_ipv4_hdr) >
329 : : rte_pktmbuf_data_len(mbuf)))
330 : : return;
331 : 0 : l3_hdr = rte_pktmbuf_mtod_offset(mbuf, void *, l2_len);
332 [ # # ]: 0 : if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) {
333 : : struct rte_ipv4_hdr *iph = l3_hdr;
334 : :
335 : 0 : l3_len = rte_ipv4_hdr_len(iph);
336 [ # # ]: 0 : if (unlikely(l2_len + l3_len > rte_pktmbuf_data_len(mbuf)))
337 : : return;
338 : : /* check that the total length reported by header is not
339 : : * greater than the total received size
340 : : */
341 [ # # # # ]: 0 : if (l2_len + rte_be_to_cpu_16(iph->total_length) >
342 : : rte_pktmbuf_data_len(mbuf))
343 : : return;
344 : :
345 : 0 : cksum = ~rte_raw_cksum(iph, l3_len);
346 : 0 : mbuf->ol_flags |= cksum ?
347 [ # # ]: 0 : RTE_MBUF_F_RX_IP_CKSUM_BAD :
348 : : RTE_MBUF_F_RX_IP_CKSUM_GOOD;
349 [ # # ]: 0 : } else if (l3 == RTE_PTYPE_L3_IPV6) {
350 : : struct rte_ipv6_hdr *iph = l3_hdr;
351 : :
352 : : l3_len = sizeof(struct rte_ipv6_hdr);
353 : : /* check that the total length reported by header is not
354 : : * greater than the total received size
355 : : */
356 [ # # ]: 0 : if (l2_len + l3_len + rte_be_to_cpu_16(iph->payload_len) >
357 [ # # ]: 0 : rte_pktmbuf_data_len(mbuf))
358 : : return;
359 : : } else {
360 : : /* - RTE_PTYPE_L3_IPV4_EXT_UNKNOWN cannot happen because
361 : : * mbuf->packet_type is filled by rte_net_get_ptype() which
362 : : * never returns this value.
363 : : * - IPv6 extensions are not supported.
364 : : */
365 : : return;
366 : : }
367 [ # # ]: 0 : if (l4 == RTE_PTYPE_L4_UDP || l4 == RTE_PTYPE_L4_TCP) {
368 : : int cksum_ok;
369 : :
370 : 0 : l4_hdr = rte_pktmbuf_mtod_offset(mbuf, void *, l2_len + l3_len);
371 : : /* Don't verify checksum for multi-segment packets. */
372 [ # # ]: 0 : if (mbuf->nb_segs > 1)
373 : : return;
374 [ # # ]: 0 : if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) {
375 [ # # ]: 0 : if (l4 == RTE_PTYPE_L4_UDP) {
376 : : udp_hdr = (struct rte_udp_hdr *)l4_hdr;
377 [ # # ]: 0 : if (udp_hdr->dgram_cksum == 0) {
378 : : /*
379 : : * For IPv4, a zero UDP checksum
380 : : * indicates that the sender did not
381 : : * generate one [RFC 768].
382 : : */
383 : 0 : mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_NONE;
384 : 0 : return;
385 : : }
386 : : }
387 : 0 : cksum_ok = !rte_ipv4_udptcp_cksum_verify(l3_hdr,
388 : : l4_hdr);
389 : : } else { /* l3 == RTE_PTYPE_L3_IPV6, checked above */
390 : 0 : cksum_ok = !rte_ipv6_udptcp_cksum_verify(l3_hdr,
391 : : l4_hdr);
392 : : }
393 : 0 : mbuf->ol_flags |= cksum_ok ?
394 [ # # ]: 0 : RTE_MBUF_F_RX_L4_CKSUM_GOOD : RTE_MBUF_F_RX_L4_CKSUM_BAD;
395 : : }
396 : : }
397 : :
398 : : static void
399 : : tap_rxq_pool_free(struct rte_mbuf *pool)
400 : : {
401 : : struct rte_mbuf *mbuf = pool;
402 : : uint16_t nb_segs = 1;
403 : :
404 : 0 : if (mbuf == NULL)
405 : : return;
406 : :
407 [ # # # # : 0 : while (mbuf->next) {
# # # # ]
408 : : mbuf = mbuf->next;
409 : 0 : nb_segs++;
410 : : }
411 : 0 : pool->nb_segs = nb_segs;
412 : 0 : rte_pktmbuf_free(pool);
413 : : }
414 : :
415 : : /* Callback to handle the rx burst of packets to the correct interface and
416 : : * file descriptor(s) in a multi-queue setup.
417 : : */
418 : : static uint16_t
419 : 0 : pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
420 : : {
421 : : struct rx_queue *rxq = queue;
422 : : struct pmd_process_private *process_private;
423 : : uint16_t num_rx;
424 : : unsigned long num_rx_bytes = 0;
425 : 0 : uint32_t trigger = tap_trigger;
426 : :
427 [ # # ]: 0 : if (trigger == rxq->trigger_seen)
428 : : return 0;
429 : :
430 : 0 : process_private = rte_eth_devices[rxq->in_port].process_private;
431 [ # # ]: 0 : for (num_rx = 0; num_rx < nb_pkts; ) {
432 [ # # ]: 0 : struct rte_mbuf *mbuf = rxq->pool;
433 : : struct rte_mbuf *seg = NULL;
434 : : struct rte_mbuf *new_tail = NULL;
435 : : uint16_t data_off = rte_pktmbuf_headroom(mbuf);
436 : : int len;
437 : :
438 : 0 : len = readv(process_private->fds[rxq->queue_id],
439 : 0 : *rxq->iovecs,
440 [ # # ]: 0 : 1 + (rxq->rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER ?
441 : 0 : rxq->nb_rx_desc : 1));
442 [ # # ]: 0 : if (len < (int)sizeof(struct tun_pi))
443 : : break;
444 : :
445 : : /* Packet couldn't fit in the provided mbuf */
446 [ # # ]: 0 : if (unlikely(rxq->pi.flags & TUN_PKT_STRIP)) {
447 : 0 : rxq->stats.ierrors++;
448 : 0 : continue;
449 : : }
450 : :
451 : 0 : len -= sizeof(struct tun_pi);
452 : :
453 : 0 : mbuf->pkt_len = len;
454 : 0 : mbuf->port = rxq->in_port;
455 : 0 : while (1) {
456 : 0 : struct rte_mbuf *buf = rte_pktmbuf_alloc(rxq->mp);
457 : :
458 [ # # ]: 0 : if (unlikely(!buf)) {
459 : 0 : rxq->stats.rx_nombuf++;
460 : : /* No new buf has been allocated: do nothing */
461 [ # # ]: 0 : if (!new_tail || !seg)
462 : 0 : goto end;
463 : :
464 : 0 : seg->next = NULL;
465 : : tap_rxq_pool_free(mbuf);
466 : :
467 : 0 : goto end;
468 : : }
469 [ # # ]: 0 : seg = seg ? seg->next : mbuf;
470 [ # # ]: 0 : if (rxq->pool == mbuf)
471 : 0 : rxq->pool = buf;
472 [ # # ]: 0 : if (new_tail)
473 : 0 : new_tail->next = buf;
474 : : new_tail = buf;
475 : 0 : new_tail->next = seg->next;
476 : :
477 : : /* iovecs[0] is reserved for packet info (pi) */
478 : 0 : (*rxq->iovecs)[mbuf->nb_segs].iov_len =
479 : 0 : buf->buf_len - data_off;
480 : 0 : (*rxq->iovecs)[mbuf->nb_segs].iov_base =
481 : 0 : (char *)buf->buf_addr + data_off;
482 : :
483 : 0 : seg->data_len = RTE_MIN(seg->buf_len - data_off, len);
484 : 0 : seg->data_off = data_off;
485 : :
486 : 0 : len -= seg->data_len;
487 [ # # ]: 0 : if (len <= 0)
488 : : break;
489 : 0 : mbuf->nb_segs++;
490 : : /* First segment has headroom, not the others */
491 : : data_off = 0;
492 : : }
493 : 0 : seg->next = NULL;
494 : 0 : mbuf->packet_type = rte_net_get_ptype(mbuf, NULL,
495 : : RTE_PTYPE_ALL_MASK);
496 [ # # ]: 0 : if (rxq->rxmode->offloads & RTE_ETH_RX_OFFLOAD_CHECKSUM)
497 : 0 : tap_verify_csum(mbuf);
498 : :
499 : : /* account for the receive frame */
500 : 0 : bufs[num_rx++] = mbuf;
501 : 0 : num_rx_bytes += mbuf->pkt_len;
502 : : }
503 : 0 : end:
504 : 0 : rxq->stats.ipackets += num_rx;
505 : 0 : rxq->stats.ibytes += num_rx_bytes;
506 : :
507 [ # # ]: 0 : if (trigger && num_rx < nb_pkts)
508 : 0 : rxq->trigger_seen = trigger;
509 : :
510 : : return num_rx;
511 : : }
512 : :
513 : : static inline int
514 : 0 : tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
515 : : struct rte_mbuf **pmbufs,
516 : : uint16_t *num_packets, unsigned long *num_tx_bytes)
517 : : {
518 : : struct pmd_process_private *process_private;
519 : : int i;
520 : :
521 : 0 : process_private = rte_eth_devices[txq->out_port].process_private;
522 : :
523 [ # # ]: 0 : for (i = 0; i < num_mbufs; i++) {
524 : 0 : struct rte_mbuf *mbuf = pmbufs[i];
525 : 0 : struct iovec iovecs[mbuf->nb_segs + 2];
526 : 0 : struct tun_pi pi = { .flags = 0, .proto = 0x00 };
527 : : struct rte_mbuf *seg = mbuf;
528 : : uint64_t l4_ol_flags;
529 : : int proto;
530 : : int n;
531 : : int j;
532 : : int k; /* current index in iovecs for copying segments */
533 : :
534 [ # # ]: 0 : if (txq->type == ETH_TUNTAP_TYPE_TUN) {
535 : : /*
536 : : * TUN and TAP are created with IFF_NO_PI disabled.
537 : : * For TUN PMD this mandatory as fields are used by
538 : : * Kernel tun.c to determine whether its IP or non IP
539 : : * packets.
540 : : *
541 : : * The logic fetches the first byte of data from mbuf
542 : : * then compares whether its v4 or v6. If first byte
543 : : * is 4 or 6, then protocol field is updated.
544 : : */
545 : 0 : char *buff_data = rte_pktmbuf_mtod(seg, void *);
546 : 0 : proto = (*buff_data & 0xf0);
547 [ # # # # ]: 0 : pi.proto = (proto == 0x40) ?
548 : : rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) :
549 : : ((proto == 0x60) ?
550 : : rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) :
551 : : 0x00);
552 : : }
553 : :
554 : : k = 0;
555 : 0 : iovecs[k].iov_base = π
556 : 0 : iovecs[k].iov_len = sizeof(pi);
557 : : k++;
558 : :
559 : 0 : l4_ol_flags = mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK;
560 [ # # # # ]: 0 : if (txq->csum && (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM ||
561 : 0 : l4_ol_flags == RTE_MBUF_F_TX_UDP_CKSUM ||
562 [ # # ]: 0 : l4_ol_flags == RTE_MBUF_F_TX_TCP_CKSUM)) {
563 : 0 : unsigned int hdrlens = mbuf->l2_len + mbuf->l3_len;
564 : : uint16_t *l4_cksum;
565 : : void *l3_hdr;
566 : :
567 [ # # ]: 0 : if (l4_ol_flags == RTE_MBUF_F_TX_UDP_CKSUM)
568 : 0 : hdrlens += sizeof(struct rte_udp_hdr);
569 [ # # ]: 0 : else if (l4_ol_flags == RTE_MBUF_F_TX_TCP_CKSUM)
570 : 0 : hdrlens += sizeof(struct rte_tcp_hdr);
571 [ # # ]: 0 : else if (l4_ol_flags != RTE_MBUF_F_TX_L4_NO_CKSUM)
572 : 0 : return -1;
573 : :
574 : : /* Support only packets with at least layer 4
575 : : * header included in the first segment
576 : : */
577 [ # # ]: 0 : if (rte_pktmbuf_data_len(mbuf) < hdrlens)
578 : 0 : return -1;
579 : :
580 : : /* To change checksums (considering that a mbuf can be
581 : : * indirect, for example), copy l2, l3 and l4 headers
582 : : * in a new segment and chain it to existing data
583 : : */
584 : 0 : seg = rte_pktmbuf_copy(mbuf, mbuf->pool, 0, hdrlens);
585 [ # # ]: 0 : if (seg == NULL)
586 : 0 : return -1;
587 [ # # ]: 0 : rte_pktmbuf_adj(mbuf, hdrlens);
588 : : rte_pktmbuf_chain(seg, mbuf);
589 : 0 : pmbufs[i] = mbuf = seg;
590 : :
591 : 0 : l3_hdr = rte_pktmbuf_mtod_offset(mbuf, void *, mbuf->l2_len);
592 [ # # ]: 0 : if (mbuf->ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
593 : : struct rte_ipv4_hdr *iph = l3_hdr;
594 : :
595 : 0 : iph->hdr_checksum = 0;
596 : 0 : iph->hdr_checksum = rte_ipv4_cksum(iph);
597 : : }
598 : :
599 [ # # ]: 0 : if (l4_ol_flags == RTE_MBUF_F_TX_L4_NO_CKSUM)
600 : 0 : goto skip_l4_cksum;
601 : :
602 [ # # ]: 0 : if (l4_ol_flags == RTE_MBUF_F_TX_UDP_CKSUM) {
603 : : struct rte_udp_hdr *udp_hdr;
604 : :
605 : 0 : udp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_udp_hdr *,
606 : : mbuf->l2_len + mbuf->l3_len);
607 : 0 : l4_cksum = &udp_hdr->dgram_cksum;
608 : : } else {
609 : : struct rte_tcp_hdr *tcp_hdr;
610 : :
611 : 0 : tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *,
612 : : mbuf->l2_len + mbuf->l3_len);
613 : 0 : l4_cksum = &tcp_hdr->cksum;
614 : : }
615 : :
616 : 0 : *l4_cksum = 0;
617 [ # # ]: 0 : if (mbuf->ol_flags & RTE_MBUF_F_TX_IPV4) {
618 : 0 : *l4_cksum = rte_ipv4_udptcp_cksum_mbuf(mbuf, l3_hdr,
619 : 0 : mbuf->l2_len + mbuf->l3_len);
620 : : } else {
621 : 0 : *l4_cksum = rte_ipv6_udptcp_cksum_mbuf(mbuf, l3_hdr,
622 : 0 : mbuf->l2_len + mbuf->l3_len);
623 : : }
624 : : }
625 : :
626 : 0 : skip_l4_cksum:
627 [ # # ]: 0 : for (j = 0; j < mbuf->nb_segs; j++) {
628 : 0 : iovecs[k].iov_len = rte_pktmbuf_data_len(seg);
629 : 0 : iovecs[k].iov_base = rte_pktmbuf_mtod(seg, void *);
630 : 0 : k++;
631 : 0 : seg = seg->next;
632 : : }
633 : :
634 : : /* copy the tx frame data */
635 : 0 : n = writev(process_private->fds[txq->queue_id], iovecs, k);
636 [ # # ]: 0 : if (n <= 0)
637 : 0 : return -1;
638 : :
639 : 0 : (*num_packets)++;
640 : 0 : (*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
641 : : }
642 : : return 0;
643 : : }
644 : :
645 : : /* Callback to handle sending packets from the tap interface
646 : : */
647 : : static uint16_t
648 : 0 : pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
649 : : {
650 : : struct tx_queue *txq = queue;
651 : : uint16_t num_tx = 0;
652 : 0 : uint16_t num_packets = 0;
653 : 0 : unsigned long num_tx_bytes = 0;
654 : : uint32_t max_size;
655 : : int i;
656 : :
657 [ # # ]: 0 : if (unlikely(nb_pkts == 0))
658 : : return 0;
659 : :
660 : : struct rte_mbuf *gso_mbufs[MAX_GSO_MBUFS];
661 : 0 : max_size = *txq->mtu + (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + 4);
662 [ # # ]: 0 : for (i = 0; i < nb_pkts; i++) {
663 : 0 : struct rte_mbuf *mbuf_in = bufs[num_tx];
664 : : struct rte_mbuf **mbuf;
665 : : uint16_t num_mbufs = 0;
666 : : uint16_t tso_segsz = 0;
667 : : int ret;
668 : : int num_tso_mbufs;
669 : : uint16_t hdrs_len;
670 : : uint64_t tso;
671 : :
672 : 0 : tso = mbuf_in->ol_flags & RTE_MBUF_F_TX_TCP_SEG;
673 [ # # ]: 0 : if (tso) {
674 : 0 : struct rte_gso_ctx *gso_ctx = &txq->gso_ctx;
675 : :
676 : : /* TCP segmentation implies TCP checksum offload */
677 : 0 : mbuf_in->ol_flags |= RTE_MBUF_F_TX_TCP_CKSUM;
678 : :
679 : : /* gso size is calculated without RTE_ETHER_CRC_LEN */
680 : 0 : hdrs_len = mbuf_in->l2_len + mbuf_in->l3_len +
681 : 0 : mbuf_in->l4_len;
682 : 0 : tso_segsz = mbuf_in->tso_segsz + hdrs_len;
683 [ # # ]: 0 : if (unlikely(tso_segsz == hdrs_len) ||
684 [ # # ]: 0 : tso_segsz > *txq->mtu) {
685 : 0 : txq->stats.errs++;
686 : 0 : break;
687 : : }
688 : 0 : gso_ctx->gso_size = tso_segsz;
689 : : /* 'mbuf_in' packet to segment */
690 : 0 : num_tso_mbufs = rte_gso_segment(mbuf_in,
691 : : gso_ctx, /* gso control block */
692 : : (struct rte_mbuf **)&gso_mbufs, /* out mbufs */
693 : : RTE_DIM(gso_mbufs)); /* max tso mbufs */
694 : :
695 : : /* ret contains the number of new created mbufs */
696 [ # # ]: 0 : if (num_tso_mbufs < 0)
697 : : break;
698 : :
699 [ # # ]: 0 : if (num_tso_mbufs >= 1) {
700 : : mbuf = gso_mbufs;
701 : 0 : num_mbufs = num_tso_mbufs;
702 : : } else {
703 : : /* 0 means it can be transmitted directly
704 : : * without gso.
705 : : */
706 : : mbuf = &mbuf_in;
707 : : num_mbufs = 1;
708 : : }
709 : : } else {
710 : : /* stats.errs will be incremented */
711 [ # # ]: 0 : if (rte_pktmbuf_pkt_len(mbuf_in) > max_size)
712 : : break;
713 : :
714 : : /* ret 0 indicates no new mbufs were created */
715 : : num_tso_mbufs = 0;
716 : : mbuf = &mbuf_in;
717 : : num_mbufs = 1;
718 : : }
719 : :
720 : 0 : ret = tap_write_mbufs(txq, num_mbufs, mbuf,
721 : : &num_packets, &num_tx_bytes);
722 [ # # ]: 0 : if (ret == -1) {
723 : 0 : txq->stats.errs++;
724 : : /* free tso mbufs */
725 [ # # ]: 0 : if (num_tso_mbufs > 0)
726 : 0 : rte_pktmbuf_free_bulk(mbuf, num_tso_mbufs);
727 : : break;
728 : : }
729 : 0 : num_tx++;
730 [ # # ]: 0 : if (num_tso_mbufs == 0) {
731 : : /* tap_write_mbufs may prepend a segment to mbuf_in */
732 : 0 : rte_pktmbuf_free(mbuf[0]);
733 : : } else {
734 : : /* free original mbuf */
735 : 0 : rte_pktmbuf_free(mbuf_in);
736 : : /* free tso mbufs */
737 : 0 : rte_pktmbuf_free_bulk(mbuf, num_tso_mbufs);
738 : : }
739 : : }
740 : :
741 : 0 : txq->stats.opackets += num_packets;
742 : 0 : txq->stats.errs += nb_pkts - num_tx;
743 : 0 : txq->stats.obytes += num_tx_bytes;
744 : :
745 : 0 : return num_tx;
746 : : }
747 : :
748 : : static int
749 : 0 : tap_link_set_down(struct rte_eth_dev *dev)
750 : : {
751 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
752 : :
753 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
754 : 0 : return tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_UP, 0);
755 : : }
756 : :
757 : : static int
758 : 0 : tap_link_set_up(struct rte_eth_dev *dev)
759 : : {
760 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
761 : : int ret;
762 : :
763 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
764 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_UP, 1);
765 [ # # ]: 0 : if (ret < 0)
766 : : return ret;
767 [ # # ]: 0 : if (pmd->remote_if_index)
768 : 0 : return tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index, IFF_UP, 1);
769 : : return 0;
770 : : }
771 : :
772 : : static int
773 : 0 : tap_mp_req_on_rxtx(struct rte_eth_dev *dev)
774 : : {
775 : : struct rte_mp_msg msg;
776 : : struct ipc_queues *request_param = (struct ipc_queues *)msg.param;
777 : : int err;
778 : 0 : struct pmd_process_private *process_private = dev->process_private;
779 : : int i;
780 : :
781 : : memset(&msg, 0, sizeof(msg));
782 : : strlcpy(msg.name, TAP_MP_REQ_START_RXTX, sizeof(msg.name));
783 : 0 : strlcpy(request_param->port_name, dev->data->name, sizeof(request_param->port_name));
784 : 0 : msg.len_param = sizeof(*request_param);
785 : :
786 : : /* rx and tx share file descriptors and nb_tx_queues == nb_rx_queues */
787 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
788 : 0 : msg.fds[i] = process_private->fds[i];
789 : :
790 : 0 : request_param->q_count = dev->data->nb_rx_queues;
791 : 0 : msg.num_fds = dev->data->nb_rx_queues;
792 : :
793 : 0 : err = rte_mp_sendmsg(&msg);
794 [ # # ]: 0 : if (err < 0) {
795 : 0 : TAP_LOG(ERR, "Failed to send start req to secondary %d",
796 : : rte_errno);
797 : 0 : return -1;
798 : : }
799 : :
800 : : return 0;
801 : : }
802 : :
803 : : static int
804 : 0 : tap_dev_start(struct rte_eth_dev *dev)
805 : : {
806 : : int err, i;
807 : :
808 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
809 : 0 : tap_mp_req_on_rxtx(dev);
810 : :
811 : 0 : err = tap_intr_handle_set(dev, 1);
812 [ # # ]: 0 : if (err)
813 : : return err;
814 : :
815 : 0 : err = tap_link_set_up(dev);
816 [ # # ]: 0 : if (err) {
817 : 0 : tap_intr_handle_set(dev, 0);
818 : 0 : return err;
819 : : }
820 : :
821 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
822 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
823 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
824 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
825 : :
826 : : return err;
827 : : }
828 : :
829 : : static int
830 : 0 : tap_mp_req_start_rxtx(const struct rte_mp_msg *request, __rte_unused const void *peer)
831 : : {
832 : : struct rte_eth_dev *dev;
833 : : const struct ipc_queues *request_param =
834 : : (const struct ipc_queues *)request->param;
835 : : struct pmd_process_private *process_private;
836 : :
837 : 0 : dev = rte_eth_dev_get_by_name(request_param->port_name);
838 [ # # ]: 0 : if (!dev) {
839 : 0 : TAP_LOG(ERR, "Failed to get dev for %s",
840 : : request_param->port_name);
841 : 0 : return -1;
842 : : }
843 : :
844 : 0 : process_private = dev->process_private;
845 : 0 : TAP_LOG(DEBUG, "tap_attach q:%d", request_param->q_count);
846 : :
847 [ # # ]: 0 : for (int q = 0; q < request_param->q_count; q++)
848 : 0 : process_private->fds[q] = request->fds[q];
849 : :
850 : :
851 : : return 0;
852 : : }
853 : :
854 : : /* This function gets called when the current port gets stopped.
855 : : */
856 : : static int
857 : 0 : tap_dev_stop(struct rte_eth_dev *dev)
858 : : {
859 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
860 : : int i;
861 : :
862 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
863 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
864 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
865 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
866 : :
867 : 0 : tap_intr_handle_set(dev, 0);
868 [ # # ]: 0 : if (!pmd->persist)
869 : 0 : tap_link_set_down(dev);
870 : :
871 : 0 : return 0;
872 : : }
873 : :
874 : : static int
875 : 0 : tap_dev_configure(struct rte_eth_dev *dev)
876 : : {
877 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
878 : :
879 [ # # ]: 0 : if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
880 : 0 : TAP_LOG(ERR,
881 : : "%s: number of rx queues %d must be equal to number of tx queues %d",
882 : : dev->device->name,
883 : : dev->data->nb_rx_queues,
884 : : dev->data->nb_tx_queues);
885 : 0 : return -1;
886 : : }
887 : :
888 : 0 : TAP_LOG(INFO, "%s: %s: TX configured queues number: %u",
889 : : dev->device->name, pmd->name, dev->data->nb_tx_queues);
890 : :
891 : 0 : TAP_LOG(INFO, "%s: %s: RX configured queues number: %u",
892 : : dev->device->name, pmd->name, dev->data->nb_rx_queues);
893 : :
894 : 0 : return 0;
895 : : }
896 : :
897 : : static uint32_t
898 : 0 : tap_dev_speed_capa(void)
899 : : {
900 : 0 : uint32_t speed = pmd_link.link_speed;
901 : : uint32_t capa = 0;
902 : :
903 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_10M)
904 : : capa |= RTE_ETH_LINK_SPEED_10M;
905 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_100M)
906 : 0 : capa |= RTE_ETH_LINK_SPEED_100M;
907 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_1G)
908 : 0 : capa |= RTE_ETH_LINK_SPEED_1G;
909 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_5G)
910 : 0 : capa |= RTE_ETH_LINK_SPEED_2_5G;
911 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_5G)
912 : 0 : capa |= RTE_ETH_LINK_SPEED_5G;
913 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_10G)
914 : 0 : capa |= RTE_ETH_LINK_SPEED_10G;
915 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_20G)
916 : 0 : capa |= RTE_ETH_LINK_SPEED_20G;
917 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_25G)
918 : 0 : capa |= RTE_ETH_LINK_SPEED_25G;
919 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_40G)
920 : 0 : capa |= RTE_ETH_LINK_SPEED_40G;
921 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_50G)
922 : 0 : capa |= RTE_ETH_LINK_SPEED_50G;
923 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_56G)
924 : 0 : capa |= RTE_ETH_LINK_SPEED_56G;
925 [ # # ]: 0 : if (speed >= RTE_ETH_SPEED_NUM_100G)
926 : 0 : capa |= RTE_ETH_LINK_SPEED_100G;
927 : :
928 : 0 : return capa;
929 : : }
930 : :
931 : : static int
932 : 0 : tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
933 : : {
934 : 0 : struct pmd_internals *internals = dev->data->dev_private;
935 : :
936 : 0 : dev_info->if_index = internals->if_index;
937 : 0 : dev_info->max_mac_addrs = 1;
938 : 0 : dev_info->max_rx_pktlen = RTE_ETHER_MAX_JUMBO_FRAME_LEN;
939 : 0 : dev_info->max_rx_queues = RTE_PMD_TAP_MAX_QUEUES;
940 : 0 : dev_info->max_tx_queues = RTE_PMD_TAP_MAX_QUEUES;
941 : 0 : dev_info->min_rx_bufsize = 0;
942 : 0 : dev_info->speed_capa = tap_dev_speed_capa();
943 : 0 : dev_info->rx_queue_offload_capa = TAP_RX_OFFLOAD;
944 : 0 : dev_info->rx_offload_capa = dev_info->rx_queue_offload_capa;
945 : 0 : dev_info->tx_queue_offload_capa = TAP_TX_OFFLOAD;
946 : 0 : dev_info->tx_offload_capa = dev_info->tx_queue_offload_capa;
947 : 0 : dev_info->hash_key_size = TAP_RSS_HASH_KEY_SIZE;
948 : : /*
949 : : * limitation: TAP supports all of IP, UDP and TCP hash
950 : : * functions together and not in partial combinations
951 : : */
952 : 0 : dev_info->flow_type_rss_offloads = ~TAP_RSS_HF_MASK;
953 : 0 : dev_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
954 : :
955 : 0 : return 0;
956 : : }
957 : :
958 : : static int
959 : 0 : tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats,
960 : : struct eth_queue_stats *qstats)
961 : : {
962 : : unsigned int i, imax;
963 : : unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
964 : : unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
965 : : unsigned long rx_nombuf = 0, ierrors = 0;
966 : 0 : const struct pmd_internals *pmd = dev->data->dev_private;
967 : :
968 : : /* rx queue statistics */
969 : 0 : imax = (dev->data->nb_rx_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
970 : 0 : dev->data->nb_rx_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
971 [ # # ]: 0 : for (i = 0; i < imax; i++) {
972 [ # # ]: 0 : if (qstats != NULL) {
973 : 0 : qstats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
974 : 0 : qstats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
975 : : }
976 : 0 : rx_total += pmd->rxq[i].stats.ipackets;
977 : 0 : rx_bytes_total += pmd->rxq[i].stats.ibytes;
978 : 0 : rx_nombuf += pmd->rxq[i].stats.rx_nombuf;
979 : 0 : ierrors += pmd->rxq[i].stats.ierrors;
980 : : }
981 : :
982 : : /* tx queue statistics */
983 : 0 : imax = (dev->data->nb_tx_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
984 : 0 : dev->data->nb_tx_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
985 : :
986 [ # # ]: 0 : for (i = 0; i < imax; i++) {
987 [ # # ]: 0 : if (qstats != NULL) {
988 : 0 : qstats->q_opackets[i] = pmd->txq[i].stats.opackets;
989 : 0 : qstats->q_obytes[i] = pmd->txq[i].stats.obytes;
990 : : }
991 : 0 : tx_total += pmd->txq[i].stats.opackets;
992 : 0 : tx_bytes_total += pmd->txq[i].stats.obytes;
993 : 0 : tx_err_total += pmd->txq[i].stats.errs;
994 : : }
995 : :
996 : 0 : tap_stats->ipackets = rx_total;
997 : 0 : tap_stats->ibytes = rx_bytes_total;
998 : 0 : tap_stats->ierrors = ierrors;
999 : 0 : tap_stats->rx_nombuf = rx_nombuf;
1000 : 0 : tap_stats->opackets = tx_total;
1001 : 0 : tap_stats->oerrors = tx_err_total;
1002 : 0 : tap_stats->obytes = tx_bytes_total;
1003 : 0 : return 0;
1004 : : }
1005 : :
1006 : : static int
1007 : 0 : tap_stats_reset(struct rte_eth_dev *dev)
1008 : : {
1009 : : int i;
1010 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1011 : :
1012 [ # # ]: 0 : for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
1013 : 0 : pmd->rxq[i].stats.ipackets = 0;
1014 : 0 : pmd->rxq[i].stats.ibytes = 0;
1015 : 0 : pmd->rxq[i].stats.ierrors = 0;
1016 : 0 : pmd->rxq[i].stats.rx_nombuf = 0;
1017 : :
1018 : 0 : pmd->txq[i].stats.opackets = 0;
1019 : 0 : pmd->txq[i].stats.errs = 0;
1020 : 0 : pmd->txq[i].stats.obytes = 0;
1021 : : }
1022 : :
1023 : 0 : return 0;
1024 : : }
1025 : :
1026 : : static void
1027 : : tap_queue_close(struct pmd_process_private *process_private, uint16_t qid)
1028 : : {
1029 [ # # ]: 0 : if (process_private->fds[qid] != -1) {
1030 : 0 : close(process_private->fds[qid]);
1031 : 0 : process_private->fds[qid] = -1;
1032 : : }
1033 : : }
1034 : :
1035 : : static int
1036 : 0 : tap_dev_close(struct rte_eth_dev *dev)
1037 : : {
1038 : : int i;
1039 : 0 : struct pmd_internals *internals = dev->data->dev_private;
1040 : 0 : struct pmd_process_private *process_private = dev->process_private;
1041 : :
1042 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
1043 : 0 : free(dev->process_private);
1044 : 0 : dev->process_private = NULL;
1045 [ # # ]: 0 : if (tap_devices_count == 1)
1046 : 0 : rte_mp_action_unregister(TAP_MP_REQ_START_RXTX);
1047 : 0 : tap_devices_count--;
1048 : 0 : return 0;
1049 : : }
1050 : :
1051 [ # # ]: 0 : if (!internals->persist)
1052 : 0 : tap_link_set_down(dev);
1053 : :
1054 : : #ifdef HAVE_TCA_FLOWER
1055 [ # # ]: 0 : if (internals->nlsk_fd != -1) {
1056 : 0 : tap_flow_flush(dev, NULL);
1057 : 0 : tap_flow_implicit_flush(internals, NULL);
1058 : 0 : tap_flow_bpf_destroy(internals);
1059 : : }
1060 : : #endif
1061 : :
1062 [ # # ]: 0 : for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
1063 : : struct rx_queue *rxq = &internals->rxq[i];
1064 : :
1065 : : tap_queue_close(process_private, i);
1066 : :
1067 [ # # ]: 0 : tap_rxq_pool_free(rxq->pool);
1068 : 0 : rte_free(rxq->iovecs);
1069 : 0 : rxq->pool = NULL;
1070 : 0 : rxq->iovecs = NULL;
1071 : : }
1072 : :
1073 [ # # ]: 0 : if (internals->remote_if_index) {
1074 : : /* Restore initial remote state */
1075 : 0 : int ret = tap_nl_set_flags(internals->nlsk_fd, internals->remote_if_index,
1076 : : internals->remote_initial_flags, 1);
1077 [ # # ]: 0 : if (ret)
1078 : 0 : TAP_LOG(ERR, "restore remote state failed: %d", ret);
1079 : : }
1080 : :
1081 : 0 : rte_mempool_free(internals->gso_ctx_mp);
1082 : 0 : internals->gso_ctx_mp = NULL;
1083 : :
1084 [ # # ]: 0 : if (internals->ka_fd != -1) {
1085 : 0 : close(internals->ka_fd);
1086 : 0 : internals->ka_fd = -1;
1087 : : }
1088 : :
1089 : : /* mac_addrs must not be freed alone because part of dev_private */
1090 : 0 : dev->data->mac_addrs = NULL;
1091 : :
1092 : 0 : internals = dev->data->dev_private;
1093 : 0 : TAP_LOG(DEBUG, "Closing %s Ethernet device on numa %u",
1094 : : tuntap_types[internals->type], rte_socket_id());
1095 : :
1096 : 0 : rte_intr_instance_free(internals->intr_handle);
1097 : :
1098 [ # # ]: 0 : if (internals->nlsk_fd != -1) {
1099 : 0 : tap_nl_final(internals->nlsk_fd);
1100 : 0 : internals->nlsk_fd = -1;
1101 : : }
1102 : 0 : free(dev->process_private);
1103 : 0 : dev->process_private = NULL;
1104 : :
1105 [ # # ]: 0 : if (tap_devices_count == 1)
1106 : 0 : rte_mp_action_unregister(TAP_MP_KEY);
1107 : 0 : tap_devices_count--;
1108 : : /*
1109 : : * Since TUN device has no more opened file descriptors
1110 : : * it will be removed from kernel
1111 : : */
1112 : :
1113 : 0 : return 0;
1114 : : }
1115 : :
1116 : : static void
1117 : 0 : tap_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1118 : : {
1119 : 0 : struct rx_queue *rxq = dev->data->rx_queues[qid];
1120 : : struct pmd_process_private *process_private;
1121 : :
1122 [ # # ]: 0 : if (!rxq)
1123 : : return;
1124 : :
1125 : 0 : process_private = rte_eth_devices[rxq->in_port].process_private;
1126 : :
1127 [ # # ]: 0 : tap_rxq_pool_free(rxq->pool);
1128 : 0 : rte_free(rxq->iovecs);
1129 : 0 : rxq->pool = NULL;
1130 : 0 : rxq->iovecs = NULL;
1131 : :
1132 [ # # ]: 0 : if (dev->data->tx_queues[qid] == NULL)
1133 [ # # ]: 0 : tap_queue_close(process_private, qid);
1134 : : }
1135 : :
1136 : : static void
1137 : 0 : tap_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1138 : : {
1139 : 0 : struct tx_queue *txq = dev->data->tx_queues[qid];
1140 : : struct pmd_process_private *process_private;
1141 : :
1142 [ # # ]: 0 : if (!txq)
1143 : : return;
1144 : :
1145 : 0 : process_private = rte_eth_devices[txq->out_port].process_private;
1146 [ # # ]: 0 : if (dev->data->rx_queues[qid] == NULL)
1147 [ # # ]: 0 : tap_queue_close(process_private, qid);
1148 : : }
1149 : :
1150 : : static int
1151 : 0 : tap_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
1152 : : {
1153 : 0 : struct rte_eth_link *dev_link = &dev->data->dev_link;
1154 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1155 : 0 : unsigned int flags = 0;
1156 : :
1157 [ # # ]: 0 : if (pmd->remote_if_index) {
1158 [ # # ]: 0 : if (tap_nl_get_flags(pmd->nlsk_fd, pmd->remote_if_index, &flags) == 0) {
1159 [ # # ]: 0 : if (!(flags & IFF_UP) || !(flags & IFF_RUNNING)) {
1160 : 0 : dev_link->link_status = RTE_ETH_LINK_DOWN;
1161 : 0 : return 0;
1162 : : }
1163 : : }
1164 : : }
1165 [ # # ]: 0 : if (tap_nl_get_flags(pmd->nlsk_fd, pmd->if_index, &flags) == 0) {
1166 [ # # ]: 0 : if ((flags & IFF_UP) && (flags & IFF_RUNNING))
1167 : 0 : dev_link->link_status = RTE_ETH_LINK_UP;
1168 : : else
1169 : 0 : dev_link->link_status = RTE_ETH_LINK_DOWN;
1170 : : }
1171 : : return 0;
1172 : : }
1173 : :
1174 : : static int
1175 : 0 : tap_promisc_enable(struct rte_eth_dev *dev)
1176 : : {
1177 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1178 : : int ret;
1179 : :
1180 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_PROMISC, 1);
1181 [ # # ]: 0 : if (ret != 0)
1182 : : return ret;
1183 : :
1184 [ # # ]: 0 : if (pmd->remote_if_index) {
1185 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index, IFF_PROMISC, 1);
1186 [ # # ]: 0 : if (ret != 0)
1187 : : return ret;
1188 : : }
1189 : :
1190 : : #ifdef HAVE_TCA_FLOWER
1191 [ # # # # ]: 0 : if (pmd->remote_if_index && !pmd->flow_isolate) {
1192 : 0 : dev->data->promiscuous = 1;
1193 : 0 : ret = tap_flow_implicit_create(pmd, TAP_REMOTE_PROMISC);
1194 [ # # ]: 0 : if (ret != 0) {
1195 : : /* Rollback promisc flag */
1196 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_PROMISC, 0);
1197 [ # # ]: 0 : if (pmd->remote_if_index)
1198 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index,
1199 : : IFF_PROMISC, 0);
1200 : : /*
1201 : : * rte_eth_dev_promiscuous_enable() rollback
1202 : : * dev->data->promiscuous in the case of failure.
1203 : : */
1204 : 0 : return ret;
1205 : : }
1206 : : }
1207 : : #endif
1208 : : return 0;
1209 : : }
1210 : :
1211 : : static int
1212 : 0 : tap_promisc_disable(struct rte_eth_dev *dev)
1213 : : {
1214 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1215 : : int ret;
1216 : :
1217 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_PROMISC, 0);
1218 [ # # ]: 0 : if (ret != 0)
1219 : : return ret;
1220 : :
1221 [ # # ]: 0 : if (pmd->remote_if_index) {
1222 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index, IFF_PROMISC, 0);
1223 [ # # ]: 0 : if (ret != 0)
1224 : : return ret;
1225 : : }
1226 : :
1227 : : #ifdef HAVE_TCA_FLOWER
1228 [ # # # # ]: 0 : if (pmd->remote_if_index && !pmd->flow_isolate) {
1229 : 0 : dev->data->promiscuous = 0;
1230 : 0 : ret = tap_flow_implicit_destroy(pmd, TAP_REMOTE_PROMISC);
1231 [ # # ]: 0 : if (ret != 0) {
1232 : : /* Rollback promisc flag */
1233 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_PROMISC, 1);
1234 [ # # ]: 0 : if (pmd->remote_if_index)
1235 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index,
1236 : : IFF_PROMISC, 1);
1237 : : /*
1238 : : * rte_eth_dev_promiscuous_disable() rollback
1239 : : * dev->data->promiscuous in the case of failure.
1240 : : */
1241 : 0 : return ret;
1242 : : }
1243 : : }
1244 : : #endif
1245 : :
1246 : : return 0;
1247 : : }
1248 : :
1249 : : static int
1250 : 0 : tap_allmulti_enable(struct rte_eth_dev *dev)
1251 : : {
1252 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1253 : : int ret;
1254 : :
1255 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_ALLMULTI, 1);
1256 [ # # ]: 0 : if (ret != 0)
1257 : : return ret;
1258 : :
1259 [ # # ]: 0 : if (pmd->remote_if_index) {
1260 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index, IFF_ALLMULTI, 1);
1261 [ # # ]: 0 : if (ret != 0)
1262 : : return ret;
1263 : : }
1264 : :
1265 : : #ifdef HAVE_TCA_FLOWER
1266 [ # # # # ]: 0 : if (pmd->remote_if_index && !pmd->flow_isolate) {
1267 : 0 : dev->data->all_multicast = 1;
1268 : 0 : ret = tap_flow_implicit_create(pmd, TAP_REMOTE_ALLMULTI);
1269 [ # # ]: 0 : if (ret != 0) {
1270 : : /* Rollback allmulti flag */
1271 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_ALLMULTI, 0);
1272 [ # # ]: 0 : if (pmd->remote_if_index)
1273 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index,
1274 : : IFF_ALLMULTI, 0);
1275 : : /*
1276 : : * rte_eth_dev_allmulticast_enable() rollback
1277 : : * dev->data->all_multicast in the case of failure.
1278 : : */
1279 : 0 : return ret;
1280 : : }
1281 : : }
1282 : : #endif
1283 : :
1284 : : return 0;
1285 : : }
1286 : :
1287 : : static int
1288 : 0 : tap_allmulti_disable(struct rte_eth_dev *dev)
1289 : : {
1290 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1291 : : int ret;
1292 : :
1293 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_ALLMULTI, 0);
1294 [ # # ]: 0 : if (ret != 0)
1295 : : return ret;
1296 : :
1297 [ # # ]: 0 : if (pmd->remote_if_index) {
1298 : 0 : ret = tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index, IFF_ALLMULTI, 0);
1299 [ # # ]: 0 : if (ret != 0)
1300 : : return ret;
1301 : : }
1302 : :
1303 : : #ifdef HAVE_TCA_FLOWER
1304 [ # # # # ]: 0 : if (pmd->remote_if_index && !pmd->flow_isolate) {
1305 : 0 : dev->data->all_multicast = 0;
1306 : 0 : ret = tap_flow_implicit_destroy(pmd, TAP_REMOTE_ALLMULTI);
1307 [ # # ]: 0 : if (ret != 0) {
1308 : : /* Rollback allmulti flag */
1309 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->if_index, IFF_ALLMULTI, 1);
1310 [ # # ]: 0 : if (pmd->remote_if_index)
1311 : 0 : tap_nl_set_flags(pmd->nlsk_fd, pmd->remote_if_index,
1312 : : IFF_ALLMULTI, 1);
1313 : : /*
1314 : : * rte_eth_dev_allmulticast_disable() rollback
1315 : : * dev->data->all_multicast in the case of failure.
1316 : : */
1317 : 0 : return ret;
1318 : : }
1319 : : }
1320 : : #endif
1321 : :
1322 : : return 0;
1323 : : }
1324 : :
1325 : : static int
1326 : 0 : tap_mac_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
1327 : : {
1328 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1329 : : struct rte_ether_addr current_mac;
1330 : : bool set_remote = false;
1331 : : int ret;
1332 : :
1333 [ # # ]: 0 : if (pmd->type == ETH_TUNTAP_TYPE_TUN) {
1334 : 0 : TAP_LOG(ERR, "%s: can't MAC address for TUN",
1335 : : dev->device->name);
1336 : 0 : return -ENOTSUP;
1337 : : }
1338 : :
1339 [ # # ]: 0 : if (rte_is_zero_ether_addr(mac_addr)) {
1340 : 0 : TAP_LOG(ERR, "%s: can't set an empty MAC address",
1341 : : dev->device->name);
1342 : 0 : return -EINVAL;
1343 : : }
1344 : : /* Check the actual current MAC address on the tap netdevice */
1345 : 0 : ret = tap_nl_get_mac(pmd->nlsk_fd, pmd->if_index, ¤t_mac);
1346 [ # # ]: 0 : if (ret < 0)
1347 : : return ret;
1348 [ # # ]: 0 : if (rte_is_same_ether_addr(¤t_mac, mac_addr))
1349 : : return 0;
1350 : :
1351 : : /* Check the current MAC address on the remote */
1352 [ # # ]: 0 : if (pmd->remote_if_index) {
1353 : 0 : ret = tap_nl_get_mac(pmd->nlsk_fd, pmd->remote_if_index, ¤t_mac);
1354 [ # # ]: 0 : if (ret < 0)
1355 : : return ret;
1356 [ # # ]: 0 : if (!rte_is_same_ether_addr(¤t_mac, mac_addr))
1357 : : set_remote = true;
1358 : : }
1359 : :
1360 : 0 : ret = tap_nl_set_mac(pmd->nlsk_fd, pmd->if_index, mac_addr);
1361 [ # # ]: 0 : if (ret < 0)
1362 : : return ret;
1363 : :
1364 [ # # ]: 0 : if (set_remote) {
1365 : 0 : ret = tap_nl_set_mac(pmd->nlsk_fd, pmd->remote_if_index, mac_addr);
1366 [ # # ]: 0 : if (ret < 0)
1367 : : return ret;
1368 : : }
1369 : :
1370 : : rte_ether_addr_copy(mac_addr, &pmd->eth_addr);
1371 : :
1372 : : #ifdef HAVE_TCA_FLOWER
1373 [ # # # # ]: 0 : if (pmd->remote_if_index && !pmd->flow_isolate) {
1374 : : /* Replace MAC redirection rule after a MAC change */
1375 : 0 : ret = tap_flow_implicit_destroy(pmd, TAP_REMOTE_LOCAL_MAC);
1376 [ # # ]: 0 : if (ret < 0) {
1377 : 0 : TAP_LOG(ERR,
1378 : : "%s: Couldn't delete MAC redirection rule",
1379 : : dev->device->name);
1380 : 0 : return ret;
1381 : : }
1382 : 0 : ret = tap_flow_implicit_create(pmd, TAP_REMOTE_LOCAL_MAC);
1383 [ # # ]: 0 : if (ret < 0) {
1384 : 0 : TAP_LOG(ERR,
1385 : : "%s: Couldn't add MAC redirection rule",
1386 : : dev->device->name);
1387 : 0 : return ret;
1388 : : }
1389 : : }
1390 : : #endif
1391 : :
1392 : : return 0;
1393 : : }
1394 : :
1395 : 0 : static int tap_carrier_set(struct pmd_internals *pmd, int carrier)
1396 : : {
1397 : : #ifdef TUNSETCARRIER
1398 : 0 : int ret = ioctl(pmd->ka_fd, TUNSETCARRIER, &carrier);
1399 [ # # ]: 0 : if (ret < 0) {
1400 : 0 : TAP_LOG(ERR, "%s: ioctl(TUNSETCARRIER) failed: %s",
1401 : : pmd->name, strerror(errno));
1402 : 0 : return ret;
1403 : : }
1404 : : #else
1405 : : (void)pmd;
1406 : : (void)carrier;
1407 : : #endif
1408 : : return 0;
1409 : : }
1410 : :
1411 : : static int
1412 : 0 : tap_gso_ctx_setup(struct rte_gso_ctx *gso_ctx, struct rte_eth_dev *dev)
1413 : : {
1414 : : uint32_t gso_types;
1415 : : char pool_name[64];
1416 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1417 : : int ret;
1418 : :
1419 : : /* initialize GSO context */
1420 : : gso_types = RTE_ETH_TX_OFFLOAD_TCP_TSO;
1421 [ # # ]: 0 : if (!pmd->gso_ctx_mp) {
1422 : : /*
1423 : : * Create private mbuf pool with TAP_GSO_MBUF_SEG_SIZE
1424 : : * bytes size per mbuf use this pool for both direct and
1425 : : * indirect mbufs
1426 : : */
1427 : 0 : ret = snprintf(pool_name, sizeof(pool_name), "mp_%s",
1428 [ # # ]: 0 : dev->device->name);
1429 [ # # ]: 0 : if (ret < 0 || ret >= (int)sizeof(pool_name)) {
1430 : 0 : TAP_LOG(ERR,
1431 : : "%s: failed to create mbuf pool name for device %s,"
1432 : : "device name too long or output error, ret: %d",
1433 : : pmd->name, dev->device->name, ret);
1434 : 0 : return -ENAMETOOLONG;
1435 : : }
1436 : 0 : pmd->gso_ctx_mp = rte_pktmbuf_pool_create(pool_name,
1437 : : TAP_GSO_MBUFS_NUM, TAP_GSO_MBUF_CACHE_SIZE, 0,
1438 : : RTE_PKTMBUF_HEADROOM + TAP_GSO_MBUF_SEG_SIZE,
1439 : : SOCKET_ID_ANY);
1440 [ # # ]: 0 : if (!pmd->gso_ctx_mp) {
1441 : 0 : TAP_LOG(ERR,
1442 : : "%s: failed to create mbuf pool for device %s",
1443 : : pmd->name, dev->device->name);
1444 : 0 : return -1;
1445 : : }
1446 : : }
1447 : :
1448 : 0 : gso_ctx->direct_pool = pmd->gso_ctx_mp;
1449 : 0 : gso_ctx->indirect_pool = pmd->gso_ctx_mp;
1450 : 0 : gso_ctx->gso_types = gso_types;
1451 : 0 : gso_ctx->gso_size = 0; /* gso_size is set in tx_burst() per packet */
1452 : 0 : gso_ctx->flag = 0;
1453 : :
1454 : 0 : return 0;
1455 : : }
1456 : :
1457 : : static int
1458 : 0 : tap_setup_queue(struct rte_eth_dev *dev,
1459 : : struct pmd_internals *internals,
1460 : : uint16_t qid,
1461 : : int is_rx)
1462 : : {
1463 : : int fd, ret;
1464 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1465 : 0 : struct pmd_process_private *process_private = dev->process_private;
1466 : 0 : struct rx_queue *rx = &internals->rxq[qid];
1467 : : struct tx_queue *tx = &internals->txq[qid];
1468 [ # # ]: 0 : struct rte_gso_ctx *gso_ctx = is_rx ? NULL : &tx->gso_ctx;
1469 [ # # ]: 0 : const char *dir = is_rx ? "rx" : "tx";
1470 : :
1471 : 0 : fd = process_private->fds[qid];
1472 [ # # ]: 0 : if (fd != -1) {
1473 : : /* fd for this queue already exists */
1474 : 0 : TAP_LOG(DEBUG, "%s: fd %d for %s queue qid %d exists",
1475 : : pmd->name, fd, dir, qid);
1476 : : gso_ctx = NULL;
1477 : : } else {
1478 : 0 : fd = tun_alloc(pmd, 0, 0);
1479 [ # # ]: 0 : if (fd < 0) {
1480 : 0 : TAP_LOG(ERR, "%s: tun_alloc() failed.", pmd->name);
1481 : 0 : return -1;
1482 : : }
1483 : :
1484 : 0 : TAP_LOG(DEBUG, "%s: add %s queue for qid %d fd %d",
1485 : : pmd->name, dir, qid, fd);
1486 : :
1487 : 0 : process_private->fds[qid] = fd;
1488 : : }
1489 : :
1490 : 0 : tx->mtu = &dev->data->mtu;
1491 : 0 : rx->rxmode = &dev->data->dev_conf.rxmode;
1492 [ # # ]: 0 : if (gso_ctx) {
1493 : 0 : ret = tap_gso_ctx_setup(gso_ctx, dev);
1494 [ # # ]: 0 : if (ret)
1495 : : return -1;
1496 : : }
1497 : :
1498 : 0 : tx->type = pmd->type;
1499 : :
1500 : 0 : return fd;
1501 : : }
1502 : :
1503 : : static int
1504 : 0 : tap_rx_queue_setup(struct rte_eth_dev *dev,
1505 : : uint16_t rx_queue_id,
1506 : : uint16_t nb_rx_desc,
1507 : : unsigned int socket_id,
1508 : : const struct rte_eth_rxconf *rx_conf __rte_unused,
1509 : : struct rte_mempool *mp)
1510 : : {
1511 : 0 : struct pmd_internals *internals = dev->data->dev_private;
1512 : 0 : struct pmd_process_private *process_private = dev->process_private;
1513 : 0 : struct rx_queue *rxq = &internals->rxq[rx_queue_id];
1514 : 0 : struct rte_mbuf **tmp = &rxq->pool;
1515 : 0 : long iov_max = sysconf(_SC_IOV_MAX);
1516 : :
1517 [ # # ]: 0 : if (iov_max <= 0) {
1518 : 0 : TAP_LOG(WARNING,
1519 : : "_SC_IOV_MAX is not defined. Using %d as default",
1520 : : TAP_IOV_DEFAULT_MAX);
1521 : : iov_max = TAP_IOV_DEFAULT_MAX;
1522 : : }
1523 : 0 : uint16_t nb_desc = RTE_MIN(nb_rx_desc, iov_max - 1);
1524 : 0 : struct iovec (*iovecs)[nb_desc + 1];
1525 : : int data_off = RTE_PKTMBUF_HEADROOM;
1526 : : int ret = 0;
1527 : : int fd;
1528 : : int i;
1529 : :
1530 [ # # # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues || !mp) {
1531 : 0 : TAP_LOG(WARNING,
1532 : : "nb_rx_queues %d too small or mempool NULL",
1533 : : dev->data->nb_rx_queues);
1534 : 0 : return -1;
1535 : : }
1536 : :
1537 : 0 : rxq->mp = mp;
1538 : 0 : rxq->trigger_seen = 1; /* force initial burst */
1539 : 0 : rxq->in_port = dev->data->port_id;
1540 : 0 : rxq->queue_id = rx_queue_id;
1541 : 0 : rxq->nb_rx_desc = nb_desc;
1542 : 0 : iovecs = rte_zmalloc_socket(dev->device->name, sizeof(*iovecs), 0,
1543 : : socket_id);
1544 [ # # ]: 0 : if (!iovecs) {
1545 : 0 : TAP_LOG(WARNING,
1546 : : "%s: Couldn't allocate %d RX descriptors",
1547 : : dev->device->name, nb_desc);
1548 : 0 : return -ENOMEM;
1549 : : }
1550 : 0 : rxq->iovecs = iovecs;
1551 : :
1552 : 0 : dev->data->rx_queues[rx_queue_id] = rxq;
1553 : 0 : fd = tap_setup_queue(dev, internals, rx_queue_id, 1);
1554 [ # # ]: 0 : if (fd == -1) {
1555 : : ret = fd;
1556 : 0 : goto error;
1557 : : }
1558 : :
1559 : 0 : (*rxq->iovecs)[0].iov_len = sizeof(struct tun_pi);
1560 : 0 : (*rxq->iovecs)[0].iov_base = &rxq->pi;
1561 : :
1562 [ # # ]: 0 : for (i = 1; i <= nb_desc; i++) {
1563 : 0 : *tmp = rte_pktmbuf_alloc(rxq->mp);
1564 [ # # ]: 0 : if (!*tmp) {
1565 : 0 : TAP_LOG(WARNING,
1566 : : "%s: couldn't allocate memory for queue %d",
1567 : : dev->device->name, rx_queue_id);
1568 : : ret = -ENOMEM;
1569 : 0 : goto error;
1570 : : }
1571 : 0 : (*rxq->iovecs)[i].iov_len = (*tmp)->buf_len - data_off;
1572 : 0 : (*rxq->iovecs)[i].iov_base =
1573 : 0 : (char *)(*tmp)->buf_addr + data_off;
1574 : : data_off = 0;
1575 : 0 : tmp = &(*tmp)->next;
1576 : : }
1577 : :
1578 : : /* set carrier after creating at least one rxq */
1579 : 0 : ret = tap_carrier_set(internals, 1);
1580 [ # # ]: 0 : if (ret < 0)
1581 : 0 : goto error;
1582 : :
1583 : 0 : TAP_LOG(DEBUG, " RX TUNTAP device name %s, qid %d on fd %d",
1584 : : internals->name, rx_queue_id,
1585 : : process_private->fds[rx_queue_id]);
1586 : :
1587 : 0 : return 0;
1588 : :
1589 : 0 : error:
1590 [ # # ]: 0 : tap_rxq_pool_free(rxq->pool);
1591 : 0 : rxq->pool = NULL;
1592 : 0 : rte_free(rxq->iovecs);
1593 : 0 : rxq->iovecs = NULL;
1594 : 0 : return ret;
1595 : : }
1596 : :
1597 : : static int
1598 : 0 : tap_tx_queue_setup(struct rte_eth_dev *dev,
1599 : : uint16_t tx_queue_id,
1600 : : uint16_t nb_tx_desc __rte_unused,
1601 : : unsigned int socket_id __rte_unused,
1602 : : const struct rte_eth_txconf *tx_conf)
1603 : : {
1604 : 0 : struct pmd_internals *internals = dev->data->dev_private;
1605 : 0 : struct pmd_process_private *process_private = dev->process_private;
1606 : : struct tx_queue *txq;
1607 : : int ret;
1608 : : uint64_t offloads;
1609 : :
1610 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
1611 : : return -1;
1612 : 0 : dev->data->tx_queues[tx_queue_id] = &internals->txq[tx_queue_id];
1613 : 0 : txq = dev->data->tx_queues[tx_queue_id];
1614 : 0 : txq->out_port = dev->data->port_id;
1615 : 0 : txq->queue_id = tx_queue_id;
1616 : :
1617 : 0 : offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
1618 : 0 : txq->csum = !!(offloads &
1619 : : (RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
1620 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
1621 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM));
1622 : :
1623 : 0 : ret = tap_setup_queue(dev, internals, tx_queue_id, 0);
1624 [ # # ]: 0 : if (ret == -1)
1625 : : return -1;
1626 [ # # ]: 0 : TAP_LOG(DEBUG,
1627 : : " TX TUNTAP device name %s, qid %d on fd %d csum %s",
1628 : : internals->name, tx_queue_id,
1629 : : process_private->fds[tx_queue_id],
1630 : : txq->csum ? "on" : "off");
1631 : :
1632 : 0 : return 0;
1633 : : }
1634 : :
1635 : : static int
1636 : 0 : tap_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
1637 : : {
1638 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1639 : : int ret;
1640 : :
1641 : 0 : ret = tap_nl_set_mtu(pmd->nlsk_fd, pmd->if_index, mtu);
1642 [ # # ]: 0 : if (ret < 0)
1643 : : return ret;
1644 : :
1645 [ # # ]: 0 : if (pmd->remote_if_index)
1646 : 0 : return tap_nl_set_mtu(pmd->nlsk_fd, pmd->remote_if_index, mtu);
1647 : :
1648 : : return 0;
1649 : : }
1650 : :
1651 : : static int
1652 : 0 : tap_set_mc_addr_list(struct rte_eth_dev *dev __rte_unused,
1653 : : struct rte_ether_addr *mc_addr_set __rte_unused,
1654 : : uint32_t nb_mc_addr __rte_unused)
1655 : : {
1656 : : /*
1657 : : * Nothing to do actually: the tap has no filtering whatsoever, every
1658 : : * packet is received.
1659 : : */
1660 : 0 : return 0;
1661 : : }
1662 : :
1663 : : static void tap_dev_intr_handler(void *cb_arg);
1664 : : static int tap_lsc_intr_handle_set(struct rte_eth_dev *dev, int set);
1665 : :
1666 : : static int
1667 : 0 : tap_netns_change(struct rte_eth_dev *dev)
1668 : : {
1669 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1670 : : #ifdef TUNGETDEVNETNS
1671 : : int netns_fd, orig_netns_fd, new_nlsk_fd;
1672 : :
1673 : 0 : netns_fd = ioctl(pmd->ka_fd, TUNGETDEVNETNS);
1674 [ # # ]: 0 : if (netns_fd < 0) {
1675 : 0 : TAP_LOG(INFO, "%s: interface deleted", pmd->name);
1676 : 0 : return 0;
1677 : : }
1678 : :
1679 : : /* Interface was moved to another namespace */
1680 : 0 : pmd->if_index = 0;
1681 : :
1682 : : /* Save current namespace */
1683 : : orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
1684 [ # # ]: 0 : if (orig_netns_fd < 0) {
1685 : 0 : TAP_LOG(ERR, "%s: failed to open original netns: %s",
1686 : : pmd->name, strerror(errno));
1687 : 0 : close(netns_fd);
1688 : 0 : return -1;
1689 : : }
1690 : :
1691 : : /* Switch to new namespace */
1692 [ # # ]: 0 : if (setns(netns_fd, CLONE_NEWNET) < 0) {
1693 : 0 : TAP_LOG(ERR, "%s: failed to enter new netns: %s",
1694 : : pmd->name, strerror(errno));
1695 : 0 : close(netns_fd);
1696 : 0 : close(orig_netns_fd);
1697 : 0 : return -1;
1698 : : }
1699 : :
1700 : : /*
1701 : : * Update ifindex by querying interface name.
1702 : : * The interface now has a new ifindex in the new namespace.
1703 : : */
1704 : 0 : pmd->if_index = if_nametoindex(pmd->name);
1705 : :
1706 : : /* Recreate netlink socket in new namespace */
1707 : 0 : new_nlsk_fd = tap_nl_init(0);
1708 : :
1709 : : /* Recreate LSC interrupt netlink socket in new namespace */
1710 : 0 : rte_intr_callback_unregister_pending(pmd->intr_handle, tap_dev_intr_handler, dev, NULL);
1711 [ # # ]: 0 : if (tap_lsc_intr_handle_set(dev, 1) < 0)
1712 : 0 : TAP_LOG(WARNING, "%s: failed to recreate LSC interrupt socket",
1713 : : pmd->name);
1714 : :
1715 : : /* Force carrier back after switching netns */
1716 : 0 : tap_carrier_set(pmd, 1);
1717 : :
1718 : : /* Switch back to original namespace */
1719 [ # # ]: 0 : if (setns(orig_netns_fd, CLONE_NEWNET) < 0)
1720 : 0 : TAP_LOG(ERR, "%s: failed to return to original netns: %s",
1721 : : pmd->name, strerror(errno));
1722 : :
1723 : 0 : close(orig_netns_fd);
1724 : 0 : close(netns_fd);
1725 : :
1726 [ # # ]: 0 : if (pmd->if_index == 0) {
1727 : 0 : TAP_LOG(WARNING, "%s: interface moved to another namespace, "
1728 : : "failed to get new ifindex",
1729 : : pmd->name);
1730 [ # # ]: 0 : if (new_nlsk_fd >= 0)
1731 : 0 : close(new_nlsk_fd);
1732 : 0 : return -1;
1733 : : }
1734 : :
1735 [ # # ]: 0 : if (new_nlsk_fd < 0) {
1736 : 0 : TAP_LOG(WARNING, "%s: failed to recreate netlink socket in new namespace",
1737 : : pmd->name);
1738 : 0 : return -1;
1739 : : }
1740 : :
1741 : : /* Close old netlink socket and replace with new one */
1742 [ # # ]: 0 : if (pmd->nlsk_fd >= 0)
1743 : 0 : tap_nl_final(pmd->nlsk_fd);
1744 : 0 : pmd->nlsk_fd = new_nlsk_fd;
1745 : :
1746 : 0 : TAP_LOG(INFO, "%s: interface moved to another namespace, new ifindex: %u",
1747 : : pmd->name, pmd->if_index);
1748 : : #else
1749 : : TAP_LOG(WARNING, "%s: interface deleted or moved to another namespace",
1750 : : pmd->name);
1751 : : #endif
1752 : :
1753 : 0 : return 0;
1754 : : }
1755 : :
1756 : : static int
1757 : 0 : tap_nl_msg_handler(struct nlmsghdr *nh, void *arg)
1758 : : {
1759 : : struct rte_eth_dev *dev = arg;
1760 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1761 : : struct ifinfomsg *info = NLMSG_DATA(nh);
1762 : 0 : int is_local = (info->ifi_index == pmd->if_index);
1763 : 0 : int is_remote = (info->ifi_index == pmd->remote_if_index);
1764 : :
1765 : : /* Ignore messages not for our interfaces */
1766 [ # # ]: 0 : if (!is_local && !is_remote)
1767 : : return 0;
1768 : :
1769 [ # # # # ]: 0 : if (nh->nlmsg_type == RTM_DELLINK && is_local) {
1770 : : /*
1771 : : * RTM_DELLINK may indicate the interface was moved to another
1772 : : * network namespace. Check if the device still exists by
1773 : : * querying its namespace via the keep-alive fd.
1774 : : */
1775 : 0 : int ret = tap_netns_change(dev);
1776 [ # # ]: 0 : if (ret < 0)
1777 : : return ret;
1778 : : }
1779 : 0 : return tap_link_update(dev, 0);
1780 : : }
1781 : :
1782 : : static void
1783 : 0 : tap_dev_intr_handler(void *cb_arg)
1784 : : {
1785 : : struct rte_eth_dev *dev = cb_arg;
1786 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1787 : :
1788 [ # # ]: 0 : if (rte_intr_fd_get(pmd->intr_handle) >= 0)
1789 : 0 : tap_nl_recv(rte_intr_fd_get(pmd->intr_handle),
1790 : : tap_nl_msg_handler, dev);
1791 : 0 : }
1792 : :
1793 : : static int
1794 : 0 : tap_lsc_intr_handle_set(struct rte_eth_dev *dev, int set)
1795 : : {
1796 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1797 : : int ret;
1798 : :
1799 : : /* In any case, disable interrupt if the conf is no longer there. */
1800 [ # # ]: 0 : if (!dev->data->dev_conf.intr_conf.lsc) {
1801 [ # # ]: 0 : if (rte_intr_fd_get(pmd->intr_handle) != -1)
1802 : 0 : goto clean;
1803 : :
1804 : : return 0;
1805 : : }
1806 [ # # ]: 0 : if (set) {
1807 : : /*
1808 : : * Subscribe to RTMGRP_LINK to receive RTM_NEWLINK (link state
1809 : : * changes) events. Also receives RTM_DELLINK events which are
1810 : : * used for namespace change detection when TUNGETDEVNETNS is
1811 : : * available.
1812 : : */
1813 : 0 : rte_intr_fd_set(pmd->intr_handle, tap_nl_init(RTMGRP_LINK));
1814 [ # # ]: 0 : if (unlikely(rte_intr_fd_get(pmd->intr_handle) == -1))
1815 : : return -EBADF;
1816 : 0 : return rte_intr_callback_register(
1817 : 0 : pmd->intr_handle, tap_dev_intr_handler, dev);
1818 : : }
1819 : :
1820 : 0 : clean:
1821 : : do {
1822 : 0 : ret = rte_intr_callback_unregister(pmd->intr_handle,
1823 : : tap_dev_intr_handler, dev);
1824 [ # # ]: 0 : if (ret >= 0) {
1825 : : break;
1826 [ # # ]: 0 : } else if (ret == -EAGAIN) {
1827 : : rte_delay_ms(100);
1828 : : } else {
1829 : 0 : TAP_LOG(ERR, "intr callback unregister failed: %d",
1830 : : ret);
1831 : 0 : break;
1832 : : }
1833 : : } while (true);
1834 : :
1835 [ # # ]: 0 : if (rte_intr_fd_get(pmd->intr_handle) >= 0) {
1836 : 0 : tap_nl_final(rte_intr_fd_get(pmd->intr_handle));
1837 : 0 : rte_intr_fd_set(pmd->intr_handle, -1);
1838 : : }
1839 : :
1840 : : return 0;
1841 : : }
1842 : :
1843 : : static int
1844 : 0 : tap_intr_handle_set(struct rte_eth_dev *dev, int set)
1845 : : {
1846 : : int err;
1847 : :
1848 : 0 : err = tap_lsc_intr_handle_set(dev, set);
1849 [ # # ]: 0 : if (err < 0) {
1850 [ # # ]: 0 : if (!set)
1851 : 0 : tap_rx_intr_vec_set(dev, 0);
1852 : 0 : return err;
1853 : : }
1854 : 0 : err = tap_rx_intr_vec_set(dev, set);
1855 [ # # ]: 0 : if (err && set)
1856 : 0 : tap_lsc_intr_handle_set(dev, 0);
1857 : : return err;
1858 : : }
1859 : :
1860 : : static const uint32_t*
1861 : 0 : tap_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
1862 : : size_t *no_of_elements)
1863 : : {
1864 : : static const uint32_t ptypes[] = {
1865 : : RTE_PTYPE_INNER_L2_ETHER,
1866 : : RTE_PTYPE_INNER_L2_ETHER_VLAN,
1867 : : RTE_PTYPE_INNER_L2_ETHER_QINQ,
1868 : : RTE_PTYPE_INNER_L3_IPV4,
1869 : : RTE_PTYPE_INNER_L3_IPV4_EXT,
1870 : : RTE_PTYPE_INNER_L3_IPV6,
1871 : : RTE_PTYPE_INNER_L3_IPV6_EXT,
1872 : : RTE_PTYPE_INNER_L4_FRAG,
1873 : : RTE_PTYPE_INNER_L4_UDP,
1874 : : RTE_PTYPE_INNER_L4_TCP,
1875 : : RTE_PTYPE_INNER_L4_SCTP,
1876 : : RTE_PTYPE_L2_ETHER,
1877 : : RTE_PTYPE_L2_ETHER_VLAN,
1878 : : RTE_PTYPE_L2_ETHER_QINQ,
1879 : : RTE_PTYPE_L3_IPV4,
1880 : : RTE_PTYPE_L3_IPV4_EXT,
1881 : : RTE_PTYPE_L3_IPV6_EXT,
1882 : : RTE_PTYPE_L3_IPV6,
1883 : : RTE_PTYPE_L4_FRAG,
1884 : : RTE_PTYPE_L4_UDP,
1885 : : RTE_PTYPE_L4_TCP,
1886 : : RTE_PTYPE_L4_SCTP,
1887 : : };
1888 : :
1889 : 0 : *no_of_elements = RTE_DIM(ptypes);
1890 : 0 : return ptypes;
1891 : : }
1892 : :
1893 : : static int
1894 : 0 : tap_flow_ctrl_get(struct rte_eth_dev *dev __rte_unused,
1895 : : struct rte_eth_fc_conf *fc_conf)
1896 : : {
1897 : 0 : fc_conf->mode = RTE_ETH_FC_NONE;
1898 : 0 : return 0;
1899 : : }
1900 : :
1901 : : static int
1902 : 0 : tap_flow_ctrl_set(struct rte_eth_dev *dev __rte_unused,
1903 : : struct rte_eth_fc_conf *fc_conf)
1904 : : {
1905 [ # # ]: 0 : if (fc_conf->mode != RTE_ETH_FC_NONE)
1906 : 0 : return -ENOTSUP;
1907 : : return 0;
1908 : : }
1909 : :
1910 : : /**
1911 : : * DPDK callback to update the RSS hash configuration.
1912 : : *
1913 : : * @param dev
1914 : : * Pointer to Ethernet device structure.
1915 : : * @param[in] rss_conf
1916 : : * RSS configuration data.
1917 : : *
1918 : : * @return
1919 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
1920 : : */
1921 : : static int
1922 : 0 : tap_rss_hash_update(struct rte_eth_dev *dev,
1923 : : struct rte_eth_rss_conf *rss_conf)
1924 : : {
1925 [ # # ]: 0 : if (rss_conf->rss_hf & TAP_RSS_HF_MASK) {
1926 : 0 : rte_errno = EINVAL;
1927 : 0 : return -rte_errno;
1928 : : }
1929 [ # # # # ]: 0 : if (rss_conf->rss_key && rss_conf->rss_key_len) {
1930 : : /*
1931 : : * Currently TAP RSS key is hard coded
1932 : : * and cannot be updated
1933 : : */
1934 : 0 : TAP_LOG(ERR,
1935 : : "port %u RSS key cannot be updated",
1936 : : dev->data->port_id);
1937 : 0 : rte_errno = EINVAL;
1938 : 0 : return -rte_errno;
1939 : : }
1940 : : return 0;
1941 : : }
1942 : :
1943 : : static int
1944 : 0 : tap_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1945 : : {
1946 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
1947 : :
1948 : 0 : return 0;
1949 : : }
1950 : :
1951 : : static int
1952 : 0 : tap_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1953 : : {
1954 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
1955 : :
1956 : 0 : return 0;
1957 : : }
1958 : :
1959 : : static int
1960 : 0 : tap_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1961 : : {
1962 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
1963 : :
1964 : 0 : return 0;
1965 : : }
1966 : :
1967 : : static int
1968 : 0 : tap_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1969 : : {
1970 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
1971 : :
1972 : 0 : return 0;
1973 : : }
1974 : : static const struct eth_dev_ops ops = {
1975 : : .dev_start = tap_dev_start,
1976 : : .dev_stop = tap_dev_stop,
1977 : : .dev_close = tap_dev_close,
1978 : : .dev_configure = tap_dev_configure,
1979 : : .dev_infos_get = tap_dev_info,
1980 : : .rx_queue_setup = tap_rx_queue_setup,
1981 : : .tx_queue_setup = tap_tx_queue_setup,
1982 : : .rx_queue_start = tap_rx_queue_start,
1983 : : .tx_queue_start = tap_tx_queue_start,
1984 : : .rx_queue_stop = tap_rx_queue_stop,
1985 : : .tx_queue_stop = tap_tx_queue_stop,
1986 : : .rx_queue_release = tap_rx_queue_release,
1987 : : .tx_queue_release = tap_tx_queue_release,
1988 : : .flow_ctrl_get = tap_flow_ctrl_get,
1989 : : .flow_ctrl_set = tap_flow_ctrl_set,
1990 : : .link_update = tap_link_update,
1991 : : .dev_set_link_up = tap_link_set_up,
1992 : : .dev_set_link_down = tap_link_set_down,
1993 : : .promiscuous_enable = tap_promisc_enable,
1994 : : .promiscuous_disable = tap_promisc_disable,
1995 : : .allmulticast_enable = tap_allmulti_enable,
1996 : : .allmulticast_disable = tap_allmulti_disable,
1997 : : .mac_addr_set = tap_mac_set,
1998 : : .mtu_set = tap_mtu_set,
1999 : : .set_mc_addr_list = tap_set_mc_addr_list,
2000 : : .stats_get = tap_stats_get,
2001 : : .stats_reset = tap_stats_reset,
2002 : : .dev_supported_ptypes_get = tap_dev_supported_ptypes_get,
2003 : : .rss_hash_update = tap_rss_hash_update,
2004 : : #ifdef HAVE_TCA_FLOWER
2005 : : .flow_ops_get = tap_dev_flow_ops_get,
2006 : : #endif
2007 : : };
2008 : :
2009 : : static int
2010 : 0 : eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
2011 : : char *remote_iface, struct rte_ether_addr *mac_addr,
2012 : : enum rte_tuntap_type type, int persist)
2013 : : {
2014 : 0 : int numa_node = rte_socket_id();
2015 : : struct rte_eth_dev *dev;
2016 : : struct pmd_internals *pmd;
2017 : : struct pmd_process_private *process_private;
2018 : 0 : const char *tuntap_name = tuntap_types[type];
2019 : : struct rte_eth_dev_data *data;
2020 : : int i;
2021 : :
2022 : 0 : TAP_LOG(DEBUG, "%s device on numa %u", tuntap_name, rte_socket_id());
2023 : :
2024 : 0 : dev = rte_eth_vdev_allocate(vdev, sizeof(*pmd));
2025 [ # # ]: 0 : if (!dev) {
2026 : 0 : TAP_LOG(ERR, "%s Unable to allocate device struct",
2027 : : tuntap_name);
2028 : 0 : goto error_exit_nodev;
2029 : : }
2030 : :
2031 : 0 : process_private = malloc(sizeof(struct pmd_process_private));
2032 [ # # ]: 0 : if (process_private == NULL) {
2033 : 0 : TAP_LOG(ERR, "Failed to alloc memory for process private");
2034 : 0 : return -1;
2035 : : }
2036 : : memset(process_private, 0, sizeof(struct pmd_process_private));
2037 : :
2038 : 0 : pmd = dev->data->dev_private;
2039 : 0 : dev->process_private = process_private;
2040 : 0 : pmd->dev = dev;
2041 : 0 : strlcpy(pmd->name, tap_name, sizeof(pmd->name));
2042 : 0 : pmd->type = type;
2043 : 0 : pmd->ka_fd = -1;
2044 : 0 : pmd->nlsk_fd = -1;
2045 : 0 : pmd->gso_ctx_mp = NULL;
2046 : :
2047 : : /* Allocate interrupt instance */
2048 : 0 : pmd->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
2049 [ # # ]: 0 : if (pmd->intr_handle == NULL) {
2050 : 0 : TAP_LOG(ERR, "Failed to allocate intr handle");
2051 : 0 : goto error_exit;
2052 : : }
2053 : :
2054 : : /* Setup some default values */
2055 : 0 : data = dev->data;
2056 : 0 : data->dev_private = pmd;
2057 : 0 : data->dev_flags = RTE_ETH_DEV_INTR_LSC |
2058 : : RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
2059 : 0 : data->numa_node = numa_node;
2060 : :
2061 : 0 : data->dev_link = pmd_link;
2062 : 0 : data->mac_addrs = &pmd->eth_addr;
2063 : : /* Set the number of RX and TX queues */
2064 : 0 : data->nb_rx_queues = 0;
2065 : 0 : data->nb_tx_queues = 0;
2066 : :
2067 : 0 : dev->dev_ops = &ops;
2068 : 0 : dev->rx_pkt_burst = pmd_rx_burst;
2069 : 0 : dev->tx_pkt_burst = pmd_tx_burst;
2070 : :
2071 : 0 : rte_intr_type_set(pmd->intr_handle, RTE_INTR_HANDLE_EXT);
2072 : 0 : rte_intr_fd_set(pmd->intr_handle, -1);
2073 : 0 : dev->intr_handle = pmd->intr_handle;
2074 : :
2075 : : /* Presetup the fds to -1 as being not valid */
2076 [ # # ]: 0 : for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++)
2077 : 0 : process_private->fds[i] = -1;
2078 : :
2079 : :
2080 [ # # ]: 0 : if (pmd->type == ETH_TUNTAP_TYPE_TAP) {
2081 [ # # ]: 0 : if (rte_is_zero_ether_addr(mac_addr))
2082 : 0 : rte_eth_random_addr((uint8_t *)&pmd->eth_addr);
2083 : : else
2084 : : rte_ether_addr_copy(mac_addr, &pmd->eth_addr);
2085 : : }
2086 : :
2087 : : /*
2088 : : * Allocate a TUN device keep-alive file descriptor that will only be
2089 : : * closed when the TUN device itself is closed or removed.
2090 : : * This keep-alive file descriptor will guarantee that the TUN device
2091 : : * exists even when all of its queues are closed
2092 : : */
2093 : 0 : pmd->ka_fd = tun_alloc(pmd, 1, persist);
2094 [ # # ]: 0 : if (pmd->ka_fd == -1) {
2095 : 0 : TAP_LOG(ERR, "Unable to create %s interface", tuntap_name);
2096 : 0 : goto error_exit;
2097 : : }
2098 : 0 : TAP_LOG(DEBUG, "allocated %s", pmd->name);
2099 : :
2100 : : /*
2101 : : * Create netlink socket for interface control.
2102 : : * Netlink provides ifindex-based operations and is namespace-safe.
2103 : : */
2104 : 0 : pmd->nlsk_fd = tap_nl_init(0);
2105 [ # # ]: 0 : if (pmd->nlsk_fd == -1) {
2106 : 0 : TAP_LOG(ERR, "%s: failed to create netlink socket.", pmd->name);
2107 : 0 : goto error_exit;
2108 : : }
2109 : :
2110 : 0 : pmd->if_index = if_nametoindex(pmd->name);
2111 [ # # ]: 0 : if (!pmd->if_index) {
2112 : 0 : TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name);
2113 : 0 : goto error_exit;
2114 : : }
2115 : :
2116 [ # # ]: 0 : if (tap_nl_set_mtu(pmd->nlsk_fd, pmd->if_index, dev->data->mtu) < 0)
2117 : 0 : goto error_exit;
2118 : :
2119 [ # # ]: 0 : if (pmd->type == ETH_TUNTAP_TYPE_TAP) {
2120 [ # # ]: 0 : if (tap_nl_set_mac(pmd->nlsk_fd, pmd->if_index, &pmd->eth_addr) < 0)
2121 : 0 : goto error_exit;
2122 : : }
2123 : :
2124 : : /* Make network device persist after application exit */
2125 : 0 : pmd->persist = persist;
2126 : :
2127 : : #ifdef HAVE_TCA_FLOWER
2128 : : /*
2129 : : * Set up everything related to rte_flow:
2130 : : * - mandatory QDISCs
2131 : : * - rte_flow actual/implicit lists
2132 : : * - implicit rules
2133 : : */
2134 [ # # ]: 0 : if (qdisc_create_multiq(pmd->nlsk_fd, pmd->if_index) < 0) {
2135 : 0 : TAP_LOG(ERR, "%s: failed to create multiq qdisc.",
2136 : : pmd->name);
2137 : 0 : goto disable_rte_flow;
2138 : : }
2139 [ # # ]: 0 : if (qdisc_create_ingress(pmd->nlsk_fd, pmd->if_index) < 0) {
2140 : 0 : TAP_LOG(ERR, "%s: failed to create ingress qdisc.",
2141 : : pmd->name);
2142 : 0 : goto disable_rte_flow;
2143 : : }
2144 : :
2145 : 0 : LIST_INIT(&pmd->flows);
2146 : :
2147 [ # # ]: 0 : if (strlen(remote_iface)) {
2148 : 0 : pmd->remote_if_index = if_nametoindex(remote_iface);
2149 [ # # ]: 0 : if (!pmd->remote_if_index) {
2150 : 0 : TAP_LOG(ERR, "%s: failed to get %s if_index.",
2151 : : pmd->name, remote_iface);
2152 : 0 : goto error_remote;
2153 : : }
2154 : 0 : strlcpy(pmd->remote_iface, remote_iface, RTE_ETH_NAME_MAX_LEN);
2155 : :
2156 : : /* Save state of remote device */
2157 [ # # ]: 0 : if (tap_nl_get_flags(pmd->nlsk_fd, pmd->remote_if_index,
2158 : : &pmd->remote_initial_flags) < 0)
2159 : 0 : pmd->remote_initial_flags = 0;
2160 : :
2161 : : /* Replicate remote MAC address */
2162 [ # # ]: 0 : if (tap_nl_get_mac(pmd->nlsk_fd, pmd->remote_if_index, &pmd->eth_addr) < 0) {
2163 : 0 : TAP_LOG(ERR, "%s: failed to get %s MAC address.",
2164 : : pmd->name, pmd->remote_iface);
2165 : 0 : goto error_remote;
2166 : : }
2167 : :
2168 [ # # ]: 0 : if (tap_nl_set_mac(pmd->nlsk_fd, pmd->if_index, &pmd->eth_addr) < 0) {
2169 : 0 : TAP_LOG(ERR, "%s: failed to set %s MAC address.",
2170 : : pmd->name, remote_iface);
2171 : 0 : goto error_remote;
2172 : : }
2173 : :
2174 : : /*
2175 : : * Flush usually returns negative value because it tries to
2176 : : * delete every QDISC (and on a running device, one QDISC at
2177 : : * least is needed). Ignore negative return value.
2178 : : */
2179 : 0 : qdisc_flush(pmd->nlsk_fd, pmd->remote_if_index);
2180 [ # # ]: 0 : if (qdisc_create_ingress(pmd->nlsk_fd,
2181 : 0 : pmd->remote_if_index) < 0) {
2182 : 0 : TAP_LOG(ERR, "%s: failed to create ingress qdisc.",
2183 : : pmd->remote_iface);
2184 : 0 : goto error_remote;
2185 : : }
2186 : 0 : LIST_INIT(&pmd->implicit_flows);
2187 [ # # # # ]: 0 : if (tap_flow_implicit_create(pmd, TAP_REMOTE_TX) < 0 ||
2188 [ # # ]: 0 : tap_flow_implicit_create(pmd, TAP_REMOTE_LOCAL_MAC) < 0 ||
2189 [ # # ]: 0 : tap_flow_implicit_create(pmd, TAP_REMOTE_BROADCAST) < 0 ||
2190 : 0 : tap_flow_implicit_create(pmd, TAP_REMOTE_BROADCASTV6) < 0) {
2191 : 0 : TAP_LOG(ERR,
2192 : : "%s: failed to create implicit rules.",
2193 : : pmd->name);
2194 : 0 : goto error_remote;
2195 : : }
2196 : : }
2197 : : #endif
2198 : :
2199 : 0 : rte_eth_dev_probing_finish(dev);
2200 : 0 : return 0;
2201 : :
2202 : 0 : disable_rte_flow:
2203 : 0 : TAP_LOG(ERR, " Disabling rte flow support: %s(%d)",
2204 : : strerror(errno), errno);
2205 [ # # ]: 0 : if (strlen(remote_iface)) {
2206 : 0 : TAP_LOG(ERR, "Remote feature requires flow support.");
2207 : 0 : goto error_exit;
2208 : : }
2209 : 0 : rte_eth_dev_probing_finish(dev);
2210 : 0 : return 0;
2211 : :
2212 : : #ifdef HAVE_TCA_FLOWER
2213 : 0 : error_remote:
2214 : 0 : TAP_LOG(ERR, " Can't set up remote feature: %s(%d)",
2215 : : strerror(errno), errno);
2216 : 0 : tap_flow_implicit_flush(pmd, NULL);
2217 : : #endif
2218 : :
2219 : 0 : error_exit:
2220 [ # # ]: 0 : if (pmd->nlsk_fd != -1)
2221 : 0 : close(pmd->nlsk_fd);
2222 [ # # ]: 0 : if (pmd->ka_fd != -1)
2223 : 0 : close(pmd->ka_fd);
2224 : : /* mac_addrs must not be freed alone because part of dev_private */
2225 : 0 : dev->data->mac_addrs = NULL;
2226 : 0 : rte_intr_instance_free(pmd->intr_handle);
2227 : 0 : rte_eth_dev_release_port(dev);
2228 : :
2229 [ # # ]: 0 : error_exit_nodev:
2230 : 0 : TAP_LOG(ERR, "%s Unable to initialize %s",
2231 : : tuntap_name, rte_vdev_device_name(vdev));
2232 : :
2233 : 0 : return -EINVAL;
2234 : : }
2235 : :
2236 : : /* make sure name is a possible Linux network device name */
2237 : : static bool
2238 : 0 : is_valid_iface(const char *name)
2239 : : {
2240 [ # # ]: 0 : if (*name == '\0')
2241 : : return false;
2242 : :
2243 [ # # ]: 0 : if (strnlen(name, IFNAMSIZ) == IFNAMSIZ)
2244 : : return false;
2245 : :
2246 [ # # ]: 0 : while (*name) {
2247 [ # # # # ]: 0 : if (*name == '/' || *name == ':' || isspace(*name))
2248 : : return false;
2249 : 0 : name++;
2250 : : }
2251 : : return true;
2252 : : }
2253 : :
2254 : : static int
2255 : 0 : set_interface_name(const char *key __rte_unused,
2256 : : const char *value,
2257 : : void *extra_args)
2258 : : {
2259 : : char *name = (char *)extra_args;
2260 : :
2261 [ # # ]: 0 : if (value) {
2262 [ # # ]: 0 : if (!is_valid_iface(value)) {
2263 : 0 : TAP_LOG(ERR, "TAP invalid remote interface name (%s)",
2264 : : value);
2265 : 0 : return -1;
2266 : : }
2267 : : strlcpy(name, value, RTE_ETH_NAME_MAX_LEN);
2268 : : } else {
2269 : : /* use tap%d which causes kernel to choose next available */
2270 : : strlcpy(name, DEFAULT_TAP_NAME "%d", RTE_ETH_NAME_MAX_LEN);
2271 : : }
2272 : : return 0;
2273 : : }
2274 : :
2275 : : static int
2276 : 0 : set_remote_iface(const char *key __rte_unused,
2277 : : const char *value,
2278 : : void *extra_args)
2279 : : {
2280 : : char *name = (char *)extra_args;
2281 : :
2282 [ # # ]: 0 : if (value) {
2283 [ # # ]: 0 : if (!is_valid_iface(value)) {
2284 : 0 : TAP_LOG(ERR, "TAP invalid remote interface name (%s)",
2285 : : value);
2286 : 0 : return -1;
2287 : : }
2288 : : strlcpy(name, value, RTE_ETH_NAME_MAX_LEN);
2289 : : }
2290 : :
2291 : : return 0;
2292 : : }
2293 : :
2294 : : static int
2295 : 0 : set_mac_type(const char *key __rte_unused,
2296 : : const char *value,
2297 : : void *extra_args)
2298 : : {
2299 : : struct rte_ether_addr *user_mac = extra_args;
2300 : :
2301 [ # # ]: 0 : if (!value)
2302 : : return 0;
2303 : :
2304 [ # # ]: 0 : if (!strncasecmp(ETH_TAP_MAC_FIXED, value, strlen(ETH_TAP_MAC_FIXED))) {
2305 : : static int iface_idx;
2306 : :
2307 : : /* fixed mac = 02:64:74:61:70:<iface_idx> */
2308 : 0 : memcpy((char *)user_mac->addr_bytes, "\002dtap",
2309 : : RTE_ETHER_ADDR_LEN);
2310 : 0 : user_mac->addr_bytes[RTE_ETHER_ADDR_LEN - 1] =
2311 : 0 : iface_idx++ + '0';
2312 : 0 : goto success;
2313 : : }
2314 : :
2315 [ # # ]: 0 : if (rte_ether_unformat_addr(value, user_mac) < 0)
2316 : 0 : goto error;
2317 : 0 : success:
2318 : 0 : TAP_LOG(DEBUG, "TAP user MAC param (%s)", value);
2319 : 0 : return 0;
2320 : :
2321 : : error:
2322 : 0 : TAP_LOG(ERR, "TAP user MAC (%s) is not in format (%s|%s)",
2323 : : value, ETH_TAP_MAC_FIXED, ETH_TAP_USR_MAC_FMT);
2324 : 0 : return -1;
2325 : : }
2326 : :
2327 : : /*
2328 : : * Open a TUN interface device. TUN PMD
2329 : : * 1) sets tap_type as false
2330 : : * 2) intakes iface as argument.
2331 : : * 3) as interface is virtual set speed to 10G
2332 : : */
2333 : : static int
2334 [ # # ]: 0 : rte_pmd_tun_probe(struct rte_vdev_device *dev)
2335 : : {
2336 : : const char *name, *params;
2337 : : int ret;
2338 : : struct rte_kvargs *kvlist = NULL;
2339 : : char tun_name[RTE_ETH_NAME_MAX_LEN];
2340 : : char remote_iface[RTE_ETH_NAME_MAX_LEN];
2341 : : struct rte_eth_dev *eth_dev;
2342 : :
2343 : : name = rte_vdev_device_name(dev);
2344 : : params = rte_vdev_device_args(dev);
2345 : : memset(remote_iface, 0, RTE_ETH_NAME_MAX_LEN);
2346 : :
2347 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
2348 [ # # ]: 0 : strlen(params) == 0) {
2349 : 0 : eth_dev = rte_eth_dev_attach_secondary(name);
2350 [ # # ]: 0 : if (!eth_dev) {
2351 : 0 : TAP_LOG(ERR, "Failed to probe %s", name);
2352 : 0 : return -1;
2353 : : }
2354 : 0 : eth_dev->dev_ops = &ops;
2355 : 0 : eth_dev->device = &dev->device;
2356 : 0 : rte_eth_dev_probing_finish(eth_dev);
2357 : 0 : return 0;
2358 : : }
2359 : :
2360 : : /* use tun%d which causes kernel to choose next available */
2361 : : strlcpy(tun_name, DEFAULT_TUN_NAME "%d", RTE_ETH_NAME_MAX_LEN);
2362 : :
2363 [ # # # # ]: 0 : if (params && (params[0] != '\0')) {
2364 : 0 : TAP_LOG(DEBUG, "parameters (%s)", params);
2365 : :
2366 : 0 : kvlist = rte_kvargs_parse(params, valid_arguments);
2367 [ # # ]: 0 : if (kvlist) {
2368 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
2369 : 0 : ret = rte_kvargs_process_opt(kvlist,
2370 : : ETH_TAP_IFACE_ARG,
2371 : : &set_interface_name,
2372 : : tun_name);
2373 : :
2374 [ # # ]: 0 : if (ret == -1)
2375 : 0 : goto leave;
2376 : : }
2377 : : }
2378 : : }
2379 : 0 : pmd_link.link_speed = RTE_ETH_SPEED_NUM_10G;
2380 : :
2381 : 0 : TAP_LOG(DEBUG, "Initializing pmd_tun for %s", name);
2382 : :
2383 : 0 : ret = eth_dev_tap_create(dev, tun_name, remote_iface, 0,
2384 : : ETH_TUNTAP_TYPE_TUN, 0);
2385 : :
2386 : 0 : leave:
2387 [ # # ]: 0 : if (ret == -1) {
2388 : 0 : TAP_LOG(ERR, "Failed to create pmd for %s as %s",
2389 : : name, tun_name);
2390 : : }
2391 : 0 : rte_kvargs_free(kvlist);
2392 : :
2393 : 0 : return ret;
2394 : : }
2395 : :
2396 : : /* Request queue file descriptors from secondary to primary. */
2397 : : static int
2398 : 0 : tap_mp_attach_queues(const char *port_name, struct rte_eth_dev *dev)
2399 : : {
2400 : : int ret;
2401 : 0 : struct timespec timeout = {.tv_sec = 1, .tv_nsec = 0};
2402 : : struct rte_mp_msg request, *reply;
2403 : : struct rte_mp_reply replies;
2404 : : struct ipc_queues *request_param = (struct ipc_queues *)request.param;
2405 : : struct ipc_queues *reply_param;
2406 : 0 : struct pmd_process_private *process_private = dev->process_private;
2407 : :
2408 : : /* Prepare the request */
2409 : : memset(&request, 0, sizeof(request));
2410 : : strlcpy(request.name, TAP_MP_KEY, sizeof(request.name));
2411 : : strlcpy(request_param->port_name, port_name,
2412 : : sizeof(request_param->port_name));
2413 : 0 : request.len_param = sizeof(*request_param);
2414 : : /* Send request and receive reply */
2415 : 0 : ret = rte_mp_request_sync(&request, &replies, &timeout);
2416 [ # # # # ]: 0 : if (ret < 0 || replies.nb_received != 1) {
2417 : 0 : TAP_LOG(ERR, "Failed to request queues from primary: %d",
2418 : : rte_errno);
2419 : 0 : return -1;
2420 : : }
2421 : 0 : reply = &replies.msgs[0];
2422 : : reply_param = (struct ipc_queues *)reply->param;
2423 : 0 : TAP_LOG(DEBUG, "Received IPC reply for %s", reply_param->port_name);
2424 : :
2425 : : /* Attach the queues from received file descriptors */
2426 [ # # ]: 0 : if (reply_param->q_count != reply->num_fds) {
2427 : 0 : TAP_LOG(ERR, "Unexpected number of fds received");
2428 : 0 : return -1;
2429 : : }
2430 : :
2431 : 0 : dev->data->nb_rx_queues = reply_param->q_count;
2432 : 0 : dev->data->nb_tx_queues = reply_param->q_count;
2433 : :
2434 [ # # ]: 0 : for (int q = 0; q < reply_param->q_count; q++)
2435 : 0 : process_private->fds[q] = reply->fds[q];
2436 : :
2437 : 0 : free(reply);
2438 : 0 : return 0;
2439 : : }
2440 : :
2441 : : /* Send the queue file descriptors from the primary process to secondary. */
2442 : : static int
2443 : 0 : tap_mp_sync_queues(const struct rte_mp_msg *request, const void *peer)
2444 : : {
2445 : : struct rte_eth_dev *dev;
2446 : : struct pmd_process_private *process_private;
2447 : : struct rte_mp_msg reply;
2448 : : const struct ipc_queues *request_param =
2449 : : (const struct ipc_queues *)request->param;
2450 : : struct ipc_queues *reply_param =
2451 : : (struct ipc_queues *)reply.param;
2452 : : int queue;
2453 : :
2454 : : /* Get requested port */
2455 : 0 : TAP_LOG(DEBUG, "Received IPC request for %s", request_param->port_name);
2456 : 0 : dev = rte_eth_dev_get_by_name(request_param->port_name);
2457 [ # # ]: 0 : if (!dev) {
2458 : 0 : TAP_LOG(ERR, "Failed to get port id for %s",
2459 : : request_param->port_name);
2460 : 0 : return -1;
2461 : : }
2462 : 0 : process_private = dev->process_private;
2463 : :
2464 : : /* Fill file descriptors for all queues */
2465 : 0 : reply.num_fds = 0;
2466 : 0 : reply_param->q_count = 0;
2467 : :
2468 : : RTE_ASSERT(dev->data->nb_rx_queues == dev->data->nb_tx_queues);
2469 : :
2470 [ # # ]: 0 : if (dev->data->nb_rx_queues > RTE_PMD_TAP_MAX_QUEUES) {
2471 : 0 : TAP_LOG(ERR, "Number of rx/tx queues %u exceeds max number of fds %u",
2472 : : dev->data->nb_rx_queues, RTE_PMD_TAP_MAX_QUEUES);
2473 : 0 : return -1;
2474 : : }
2475 : :
2476 [ # # ]: 0 : for (queue = 0; queue < dev->data->nb_rx_queues; queue++) {
2477 : 0 : reply.fds[reply.num_fds++] = process_private->fds[queue];
2478 : 0 : reply_param->q_count++;
2479 : : }
2480 : :
2481 : : /* Send reply */
2482 : 0 : strlcpy(reply.name, request->name, sizeof(reply.name));
2483 : : strlcpy(reply_param->port_name, request_param->port_name,
2484 : : sizeof(reply_param->port_name));
2485 : 0 : reply.len_param = sizeof(*reply_param);
2486 [ # # ]: 0 : if (rte_mp_reply(&reply, peer) < 0) {
2487 : 0 : TAP_LOG(ERR, "Failed to reply an IPC request to sync queues");
2488 : 0 : return -1;
2489 : : }
2490 : : return 0;
2491 : : }
2492 : :
2493 : : /* Open a TAP interface device.
2494 : : */
2495 : : static int
2496 : 0 : rte_pmd_tap_probe(struct rte_vdev_device *dev)
2497 : : {
2498 : : const char *name, *params;
2499 : : int ret;
2500 : : struct rte_kvargs *kvlist = NULL;
2501 : : int speed;
2502 : : char tap_name[RTE_ETH_NAME_MAX_LEN];
2503 : : char remote_iface[RTE_ETH_NAME_MAX_LEN];
2504 [ # # ]: 0 : struct rte_ether_addr user_mac = { .addr_bytes = {0} };
2505 : : struct rte_eth_dev *eth_dev;
2506 : : int tap_devices_count_increased = 0;
2507 : : int persist = 0;
2508 : :
2509 : : name = rte_vdev_device_name(dev);
2510 : : params = rte_vdev_device_args(dev);
2511 : :
2512 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
2513 : 0 : eth_dev = rte_eth_dev_attach_secondary(name);
2514 [ # # ]: 0 : if (!eth_dev) {
2515 : 0 : TAP_LOG(ERR, "Failed to probe %s", name);
2516 : 0 : return -1;
2517 : : }
2518 : 0 : eth_dev->dev_ops = &ops;
2519 : 0 : eth_dev->device = &dev->device;
2520 : 0 : eth_dev->rx_pkt_burst = pmd_rx_burst;
2521 : 0 : eth_dev->tx_pkt_burst = pmd_tx_burst;
2522 [ # # ]: 0 : if (!rte_eal_primary_proc_alive(NULL)) {
2523 : 0 : TAP_LOG(ERR, "Primary process is missing");
2524 : 0 : return -1;
2525 : : }
2526 : 0 : eth_dev->process_private = malloc(sizeof(struct pmd_process_private));
2527 [ # # ]: 0 : if (eth_dev->process_private == NULL) {
2528 : 0 : TAP_LOG(ERR,
2529 : : "Failed to alloc memory for process private");
2530 : 0 : return -1;
2531 : : }
2532 : : memset(eth_dev->process_private, 0, sizeof(struct pmd_process_private));
2533 : :
2534 : 0 : ret = tap_mp_attach_queues(name, eth_dev);
2535 [ # # ]: 0 : if (ret != 0)
2536 : : return -1;
2537 : :
2538 [ # # ]: 0 : if (!tap_devices_count) {
2539 : 0 : ret = rte_mp_action_register(TAP_MP_REQ_START_RXTX, tap_mp_req_start_rxtx);
2540 [ # # # # ]: 0 : if (ret < 0 && rte_errno != ENOTSUP) {
2541 : 0 : TAP_LOG(ERR, "tap: Failed to register IPC callback: %s",
2542 : : strerror(rte_errno));
2543 : 0 : return -1;
2544 : : }
2545 : : }
2546 : 0 : tap_devices_count++;
2547 : 0 : rte_eth_dev_probing_finish(eth_dev);
2548 : 0 : return 0;
2549 : : }
2550 : :
2551 : : speed = RTE_ETH_SPEED_NUM_10G;
2552 : :
2553 : : /* use tap%d which causes kernel to choose next available */
2554 : : strlcpy(tap_name, DEFAULT_TAP_NAME "%d", RTE_ETH_NAME_MAX_LEN);
2555 : : memset(remote_iface, 0, RTE_ETH_NAME_MAX_LEN);
2556 : :
2557 [ # # # # ]: 0 : if (params && (params[0] != '\0')) {
2558 : 0 : TAP_LOG(DEBUG, "parameters (%s)", params);
2559 : :
2560 : 0 : kvlist = rte_kvargs_parse(params, valid_arguments);
2561 [ # # ]: 0 : if (kvlist) {
2562 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
2563 : 0 : ret = rte_kvargs_process_opt(kvlist,
2564 : : ETH_TAP_IFACE_ARG,
2565 : : &set_interface_name,
2566 : : tap_name);
2567 [ # # ]: 0 : if (ret == -1)
2568 : 0 : goto leave;
2569 : : }
2570 : :
2571 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ETH_TAP_REMOTE_ARG) == 1) {
2572 : 0 : ret = rte_kvargs_process(kvlist,
2573 : : ETH_TAP_REMOTE_ARG,
2574 : : &set_remote_iface,
2575 : : remote_iface);
2576 [ # # ]: 0 : if (ret == -1)
2577 : 0 : goto leave;
2578 : : }
2579 : :
2580 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ETH_TAP_MAC_ARG) == 1) {
2581 : 0 : ret = rte_kvargs_process(kvlist,
2582 : : ETH_TAP_MAC_ARG,
2583 : : &set_mac_type,
2584 : : &user_mac);
2585 [ # # ]: 0 : if (ret == -1)
2586 : 0 : goto leave;
2587 : : }
2588 : :
2589 [ # # ]: 0 : if (rte_kvargs_count(kvlist, ETH_TAP_PERSIST_ARG) == 1)
2590 : : persist = 1;
2591 : : }
2592 : : }
2593 : 0 : pmd_link.link_speed = speed;
2594 : :
2595 : 0 : TAP_LOG(DEBUG, "Initializing pmd_tap for %s", name);
2596 : :
2597 : : /* Register IPC feed callback */
2598 [ # # ]: 0 : if (!tap_devices_count) {
2599 : 0 : ret = rte_mp_action_register(TAP_MP_KEY, tap_mp_sync_queues);
2600 [ # # # # ]: 0 : if (ret < 0 && rte_errno != ENOTSUP) {
2601 : 0 : TAP_LOG(ERR, "tap: Failed to register IPC callback: %s",
2602 : : strerror(rte_errno));
2603 : 0 : goto leave;
2604 : : }
2605 : : }
2606 : 0 : tap_devices_count++;
2607 : : tap_devices_count_increased = 1;
2608 : 0 : ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac,
2609 : : ETH_TUNTAP_TYPE_TAP, persist);
2610 : :
2611 : 0 : leave:
2612 [ # # ]: 0 : if (ret == -1) {
2613 : 0 : TAP_LOG(ERR, "Failed to create pmd for %s as %s",
2614 : : name, tap_name);
2615 [ # # ]: 0 : if (tap_devices_count_increased == 1) {
2616 [ # # ]: 0 : if (tap_devices_count == 1)
2617 : 0 : rte_mp_action_unregister(TAP_MP_KEY);
2618 : 0 : tap_devices_count--;
2619 : : }
2620 : : }
2621 : 0 : rte_kvargs_free(kvlist);
2622 : :
2623 : 0 : return ret;
2624 : : }
2625 : :
2626 : : /* detach a TUNTAP device.
2627 : : */
2628 : : static int
2629 [ # # ]: 0 : rte_pmd_tap_remove(struct rte_vdev_device *dev)
2630 : : {
2631 : : struct rte_eth_dev *eth_dev = NULL;
2632 : :
2633 : : /* find the ethdev entry */
2634 : 0 : eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
2635 [ # # ]: 0 : if (!eth_dev)
2636 : : return 0;
2637 : :
2638 : 0 : tap_dev_close(eth_dev);
2639 : 0 : rte_eth_dev_release_port(eth_dev);
2640 : :
2641 : 0 : return 0;
2642 : : }
2643 : :
2644 : : static struct rte_vdev_driver pmd_tun_drv = {
2645 : : .probe = rte_pmd_tun_probe,
2646 : : .remove = rte_pmd_tap_remove,
2647 : : };
2648 : :
2649 : : static struct rte_vdev_driver pmd_tap_drv = {
2650 : : .probe = rte_pmd_tap_probe,
2651 : : .remove = rte_pmd_tap_remove,
2652 : : };
2653 : :
2654 : 254 : RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
2655 : 254 : RTE_PMD_REGISTER_VDEV(net_tun, pmd_tun_drv);
2656 : : RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
2657 : : RTE_PMD_REGISTER_PARAM_STRING(net_tun,
2658 : : ETH_TAP_IFACE_ARG "=<string> ");
2659 : : RTE_PMD_REGISTER_PARAM_STRING(net_tap,
2660 : : ETH_TAP_IFACE_ARG "=<string> "
2661 : : ETH_TAP_MAC_ARG "=" ETH_TAP_MAC_ARG_FMT " "
2662 : : ETH_TAP_REMOTE_ARG "=<string>");
2663 [ - + ]: 254 : RTE_LOG_REGISTER_DEFAULT(tap_logtype, NOTICE);
|