mbuf: replace data pointer by an offset
[dpdk.git] / lib / librte_pmd_xenvirt / rte_eth_xenvirt.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdint.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/mman.h>
40 #include <errno.h>
41 #include <sys/user.h>
42 #include <linux/binfmts.h>
43 #include <xen/xen-compat.h>
44 #if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040200
45 #include <xs.h>
46 #else
47 #include <xenstore.h>
48 #endif
49 #include <linux/virtio_ring.h>
50
51 #include <rte_mbuf.h>
52 #include <rte_ethdev.h>
53 #include <rte_malloc.h>
54 #include <rte_memcpy.h>
55 #include <rte_string_fns.h>
56 #include <rte_dev.h>
57 #include <cmdline_parse.h>
58 #include <cmdline_parse_etheraddr.h>
59
60 #include "rte_xen_lib.h"
61 #include "virtqueue.h"
62 #include "rte_eth_xenvirt.h"
63
64 #define VQ_DESC_NUM 256
65 #define VIRTIO_MBUF_BURST_SZ 64
66
67 /* virtio_idx is increased after new device is created.*/
68 static int virtio_idx = 0;
69
70 static const char *drivername = "xen dummy virtio PMD";
71
72 static struct rte_eth_link pmd_link = {
73                 .link_speed = 10000,
74                 .link_duplex = ETH_LINK_FULL_DUPLEX,
75                 .link_status = 0
76 };
77
78 static inline struct rte_mbuf *
79 rte_rxmbuf_alloc(struct rte_mempool *mp)
80 {
81         struct rte_mbuf *m;
82
83         m = __rte_mbuf_raw_alloc(mp);
84         __rte_mbuf_sanity_check_raw(m, 0);
85
86         return m;
87 }
88
89
90 static uint16_t
91 eth_xenvirt_rx(void *q, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
92 {
93         struct virtqueue *rxvq = q;
94         struct rte_mbuf *rxm, *new_mbuf;
95         uint16_t nb_used, num;
96         uint32_t len[VIRTIO_MBUF_BURST_SZ];
97         uint32_t i;
98         struct pmd_internals *pi = rxvq->internals;
99
100         nb_used = VIRTQUEUE_NUSED(rxvq);
101
102         rte_compiler_barrier(); /* rmb */
103         num = (uint16_t)(likely(nb_used <= nb_pkts) ? nb_used : nb_pkts);
104         num = (uint16_t)(likely(num <= VIRTIO_MBUF_BURST_SZ) ? num : VIRTIO_MBUF_BURST_SZ);
105         if (unlikely(num == 0)) return 0;
106
107         num = virtqueue_dequeue_burst(rxvq, rx_pkts, len, num);
108         PMD_RX_LOG(DEBUG, "used:%d dequeue:%d\n", nb_used, num);
109         for (i = 0; i < num ; i ++) {
110                 rxm = rx_pkts[i];
111                 PMD_RX_LOG(DEBUG, "packet len:%d\n", len[i]);
112                 rxm->next = NULL;
113                 rxm->data_off = RTE_PKTMBUF_HEADROOM;
114                 rxm->data_len = (uint16_t)(len[i] - sizeof(struct virtio_net_hdr));
115                 rxm->nb_segs = 1;
116                 rxm->port = pi->port_id;
117                 rxm->pkt_len  = (uint32_t)(len[i] - sizeof(struct virtio_net_hdr));
118         }
119         /* allocate new mbuf for the used descriptor */
120         while (likely(!virtqueue_full(rxvq))) {
121                 new_mbuf = rte_rxmbuf_alloc(rxvq->mpool);
122                 if (unlikely(new_mbuf == NULL)) {
123                         break;
124                 }
125                 if (unlikely(virtqueue_enqueue_recv_refill(rxvq, new_mbuf))) {
126                         rte_pktmbuf_free_seg(new_mbuf);
127                         break;
128                 }
129         }
130         pi->eth_stats.ipackets += num;
131         return num;
132 }
133
134 static uint16_t
135 eth_xenvirt_tx(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
136 {
137         struct virtqueue *txvq = tx_queue;
138         struct rte_mbuf *txm;
139         uint16_t nb_used, nb_tx, num, i;
140         int error;
141         uint32_t len[VIRTIO_MBUF_BURST_SZ];
142         struct rte_mbuf *snd_pkts[VIRTIO_MBUF_BURST_SZ];
143         struct pmd_internals *pi = txvq->internals;
144
145         nb_tx = 0;
146
147         if (unlikely(nb_pkts == 0))
148                 return 0;
149
150         PMD_TX_LOG(DEBUG, "%d packets to xmit", nb_pkts);
151         nb_used = VIRTQUEUE_NUSED(txvq);
152
153         rte_compiler_barrier();   /* rmb */
154
155         num = (uint16_t)(likely(nb_used <= VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ);
156         num = virtqueue_dequeue_burst(txvq, snd_pkts, len, num);
157
158         for (i = 0; i < num ; i ++) {
159                 /* mergable not supported, one segment only */
160                 rte_pktmbuf_free_seg(snd_pkts[i]);
161         }
162
163         while (nb_tx < nb_pkts) {
164                 if (likely(!virtqueue_full(txvq))) {
165                 /* TODO drop tx_pkts if it contains multiple segments */
166                         txm = tx_pkts[nb_tx];
167                         error = virtqueue_enqueue_xmit(txvq, txm);
168                         if (unlikely(error)) {
169                                 if (error == ENOSPC)
170                                         PMD_TX_LOG(ERR, "virtqueue_enqueue Free count = 0\n");
171                                 else if (error == EMSGSIZE)
172                                         PMD_TX_LOG(ERR, "virtqueue_enqueue Free count < 1\n");
173                                 else
174                                         PMD_TX_LOG(ERR, "virtqueue_enqueue error: %d\n", error);
175                                 break;
176                         }
177                         nb_tx++;
178                 } else {
179                         PMD_TX_LOG(ERR, "No free tx descriptors to transmit\n");
180                         /* virtqueue_notify not needed in our para-virt solution */
181                         break;
182                 }
183         }
184         pi->eth_stats.opackets += nb_tx;
185         return nb_tx;
186 }
187
188 static int
189 eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
190 {
191         RTE_LOG(ERR, PMD, "%s\n", __func__);
192         return 0;
193 }
194
195 /*
196  * Create a shared page between guest and host.
197  * Host monitors this page if it is cleared on unmap, and then
198  * do necessary clean up.
199  */
200 static void
201 gntalloc_vring_flag(int vtidx)
202 {
203         char key_str[PATH_MAX];
204         char val_str[PATH_MAX];
205         uint32_t gref_tmp;
206         void *ptr;
207
208         if (grefwatch_from_alloc(&gref_tmp, &ptr)) {
209                 RTE_LOG(ERR, PMD, "grefwatch_from_alloc error\n");
210                 exit(0);
211         }
212
213         *(uint8_t *)ptr = MAP_FLAG;
214         snprintf(val_str, sizeof(val_str), "%u", gref_tmp);
215         snprintf(key_str, sizeof(key_str),
216                 DPDK_XENSTORE_PATH"%d"VRING_FLAG_STR, vtidx);
217         xenstore_write(key_str, val_str);
218 }
219
220 /*
221  * Notify host this virtio device is started.
222  * Host could start polling this device.
223  */
224 static void
225 dev_start_notify(int vtidx)
226 {
227         char key_str[PATH_MAX];
228         char val_str[PATH_MAX];
229
230         RTE_LOG(INFO, PMD, "%s: virtio %d is started\n", __func__, vtidx);
231         gntalloc_vring_flag(vtidx);
232
233         snprintf(key_str, sizeof(key_str), "%s%s%d",
234                 DPDK_XENSTORE_PATH, EVENT_TYPE_START_STR,
235                         vtidx);
236         snprintf(val_str, sizeof(val_str), "1");
237         xenstore_write(key_str, val_str);
238 }
239
240 /*
241  * Notify host this virtio device is stopped.
242  * Host could stop polling this device.
243  */
244 static void
245 dev_stop_notify(int vtidx)
246 {
247         RTE_SET_USED(vtidx);
248 }
249
250
251 static int
252 update_mac_address(struct ether_addr *mac_addrs, int vtidx)
253 {
254         char key_str[PATH_MAX];
255         char val_str[PATH_MAX];
256         int rv;
257
258         if (mac_addrs == NULL) {
259                 RTE_LOG(ERR, PMD, "%s: NULL pointer mac specified\n", __func__);
260                 return -1;
261         }
262         rv = snprintf(key_str, sizeof(key_str),
263                         DPDK_XENSTORE_PATH"%d_ether_addr", vtidx);
264         if (rv == -1)
265                 return rv;
266         rv = snprintf(val_str, sizeof(val_str), "%02x:%02x:%02x:%02x:%02x:%02x",
267                         mac_addrs->addr_bytes[0],
268                         mac_addrs->addr_bytes[1],
269                         mac_addrs->addr_bytes[2],
270                         mac_addrs->addr_bytes[3],
271                         mac_addrs->addr_bytes[4],
272                         mac_addrs->addr_bytes[5]);
273         if (rv == -1)
274                 return rv;
275         if (xenstore_write(key_str, val_str))
276                 return rv;
277         return 0;
278 }
279
280
281 static int
282 eth_dev_start(struct rte_eth_dev *dev)
283 {
284         struct virtqueue *rxvq = dev->data->rx_queues[0];
285         struct virtqueue *txvq = dev->data->tx_queues[0];
286         struct rte_mbuf *m;
287         struct pmd_internals *pi = (struct pmd_internals *)dev->data->dev_private;
288         int rv;
289
290         dev->data->dev_link.link_status = 1;
291         while (!virtqueue_full(rxvq)) {
292                 m = rte_rxmbuf_alloc(rxvq->mpool);
293                 if (m == NULL)
294                         break;
295                 /* Enqueue allocated buffers. */
296                 if (virtqueue_enqueue_recv_refill(rxvq, m)) {
297                         rte_pktmbuf_free_seg(m);
298                         break;
299                 }
300         }
301
302         rxvq->internals = pi;
303         txvq->internals = pi;
304
305         rv = update_mac_address(dev->data->mac_addrs, pi->virtio_idx);
306         if (rv)
307                 return -1;
308         dev_start_notify(pi->virtio_idx);
309
310         return 0;
311 }
312
313 static void
314 eth_dev_stop(struct rte_eth_dev *dev)
315 {
316         struct pmd_internals *pi = (struct pmd_internals *)dev->data->dev_private;
317
318         dev->data->dev_link.link_status = 0;
319         dev_stop_notify(pi->virtio_idx);
320 }
321
322 /*
323  * Notify host this virtio device is closed.
324  * Host could do necessary clean up to this device.
325  */
326 static void
327 eth_dev_close(struct rte_eth_dev *dev)
328 {
329         RTE_SET_USED(dev);
330 }
331
332 static void
333 eth_dev_info(struct rte_eth_dev *dev,
334                 struct rte_eth_dev_info *dev_info)
335 {
336         struct pmd_internals *internals = dev->data->dev_private;
337
338         RTE_SET_USED(internals);
339         dev_info->driver_name = drivername;
340         dev_info->max_mac_addrs = 1;
341         dev_info->max_rx_pktlen = (uint32_t)2048;
342         dev_info->max_rx_queues = (uint16_t)1;
343         dev_info->max_tx_queues = (uint16_t)1;
344         dev_info->min_rx_bufsize = 0;
345         dev_info->pci_dev = NULL;
346 }
347
348 static void
349 eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
350 {
351         struct pmd_internals *internals = dev->data->dev_private;
352         if(stats)
353                 rte_memcpy(stats, &internals->eth_stats, sizeof(*stats));
354 }
355
356 static void
357 eth_stats_reset(struct rte_eth_dev *dev)
358 {
359         struct pmd_internals *internals = dev->data->dev_private;
360         /* Reset software totals */
361         memset(&internals->eth_stats, 0, sizeof(internals->eth_stats));
362 }
363
364 static void
365 eth_queue_release(void *q __rte_unused)
366 {
367 }
368
369 static int
370 eth_link_update(struct rte_eth_dev *dev __rte_unused,
371                 int wait_to_complete __rte_unused)
372 {
373         return 0;
374 }
375
376 /*
377  * Create shared vring between guest and host.
378  * Memory is allocated through grant alloc driver, so it is not physical continuous.
379  */
380 static void *
381 gntalloc_vring_create(int queue_type, uint32_t size, int vtidx)
382 {
383         char key_str[PATH_MAX] = {0};
384         char val_str[PATH_MAX] = {0};
385         void *va = NULL;
386         int pg_size;
387         uint32_t pg_num;
388         uint32_t *gref_arr = NULL;
389         phys_addr_t *pa_arr = NULL;
390         uint64_t start_index;
391         int rv;
392
393         pg_size = getpagesize();
394         size    = RTE_ALIGN_CEIL(size, pg_size);
395         pg_num  = size / pg_size;
396
397         gref_arr = calloc(pg_num, sizeof(gref_arr[0]));
398         pa_arr  = calloc(pg_num, sizeof(pa_arr[0]));
399
400         if (gref_arr == NULL || pa_arr == NULL) {
401                 RTE_LOG(ERR, PMD, "%s: calloc failed\n", __func__);
402                 goto out;
403         }
404
405         va  = gntalloc(size, gref_arr, &start_index);
406         if (va == NULL) {
407                 RTE_LOG(ERR, PMD, "%s: gntalloc failed\n", __func__);
408                 goto out;
409         }
410
411         if (get_phys_map(va, pa_arr, pg_num, pg_size))
412                 goto out;
413
414         /* write in xenstore gref and pfn for each page of vring */
415         if (grant_node_create(pg_num, gref_arr, pa_arr, val_str, sizeof(val_str))) {
416                 gntfree(va, size, start_index);
417                 va = NULL;
418                 goto out;
419         }
420
421         if (queue_type == VTNET_RQ)
422                 rv = snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"RXVRING_XENSTORE_STR, vtidx);
423         else
424                 rv = snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"TXVRING_XENSTORE_STR, vtidx);
425         if (rv == -1 || xenstore_write(key_str, val_str) == -1) {
426                 gntfree(va, size, start_index);
427                 va = NULL;
428         }
429 out:
430         if (pa_arr)
431                 free(pa_arr);
432         if (gref_arr)
433                 free(gref_arr);
434
435         return va;
436 }
437
438
439
440 static struct virtqueue *
441 virtio_queue_setup(struct rte_eth_dev *dev, int queue_type)
442 {
443         struct virtqueue *vq = NULL;
444         uint16_t vq_size = VQ_DESC_NUM;
445         int i = 0;
446         char vq_name[VIRTQUEUE_MAX_NAME_SZ];
447         size_t size;
448         struct vring *vr;
449
450         /* Allocate memory for virtqueue. */
451         if (queue_type == VTNET_RQ) {
452                 snprintf(vq_name, sizeof(vq_name), "port%d_rvq",
453                                 dev->data->port_id);
454                 vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) +
455                         vq_size * sizeof(struct vq_desc_extra), CACHE_LINE_SIZE);
456                 if (vq == NULL) {
457                         RTE_LOG(ERR, PMD, "%s: unabled to allocate virtqueue\n", __func__);
458                         return NULL;
459                 }
460                 memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name));
461         } else if(queue_type == VTNET_TQ) {
462                 snprintf(vq_name, sizeof(vq_name), "port%d_tvq",
463                         dev->data->port_id);
464                 vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) +
465                         vq_size * sizeof(struct vq_desc_extra), CACHE_LINE_SIZE);
466                 if (vq == NULL) {
467                         RTE_LOG(ERR, PMD, "%s: unabled to allocate virtqueue\n", __func__);
468                         return NULL;
469                 }
470                 memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name));
471         }
472
473         memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name));
474
475         vq->vq_alignment = VIRTIO_PCI_VRING_ALIGN;
476         vq->vq_nentries = vq_size;
477         vq->vq_free_cnt = vq_size;
478         /* Calcuate vring size according to virtio spec */
479         size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN);
480         vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN);
481         /* Allocate memory for virtio vring through gntalloc driver*/
482         vq->vq_ring_virt_mem = gntalloc_vring_create(queue_type, vq->vq_ring_size,
483                 ((struct pmd_internals *)dev->data->dev_private)->virtio_idx);
484         memset(vq->vq_ring_virt_mem, 0, vq->vq_ring_size);
485         vr = &vq->vq_ring;
486         vring_init(vr, vq_size, vq->vq_ring_virt_mem, vq->vq_alignment);
487         /*
488          * Locally maintained last consumed index, this idex trails
489          * vq_ring.used->idx.
490          */
491         vq->vq_used_cons_idx = 0;
492         vq->vq_desc_head_idx = 0;
493         vq->vq_free_cnt = vq->vq_nentries;
494         memset(vq->vq_descx, 0, sizeof(struct vq_desc_extra) * vq->vq_nentries);
495
496         /* Chain all the descriptors in the ring with an END */
497         for (i = 0; i < vq_size - 1; i++)
498                 vr->desc[i].next = (uint16_t)(i + 1);
499         vr->desc[i].next = VQ_RING_DESC_CHAIN_END;
500
501         return vq;
502 }
503
504 static int
505 eth_rx_queue_setup(struct rte_eth_dev *dev,uint16_t rx_queue_id,
506                                 uint16_t nb_rx_desc __rte_unused,
507                                 unsigned int socket_id __rte_unused,
508                                 const struct rte_eth_rxconf *rx_conf __rte_unused,
509                                 struct rte_mempool *mb_pool)
510 {
511         struct virtqueue *vq;
512         vq = dev->data->rx_queues[rx_queue_id] = virtio_queue_setup(dev, VTNET_RQ);
513         vq->mpool = mb_pool;
514         return 0;
515 }
516
517 static int
518 eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
519                                 uint16_t nb_tx_desc __rte_unused,
520                                 unsigned int socket_id __rte_unused,
521                                 const struct rte_eth_txconf *tx_conf __rte_unused)
522 {
523         dev->data->tx_queues[tx_queue_id] = virtio_queue_setup(dev, VTNET_TQ);
524         return 0;
525 }
526
527
528
529 static struct eth_dev_ops ops = {
530                 .dev_start = eth_dev_start,
531                 .dev_stop = eth_dev_stop,
532                 .dev_close = eth_dev_close,
533                 .dev_configure = eth_dev_configure,
534                 .dev_infos_get = eth_dev_info,
535                 .rx_queue_setup = eth_rx_queue_setup,
536                 .tx_queue_setup = eth_tx_queue_setup,
537                 .rx_queue_release = eth_queue_release,
538                 .tx_queue_release = eth_queue_release,
539                 .link_update = eth_link_update,
540                 .stats_get = eth_stats_get,
541                 .stats_reset = eth_stats_reset,
542 };
543
544
545 static int
546 rte_eth_xenvirt_parse_args(struct xenvirt_dict *dict,
547                         const char *name, const char *params)
548 {
549         int i;
550         char *pairs[RTE_ETH_XENVIRT_MAX_ARGS];
551         int num_of_pairs;
552         char *pair[2];
553         char *args;
554         int ret = -1;
555
556         if (params == NULL)
557                 return 0;
558
559         args = rte_zmalloc(NULL, strlen(params) + 1, CACHE_LINE_SIZE);
560         if (args == NULL) {
561                 RTE_LOG(ERR, PMD, "Couldn't parse %s device \n", name);
562                 return -1;
563         }
564         rte_memcpy(args, params, strlen(params));
565
566         num_of_pairs = rte_strsplit(args, strnlen(args, MAX_ARG_STRLEN),
567                                         pairs,
568                                         RTE_ETH_XENVIRT_MAX_ARGS ,
569                                         RTE_ETH_XENVIRT_PAIRS_DELIM);
570
571         for (i = 0; i < num_of_pairs; i++) {
572                 pair[0] = NULL;
573                 pair[1] = NULL;
574                 rte_strsplit(pairs[i], strnlen(pairs[i], MAX_ARG_STRLEN),
575                                         pair, 2,
576                                         RTE_ETH_XENVIRT_KEY_VALUE_DELIM);
577
578                 if (pair[0] == NULL || pair[1] == NULL || pair[0][0] == 0
579                         || pair[1][0] == 0) {
580                         RTE_LOG(ERR, PMD,
581                                 "Couldn't parse %s device,"
582                                 "wrong key or value \n", name);
583                         goto err;
584                 }
585
586                 if (!strncmp(pair[0], RTE_ETH_XENVIRT_MAC_PARAM,
587                                 sizeof(RTE_ETH_XENVIRT_MAC_PARAM))) {
588                         if (cmdline_parse_etheraddr(NULL,
589                                                         pair[1],
590                                                         &dict->addr) < 0) {
591                                 RTE_LOG(ERR, PMD,
592                                         "Invalid %s device ether address\n",
593                                         name);
594                                 goto err;
595                         }
596
597                         dict->addr_valid = 1;
598                 }
599         }
600
601         ret = 0;
602 err:
603         rte_free(args);
604         return ret;
605 }
606
607 enum dev_action {
608         DEV_CREATE,
609         DEV_ATTACH
610 };
611
612
613 static int
614 eth_dev_xenvirt_create(const char *name, const char *params,
615                 const unsigned numa_node,
616                 enum dev_action action)
617 {
618         struct rte_eth_dev_data *data = NULL;
619         struct rte_pci_device *pci_dev = NULL;
620         struct pmd_internals *internals = NULL;
621         struct rte_eth_dev *eth_dev = NULL;
622         struct xenvirt_dict dict;
623         bzero(&dict, sizeof(struct xenvirt_dict));
624
625         RTE_LOG(INFO, PMD, "Creating virtio rings backed ethdev on numa socket %u\n",
626                         numa_node);
627         RTE_SET_USED(action);
628
629         if (rte_eth_xenvirt_parse_args(&dict, name, params) < 0) {
630                 RTE_LOG(ERR, PMD, "%s: Failed to parse ethdev parameters\n", __func__);
631                 return -1;
632         }
633
634         /* now do all data allocation - for eth_dev structure, dummy pci driver
635          * and internal (private) data
636          */
637         data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
638         if (data == NULL)
639                 goto err;
640
641         pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node);
642         if (pci_dev == NULL)
643                 goto err;
644
645         internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
646         if (internals == NULL)
647                 goto err;
648
649         /* reserve an ethdev entry */
650         eth_dev = rte_eth_dev_allocate(name);
651         if (eth_dev == NULL)
652                 goto err;
653
654         pci_dev->numa_node = numa_node;
655
656         data->dev_private = internals;
657         data->port_id = eth_dev->data->port_id;
658         data->nb_rx_queues = (uint16_t)1;
659         data->nb_tx_queues = (uint16_t)1;
660         data->dev_link = pmd_link;
661         data->mac_addrs = rte_zmalloc("xen_virtio", ETHER_ADDR_LEN, 0);
662
663         if(dict.addr_valid)
664                 memcpy(&data->mac_addrs->addr_bytes, &dict.addr, sizeof(struct ether_addr));
665         else
666                 eth_random_addr(&data->mac_addrs->addr_bytes[0]);
667
668         eth_dev->data = data;
669         eth_dev->dev_ops = &ops;
670         eth_dev->pci_dev = pci_dev;
671
672         eth_dev->rx_pkt_burst = eth_xenvirt_rx;
673         eth_dev->tx_pkt_burst = eth_xenvirt_tx;
674
675         internals->virtio_idx = virtio_idx++;
676         internals->port_id = eth_dev->data->port_id;
677
678         return 0;
679
680 err:
681         if (data)
682                 rte_free(data);
683         if (pci_dev)
684                 rte_free(pci_dev);
685         if (internals)
686                 rte_free(internals);
687         return -1;
688 }
689
690
691 /*TODO: Support multiple process model */
692 static int
693 rte_pmd_xenvirt_devinit(const char *name, const char *params)
694 {
695         if (virtio_idx == 0) {
696                 if (xenstore_init() != 0) {
697                         RTE_LOG(ERR, PMD, "%s: xenstore init failed\n", __func__);
698                         return -1;
699                 }
700                 if (gntalloc_open() != 0) {
701                         RTE_LOG(ERR, PMD, "%s: grant init failed\n", __func__);
702                         return -1;
703                 }
704         }
705         eth_dev_xenvirt_create(name, params, rte_socket_id(), DEV_CREATE);
706         return 0;
707 }
708
709 static struct rte_driver pmd_xenvirt_drv = {
710         .name = "eth_xenvirt",
711         .type = PMD_VDEV,
712         .init = rte_pmd_xenvirt_devinit,
713 };
714
715 PMD_REGISTER_DRIVER(pmd_xenvirt_drv);