netdev-dpdk: Make memory pool name contain the socket id.
[cascardo/ovs.git] / lib / netdev-dpdk.c
1 /*
2  * Copyright (c) 2014 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <pthread.h>
24 #include <config.h>
25 #include <errno.h>
26 #include <sched.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <stdio.h>
30
31 #include "dpif-netdev.h"
32 #include "list.h"
33 #include "netdev-dpdk.h"
34 #include "netdev-provider.h"
35 #include "netdev-vport.h"
36 #include "odp-util.h"
37 #include "ofp-print.h"
38 #include "ofpbuf.h"
39 #include "ovs-thread.h"
40 #include "ovs-rcu.h"
41 #include "packet-dpif.h"
42 #include "packets.h"
43 #include "shash.h"
44 #include "sset.h"
45 #include "unaligned.h"
46 #include "timeval.h"
47 #include "unixctl.h"
48 #include "vlog.h"
49
50 VLOG_DEFINE_THIS_MODULE(dpdk);
51 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
52
53 #define DPDK_PORT_WATCHDOG_INTERVAL 5
54
55 #define OVS_CACHE_LINE_SIZE CACHE_LINE_SIZE
56 #define OVS_VPORT_DPDK "ovs_dpdk"
57
58 /*
59  * need to reserve tons of extra space in the mbufs so we can align the
60  * DMA addresses to 4KB.
61  */
62
63 #define MTU_TO_MAX_LEN(mtu)  ((mtu) + ETHER_HDR_LEN + ETHER_CRC_LEN)
64 #define MBUF_SIZE(mtu)       (MTU_TO_MAX_LEN(mtu) + (512) + \
65                              sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
66
67 /* XXX: mempool size should be based on system resources. */
68 #define NB_MBUF              (4096 * 64)
69 #define MP_CACHE_SZ          (256 * 2)
70 #define SOCKET0              0
71
72 #define NON_PMD_THREAD_TX_QUEUE 0
73
74 #define NIC_PORT_RX_Q_SIZE 2048  /* Size of Physical NIC RX Queue, Max (n+32<=4096)*/
75 #define NIC_PORT_TX_Q_SIZE 2048  /* Size of Physical NIC TX Queue, Max (n+32<=4096)*/
76
77 /* XXX: Needs per NIC value for these constants. */
78 #define RX_PTHRESH 32 /* Default values of RX prefetch threshold reg. */
79 #define RX_HTHRESH 32 /* Default values of RX host threshold reg. */
80 #define RX_WTHRESH 16 /* Default values of RX write-back threshold reg. */
81
82 #define TX_PTHRESH 36 /* Default values of TX prefetch threshold reg. */
83 #define TX_HTHRESH 0  /* Default values of TX host threshold reg. */
84 #define TX_WTHRESH 0  /* Default values of TX write-back threshold reg. */
85
86 static const struct rte_eth_conf port_conf = {
87     .rxmode = {
88         .mq_mode = ETH_MQ_RX_RSS,
89         .split_hdr_size = 0,
90         .header_split   = 0, /* Header Split disabled */
91         .hw_ip_checksum = 0, /* IP checksum offload disabled */
92         .hw_vlan_filter = 0, /* VLAN filtering disabled */
93         .jumbo_frame    = 0, /* Jumbo Frame Support disabled */
94         .hw_strip_crc   = 0,
95     },
96     .rx_adv_conf = {
97         .rss_conf = {
98             .rss_key = NULL,
99             .rss_hf = ETH_RSS_IPV4_TCP | ETH_RSS_IPV4 | ETH_RSS_IPV6
100                     | ETH_RSS_IPV4_UDP | ETH_RSS_IPV6_TCP | ETH_RSS_IPV6_UDP,
101         },
102     },
103     .txmode = {
104         .mq_mode = ETH_MQ_TX_NONE,
105     },
106 };
107
108 static const struct rte_eth_rxconf rx_conf = {
109     .rx_thresh = {
110         .pthresh = RX_PTHRESH,
111         .hthresh = RX_HTHRESH,
112         .wthresh = RX_WTHRESH,
113     },
114 };
115
116 static const struct rte_eth_txconf tx_conf = {
117     .tx_thresh = {
118         .pthresh = TX_PTHRESH,
119         .hthresh = TX_HTHRESH,
120         .wthresh = TX_WTHRESH,
121     },
122     .tx_free_thresh = 0,
123     .tx_rs_thresh = 0,
124     .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS|ETH_TXQ_FLAGS_NOOFFLOADS,
125 };
126
127 enum { MAX_RX_QUEUE_LEN = 192 };
128 enum { MAX_TX_QUEUE_LEN = 384 };
129 enum { DPDK_RING_SIZE = 256 };
130 BUILD_ASSERT_DECL(IS_POW2(DPDK_RING_SIZE));
131 enum { DRAIN_TSC = 200000ULL };
132
133 static int rte_eal_init_ret = ENODEV;
134
135 static struct ovs_mutex dpdk_mutex = OVS_MUTEX_INITIALIZER;
136
137 /* Contains all 'struct dpdk_dev's. */
138 static struct list dpdk_list OVS_GUARDED_BY(dpdk_mutex)
139     = LIST_INITIALIZER(&dpdk_list);
140
141 static struct list dpdk_mp_list OVS_GUARDED_BY(dpdk_mutex)
142     = LIST_INITIALIZER(&dpdk_mp_list);
143
144 /* This mutex must be used by non pmd threads when allocating or freeing
145  * mbufs through mempools. Since dpdk_queue_pkts() and dpdk_queue_flush() may
146  * use mempools, a non pmd thread should hold this mutex while calling them */
147 struct ovs_mutex nonpmd_mempool_mutex = OVS_MUTEX_INITIALIZER;
148
149 struct dpdk_mp {
150     struct rte_mempool *mp;
151     int mtu;
152     int socket_id;
153     int refcount;
154     struct list list_node OVS_GUARDED_BY(dpdk_mutex);
155 };
156
157 struct dpdk_tx_queue {
158     rte_spinlock_t tx_lock;
159     int count;
160     uint64_t tsc;
161     struct rte_mbuf *burst_pkts[MAX_TX_QUEUE_LEN];
162 };
163
164 /* dpdk has no way to remove dpdk ring ethernet devices
165    so we have to keep them around once they've been created
166 */
167
168 static struct list dpdk_ring_list OVS_GUARDED_BY(dpdk_mutex)
169     = LIST_INITIALIZER(&dpdk_ring_list);
170
171 struct dpdk_ring {
172     /* For the client rings */
173     struct rte_ring *cring_tx;
174     struct rte_ring *cring_rx;
175     int user_port_id; /* User given port no, parsed from port name */
176     int eth_port_id; /* ethernet device port id */
177     struct list list_node OVS_GUARDED_BY(dpdk_mutex);
178 };
179
180 struct netdev_dpdk {
181     struct netdev up;
182     int port_id;
183     int max_packet_len;
184
185     struct dpdk_tx_queue tx_q[NR_QUEUE];
186
187     struct ovs_mutex mutex OVS_ACQ_AFTER(dpdk_mutex);
188
189     struct dpdk_mp *dpdk_mp;
190     int mtu;
191     int socket_id;
192     int buf_size;
193     struct netdev_stats stats_offset;
194     struct netdev_stats stats;
195
196     uint8_t hwaddr[ETH_ADDR_LEN];
197     enum netdev_flags flags;
198
199     struct rte_eth_link link;
200     int link_reset_cnt;
201
202     /* In dpdk_list. */
203     struct list list_node OVS_GUARDED_BY(dpdk_mutex);
204 };
205
206 struct netdev_rxq_dpdk {
207     struct netdev_rxq up;
208     int port_id;
209 };
210
211 static bool thread_is_pmd(void);
212
213 static int netdev_dpdk_construct(struct netdev *);
214
215 static bool
216 is_dpdk_class(const struct netdev_class *class)
217 {
218     return class->construct == netdev_dpdk_construct;
219 }
220
221 /* XXX: use dpdk malloc for entire OVS. infact huge page shld be used
222  * for all other sengments data, bss and text. */
223
224 static void *
225 dpdk_rte_mzalloc(size_t sz)
226 {
227     void *ptr;
228
229     ptr = rte_zmalloc(OVS_VPORT_DPDK, sz, OVS_CACHE_LINE_SIZE);
230     if (ptr == NULL) {
231         out_of_memory();
232     }
233     return ptr;
234 }
235
236 /* XXX this function should be called only by pmd threads (or by non pmd
237  * threads holding the nonpmd_mempool_mutex) */
238 void
239 free_dpdk_buf(struct dpif_packet *p)
240 {
241     struct rte_mbuf *pkt = (struct rte_mbuf *) p;
242
243     rte_pktmbuf_free_seg(pkt);
244 }
245
246 static void
247 __rte_pktmbuf_init(struct rte_mempool *mp,
248                    void *opaque_arg OVS_UNUSED,
249                    void *_m,
250                    unsigned i OVS_UNUSED)
251 {
252     struct rte_mbuf *m = _m;
253     uint32_t buf_len = mp->elt_size - sizeof(struct dpif_packet);
254
255     RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct dpif_packet));
256
257     memset(m, 0, mp->elt_size);
258
259     /* start of buffer is just after mbuf structure */
260     m->buf_addr = (char *)m + sizeof(struct dpif_packet);
261     m->buf_physaddr = rte_mempool_virt2phy(mp, m) +
262                     sizeof(struct dpif_packet);
263     m->buf_len = (uint16_t)buf_len;
264
265     /* keep some headroom between start of buffer and data */
266     m->pkt.data = (char*) m->buf_addr + RTE_MIN(RTE_PKTMBUF_HEADROOM, m->buf_len);
267
268     /* init some constant fields */
269     m->type = RTE_MBUF_PKT;
270     m->pool = mp;
271     m->pkt.nb_segs = 1;
272     m->pkt.in_port = 0xff;
273 }
274
275 static void
276 ovs_rte_pktmbuf_init(struct rte_mempool *mp,
277                      void *opaque_arg OVS_UNUSED,
278                      void *_m,
279                      unsigned i OVS_UNUSED)
280 {
281     struct rte_mbuf *m = _m;
282
283     __rte_pktmbuf_init(mp, opaque_arg, _m, i);
284
285     ofpbuf_init_dpdk((struct ofpbuf *) m, m->buf_len);
286 }
287
288 static struct dpdk_mp *
289 dpdk_mp_get(int socket_id, int mtu) OVS_REQUIRES(dpdk_mutex)
290 {
291     struct dpdk_mp *dmp = NULL;
292     char mp_name[RTE_MEMPOOL_NAMESIZE];
293
294     LIST_FOR_EACH (dmp, list_node, &dpdk_mp_list) {
295         if (dmp->socket_id == socket_id && dmp->mtu == mtu) {
296             dmp->refcount++;
297             return dmp;
298         }
299     }
300
301     dmp = dpdk_rte_mzalloc(sizeof *dmp);
302     dmp->socket_id = socket_id;
303     dmp->mtu = mtu;
304     dmp->refcount = 1;
305
306     if (snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, "ovs_mp_%d_%d", dmp->mtu,
307                  dmp->socket_id) < 0) {
308         return NULL;
309     }
310
311     dmp->mp = rte_mempool_create(mp_name, NB_MBUF, MBUF_SIZE(mtu),
312                                  MP_CACHE_SZ,
313                                  sizeof(struct rte_pktmbuf_pool_private),
314                                  rte_pktmbuf_pool_init, NULL,
315                                  ovs_rte_pktmbuf_init, NULL,
316                                  socket_id, 0);
317
318     if (dmp->mp == NULL) {
319         return NULL;
320     }
321
322     list_push_back(&dpdk_mp_list, &dmp->list_node);
323     return dmp;
324 }
325
326 static void
327 dpdk_mp_put(struct dpdk_mp *dmp)
328 {
329
330     if (!dmp) {
331         return;
332     }
333
334     dmp->refcount--;
335     ovs_assert(dmp->refcount >= 0);
336
337 #if 0
338     /* I could not find any API to destroy mp. */
339     if (dmp->refcount == 0) {
340         list_delete(dmp->list_node);
341         /* destroy mp-pool. */
342     }
343 #endif
344 }
345
346 static void
347 check_link_status(struct netdev_dpdk *dev)
348 {
349     struct rte_eth_link link;
350
351     rte_eth_link_get_nowait(dev->port_id, &link);
352
353     if (dev->link.link_status != link.link_status) {
354         netdev_change_seq_changed(&dev->up);
355
356         dev->link_reset_cnt++;
357         dev->link = link;
358         if (dev->link.link_status) {
359             VLOG_DBG_RL(&rl, "Port %d Link Up - speed %u Mbps - %s",
360                         dev->port_id, (unsigned)dev->link.link_speed,
361                         (dev->link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
362                          ("full-duplex") : ("half-duplex"));
363         } else {
364             VLOG_DBG_RL(&rl, "Port %d Link Down", dev->port_id);
365         }
366     }
367 }
368
369 static void *
370 dpdk_watchdog(void *dummy OVS_UNUSED)
371 {
372     struct netdev_dpdk *dev;
373
374     pthread_detach(pthread_self());
375
376     for (;;) {
377         ovs_mutex_lock(&dpdk_mutex);
378         LIST_FOR_EACH (dev, list_node, &dpdk_list) {
379             ovs_mutex_lock(&dev->mutex);
380             check_link_status(dev);
381             ovs_mutex_unlock(&dev->mutex);
382         }
383         ovs_mutex_unlock(&dpdk_mutex);
384         xsleep(DPDK_PORT_WATCHDOG_INTERVAL);
385     }
386
387     return NULL;
388 }
389
390 static int
391 dpdk_eth_dev_init(struct netdev_dpdk *dev) OVS_REQUIRES(dpdk_mutex)
392 {
393     struct rte_pktmbuf_pool_private *mbp_priv;
394     struct ether_addr eth_addr;
395     int diag;
396     int i;
397
398     if (dev->port_id < 0 || dev->port_id >= rte_eth_dev_count()) {
399         return ENODEV;
400     }
401
402     diag = rte_eth_dev_configure(dev->port_id, NR_QUEUE, NR_QUEUE,  &port_conf);
403     if (diag) {
404         VLOG_ERR("eth dev config error %d",diag);
405         return -diag;
406     }
407
408     for (i = 0; i < NR_QUEUE; i++) {
409         diag = rte_eth_tx_queue_setup(dev->port_id, i, NIC_PORT_TX_Q_SIZE,
410                                       dev->socket_id, &tx_conf);
411         if (diag) {
412             VLOG_ERR("eth dev tx queue setup error %d",diag);
413             return -diag;
414         }
415     }
416
417     for (i = 0; i < NR_QUEUE; i++) {
418         diag = rte_eth_rx_queue_setup(dev->port_id, i, NIC_PORT_RX_Q_SIZE,
419                                       dev->socket_id,
420                                       &rx_conf, dev->dpdk_mp->mp);
421         if (diag) {
422             VLOG_ERR("eth dev rx queue setup error %d",diag);
423             return -diag;
424         }
425     }
426
427     diag = rte_eth_dev_start(dev->port_id);
428     if (diag) {
429         VLOG_ERR("eth dev start error %d",diag);
430         return -diag;
431     }
432
433     rte_eth_promiscuous_enable(dev->port_id);
434     rte_eth_allmulticast_enable(dev->port_id);
435
436     memset(&eth_addr, 0x0, sizeof(eth_addr));
437     rte_eth_macaddr_get(dev->port_id, &eth_addr);
438     VLOG_INFO_RL(&rl, "Port %d: "ETH_ADDR_FMT"",
439                     dev->port_id, ETH_ADDR_ARGS(eth_addr.addr_bytes));
440
441     memcpy(dev->hwaddr, eth_addr.addr_bytes, ETH_ADDR_LEN);
442     rte_eth_link_get_nowait(dev->port_id, &dev->link);
443
444     mbp_priv = rte_mempool_get_priv(dev->dpdk_mp->mp);
445     dev->buf_size = mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM;
446
447     dev->flags = NETDEV_UP | NETDEV_PROMISC;
448     return 0;
449 }
450
451 static struct netdev_dpdk *
452 netdev_dpdk_cast(const struct netdev *netdev)
453 {
454     return CONTAINER_OF(netdev, struct netdev_dpdk, up);
455 }
456
457 static struct netdev *
458 netdev_dpdk_alloc(void)
459 {
460     struct netdev_dpdk *netdev = dpdk_rte_mzalloc(sizeof *netdev);
461     return &netdev->up;
462 }
463
464 static int
465 netdev_dpdk_init(struct netdev *netdev_, unsigned int port_no) OVS_REQUIRES(dpdk_mutex)
466 {
467     struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
468     int err = 0;
469     int i;
470
471     ovs_mutex_init(&netdev->mutex);
472
473     ovs_mutex_lock(&netdev->mutex);
474
475     for (i = 0; i < NR_QUEUE; i++) {
476         rte_spinlock_init(&netdev->tx_q[i].tx_lock);
477     }
478
479     netdev->port_id = port_no;
480
481     netdev->flags = 0;
482     netdev->mtu = ETHER_MTU;
483     netdev->max_packet_len = MTU_TO_MAX_LEN(netdev->mtu);
484
485     /* XXX: need to discover device node at run time. */
486     netdev->socket_id = SOCKET0;
487
488     netdev->dpdk_mp = dpdk_mp_get(netdev->socket_id, netdev->mtu);
489     if (!netdev->dpdk_mp) {
490         err = ENOMEM;
491         goto unlock;
492     }
493
494     err = dpdk_eth_dev_init(netdev);
495     if (err) {
496         goto unlock;
497     }
498     netdev_->n_rxq = NR_QUEUE;
499
500     list_push_back(&dpdk_list, &netdev->list_node);
501
502 unlock:
503     ovs_mutex_unlock(&netdev->mutex);
504     return err;
505 }
506
507 static int
508 dpdk_dev_parse_name(const char dev_name[], const char prefix[],
509                     unsigned int *port_no)
510 {
511     const char *cport;
512
513     if (strncmp(dev_name, prefix, strlen(prefix))) {
514         return ENODEV;
515     }
516
517     cport = dev_name + strlen(prefix);
518     *port_no = strtol(cport, 0, 0); /* string must be null terminated */
519     return 0;
520 }
521
522 static int
523 netdev_dpdk_construct(struct netdev *netdev)
524 {
525     unsigned int port_no;
526     int err;
527
528     if (rte_eal_init_ret) {
529         return rte_eal_init_ret;
530     }
531
532     /* Names always start with "dpdk" */
533     err = dpdk_dev_parse_name(netdev->name, "dpdk", &port_no);
534     if (err) {
535         return err;
536     }
537
538     ovs_mutex_lock(&dpdk_mutex);
539     err = netdev_dpdk_init(netdev, port_no);
540     ovs_mutex_unlock(&dpdk_mutex);
541     return err;
542 }
543
544 static void
545 netdev_dpdk_destruct(struct netdev *netdev_)
546 {
547     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
548
549     ovs_mutex_lock(&dev->mutex);
550     rte_eth_dev_stop(dev->port_id);
551     ovs_mutex_unlock(&dev->mutex);
552
553     ovs_mutex_lock(&dpdk_mutex);
554     list_remove(&dev->list_node);
555     dpdk_mp_put(dev->dpdk_mp);
556     ovs_mutex_unlock(&dpdk_mutex);
557
558     ovs_mutex_destroy(&dev->mutex);
559 }
560
561 static void
562 netdev_dpdk_dealloc(struct netdev *netdev_)
563 {
564     struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
565
566     rte_free(netdev);
567 }
568
569 static int
570 netdev_dpdk_get_config(const struct netdev *netdev_, struct smap *args)
571 {
572     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
573
574     ovs_mutex_lock(&dev->mutex);
575
576     /* XXX: Allow to configure number of queues. */
577     smap_add_format(args, "configured_rx_queues", "%u", netdev_->n_rxq);
578     smap_add_format(args, "configured_tx_queues", "%u", netdev_->n_rxq);
579     ovs_mutex_unlock(&dev->mutex);
580
581     return 0;
582 }
583
584 static struct netdev_rxq *
585 netdev_dpdk_rxq_alloc(void)
586 {
587     struct netdev_rxq_dpdk *rx = dpdk_rte_mzalloc(sizeof *rx);
588
589     return &rx->up;
590 }
591
592 static struct netdev_rxq_dpdk *
593 netdev_rxq_dpdk_cast(const struct netdev_rxq *rx)
594 {
595     return CONTAINER_OF(rx, struct netdev_rxq_dpdk, up);
596 }
597
598 static int
599 netdev_dpdk_rxq_construct(struct netdev_rxq *rxq_)
600 {
601     struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq_);
602     struct netdev_dpdk *netdev = netdev_dpdk_cast(rx->up.netdev);
603
604     ovs_mutex_lock(&netdev->mutex);
605     rx->port_id = netdev->port_id;
606     ovs_mutex_unlock(&netdev->mutex);
607
608     return 0;
609 }
610
611 static void
612 netdev_dpdk_rxq_destruct(struct netdev_rxq *rxq_ OVS_UNUSED)
613 {
614 }
615
616 static void
617 netdev_dpdk_rxq_dealloc(struct netdev_rxq *rxq_)
618 {
619     struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq_);
620
621     rte_free(rx);
622 }
623
624 static inline void
625 dpdk_queue_flush__(struct netdev_dpdk *dev, int qid)
626 {
627     struct dpdk_tx_queue *txq = &dev->tx_q[qid];
628     uint32_t nb_tx = 0;
629
630     while (nb_tx != txq->count) {
631         uint32_t ret;
632
633         ret = rte_eth_tx_burst(dev->port_id, qid, txq->burst_pkts + nb_tx,
634                                txq->count - nb_tx);
635         if (!ret) {
636             break;
637         }
638
639         nb_tx += ret;
640     }
641
642     if (OVS_UNLIKELY(nb_tx != txq->count)) {
643         /* free buffers, which we couldn't transmit, one at a time (each
644          * packet could come from a different mempool) */
645         int i;
646
647         for (i = nb_tx; i < txq->count; i++) {
648             rte_pktmbuf_free_seg(txq->burst_pkts[i]);
649         }
650         ovs_mutex_lock(&dev->mutex);
651         dev->stats.tx_dropped += txq->count-nb_tx;
652         ovs_mutex_unlock(&dev->mutex);
653     }
654
655     txq->count = 0;
656     txq->tsc = rte_get_timer_cycles();
657 }
658
659 static inline void
660 dpdk_queue_flush(struct netdev_dpdk *dev, int qid)
661 {
662     struct dpdk_tx_queue *txq = &dev->tx_q[qid];
663
664     if (txq->count == 0) {
665         return;
666     }
667     rte_spinlock_lock(&txq->tx_lock);
668     dpdk_queue_flush__(dev, qid);
669     rte_spinlock_unlock(&txq->tx_lock);
670 }
671
672 static int
673 netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **packets,
674                      int *c)
675 {
676     struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq_);
677     struct netdev *netdev = rx->up.netdev;
678     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
679     int nb_rx;
680
681     dpdk_queue_flush(dev, rxq_->queue_id);
682
683     nb_rx = rte_eth_rx_burst(rx->port_id, rxq_->queue_id,
684                              (struct rte_mbuf **) packets,
685                              MIN((int)NETDEV_MAX_RX_BATCH,
686                                  (int)MAX_RX_QUEUE_LEN));
687     if (!nb_rx) {
688         return EAGAIN;
689     }
690
691     *c = nb_rx;
692
693     return 0;
694 }
695
696 inline static void
697 dpdk_queue_pkts(struct netdev_dpdk *dev, int qid,
698                struct rte_mbuf **pkts, int cnt)
699 {
700     struct dpdk_tx_queue *txq = &dev->tx_q[qid];
701     uint64_t diff_tsc;
702
703     int i = 0;
704
705     rte_spinlock_lock(&txq->tx_lock);
706     while (i < cnt) {
707         int freeslots = MAX_TX_QUEUE_LEN - txq->count;
708         int tocopy = MIN(freeslots, cnt-i);
709
710         memcpy(&txq->burst_pkts[txq->count], &pkts[i],
711                tocopy * sizeof (struct rte_mbuf *));
712
713         txq->count += tocopy;
714         i += tocopy;
715
716         if (txq->count == MAX_TX_QUEUE_LEN) {
717             dpdk_queue_flush__(dev, qid);
718         }
719         diff_tsc = rte_get_timer_cycles() - txq->tsc;
720         if (diff_tsc >= DRAIN_TSC) {
721             dpdk_queue_flush__(dev, qid);
722         }
723     }
724     rte_spinlock_unlock(&txq->tx_lock);
725 }
726
727 /* Tx function. Transmit packets indefinitely */
728 static void
729 dpdk_do_tx_copy(struct netdev *netdev, struct dpif_packet ** pkts, int cnt)
730     OVS_NO_THREAD_SAFETY_ANALYSIS
731 {
732     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
733     struct rte_mbuf *mbufs[cnt];
734     int dropped = 0;
735     int newcnt = 0;
736     int i;
737
738     /* If we are on a non pmd thread we have to use the mempool mutex, because
739      * every non pmd thread shares the same mempool cache */
740
741     if (!thread_is_pmd()) {
742         ovs_mutex_lock(&nonpmd_mempool_mutex);
743     }
744
745     for (i = 0; i < cnt; i++) {
746         int size = ofpbuf_size(&pkts[i]->ofpbuf);
747
748         if (OVS_UNLIKELY(size > dev->max_packet_len)) {
749             VLOG_WARN_RL(&rl, "Too big size %d max_packet_len %d",
750                          (int)size , dev->max_packet_len);
751
752             dropped++;
753             continue;
754         }
755
756         mbufs[newcnt] = rte_pktmbuf_alloc(dev->dpdk_mp->mp);
757
758         if (!mbufs[newcnt]) {
759             dropped += cnt - i;
760             break;
761         }
762
763         /* We have to do a copy for now */
764         memcpy(mbufs[newcnt]->pkt.data, ofpbuf_data(&pkts[i]->ofpbuf), size);
765
766         rte_pktmbuf_data_len(mbufs[newcnt]) = size;
767         rte_pktmbuf_pkt_len(mbufs[newcnt]) = size;
768
769         newcnt++;
770     }
771
772     if (OVS_UNLIKELY(dropped)) {
773         ovs_mutex_lock(&dev->mutex);
774         dev->stats.tx_dropped += dropped;
775         ovs_mutex_unlock(&dev->mutex);
776     }
777
778     dpdk_queue_pkts(dev, NON_PMD_THREAD_TX_QUEUE, mbufs, newcnt);
779     dpdk_queue_flush(dev, NON_PMD_THREAD_TX_QUEUE);
780
781     if (!thread_is_pmd()) {
782         ovs_mutex_unlock(&nonpmd_mempool_mutex);
783     }
784 }
785
786 static int
787 netdev_dpdk_send(struct netdev *netdev, struct dpif_packet **pkts, int cnt,
788                  bool may_steal)
789 {
790     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
791     int ret;
792     int i;
793
794     if (!may_steal || pkts[0]->ofpbuf.source != OFPBUF_DPDK) {
795         dpdk_do_tx_copy(netdev, pkts, cnt);
796
797         if (may_steal) {
798             for (i = 0; i < cnt; i++) {
799                 dpif_packet_delete(pkts[i]);
800             }
801         }
802     } else {
803         int qid;
804         int next_tx_idx = 0;
805         int dropped = 0;
806
807         qid = rte_lcore_id() % NR_QUEUE;
808
809         for (i = 0; i < cnt; i++) {
810             int size = ofpbuf_size(&pkts[i]->ofpbuf);
811             if (OVS_UNLIKELY(size > dev->max_packet_len)) {
812                 if (next_tx_idx != i) {
813                     dpdk_queue_pkts(dev, qid,
814                                     (struct rte_mbuf **)&pkts[next_tx_idx],
815                                     i-next_tx_idx);
816                 }
817
818                 VLOG_WARN_RL(&rl, "Too big size %d max_packet_len %d",
819                              (int)size , dev->max_packet_len);
820
821                 dpif_packet_delete(pkts[i]);
822                 dropped++;
823                 next_tx_idx = i + 1;
824             }
825         }
826         if (next_tx_idx != cnt) {
827            dpdk_queue_pkts(dev, qid,
828                             (struct rte_mbuf **)&pkts[next_tx_idx],
829                             cnt-next_tx_idx);
830         }
831
832         if (OVS_UNLIKELY(dropped)) {
833             ovs_mutex_lock(&dev->mutex);
834             dev->stats.tx_dropped += dropped;
835             ovs_mutex_unlock(&dev->mutex);
836         }
837     }
838     ret = 0;
839
840     return ret;
841 }
842
843 static int
844 netdev_dpdk_set_etheraddr(struct netdev *netdev,
845                           const uint8_t mac[ETH_ADDR_LEN])
846 {
847     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
848
849     ovs_mutex_lock(&dev->mutex);
850     if (!eth_addr_equals(dev->hwaddr, mac)) {
851         memcpy(dev->hwaddr, mac, ETH_ADDR_LEN);
852         netdev_change_seq_changed(netdev);
853     }
854     ovs_mutex_unlock(&dev->mutex);
855
856     return 0;
857 }
858
859 static int
860 netdev_dpdk_get_etheraddr(const struct netdev *netdev,
861                           uint8_t mac[ETH_ADDR_LEN])
862 {
863     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
864
865     ovs_mutex_lock(&dev->mutex);
866     memcpy(mac, dev->hwaddr, ETH_ADDR_LEN);
867     ovs_mutex_unlock(&dev->mutex);
868
869     return 0;
870 }
871
872 static int
873 netdev_dpdk_get_mtu(const struct netdev *netdev, int *mtup)
874 {
875     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
876
877     ovs_mutex_lock(&dev->mutex);
878     *mtup = dev->mtu;
879     ovs_mutex_unlock(&dev->mutex);
880
881     return 0;
882 }
883
884 static int
885 netdev_dpdk_set_mtu(const struct netdev *netdev, int mtu)
886 {
887     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
888     int old_mtu, err;
889     struct dpdk_mp *old_mp;
890     struct dpdk_mp *mp;
891
892     ovs_mutex_lock(&dpdk_mutex);
893     ovs_mutex_lock(&dev->mutex);
894     if (dev->mtu == mtu) {
895         err = 0;
896         goto out;
897     }
898
899     mp = dpdk_mp_get(dev->socket_id, dev->mtu);
900     if (!mp) {
901         err = ENOMEM;
902         goto out;
903     }
904
905     rte_eth_dev_stop(dev->port_id);
906
907     old_mtu = dev->mtu;
908     old_mp = dev->dpdk_mp;
909     dev->dpdk_mp = mp;
910     dev->mtu = mtu;
911     dev->max_packet_len = MTU_TO_MAX_LEN(dev->mtu);
912
913     err = dpdk_eth_dev_init(dev);
914     if (err) {
915         dpdk_mp_put(mp);
916         dev->mtu = old_mtu;
917         dev->dpdk_mp = old_mp;
918         dev->max_packet_len = MTU_TO_MAX_LEN(dev->mtu);
919         dpdk_eth_dev_init(dev);
920         goto out;
921     }
922
923     dpdk_mp_put(old_mp);
924     netdev_change_seq_changed(netdev);
925 out:
926     ovs_mutex_unlock(&dev->mutex);
927     ovs_mutex_unlock(&dpdk_mutex);
928     return err;
929 }
930
931 static int
932 netdev_dpdk_get_carrier(const struct netdev *netdev_, bool *carrier);
933
934 static int
935 netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
936 {
937     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
938     struct rte_eth_stats rte_stats;
939     bool gg;
940
941     netdev_dpdk_get_carrier(netdev, &gg);
942     ovs_mutex_lock(&dev->mutex);
943     rte_eth_stats_get(dev->port_id, &rte_stats);
944
945     *stats = dev->stats_offset;
946
947     stats->rx_packets += rte_stats.ipackets;
948     stats->tx_packets += rte_stats.opackets;
949     stats->rx_bytes += rte_stats.ibytes;
950     stats->tx_bytes += rte_stats.obytes;
951     stats->rx_errors += rte_stats.ierrors;
952     stats->tx_errors += rte_stats.oerrors;
953     stats->multicast += rte_stats.imcasts;
954
955     stats->tx_dropped += dev->stats.tx_dropped;
956     ovs_mutex_unlock(&dev->mutex);
957
958     return 0;
959 }
960
961 static int
962 netdev_dpdk_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
963 {
964     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
965
966     ovs_mutex_lock(&dev->mutex);
967     dev->stats_offset = *stats;
968     ovs_mutex_unlock(&dev->mutex);
969
970     return 0;
971 }
972
973 static int
974 netdev_dpdk_get_features(const struct netdev *netdev_,
975                          enum netdev_features *current,
976                          enum netdev_features *advertised OVS_UNUSED,
977                          enum netdev_features *supported OVS_UNUSED,
978                          enum netdev_features *peer OVS_UNUSED)
979 {
980     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
981     struct rte_eth_link link;
982
983     ovs_mutex_lock(&dev->mutex);
984     link = dev->link;
985     ovs_mutex_unlock(&dev->mutex);
986
987     if (link.link_duplex == ETH_LINK_AUTONEG_DUPLEX) {
988         if (link.link_speed == ETH_LINK_SPEED_AUTONEG) {
989             *current = NETDEV_F_AUTONEG;
990         }
991     } else if (link.link_duplex == ETH_LINK_HALF_DUPLEX) {
992         if (link.link_speed == ETH_LINK_SPEED_10) {
993             *current = NETDEV_F_10MB_HD;
994         }
995         if (link.link_speed == ETH_LINK_SPEED_100) {
996             *current = NETDEV_F_100MB_HD;
997         }
998         if (link.link_speed == ETH_LINK_SPEED_1000) {
999             *current = NETDEV_F_1GB_HD;
1000         }
1001     } else if (link.link_duplex == ETH_LINK_FULL_DUPLEX) {
1002         if (link.link_speed == ETH_LINK_SPEED_10) {
1003             *current = NETDEV_F_10MB_FD;
1004         }
1005         if (link.link_speed == ETH_LINK_SPEED_100) {
1006             *current = NETDEV_F_100MB_FD;
1007         }
1008         if (link.link_speed == ETH_LINK_SPEED_1000) {
1009             *current = NETDEV_F_1GB_FD;
1010         }
1011         if (link.link_speed == ETH_LINK_SPEED_10000) {
1012             *current = NETDEV_F_10GB_FD;
1013         }
1014     }
1015
1016     return 0;
1017 }
1018
1019 static int
1020 netdev_dpdk_get_ifindex(const struct netdev *netdev)
1021 {
1022     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
1023     int ifindex;
1024
1025     ovs_mutex_lock(&dev->mutex);
1026     ifindex = dev->port_id;
1027     ovs_mutex_unlock(&dev->mutex);
1028
1029     return ifindex;
1030 }
1031
1032 static int
1033 netdev_dpdk_get_carrier(const struct netdev *netdev_, bool *carrier)
1034 {
1035     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
1036
1037     ovs_mutex_lock(&dev->mutex);
1038     check_link_status(dev);
1039     *carrier = dev->link.link_status;
1040     ovs_mutex_unlock(&dev->mutex);
1041
1042     return 0;
1043 }
1044
1045 static long long int
1046 netdev_dpdk_get_carrier_resets(const struct netdev *netdev_)
1047 {
1048     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
1049     long long int carrier_resets;
1050
1051     ovs_mutex_lock(&dev->mutex);
1052     carrier_resets = dev->link_reset_cnt;
1053     ovs_mutex_unlock(&dev->mutex);
1054
1055     return carrier_resets;
1056 }
1057
1058 static int
1059 netdev_dpdk_set_miimon(struct netdev *netdev_ OVS_UNUSED,
1060                        long long int interval OVS_UNUSED)
1061 {
1062     return 0;
1063 }
1064
1065 static int
1066 netdev_dpdk_update_flags__(struct netdev_dpdk *dev,
1067                            enum netdev_flags off, enum netdev_flags on,
1068                            enum netdev_flags *old_flagsp) OVS_REQUIRES(dev->mutex)
1069 {
1070     int err;
1071
1072     if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
1073         return EINVAL;
1074     }
1075
1076     *old_flagsp = dev->flags;
1077     dev->flags |= on;
1078     dev->flags &= ~off;
1079
1080     if (dev->flags == *old_flagsp) {
1081         return 0;
1082     }
1083
1084     if (dev->flags & NETDEV_UP) {
1085         err = rte_eth_dev_start(dev->port_id);
1086         if (err)
1087             return -err;
1088     }
1089
1090     if (dev->flags & NETDEV_PROMISC) {
1091         rte_eth_promiscuous_enable(dev->port_id);
1092     }
1093
1094     if (!(dev->flags & NETDEV_UP)) {
1095         rte_eth_dev_stop(dev->port_id);
1096     }
1097
1098     return 0;
1099 }
1100
1101 static int
1102 netdev_dpdk_update_flags(struct netdev *netdev_,
1103                          enum netdev_flags off, enum netdev_flags on,
1104                          enum netdev_flags *old_flagsp)
1105 {
1106     struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
1107     int error;
1108
1109     ovs_mutex_lock(&netdev->mutex);
1110     error = netdev_dpdk_update_flags__(netdev, off, on, old_flagsp);
1111     ovs_mutex_unlock(&netdev->mutex);
1112
1113     return error;
1114 }
1115
1116 static int
1117 netdev_dpdk_get_status(const struct netdev *netdev_, struct smap *args)
1118 {
1119     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
1120     struct rte_eth_dev_info dev_info;
1121
1122     if (dev->port_id <= 0)
1123         return ENODEV;
1124
1125     ovs_mutex_lock(&dev->mutex);
1126     rte_eth_dev_info_get(dev->port_id, &dev_info);
1127     ovs_mutex_unlock(&dev->mutex);
1128
1129     smap_add_format(args, "driver_name", "%s", dev_info.driver_name);
1130
1131     smap_add_format(args, "port_no", "%d", dev->port_id);
1132     smap_add_format(args, "numa_id", "%d", rte_eth_dev_socket_id(dev->port_id));
1133     smap_add_format(args, "driver_name", "%s", dev_info.driver_name);
1134     smap_add_format(args, "min_rx_bufsize", "%u", dev_info.min_rx_bufsize);
1135     smap_add_format(args, "max_rx_pktlen", "%u", dev_info.max_rx_pktlen);
1136     smap_add_format(args, "max_rx_queues", "%u", dev_info.max_rx_queues);
1137     smap_add_format(args, "max_tx_queues", "%u", dev_info.max_tx_queues);
1138     smap_add_format(args, "max_mac_addrs", "%u", dev_info.max_mac_addrs);
1139     smap_add_format(args, "max_hash_mac_addrs", "%u", dev_info.max_hash_mac_addrs);
1140     smap_add_format(args, "max_vfs", "%u", dev_info.max_vfs);
1141     smap_add_format(args, "max_vmdq_pools", "%u", dev_info.max_vmdq_pools);
1142
1143     smap_add_format(args, "pci-vendor_id", "0x%u", dev_info.pci_dev->id.vendor_id);
1144     smap_add_format(args, "pci-device_id", "0x%x", dev_info.pci_dev->id.device_id);
1145
1146     return 0;
1147 }
1148
1149 static void
1150 netdev_dpdk_set_admin_state__(struct netdev_dpdk *dev, bool admin_state)
1151     OVS_REQUIRES(dev->mutex)
1152 {
1153     enum netdev_flags old_flags;
1154
1155     if (admin_state) {
1156         netdev_dpdk_update_flags__(dev, 0, NETDEV_UP, &old_flags);
1157     } else {
1158         netdev_dpdk_update_flags__(dev, NETDEV_UP, 0, &old_flags);
1159     }
1160 }
1161
1162 static void
1163 netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,
1164                             const char *argv[], void *aux OVS_UNUSED)
1165 {
1166     bool up;
1167
1168     if (!strcasecmp(argv[argc - 1], "up")) {
1169         up = true;
1170     } else if ( !strcasecmp(argv[argc - 1], "down")) {
1171         up = false;
1172     } else {
1173         unixctl_command_reply_error(conn, "Invalid Admin State");
1174         return;
1175     }
1176
1177     if (argc > 2) {
1178         struct netdev *netdev = netdev_from_name(argv[1]);
1179         if (netdev && is_dpdk_class(netdev->netdev_class)) {
1180             struct netdev_dpdk *dpdk_dev = netdev_dpdk_cast(netdev);
1181
1182             ovs_mutex_lock(&dpdk_dev->mutex);
1183             netdev_dpdk_set_admin_state__(dpdk_dev, up);
1184             ovs_mutex_unlock(&dpdk_dev->mutex);
1185
1186             netdev_close(netdev);
1187         } else {
1188             unixctl_command_reply_error(conn, "Not a DPDK Interface");
1189             netdev_close(netdev);
1190             return;
1191         }
1192     } else {
1193         struct netdev_dpdk *netdev;
1194
1195         ovs_mutex_lock(&dpdk_mutex);
1196         LIST_FOR_EACH (netdev, list_node, &dpdk_list) {
1197             ovs_mutex_lock(&netdev->mutex);
1198             netdev_dpdk_set_admin_state__(netdev, up);
1199             ovs_mutex_unlock(&netdev->mutex);
1200         }
1201         ovs_mutex_unlock(&dpdk_mutex);
1202     }
1203     unixctl_command_reply(conn, "OK");
1204 }
1205
1206 static void
1207 dpdk_common_init(void)
1208 {
1209     unixctl_command_register("netdev-dpdk/set-admin-state",
1210                              "[netdev] up|down", 1, 2,
1211                              netdev_dpdk_set_admin_state, NULL);
1212
1213     ovs_thread_create("dpdk_watchdog", dpdk_watchdog, NULL);
1214 }
1215
1216 static int
1217 dpdk_class_init(void)
1218 {
1219     int result;
1220
1221     result = rte_eal_pci_probe();
1222     if (result) {
1223         VLOG_ERR("Cannot probe PCI");
1224         return -result;
1225     }
1226
1227     VLOG_INFO("Ethernet Device Count: %d", (int)rte_eth_dev_count());
1228
1229     return 0;
1230 }
1231
1232 /* Client Rings */
1233
1234 static int
1235 dpdk_ring_create(const char dev_name[], unsigned int port_no,
1236                  unsigned int *eth_port_id)
1237 {
1238     struct dpdk_ring *ivshmem;
1239     char ring_name[10];
1240     int err;
1241
1242     ivshmem = dpdk_rte_mzalloc(sizeof *ivshmem);
1243     if (ivshmem == NULL) {
1244         return ENOMEM;
1245     }
1246
1247     err = snprintf(ring_name, 10, "%s_tx", dev_name);
1248     if (err < 0) {
1249         return -err;
1250     }
1251
1252     ivshmem->cring_tx = rte_ring_create(ring_name, DPDK_RING_SIZE, SOCKET0, 0);
1253     if (ivshmem->cring_tx == NULL) {
1254         rte_free(ivshmem);
1255         return ENOMEM;
1256     }
1257
1258     err = snprintf(ring_name, 10, "%s_rx", dev_name);
1259     if (err < 0) {
1260         return -err;
1261     }
1262
1263     ivshmem->cring_rx = rte_ring_create(ring_name, DPDK_RING_SIZE, SOCKET0, 0);
1264     if (ivshmem->cring_rx == NULL) {
1265         rte_free(ivshmem);
1266         return ENOMEM;
1267     }
1268
1269     err = rte_eth_from_rings(dev_name, &ivshmem->cring_rx, 1,
1270                              &ivshmem->cring_tx, 1, SOCKET0);
1271
1272     if (err < 0) {
1273         rte_free(ivshmem);
1274         return ENODEV;
1275     }
1276
1277     ivshmem->user_port_id = port_no;
1278     ivshmem->eth_port_id = rte_eth_dev_count() - 1;
1279     list_push_back(&dpdk_ring_list, &ivshmem->list_node);
1280
1281     *eth_port_id = ivshmem->eth_port_id;
1282     return 0;
1283 }
1284
1285 static int
1286 dpdk_ring_open(const char dev_name[], unsigned int *eth_port_id) OVS_REQUIRES(dpdk_mutex)
1287 {
1288     struct dpdk_ring *ivshmem;
1289     unsigned int port_no;
1290     int err = 0;
1291
1292     /* Names always start with "dpdkr" */
1293     err = dpdk_dev_parse_name(dev_name, "dpdkr", &port_no);
1294     if (err) {
1295         return err;
1296     }
1297
1298     /* look through our list to find the device */
1299     LIST_FOR_EACH (ivshmem, list_node, &dpdk_ring_list) {
1300          if (ivshmem->user_port_id == port_no) {
1301             VLOG_INFO("Found dpdk ring device %s:\n", dev_name);
1302             *eth_port_id = ivshmem->eth_port_id; /* really all that is needed */
1303             return 0;
1304          }
1305     }
1306     /* Need to create the device rings */
1307     return dpdk_ring_create(dev_name, port_no, eth_port_id);
1308 }
1309
1310 static int
1311 netdev_dpdk_ring_construct(struct netdev *netdev)
1312 {
1313     unsigned int port_no = 0;
1314     int err = 0;
1315
1316     if (rte_eal_init_ret) {
1317         return rte_eal_init_ret;
1318     }
1319
1320     ovs_mutex_lock(&dpdk_mutex);
1321
1322     err = dpdk_ring_open(netdev->name, &port_no);
1323     if (err) {
1324         goto unlock_dpdk;
1325     }
1326
1327     err = netdev_dpdk_init(netdev, port_no);
1328
1329 unlock_dpdk:
1330     ovs_mutex_unlock(&dpdk_mutex);
1331     return err;
1332 }
1333
1334 #define NETDEV_DPDK_CLASS(NAME, INIT, CONSTRUCT)              \
1335 {                                                             \
1336     NAME,                                                     \
1337     INIT,                       /* init */                    \
1338     NULL,                       /* netdev_dpdk_run */         \
1339     NULL,                       /* netdev_dpdk_wait */        \
1340                                                               \
1341     netdev_dpdk_alloc,                                        \
1342     CONSTRUCT,                                                \
1343     netdev_dpdk_destruct,                                     \
1344     netdev_dpdk_dealloc,                                      \
1345     netdev_dpdk_get_config,                                   \
1346     NULL,                       /* netdev_dpdk_set_config */  \
1347     NULL,                       /* get_tunnel_config */       \
1348                                                               \
1349     netdev_dpdk_send,           /* send */                    \
1350     NULL,                       /* send_wait */               \
1351                                                               \
1352     netdev_dpdk_set_etheraddr,                                \
1353     netdev_dpdk_get_etheraddr,                                \
1354     netdev_dpdk_get_mtu,                                      \
1355     netdev_dpdk_set_mtu,                                      \
1356     netdev_dpdk_get_ifindex,                                  \
1357     netdev_dpdk_get_carrier,                                  \
1358     netdev_dpdk_get_carrier_resets,                           \
1359     netdev_dpdk_set_miimon,                                   \
1360     netdev_dpdk_get_stats,                                    \
1361     netdev_dpdk_set_stats,                                    \
1362     netdev_dpdk_get_features,                                 \
1363     NULL,                       /* set_advertisements */      \
1364                                                               \
1365     NULL,                       /* set_policing */            \
1366     NULL,                       /* get_qos_types */           \
1367     NULL,                       /* get_qos_capabilities */    \
1368     NULL,                       /* get_qos */                 \
1369     NULL,                       /* set_qos */                 \
1370     NULL,                       /* get_queue */               \
1371     NULL,                       /* set_queue */               \
1372     NULL,                       /* delete_queue */            \
1373     NULL,                       /* get_queue_stats */         \
1374     NULL,                       /* queue_dump_start */        \
1375     NULL,                       /* queue_dump_next */         \
1376     NULL,                       /* queue_dump_done */         \
1377     NULL,                       /* dump_queue_stats */        \
1378                                                               \
1379     NULL,                       /* get_in4 */                 \
1380     NULL,                       /* set_in4 */                 \
1381     NULL,                       /* get_in6 */                 \
1382     NULL,                       /* add_router */              \
1383     NULL,                       /* get_next_hop */            \
1384     netdev_dpdk_get_status,                                   \
1385     NULL,                       /* arp_lookup */              \
1386                                                               \
1387     netdev_dpdk_update_flags,                                 \
1388                                                               \
1389     netdev_dpdk_rxq_alloc,                                    \
1390     netdev_dpdk_rxq_construct,                                \
1391     netdev_dpdk_rxq_destruct,                                 \
1392     netdev_dpdk_rxq_dealloc,                                  \
1393     netdev_dpdk_rxq_recv,                                     \
1394     NULL,                       /* rx_wait */                 \
1395     NULL,                       /* rxq_drain */               \
1396 }
1397
1398 int
1399 dpdk_init(int argc, char **argv)
1400 {
1401     int result;
1402
1403     if (argc < 2 || strcmp(argv[1], "--dpdk"))
1404         return 0;
1405
1406     /* Make sure program name passed to rte_eal_init() is vswitchd. */
1407     argv[1] = argv[0];
1408
1409     argc--;
1410     argv++;
1411
1412     /* Make sure things are initialized ... */
1413     result = rte_eal_init(argc, argv);
1414     if (result < 0) {
1415         ovs_abort(result, "Cannot init EAL\n");
1416     }
1417
1418     rte_memzone_dump(stdout);
1419     rte_eal_init_ret = 0;
1420
1421     if (argc > result) {
1422         argv[result] = argv[0];
1423     }
1424
1425     /* We are called from the main thread here */
1426     thread_set_nonpmd();
1427
1428     return result + 1;
1429 }
1430
1431 const struct netdev_class dpdk_class =
1432     NETDEV_DPDK_CLASS(
1433         "dpdk",
1434         dpdk_class_init,
1435         netdev_dpdk_construct);
1436
1437 const struct netdev_class dpdk_ring_class =
1438     NETDEV_DPDK_CLASS(
1439         "dpdkr",
1440         NULL,
1441         netdev_dpdk_ring_construct);
1442
1443 void
1444 netdev_dpdk_register(void)
1445 {
1446     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
1447
1448     if (rte_eal_init_ret) {
1449         return;
1450     }
1451
1452     if (ovsthread_once_start(&once)) {
1453         dpdk_common_init();
1454         netdev_register_provider(&dpdk_class);
1455         netdev_register_provider(&dpdk_ring_class);
1456         ovsthread_once_done(&once);
1457     }
1458 }
1459
1460 int
1461 pmd_thread_setaffinity_cpu(int cpu)
1462 {
1463     cpu_set_t cpuset;
1464     int err;
1465
1466     CPU_ZERO(&cpuset);
1467     CPU_SET(cpu, &cpuset);
1468     err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1469     if (err) {
1470         VLOG_ERR("Thread affinity error %d",err);
1471         return err;
1472     }
1473     /* lcore_id 0 is reseved for use by non pmd threads. */
1474     RTE_PER_LCORE(_lcore_id) = cpu + 1;
1475
1476     return 0;
1477 }
1478
1479 void
1480 thread_set_nonpmd(void)
1481 {
1482     /* We cannot have RTE_MAX_LCORE pmd threads, because lcore_id 0 is reserved
1483      * for non pmd threads */
1484     BUILD_ASSERT(NR_PMD_THREADS < RTE_MAX_LCORE);
1485     /* We have to use 0 to allow non pmd threads to perform certain DPDK
1486      * operations, like rte_eth_dev_configure(). */
1487     RTE_PER_LCORE(_lcore_id) = 0;
1488 }
1489
1490 static bool
1491 thread_is_pmd(void)
1492 {
1493     return rte_lcore_id() != 0;
1494 }