Line data Source code
1 : /*
2 : * Copyright (C) 2016 Semihalf.
3 : *
4 : * This program is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU General Public License as
6 : * published by the Free Software Foundation version 2.
7 : *
8 : * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 : * kind, whether express or implied; without even the implied warranty
10 : * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 : * GNU General Public License for more details.
12 : *
13 : * vr_dpdk_tapdev.c -- DPDK tap device
14 : *
15 : */
16 :
17 : #include "vr_dpdk.h"
18 : #include "vhost.h"
19 : // #include "vr_packet.h"
20 :
21 : #include <rte_errno.h>
22 : #include <rte_ethdev.h>
23 : #include <rte_port_ring.h>
24 : #include <rte_malloc.h>
25 :
26 : #include <fcntl.h>
27 : #include <linux/if.h>
28 : #include <linux/if_tun.h>
29 : #include <sys/ioctl.h>
30 : #include <sys/stat.h>
31 : #include <sys/types.h>
32 : #include <sys/socket.h>
33 : #include <netinet/in.h>
34 : #include <linux/netlink.h>
35 : #include <linux/rtnetlink.h>
36 :
37 : /*
38 : * vr_dpdk_tapdev_init - initializes TAP device using specified Ethernet port.
39 : *
40 : * Returns 0 on success, < 0 otherwise.
41 : */
42 : int
43 0 : vr_dpdk_tapdev_init(struct vr_interface *vif)
44 : {
45 : int i, fd;
46 0 : struct vr_dpdk_tapdev *tapdev = NULL;
47 : struct ifreq ifr;
48 : struct sockaddr_nl tap_nl_addr;
49 :
50 0 : RTE_LOG(INFO, VROUTER, " creating TAP device %s\n", vif->vif_name);
51 :
52 : /* If vif is vhost0, reuse previously existed slot if any. */
53 0 : if (vif_is_vhost(vif)) {
54 0 : for (i = 0; i < VR_DPDK_MAX_TAP_INTERFACES; i++) {
55 0 : if ((vr_dpdk.tapdevs[i].tapdev_vhost_fd > 0) &&
56 0 : (!strncmp((char *)vif->vif_name, vr_dpdk.tapdevs[i].tapdev_name,
57 : VR_INTERFACE_NAME_LEN - 1))) {
58 0 : RTE_LOG(INFO, VROUTER, " TAP device %s already exists\n",
59 : vif->vif_name);
60 0 : tapdev = &vr_dpdk.tapdevs[i];
61 0 : fd = tapdev->tapdev_fd = tapdev->tapdev_vhost_fd;
62 0 : goto enable_tap;
63 : }
64 : }
65 : }
66 :
67 : /* Find an empty TAP slot. */
68 0 : for (i = 0; i < VR_DPDK_MAX_TAP_INTERFACES; i++) {
69 0 : if (vr_dpdk.tapdevs[i].tapdev_fd <= 0) {
70 0 : tapdev = &vr_dpdk.tapdevs[i];
71 0 : break;
72 : }
73 : }
74 :
75 0 : if (tapdev == NULL) {
76 0 : RTE_LOG(ERR, VROUTER, " error allocating TAP device %s\n",
77 : vif->vif_name);
78 0 : return -ENOMEM;
79 : }
80 :
81 : /* Open TUN device. */
82 0 : fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
83 0 : if (fd == -1) {
84 0 : RTE_LOG(ERR, VROUTER, " error opening TAP device %s: %s (%d)\n",
85 : vif->vif_name, rte_strerror(errno), errno);
86 0 : goto error;
87 : }
88 :
89 : /* Create TAP interface. */
90 0 : memset(&ifr, 0, sizeof(ifr));
91 0 : memcpy(ifr.ifr_name, (char *)vif->vif_name, sizeof(ifr.ifr_name) - 1);
92 0 : if (vif_is_vhost(vif))
93 0 : tapdev->tapdev_vhost_fd = fd;
94 : else
95 0 : tapdev->tapdev_vhost_fd = -1;
96 0 : ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
97 0 : if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
98 0 : RTE_LOG(ERR, VROUTER, " error creating TAP interface %s: %s (%d)\n",
99 : vif->vif_name, rte_strerror(errno), errno);
100 0 : goto error;
101 : }
102 :
103 0 : enable_tap:
104 : /* Enable TAP device. */
105 0 : vif->vif_os = tapdev;
106 0 : tapdev->tapdev_vif = vif;
107 0 : memset(tapdev->tapdev_name, 0, VR_INTERFACE_NAME_LEN);
108 0 : memcpy(tapdev->tapdev_name, (char *)vif->vif_name,
109 : VR_INTERFACE_NAME_LEN - 1);
110 0 : synchronize_rcu();
111 0 : tapdev->tapdev_fd = fd;
112 :
113 : /* Create tap netlink socket for link up/down mtu change notifications */
114 0 : if(vif_is_vhost(vif) && (vr_dpdk.tap_nl_fd <= 0)) {
115 0 : vr_dpdk.tap_nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
116 0 : if (vr_dpdk.tap_nl_fd < 0) {
117 0 : RTE_LOG(ERR, VROUTER, " error creating tap netlink socket\n");
118 0 : goto error;
119 : }
120 :
121 0 : memset ((void *) &tap_nl_addr, 0, sizeof (tap_nl_addr));
122 0 : tap_nl_addr.nl_family = AF_NETLINK;
123 0 : tap_nl_addr.nl_pid = getpid ();
124 0 : tap_nl_addr.nl_groups = RTMGRP_LINK;
125 0 : if (bind(vr_dpdk.tap_nl_fd,
126 : (struct sockaddr *) &tap_nl_addr, sizeof (tap_nl_addr)) < 0) {
127 0 : RTE_LOG(ERR, VROUTER, " error binding tap netlink socket\n");
128 0 : goto error;
129 : }
130 : }
131 :
132 0 : return 0;
133 :
134 0 : error:
135 0 : if (tapdev->tapdev_fd > 0) {
136 0 : close(tapdev->tapdev_fd);
137 0 : tapdev->tapdev_fd = -1;
138 : }
139 :
140 0 : if (vr_dpdk.tap_nl_fd > 0) {
141 0 : close(vr_dpdk.tap_nl_fd);
142 0 : vr_dpdk.tap_nl_fd = -1;
143 : }
144 :
145 0 : return -EINVAL;
146 : }
147 :
148 : /*
149 : * vr_dpdk_tapdev_release - release TAP device.
150 : *
151 : * Returns 0 on success, < 0 otherwise.
152 : */
153 : int
154 49 : vr_dpdk_tapdev_release(struct vr_interface *vif)
155 : {
156 : unsigned lcore_id;
157 : struct rte_mbuf *mbuf;
158 49 : struct vr_dpdk_tapdev *tapdev = vif->vif_os;
159 : int fd;
160 :
161 49 : if (tapdev != NULL)
162 0 : fd = tapdev->tapdev_fd;
163 : else
164 49 : return 0;
165 :
166 0 : RTE_LOG(INFO, VROUTER, " releasing vif %u TAP device %s\n",
167 : vif->vif_idx, vif->vif_name);
168 :
169 0 : if (fd > 0) {
170 0 : tapdev->tapdev_fd = -1;
171 0 : synchronize_rcu();
172 0 : if (tapdev->tapdev_vhost_fd < 0)
173 0 : close(fd);
174 : }
175 :
176 0 : vif->vif_os = NULL;
177 0 : tapdev->tapdev_vif = NULL;
178 :
179 : /* Drop RX and TX mbufs. */
180 0 : if (tapdev->tapdev_rx_ring) {
181 0 : while (rte_ring_sc_dequeue(tapdev->tapdev_rx_ring,
182 0 : (void **)&mbuf) == 0) {
183 0 : rte_pktmbuf_free(mbuf);
184 : }
185 : }
186 :
187 0 : RTE_LCORE_FOREACH(lcore_id) {
188 0 : if (tapdev->tapdev_tx_rings[lcore_id]) {
189 0 : while (rte_ring_sc_dequeue(tapdev->tapdev_tx_rings[lcore_id],
190 0 : (void **)&mbuf) == 0) {
191 0 : rte_pktmbuf_free(mbuf);
192 : }
193 : }
194 : }
195 :
196 0 : return 0;
197 : }
198 :
199 : /*
200 : * dpdk_tapdev_rx_queue_release - release TAP RX queue.
201 : */
202 : static void
203 0 : dpdk_tapdev_rx_queue_release(unsigned lcore_id,
204 : unsigned queue_index __attribute__((unused)),
205 : struct vr_interface *vif)
206 : {
207 0 : struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];
208 0 : struct vr_dpdk_queue *rx_queue = &lcore->lcore_rx_queues[vif->vif_idx];
209 0 : struct vr_dpdk_queue_params *rx_queue_params
210 0 : = &lcore->lcore_rx_queue_params[vif->vif_idx];
211 :
212 : /* Free the queue. */
213 0 : if (rx_queue->rxq_ops.f_free(rx_queue->q_queue_h)) {
214 0 : RTE_LOG(ERR, VROUTER, " error freeing lcore %u TAP device RX queue\n",
215 : lcore_id);
216 : }
217 :
218 : /* Reset the queue. */
219 0 : vrouter_put_interface(rx_queue->q_vif);
220 0 : memset(rx_queue, 0, sizeof(*rx_queue));
221 0 : memset(rx_queue_params, 0, sizeof(*rx_queue_params));
222 0 : }
223 :
224 :
225 : /*
226 : * vr_dpdk_tapdev_rx_queue_init - init TAP RX queue.
227 : *
228 : * Returns queue pointer on success, NULL otherwise.
229 : */
230 : struct vr_dpdk_queue *
231 0 : vr_dpdk_tapdev_rx_queue_init(unsigned lcore_id, struct vr_interface *vif,
232 : unsigned queue_id)
233 : {
234 0 : struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];
235 0 : const unsigned socket_id = rte_lcore_to_socket_id(lcore_id);
236 0 : unsigned vif_idx = vif->vif_idx;
237 0 : struct vr_dpdk_tapdev *tapdev = vif->vif_os;
238 0 : struct vr_dpdk_queue *rx_queue = &lcore->lcore_rx_queues[vif_idx];
239 0 : struct vr_dpdk_queue_params *rx_queue_params
240 : = &lcore->lcore_rx_queue_params[vif_idx];
241 :
242 : /* Init queue. */
243 0 : rx_queue->rxq_ops = rte_port_ring_reader_ops;
244 0 : rx_queue->q_queue_h = NULL;
245 0 : rx_queue->q_vif = vrouter_get_interface(vif->vif_rid, vif_idx);
246 :
247 : /* Allocate RX ring if needed. */
248 0 : if (tapdev->tapdev_rx_ring == NULL) {
249 0 : tapdev->tapdev_rx_ring = vr_dpdk_ring_allocate(lcore_id,
250 : "tapdev_rx_ring", vr_dpdk_rx_ring_sz,
251 : RING_F_SP_ENQ | RING_F_SC_DEQ);
252 0 : if (tapdev->tapdev_rx_ring == NULL)
253 0 : goto error;
254 : }
255 :
256 : /* Create the queue. */
257 0 : struct rte_port_ring_reader_params reader_params = {
258 0 : .ring = tapdev->tapdev_rx_ring,
259 : };
260 0 : rx_queue->q_queue_h = rx_queue->rxq_ops.f_create(&reader_params,
261 : socket_id);
262 0 : if (rx_queue->q_queue_h == NULL)
263 0 : goto error;
264 :
265 0 : rx_queue->vring_queue_id = queue_id;
266 : /* Store queue params. */
267 0 : rx_queue_params->qp_release_op = &dpdk_tapdev_rx_queue_release;
268 0 : rx_queue_params->qp_ring.ring_p = tapdev->tapdev_rx_ring;
269 :
270 0 : return rx_queue;
271 :
272 0 : error:
273 0 : RTE_LOG(ERR, VROUTER,
274 : " error initializing tapdev %s RX queue\n", vif->vif_name);
275 0 : return NULL;
276 : }
277 :
278 : /*
279 : * dpdk_tapdev_tx_queue_release - release TAP TX queue.
280 : */
281 : static void
282 0 : dpdk_tapdev_tx_queue_release(unsigned lcore_id, unsigned queue_index,
283 : struct vr_interface *vif)
284 : {
285 0 : struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];
286 0 : struct vr_dpdk_queue *tx_queue =
287 0 : &lcore->lcore_tx_queues[vif->vif_idx][queue_index];
288 0 : struct vr_dpdk_queue_params *tx_queue_params
289 0 : = &lcore->lcore_tx_queue_params[vif->vif_idx][queue_index];
290 :
291 0 : tx_queue->txq_ops.f_tx = NULL;
292 : rte_wmb();
293 :
294 : /* Flush and free the queue. */
295 0 : if (tx_queue->txq_ops.f_free(tx_queue->q_queue_h)) {
296 0 : RTE_LOG(ERR, VROUTER, " error freeing lcore %u TAP device TX queue\n",
297 : lcore_id);
298 : }
299 :
300 : /* Reset the queue. */
301 0 : vrouter_put_interface(tx_queue->q_vif);
302 0 : memset(tx_queue, 0, sizeof(*tx_queue));
303 0 : memset(tx_queue_params, 0, sizeof(*tx_queue_params));
304 0 : }
305 :
306 : /*
307 : * vr_dpdk_tapdev_tx_queue_init - init TAP TX queue.
308 : *
309 : * Returns queue pointer on success, NULL otherwise.
310 : */
311 : struct vr_dpdk_queue *
312 0 : vr_dpdk_tapdev_tx_queue_init(unsigned lcore_id, struct vr_interface *vif,
313 : unsigned queue_id)
314 : {
315 0 : struct vr_dpdk_lcore *lcore = vr_dpdk.lcores[lcore_id];
316 0 : const unsigned socket_id = rte_lcore_to_socket_id(lcore_id);
317 0 : unsigned vif_idx = vif->vif_idx;
318 0 : struct vr_dpdk_tapdev *tapdev = vif->vif_os;
319 0 : struct vr_dpdk_queue *tx_queue = &lcore->lcore_tx_queues[vif_idx][0];
320 0 : struct vr_dpdk_queue_params *tx_queue_params
321 : = &lcore->lcore_tx_queue_params[vif_idx][0];
322 :
323 : /* Init queue. */
324 0 : tx_queue->txq_ops = rte_port_ring_writer_ops;
325 0 : tx_queue->q_queue_h = NULL;
326 0 : tx_queue->q_vif = vrouter_get_interface(vif->vif_rid, vif_idx);
327 :
328 : /* Allocate TX ring if needed. */
329 0 : if (tapdev->tapdev_tx_rings[lcore_id] == NULL) {
330 0 : tapdev->tapdev_tx_rings[lcore_id] = vr_dpdk_ring_allocate(lcore_id,
331 : "tapdev_tx_ring", vr_dpdk_tx_ring_sz,
332 : RING_F_SP_ENQ | RING_F_SC_DEQ);
333 0 : if (tapdev->tapdev_tx_rings[lcore_id] == NULL)
334 0 : goto error;
335 : }
336 :
337 : /* Create the queue. */
338 0 : struct rte_port_ring_writer_params writer_params = {
339 0 : .ring = tapdev->tapdev_tx_rings[lcore_id],
340 : .tx_burst_sz = VR_DPDK_TX_BURST_SZ,
341 : };
342 0 : tx_queue->q_queue_h = tx_queue->txq_ops.f_create(&writer_params,
343 : socket_id);
344 0 : if (tx_queue->q_queue_h == NULL)
345 0 : goto error;
346 :
347 : /* Store queue params. */
348 0 : tx_queue_params->qp_release_op = &dpdk_tapdev_tx_queue_release;
349 0 : tx_queue_params->qp_ring.ring_p = tapdev->tapdev_tx_rings[lcore_id];
350 :
351 0 : return tx_queue;
352 :
353 0 : error:
354 0 : RTE_LOG(ERR, VROUTER,
355 : " error initializing tapdev %s TX queue\n", vif->vif_name);
356 0 : return NULL;
357 : }
358 :
359 : /*
360 : * vr_dpdk_tapdev_rx_burst - RX a burst of packets from the TAP device.
361 : *
362 : * Returns number of actual packets received, or 0 otherwise.
363 : */
364 : unsigned
365 0 : vr_dpdk_tapdev_rx_burst(struct vr_dpdk_tapdev *tapdev, struct rte_mbuf **mbufs,
366 : unsigned num, int datapath)
367 : {
368 : int i, fd;
369 0 : unsigned ret = 0;
370 : struct rte_mbuf *mbuf;
371 : struct vr_interface *vif;
372 : struct vr_interface_stats *stats;
373 0 : unsigned lcore_id = rte_lcore_id();
374 : ssize_t len;
375 :
376 0 : fd = tapdev->tapdev_fd;
377 0 : if (unlikely(fd <= 0))
378 0 : return 0;
379 :
380 0 : for (i = 0; i < num; i++) {
381 0 : vif = tapdev->tapdev_vif;
382 :
383 0 : if (datapath && vif_is_vhost(vif))
384 0 : continue;
385 :
386 0 : stats = vif_get_stats(vif, lcore_id);
387 :
388 0 : mbuf = rte_pktmbuf_alloc(vr_dpdk.rss_mempool);
389 0 : if (unlikely(mbuf == NULL)) {
390 0 : stats->vis_dev_inombufs++;
391 0 : break;
392 : }
393 :
394 : /* TODO: need a separate syscall counter for devices. */
395 0 : stats->vis_port_isyscalls++;
396 0 : len = read(fd, rte_pktmbuf_mtod(mbuf, void *),
397 0 : (mbuf->buf_len - rte_pktmbuf_headroom(mbuf)));
398 0 : if (unlikely(len <= 0)) {
399 : /* No packets to receive. */
400 0 : rte_pktmbuf_free(mbuf);
401 0 : break;
402 : } else {
403 0 : ret++;
404 :
405 0 : mbuf->pkt_len = mbuf->data_len = len;
406 0 : stats->vis_dev_ibytes += len;
407 0 : stats->vis_dev_ipackets++;
408 0 : mbufs[i] = mbuf;
409 : }
410 : }
411 0 : return ret;
412 : }
413 :
414 : /*
415 : * vr_dpdk_tapdev_dequeue_burst - dequeue a burst of packets from the TAP device.
416 : *
417 : * Returns number of actual packets dequeued, or 0 otherwise.
418 : */
419 : unsigned
420 0 : vr_dpdk_tapdev_dequeue_burst(struct vr_dpdk_tapdev *tapdev, struct rte_mbuf **mbufs,
421 : unsigned num)
422 : {
423 : int fd;
424 :
425 0 : fd = tapdev->tapdev_fd;
426 0 : if (unlikely(fd <= 0))
427 0 : return 0;
428 :
429 : /* Try to RX from the TAP. */
430 0 : if (likely(tapdev->tapdev_rx_ring != NULL)) {
431 0 : return rte_ring_sc_dequeue_burst(tapdev->tapdev_rx_ring,
432 : (void **)mbufs, num, NULL);
433 : }
434 0 : return 0;
435 : }
436 :
437 : /*
438 : * vr_dpdk_tapdev_tx_burst - TX a burst of packets to the TAP device.
439 : *
440 : * Returns number of actual packets sent, or 0 otherwise.
441 : */
442 : unsigned
443 0 : vr_dpdk_tapdev_tx_burst(struct vr_dpdk_tapdev *tapdev, struct rte_mbuf **mbufs,
444 : unsigned num, int datapath)
445 : {
446 : int i, fd;
447 0 : unsigned ret = 0;
448 : struct rte_mbuf *mbuf;
449 : struct vr_interface *vif;
450 : struct vr_interface_stats *stats;
451 0 : unsigned lcore_id = rte_lcore_id();
452 : ssize_t len;
453 :
454 0 : fd = tapdev->tapdev_fd;
455 0 : if (unlikely(fd <= 0))
456 0 : return 0;
457 :
458 0 : for (i = 0; i < num; i++) {
459 0 : vif = tapdev->tapdev_vif;
460 :
461 0 : if (datapath && vif_is_vhost(vif))
462 0 : continue;
463 :
464 0 : stats = vif_get_stats(vif, lcore_id);
465 0 : mbuf = mbufs[i];
466 :
467 : /* TODO: need a separate syscall counter for devices. */
468 0 : stats->vis_port_osyscalls++;
469 0 : len = write(fd, rte_pktmbuf_mtod(mbufs[i], void *),
470 0 : rte_pktmbuf_data_len(mbuf));
471 0 : if (unlikely(len != (ssize_t)rte_pktmbuf_data_len(mbufs[i]))) {
472 : /* Error sending packet. */
473 0 : stats->vis_dev_oerrors++;
474 0 : break;
475 : } else {
476 0 : stats->vis_dev_obytes += len;
477 0 : stats->vis_dev_opackets++;
478 0 : ret++;
479 : }
480 0 : rte_pktmbuf_free(mbuf);
481 : }
482 :
483 0 : return ret;
484 : }
485 :
486 : /*
487 : * vr_dpdk_tapdev_enqueue_burst - enqueue a burst of packets to the TAP device.
488 : *
489 : * Returns number of actual packets enqueued, or 0 otherwise.
490 : */
491 : unsigned
492 0 : vr_dpdk_tapdev_enqueue_burst(struct vr_dpdk_tapdev *tapdev, struct rte_mbuf **mbufs,
493 : unsigned num)
494 : {
495 : int fd;
496 0 : unsigned lcore_id = rte_lcore_id();
497 :
498 0 : fd = tapdev->tapdev_fd;
499 0 : if (unlikely(fd <= 0))
500 0 : return 0;
501 :
502 0 : if (likely(tapdev->tapdev_tx_rings[lcore_id] != NULL)) {
503 0 : return rte_ring_sp_enqueue_burst(tapdev->tapdev_tx_rings[lcore_id],
504 : (void **)mbufs, num, NULL);
505 : }
506 :
507 0 : return 0;
508 : }
509 :
510 : /*
511 : * vr_dpdk_tapdev_rxtx -- RX/TX to/from all the TAP devices.
512 : *
513 : * Returns total number of packets processed.
514 : */
515 : uint64_t
516 2825387 : vr_dpdk_tapdev_rxtx(void)
517 : {
518 : int i, fd;
519 : struct vr_dpdk_tapdev *tapdev;
520 : struct rte_mbuf *mbuf;
521 : struct vr_interface *vif;
522 : struct vr_interface_stats *stats;
523 : unsigned lcore_id;
524 2825387 : uint64_t total_pkts = 0;
525 : unsigned nb_pkts;
526 :
527 48031579 : for (i = 0; i < VR_DPDK_MAX_TAP_INTERFACES; i++) {
528 45206192 : tapdev = &vr_dpdk.tapdevs[i];
529 :
530 45206192 : fd = tapdev->tapdev_fd;
531 45206192 : if (fd > 0) {
532 0 : vif = tapdev->tapdev_vif;
533 0 : stats = vif_get_stats(vif, rte_lcore_id());
534 :
535 : /* Try to RX from the TAP. */
536 0 : if (likely(tapdev->tapdev_rx_ring != NULL)) {
537 0 : nb_pkts = vr_dpdk_tapdev_rx_burst(tapdev, &mbuf, 1,
538 : VR_DPDK_MGMTPATH);
539 :
540 0 : if (likely(nb_pkts > 0)) {
541 0 : total_pkts++;
542 0 : if (unlikely(rte_ring_sp_enqueue(tapdev->tapdev_rx_ring,
543 : mbuf) != 0)) {
544 0 : rte_pktmbuf_free(mbuf);
545 0 : stats->vis_dev_ierrors++;
546 : }
547 : }
548 : }
549 :
550 : /* Now try to TX to the TAP. */
551 0 : RTE_LCORE_FOREACH(lcore_id) {
552 0 : if (likely(tapdev->tapdev_tx_rings[lcore_id] != NULL)) {
553 0 : if (likely(rte_ring_sc_dequeue(
554 : tapdev->tapdev_tx_rings[lcore_id],
555 : (void **)&mbuf) == 0))
556 : {
557 0 : total_pkts++;
558 0 : nb_pkts = vr_dpdk_tapdev_tx_burst(tapdev, &mbuf, 1,
559 : VR_DPDK_MGMTPATH);
560 :
561 0 : if (likely(nb_pkts > 0)) {
562 0 : total_pkts++;
563 : } else {
564 0 : rte_pktmbuf_free(mbuf);
565 : }
566 : }
567 : } /* if TAP TX ring. */
568 : } /* for each lcore. */
569 : } /* if TAP FD. */
570 : } /* for all TAP devices. */
571 :
572 2825387 : return total_pkts;
573 : }
574 :
575 0 : static void vr_dpdk_handle_vhost0_notification(uint32_t mtu, uint32_t if_up)
576 : {
577 : static int vhost_mtu = 1500; /* Default MTU */
578 :
579 : struct vr_interface *vif;
580 0 : struct vrouter *router = vrouter_get(0);
581 0 : struct vr_dpdk_ethdev *ethdev = NULL;
582 0 : uint8_t slave_port_id, port_id = 0;
583 0 : int ret = 0, i;
584 :
585 0 : if (router->vr_eth_if[0])
586 0 : ethdev = (struct vr_dpdk_ethdev *)router->vr_eth_if[0]->vif_os;
587 :
588 0 : if (ethdev == NULL) {
589 0 : RTE_LOG(ERR, VROUTER, "%s error: NULL ethdev\n", __func__);
590 0 : return;
591 : }
592 :
593 0 : port_id = ethdev->ethdev_port_id;
594 :
595 0 : if (vhost_mtu != mtu) {
596 : /*
597 : * TODO: DPDK bond PMD does not implement mtu_set op, so we need to
598 : * set the MTU manually for all the slaves.
599 : */
600 0 : if (ethdev->ethdev_nb_slaves > 0) {
601 0 : RTE_LOG(INFO, VROUTER, "Changing bond eth device %" PRIu8 " MTU\n", port_id);
602 :
603 0 : rte_eth_devices[port_id].data->mtu = mtu;
604 0 : for (i = 0; i < ethdev->ethdev_nb_slaves; i++) {
605 0 : slave_port_id = ethdev->ethdev_slaves[i];
606 0 : RTE_LOG(INFO, VROUTER,
607 : " changing bond member eth device %" PRIu8 " MTU to %u\n",
608 : slave_port_id, mtu);
609 :
610 0 : ret = rte_eth_dev_set_mtu(slave_port_id, mtu);
611 0 : if (ret < 0) {
612 : /*
613 : * Do not return error as some NICs (such as X710) do not allow setting
614 : * the MTU while the NIC is up and running. The max_rx_pkt_len is anyway
615 : * set to support jumbo frames, so continue further here to set vif_mtu.
616 : */
617 0 : RTE_LOG(DEBUG, VROUTER,
618 : " error changing bond member eth device %" PRIu8 " MTU: %s (%d)\n",
619 : slave_port_id, rte_strerror(-ret), -ret);
620 : }
621 : }
622 : } else {
623 0 : RTE_LOG(INFO, VROUTER, "Changing eth device MTU to %u\n", mtu);
624 :
625 0 : rte_eth_devices[port_id].data->mtu = mtu;
626 0 : ret = rte_eth_dev_set_mtu(port_id, mtu);
627 0 : if (ret < 0) {
628 : /*
629 : * Do not return error as some NICs (such as X710) do not allow setting
630 : * the MTU while the NIC is up and running. The max_rx_pkt_len is anyway
631 : * set to support jumbo frames, so continue further here to set vif_mtu.
632 : */
633 0 : RTE_LOG(DEBUG, VROUTER,
634 : "Error changing eth device MTU: %s (%d)\n",
635 : rte_strerror(-ret), -ret);
636 : }
637 : }
638 :
639 : /* On success, inform vrouter about new MTU */
640 0 : for (i = 0; i < router->vr_max_interfaces; i++) {
641 0 : vif = __vrouter_get_interface(router, i);
642 0 : if (vif && (vif->vif_type == VIF_TYPE_PHYSICAL)) {
643 : /* Ethernet header size */
644 0 : mtu += sizeof(struct vr_eth);
645 0 : if (vr_dpdk.vlan_tag != VLAN_ID_INVALID) {
646 : /* 802.1q header size */
647 0 : mtu += sizeof(uint32_t);
648 : }
649 0 : vif->vif_mtu = mtu;
650 0 : if (vif->vif_bridge[0])
651 0 : vif->vif_bridge[0]->vif_mtu = mtu;
652 : }
653 : }
654 :
655 : /* Save the new MTU */
656 0 : vhost_mtu = mtu;
657 : }
658 :
659 : }
660 :
661 2825387 : void vr_dpdk_tapdev_handle_notifications(void)
662 : {
663 : int32_t status;
664 : char buf[4096];
665 2825387 : struct iovec iov = {buf, sizeof buf};
666 : struct sockaddr_nl snl;
667 2825387 : struct msghdr msg = {(void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
668 : struct nlmsghdr *h;
669 : struct ifinfomsg *ifi;
670 :
671 2825387 : status = recvmsg(vr_dpdk.tap_nl_fd, &msg, MSG_DONTWAIT);
672 2825387 : if (status <= 0) {
673 : /* Nothing to process */
674 2825387 : return;
675 : }
676 :
677 0 : for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
678 0 : h = NLMSG_NEXT (h, status))
679 : {
680 : /* Finish reading */
681 0 : if (h->nlmsg_type == NLMSG_DONE)
682 0 : return;
683 :
684 : /* Message is some kind of error */
685 0 : if (h->nlmsg_type == NLMSG_ERROR) {
686 0 : RTE_LOG(ERR, VROUTER, "read_netlink: Message error\n");
687 0 : return; /* Error */
688 : }
689 :
690 0 : if (h->nlmsg_type == RTM_NEWLINK) {
691 : int len;
692 : struct rtattr *attribute;
693 0 : char *ifname = NULL;
694 0 : uint32_t mtu = 0;
695 :
696 0 : ifi = NLMSG_DATA (h);
697 :
698 0 : len = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
699 :
700 : /* loop over all attributes for the NEWLINK message */
701 0 : for (attribute = IFLA_RTA(ifi); RTA_OK(attribute, len);
702 0 : attribute = RTA_NEXT(attribute, len))
703 : {
704 0 : switch(attribute->rta_type) {
705 0 : case IFLA_IFNAME:
706 0 : ifname = (char*) RTA_DATA(attribute);
707 0 : break;
708 0 : case IFLA_MTU:
709 0 : mtu = *(uint32_t*) RTA_DATA(attribute);
710 0 : break;
711 0 : default:
712 0 : break;
713 : }
714 : }
715 :
716 0 : if (ifname && (strncmp(ifname, VHOST_IFNAME, (strlen(VHOST_IFNAME) + 1)) == 0)) {
717 0 : RTE_LOG(INFO, VROUTER, "Notification received for vhost0\n");
718 0 : vr_dpdk_handle_vhost0_notification
719 0 : (mtu, (ifi->ifi_flags & IFF_UP));
720 : }
721 : }
722 : }
723 : }
|