Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Fix bug in virtio NIC
[palacios.git] / palacios / src / devices / lnx_virtio_nic.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2010, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2010, Cui Zheng <cuizheng@cs.unm.edu>
12  * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Lei Xia <lxia@northwestern.edu>
16  *         Cui Zheng <cuizheng@cs.unm.edu>
17  *               
18  *
19  * This is free software.  You are permitted to use,
20  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21  */
22  
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_dev_mgr.h>
25 #include <devices/lnx_virtio_pci.h>
26 #include <palacios/vm_guest_mem.h>
27 #include <palacios/vmm_sprintf.h>
28 #include <vnet/vnet.h>
29 #include <palacios/vmm_lock.h>
30 #include <palacios/vmm_util.h>
31 #include <devices/pci.h>
32 #include <palacios/vmm_ethernet.h>
33 #include <palacios/vmm_time.h>
34
35
36 #ifndef V3_CONFIG_DEBUG_VIRTIO_NET
37 #undef PrintDebug
38 #define PrintDebug(fmt, args...)
39 #endif
40
41 #ifndef V3_CONFIG_VNET
42 static int net_debug = 0;
43 #endif
44
45 #define TX_QUEUE_SIZE 4096
46 #define RX_QUEUE_SIZE 4096
47 #define CTRL_QUEUE_SIZE 64
48
49 /* The feature bitmap for virtio nic
50   * from Linux */
51 #define VIRTIO_NET_F_CSUM       0       /* Host handles pkts w/ partial csum */
52 #define VIRTIO_NET_F_GUEST_CSUM 1       /* Guest handles pkts w/ partial csum */
53 #define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
54 #define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
55 #define VIRTIO_NET_F_GUEST_TSO4 7       /* Guest can handle TSOv4 in. */
56 #define VIRTIO_NET_F_GUEST_TSO6 8       /* Guest can handle TSOv6 in. */
57 #define VIRTIO_NET_F_GUEST_ECN  9       /* Guest can handle TSO[6] w/ ECN in. */
58 #define VIRTIO_NET_F_GUEST_UFO  10      /* Guest can handle UFO in. */
59 #define VIRTIO_NET_F_HOST_TSO4  11      /* Host can handle TSOv4 in. */
60 #define VIRTIO_NET_F_HOST_TSO6  12      /* Host can handle TSOv6 in. */
61 #define VIRTIO_NET_F_HOST_ECN   13      /* Host can handle TSO[6] w/ ECN in. */
62 #define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
63 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
64 #define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
65
66 /* Port to get virtio config */
67 #define VIRTIO_NET_CONFIG 20  
68
69 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
70
71 /* for gso_type in virtio_net_hdr */
72 #define VIRTIO_NET_HDR_GSO_NONE         0      
73 #define VIRTIO_NET_HDR_GSO_TCPV4        1     /* GSO frame, IPv4 TCP (TSO) */
74 #define VIRTIO_NET_HDR_GSO_UDP          3       /* GSO frame, IPv4 UDP (UFO) */
75 #define VIRTIO_NET_HDR_GSO_TCPV6        4       /* GSO frame, IPv6 TCP */
76 #define VIRTIO_NET_HDR_GSO_ECN          0x80    /* TCP has ECN set */   
77
78
79 /* for flags in virtio_net_hdr */
80 #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1       /* Use csum_start, csum_offset */
81
82
83 /* First element of the scatter-gather list, used with GSO or CSUM features */
84 struct virtio_net_hdr
85 {
86     uint8_t flags;
87     uint8_t gso_type;
88     uint16_t hdr_len;           /* Ethernet + IP + tcp/udp hdrs */
89     uint16_t gso_size;          /* Bytes to append to hdr_len per frame */
90     uint16_t csum_start;        /* Position to start checksumming from */
91     uint16_t csum_offset;       /* Offset after that to place checksum */
92 }__attribute__((packed));
93
94
95 /* The header to use when the MRG_RXBUF 
96  * feature has been negotiated. */
97 struct virtio_net_hdr_mrg_rxbuf {
98     struct virtio_net_hdr hdr;
99     uint16_t num_buffers;       /* Number of merged rx buffers */
100 };
101
102 struct virtio_net_config
103 {
104     uint8_t mac[ETH_ALEN];      /* VIRTIO_NET_F_MAC */
105     uint16_t status;
106 } __attribute__((packed));
107
108 struct virtio_dev_state {
109     struct vm_device * pci_bus;
110     struct list_head dev_list;
111     struct v3_vm_info *vm;
112
113     uint8_t mac[ETH_ALEN];
114 };
115
116 struct virtio_net_state {
117     struct virtio_net_config net_cfg;
118     struct virtio_config virtio_cfg;
119
120     struct v3_vm_info * vm;
121     struct vm_device * dev;
122     struct pci_device * pci_dev; 
123     int io_range_size;
124
125     uint16_t status;
126     
127     struct virtio_queue rx_vq;          /* idx 0*/
128     struct virtio_queue tx_vq;          /* idx 1*/
129     struct virtio_queue ctrl_vq;        /* idx 2*/
130
131     uint8_t mergeable_rx_bufs;
132
133     struct v3_timer * timer;
134     struct vnet_thread * poll_thread;
135
136     struct nic_statistics stats;
137
138     struct v3_dev_net_ops * net_ops;
139     v3_lock_t rx_lock, tx_lock;
140
141     uint8_t tx_notify, rx_notify;
142     uint32_t tx_pkts, rx_pkts;
143     uint64_t past_us;
144
145     void * backend_data;
146     struct virtio_dev_state * virtio_dev;
147     struct list_head dev_link;
148 };
149
150
151 static int virtio_init_state(struct virtio_net_state * virtio) 
152 {
153     virtio->rx_vq.queue_size = RX_QUEUE_SIZE;
154     virtio->tx_vq.queue_size = TX_QUEUE_SIZE;
155     virtio->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
156
157     virtio->rx_vq.ring_desc_addr = 0;
158     virtio->rx_vq.ring_avail_addr = 0;
159     virtio->rx_vq.ring_used_addr = 0;
160     virtio->rx_vq.pfn = 0;
161     virtio->rx_vq.cur_avail_idx = 0;
162
163     virtio->tx_vq.ring_desc_addr = 0;
164     virtio->tx_vq.ring_avail_addr = 0;
165     virtio->tx_vq.ring_used_addr = 0;
166     virtio->tx_vq.pfn = 0;
167     virtio->tx_vq.cur_avail_idx = 0;
168
169     virtio->ctrl_vq.ring_desc_addr = 0;
170     virtio->ctrl_vq.ring_avail_addr = 0;
171     virtio->ctrl_vq.ring_used_addr = 0;
172     virtio->ctrl_vq.pfn = 0;
173     virtio->ctrl_vq.cur_avail_idx = 0;
174
175     virtio->virtio_cfg.pci_isr = 0;
176
177     virtio->mergeable_rx_bufs = 1;
178         
179     virtio->virtio_cfg.host_features = 0 | (1 << VIRTIO_NET_F_MAC);
180     if(virtio->mergeable_rx_bufs) {
181         virtio->virtio_cfg.host_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
182     }
183
184     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
185         (v3_lock_init(&(virtio->tx_lock)) == -1)){
186         PrintError("Virtio NIC: Failure to init locks for net_state\n");
187     }
188
189     return 0;
190 }
191
192 static int tx_one_pkt(struct guest_info * core, 
193                       struct virtio_net_state * virtio, 
194                       struct vring_desc * buf_desc) 
195 {
196     uint8_t * buf = NULL;
197     uint32_t len = buf_desc->length;
198     int synchronize = virtio->tx_notify;
199
200     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
201         PrintDebug("Could not translate buffer address\n");
202         return -1;
203     }
204
205     V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len);
206     if(net_debug >= 4){
207         v3_hexdump(buf, len, NULL, 0);
208     }
209
210     if(virtio->net_ops->send(buf, len, synchronize, virtio->backend_data) < 0){
211         virtio->stats.tx_dropped ++;
212         return -1;
213     }
214
215     virtio->stats.tx_pkts ++;
216     virtio->stats.tx_bytes += len;
217
218     return 0;
219 }
220
221
222 /*copy data into ring buffer */
223 static inline int copy_data_to_desc(struct guest_info * core, 
224                   struct virtio_net_state * virtio_state, 
225                   struct vring_desc * desc, 
226                   uchar_t * buf, 
227                   uint_t buf_len,
228                   uint_t dst_offset){
229     uint32_t len;
230     uint8_t * desc_buf = NULL;
231
232     if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
233         PrintDebug("Could not translate buffer address\n");
234         return -1;
235     }
236     len = (desc->length < (buf_len+dst_offset))?(desc->length - dst_offset):buf_len;
237     memcpy(desc_buf + dst_offset, buf, len);
238
239     return len;
240 }
241
242
243 static inline int get_desc_count(struct virtio_queue * q, int index) {
244     struct vring_desc * tmp_desc = &(q->desc[index]);
245     int cnt = 1;
246     
247     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
248         tmp_desc = &(q->desc[tmp_desc->next]);
249         cnt++;
250     }
251
252     return cnt;
253 }
254
255 static inline void enable_cb(struct virtio_queue *queue){
256     if(queue->used){
257         queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
258     }
259 }
260
261 static inline void disable_cb(struct virtio_queue *queue) {
262     if(queue->used){
263         queue->used->flags |= VRING_NO_NOTIFY_FLAG;
264     }
265 }
266
267 static int handle_pkt_tx(struct guest_info * core, 
268                          struct virtio_net_state * virtio_state) 
269 {
270     struct virtio_queue *q = &(virtio_state->tx_vq);
271     int txed = 0;
272     unsigned long flags; 
273
274     if (!q->ring_avail_addr) {
275         return -1;
276     }
277
278     flags = v3_lock_irqsave(virtio_state->tx_lock);
279     while (q->cur_avail_idx != q->avail->index) {
280         struct virtio_net_hdr_mrg_rxbuf * hdr = NULL;
281         struct vring_desc * hdr_desc = NULL;
282         addr_t hdr_addr = 0;
283         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
284         int desc_cnt = get_desc_count(q, desc_idx);
285
286         if(desc_cnt != 2){
287             PrintError("VNIC: merged rx buffer not supported, desc_cnt %d\n", desc_cnt);
288             goto exit_error;
289         }
290
291         hdr_desc = &(q->desc[desc_idx]);
292         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
293             PrintError("Could not translate block header address\n");
294             goto exit_error;
295         }
296
297         hdr = (struct virtio_net_hdr_mrg_rxbuf *)hdr_addr;
298         desc_idx = hdr_desc->next;
299
300         V3_Net_Print(2, "Virtio NIC: TX hdr count : %d\n", hdr->num_buffers);
301
302         /* here we assumed that one ethernet pkt is not splitted into multiple buffer */        
303         struct vring_desc * buf_desc = &(q->desc[desc_idx]);
304         if (tx_one_pkt(core, virtio_state, buf_desc) == -1) {
305             PrintError("Virtio NIC: Error handling nic operation\n");
306             goto exit_error;
307         }
308         if(buf_desc->next & VIRTIO_NEXT_FLAG){
309             PrintError("Virtio NIC: TX more buffer need to read\n");
310         }
311             
312         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
313         q->used->ring[q->used->index % q->queue_size].length = buf_desc->length; /* What do we set this to???? */
314         q->used->index ++;
315         
316         q->cur_avail_idx ++;
317
318         txed ++;
319     }
320
321     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
322
323     if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
324         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev);
325         virtio_state->virtio_cfg.pci_isr = 0x1;
326         virtio_state->stats.rx_interrupts ++;
327     }
328
329     if(txed > 0) {
330         V3_Net_Print(2, "Virtio Handle TX: txed pkts: %d\n", txed);
331     }
332
333     return 0;
334
335 exit_error:
336         
337     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
338     return -1;
339 }
340
341
342 static int virtio_setup_queue(struct guest_info *core, 
343                               struct virtio_net_state * virtio_state, 
344                               struct virtio_queue * queue, 
345                               addr_t pfn, addr_t page_addr) {
346     queue->pfn = pfn;
347                 
348     queue->ring_desc_addr = page_addr;
349     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
350     queue->ring_used_addr = ((queue->ring_avail_addr) + 
351                              (sizeof(struct vring_avail)) + 
352                              (queue->queue_size * sizeof(uint16_t)));
353
354     // round up to next page boundary.
355     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
356     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
357         PrintError("Could not translate ring descriptor address\n");
358          return -1;
359     }
360  
361     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
362         PrintError("Could not translate ring available address\n");
363         return -1;
364     }
365
366     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
367         PrintError("Could not translate ring used address\n");
368         return -1;
369     }
370
371     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
372                (void *)(queue->ring_desc_addr),
373                (void *)(queue->ring_avail_addr),
374                (void *)(queue->ring_used_addr));
375     
376     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
377                queue->desc, queue->avail, queue->used);
378     
379     return 0;
380 }
381
382 static int virtio_io_write(struct guest_info *core, 
383                            uint16_t port, void * src, 
384                            uint_t length, void * private_data) 
385 {
386     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
387     int port_idx = port % virtio->io_range_size;
388
389     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n", private_data,
390                port, port_idx,  length, *(uint32_t *)src);
391
392     switch (port_idx) {
393         case GUEST_FEATURES_PORT:
394             if (length != 4) {
395                 PrintError("Illegal write length for guest features\n");
396                 return -1;
397             }       
398             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
399             break;
400                 
401         case VRING_PG_NUM_PORT:
402             if (length != 4) {
403                 PrintError("Illegal write length for page frame number\n");
404                 return -1;
405             }
406             addr_t pfn = *(uint32_t *)src;
407             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
408             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
409             switch (queue_idx) {
410                 case 0:
411                     virtio_setup_queue(core, virtio, &virtio->rx_vq, pfn, page_addr);
412                     break;
413                 case 1:
414                     virtio_setup_queue(core, virtio, &virtio->tx_vq, pfn, page_addr);
415                     if(virtio->tx_notify == 0){
416                         disable_cb(&virtio->tx_vq);
417                         vnet_thread_wakeup(virtio->poll_thread);
418                     }
419                     break;
420                 case 2:
421                     virtio_setup_queue(core, virtio, &virtio->ctrl_vq, pfn, page_addr);
422                     break;          
423                 default:
424                     break;
425             }
426             break;
427                 
428         case VRING_Q_SEL_PORT:
429             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
430             if (virtio->virtio_cfg.vring_queue_selector > 2) {
431                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
432                            virtio->virtio_cfg.vring_queue_selector);
433                 return -1;
434             }
435             break;
436                 
437         case VRING_Q_NOTIFY_PORT: 
438             {
439                 uint16_t queue_idx = *(uint16_t *)src;                  
440                 if (queue_idx == 0){
441                     /* receive queue refill */
442                     virtio->stats.tx_interrupts ++;
443                 } else if (queue_idx == 1){
444                     if (handle_pkt_tx(core, virtio) == -1) {
445                         PrintError("Could not handle Virtio NIC tx kick\n");
446                         return -1;
447                     }
448                     virtio->stats.tx_interrupts ++;
449                 } else if (queue_idx == 2){
450                     /* ctrl */
451                 } else {
452                     PrintError("Wrong queue index %d\n", queue_idx);
453                 }       
454                 break;          
455             }
456         
457         case VIRTIO_STATUS_PORT:
458             virtio->virtio_cfg.status = *(uint8_t *)src;
459             if (virtio->virtio_cfg.status == 0) {
460                 virtio_init_state(virtio);
461             }
462             break;
463
464         case VIRTIO_ISR_PORT:
465             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
466             break;
467                 
468         default:
469             return -1;
470             break;
471     }
472
473     return length;
474 }
475
476 static int virtio_io_read(struct guest_info *core, 
477                           uint16_t port, void * dst, 
478                           uint_t length, void * private_data) 
479 {
480     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
481     int port_idx = port % virtio->io_range_size;
482     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
483
484     PrintDebug("Virtio NIC %p: Read  for port 0x%x (index =%d), length=%d\n", private_data,
485                port, port_idx, length);
486         
487     switch (port_idx) {
488         case HOST_FEATURES_PORT:
489             if (length != 4) {
490                 PrintError("Illegal read length for host features\n");
491                 //return -1;
492             }
493             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
494             break;
495
496         case VRING_PG_NUM_PORT:
497             if (length != 4) {
498                 PrintError("Illegal read length for page frame number\n");
499                 return -1;
500             }
501             switch (queue_idx) {
502                 case 0:
503                     *(uint32_t *)dst = virtio->rx_vq.pfn;
504                     break;
505                 case 1:
506                     *(uint32_t *)dst = virtio->tx_vq.pfn;
507                     break;      
508                 case 2:
509                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
510                     break;
511                 default:
512                     break;
513             }
514             break;
515
516         case VRING_SIZE_PORT:
517             if (length != 2) {
518                 PrintError("Illegal read length for vring size\n");
519                 return -1;
520             }
521             switch (queue_idx) {
522                 case 0:
523                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
524                     break;
525                 case 1:
526                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
527                     break;      
528                 case 2:
529                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
530                     break;
531                 default:
532                     break;
533             }
534             break;
535
536         case VIRTIO_STATUS_PORT:
537             if (length != 1) {
538                 PrintError("Illegal read length for status\n");
539                 return -1;
540             }
541             *(uint8_t *)dst = virtio->virtio_cfg.status;
542             break;
543                 
544         case VIRTIO_ISR_PORT:
545             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
546             virtio->virtio_cfg.pci_isr = 0;
547             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
548             break;
549
550         case VIRTIO_NET_CONFIG ... VIRTIO_NET_CONFIG + ETH_ALEN:
551             *(uint8_t *)dst = virtio->net_cfg.mac[port_idx-VIRTIO_NET_CONFIG];
552             break;
553
554         default:
555             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", port_idx);
556             return -1;
557     }
558
559     return length;
560 }
561
562
563 /* receiving raw ethernet pkt from backend */
564 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
565     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
566     struct virtio_queue * q = &(virtio->rx_vq);
567     struct virtio_net_hdr_mrg_rxbuf hdr;
568     unsigned long flags;
569     uint8_t kick_guest = 0;
570
571     V3_Net_Print(2, "Virtio-NIC: virtio_rx: size: %d\n", size);
572
573     if (!q->ring_avail_addr) {
574         V3_Net_Print(2, "Virtio NIC: RX Queue not set\n");
575         virtio->stats.rx_dropped ++;
576         
577         return -1;
578     }
579
580     memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
581
582     flags = v3_lock_irqsave(virtio->rx_lock);
583
584     if (q->cur_avail_idx != q->avail->index){
585         uint16_t buf_idx;
586         struct vring_desc * buf_desc;
587         uint32_t hdr_len, len;
588        uint32_t offset = 0;
589
590         hdr_len = (virtio->mergeable_rx_bufs)?
591             sizeof(struct virtio_net_hdr_mrg_rxbuf):sizeof(struct virtio_net_hdr);
592
593         if(virtio->mergeable_rx_bufs){/* merged buffer */
594             struct vring_desc * hdr_desc;
595             uint16_t old_idx = q->cur_avail_idx;
596
597             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
598             hdr_desc = &(q->desc[buf_idx]);
599
600             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
601                                     virtio, hdr_desc, buf, size, hdr_len);
602             if(len < 0){
603                 goto err_exit;
604             }
605             offset += len;
606
607             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
608             q->used->ring[q->used->index % q->queue_size].length = hdr_len + offset;
609             q->cur_avail_idx ++;
610             hdr.num_buffers ++;
611
612             while(offset < size) {
613                 buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
614                 buf_desc = &(q->desc[buf_idx]);
615
616                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
617                                         virtio, buf_desc, buf+offset, size-offset, 0);  
618                 if (len < 0){
619                     V3_Net_Print(2, "Virtio NIC:merged buffer, %d buffer size %d\n", hdr.num_buffers, len);
620                     q->cur_avail_idx = old_idx;
621                     goto err_exit;
622                 }
623                 offset += len;
624                 buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
625
626                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
627                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].length = len;
628                 q->cur_avail_idx ++;   
629
630                 hdr.num_buffers ++;
631             }
632
633             copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
634                               virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
635             q->used->index += hdr.num_buffers;
636         }else{
637             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
638             buf_desc = &(q->desc[buf_idx]);
639
640             /* copy header */
641             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
642                                     virtio, buf_desc, (uchar_t *)&(hdr.hdr), hdr_len, 0);
643             if(len < hdr_len){
644                 V3_Net_Print(2, "Virtio NIC: rx copy header error %d, hdr_len %d\n", len, hdr_len);
645                 goto err_exit;
646             }
647
648             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
649                                     virtio, buf_desc, buf, size, hdr_len);
650             if(len < 0){
651                 V3_Net_Print(2, "Virtio NIC: rx copy data error %d\n", len);
652                 goto err_exit;
653             }
654             offset += len;
655
656             /* copy rest of data */
657             while(offset < size && 
658                   (buf_desc->flags & VIRTIO_NEXT_FLAG)){
659                 buf_desc = &(q->desc[buf_desc->next]);
660                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
661                                         virtio, buf_desc, buf+offset, size-offset, 0);      
662                 if (len < 0) {
663                     break;
664                 }
665                 offset += len;
666             }
667             buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
668
669             if(offset < size){
670                 V3_Net_Print(2, "Virtio NIC: rx not enough ring buffer, buffer size %d\n", len);
671                 goto err_exit;
672             }
673                 
674             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
675             q->used->ring[q->used->index % q->queue_size].length = size + hdr_len; /* This should be the total length of data sent to guest (header+pkt_data) */
676             q->used->index ++;
677             q->cur_avail_idx ++;
678         } 
679
680         virtio->stats.rx_pkts ++;
681         virtio->stats.rx_bytes += size;
682     } else {
683         V3_Net_Print(2, "Virtio NIC: Guest RX queue is full\n");
684         virtio->stats.rx_dropped ++;
685
686         /* kick guest to refill RX queue */
687         kick_guest = 1;
688     }
689
690     v3_unlock_irqrestore(virtio->rx_lock, flags);
691
692     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG) || kick_guest) {
693         V3_Net_Print(2, "Virtio NIC: RX Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
694
695         virtio->virtio_cfg.pci_isr = 0x1;       
696         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
697         virtio->stats.rx_interrupts ++;
698     }
699
700     /* notify guest if it is in guest mode */
701     if((kick_guest || virtio->rx_notify == 1) && 
702         V3_Get_CPU() != virtio->virtio_dev->vm->cores[0].pcpu_id){
703         v3_interrupt_cpu(virtio->virtio_dev->vm, virtio->virtio_dev->vm->cores[0].pcpu_id, 0);
704     }
705
706     return 0;
707
708 err_exit:
709     virtio->stats.rx_dropped ++;
710     v3_unlock_irqrestore(virtio->rx_lock, flags);
711  
712     return -1;
713 }
714
715 static int virtio_free(struct virtio_dev_state * virtio) {
716     struct virtio_net_state * backend = NULL;
717     struct virtio_net_state * tmp = NULL;
718
719
720     list_for_each_entry_safe(backend, tmp, &(virtio->dev_list), dev_link) {
721
722         // unregister from PCI
723
724         list_del(&(backend->dev_link));
725         V3_Free(backend);
726     }
727
728     V3_Free(virtio);
729     return 0;
730 }
731
732
733 static struct v3_device_ops dev_ops = {
734     .free = (int (*)(void *))virtio_free,
735 };
736
737
738 static int virtio_tx_flush(void * args){
739     struct virtio_net_state *virtio  = (struct virtio_net_state *)args;
740
741     V3_Print("Virtio TX Poll Thread Starting for %s\n", virtio->vm->name);
742
743     while(1){
744         if(virtio->tx_notify == 0){
745             handle_pkt_tx(&(virtio->vm->cores[0]), virtio);
746             v3_yield(NULL);
747         }else {
748             vnet_thread_sleep(-1);
749         }
750     }
751
752     return 0;
753 }
754
755 static int register_dev(struct virtio_dev_state * virtio, 
756                         struct virtio_net_state * net_state) 
757 {
758     struct pci_device * pci_dev = NULL;
759     struct v3_pci_bar bars[6];
760     int num_ports = sizeof(struct virtio_config);
761     int tmp_ports = num_ports;
762     int i;
763
764     // This gets the number of ports, rounded up to a power of 2
765     net_state->io_range_size = 1; // must be a power of 2
766     while (tmp_ports > 0) {
767         tmp_ports >>= 1;
768         net_state->io_range_size <<= 1;
769     }
770         
771     /* this is to account for any low order bits being set in num_ports
772       * if there are none, then num_ports was already a power of 2 so we shift right to reset it
773       */
774     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
775         net_state->io_range_size >>= 1;
776     }
777     
778     for (i = 0; i < 6; i++) {
779         bars[i].type = PCI_BAR_NONE;
780     }
781     
782     PrintDebug("Virtio-NIC io_range_size = %d\n", net_state->io_range_size);
783     
784     bars[0].type = PCI_BAR_IO;
785     bars[0].default_base_port = -1;
786     bars[0].num_ports = net_state->io_range_size;
787     bars[0].io_read = virtio_io_read;
788     bars[0].io_write = virtio_io_write;
789     bars[0].private_data = net_state;
790     
791     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
792                                      0, 4/*PCI_AUTO_DEV_NUM*/, 0,
793                                      "LNX_VIRTIO_NIC", bars,
794                                      NULL, NULL, NULL, net_state);
795     
796     if (!pci_dev) {
797         PrintError("Virtio NIC: Could not register PCI Device\n");
798         return -1;
799     }
800
801     PrintDebug("Virtio NIC:  registered to PCI bus\n");
802     
803     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
804     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
805         
806
807     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
808     pci_dev->config_header.class = PCI_CLASS_NETWORK;
809     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
810     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
811     pci_dev->config_header.intr_pin = 1;
812     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
813
814     net_state->pci_dev = pci_dev;
815     net_state->virtio_dev = virtio;
816
817     memcpy(net_state->net_cfg.mac, virtio->mac, 6);                           
818         
819     virtio_init_state(net_state);
820
821     /* Add backend to list of devices */
822     list_add(&(net_state->dev_link), &(virtio->dev_list));
823
824     return 0;
825 }
826
827
828 #define RATE_UPPER_THRESHOLD 10  /* 10000 pkts per second, around 100Mbits */
829 #define RATE_LOWER_THRESHOLD 1
830 #define PROFILE_PERIOD 10000 /*us*/
831
832 static void virtio_nic_timer(struct guest_info * core, 
833                              uint64_t cpu_cycles, uint64_t cpu_freq, 
834                              void * priv_data) {
835     struct virtio_net_state * net_state = (struct virtio_net_state *)priv_data;
836     uint64_t period_us;
837     static int profile_ms = 0;
838
839     if(!net_state->status){ /* VNIC is not in working status */
840         return;
841     }
842
843     period_us = (1000*cpu_cycles)/cpu_freq;
844     net_state->past_us += period_us;
845
846     if(net_state->past_us > PROFILE_PERIOD){ 
847         uint32_t tx_rate, rx_rate;
848         
849         tx_rate = (net_state->stats.tx_pkts - net_state->tx_pkts)/(net_state->past_us/1000); /* pkts/per ms */
850         rx_rate = (net_state->stats.rx_pkts - net_state->rx_pkts)/(net_state->past_us/1000);
851
852         net_state->tx_pkts = net_state->stats.tx_pkts;
853         net_state->rx_pkts = net_state->stats.rx_pkts;
854
855         if(tx_rate > RATE_UPPER_THRESHOLD && net_state->tx_notify == 1){
856             V3_Print("Virtio NIC: Switch TX to VMM driven mode\n");
857             disable_cb(&(net_state->tx_vq));
858             net_state->tx_notify = 0;
859             vnet_thread_wakeup(net_state->poll_thread);
860         }
861
862         if(tx_rate < RATE_LOWER_THRESHOLD && net_state->tx_notify == 0){
863             V3_Print("Virtio NIC: Switch TX to Guest  driven mode\n");
864             enable_cb(&(net_state->tx_vq));
865             net_state->tx_notify = 1;
866         }
867
868         if(rx_rate > RATE_UPPER_THRESHOLD && net_state->rx_notify == 1){
869             V3_Print("Virtio NIC: Switch RX to VMM None notify mode\n");
870             net_state->rx_notify = 0;
871         }
872
873         if(rx_rate < RATE_LOWER_THRESHOLD && net_state->rx_notify == 0){
874             V3_Print("Virtio NIC: Switch RX to VMM notify mode\n");
875             net_state->rx_notify = 1;
876         }
877
878         net_state->past_us = 0;
879     }
880
881     profile_ms += period_us/1000;
882     if(profile_ms > 20000){
883         V3_Net_Print(1, "Virtio NIC: TX: Pkt: %lld, Bytes: %lld\n\t\tRX Pkt: %lld. Bytes: %lld\n\t\tDropped: tx %lld, rx %lld\nInterrupts: tx %d, rx %d\nTotal Exit: %lld\n",
884                 net_state->stats.tx_pkts, net_state->stats.tx_bytes,
885                 net_state->stats.rx_pkts, net_state->stats.rx_bytes,
886                 net_state->stats.tx_dropped, net_state->stats.rx_dropped,
887                 net_state->stats.tx_interrupts, net_state->stats.rx_interrupts,
888                 net_state->vm->cores[0].num_exits);
889         profile_ms = 0;
890     }
891 }
892
893 static struct v3_timer_ops timer_ops = {
894     .update_timer = virtio_nic_timer,
895 };
896
897
898 static int connect_fn(struct v3_vm_info * info, 
899                       void * frontend_data, 
900                       struct v3_dev_net_ops * ops, 
901                       v3_cfg_tree_t * cfg, 
902                       void * private_data) {
903     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
904     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
905
906     memset(net_state, 0, sizeof(struct virtio_net_state));
907     register_dev(virtio, net_state);
908
909     net_state->vm = info;
910     net_state->net_ops = ops;
911     net_state->backend_data = private_data;
912     net_state->virtio_dev = virtio;
913     net_state->tx_notify = 0;
914     net_state->rx_notify = 0;
915         
916     net_state->timer = v3_add_timer(&(info->cores[0]),&timer_ops,net_state);
917
918     PrintError("net_state 0x%p\n", (void *)net_state);
919
920     ops->recv = virtio_rx;
921     ops->frontend_data = net_state;
922     memcpy(ops->fnt_mac, virtio->mac, ETH_ALEN);
923
924     net_state->poll_thread = vnet_start_thread(virtio_tx_flush, (void *)net_state, "Virtio_Poll");
925
926     net_state->status = 1;
927
928     return 0;
929 }
930
931 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
932     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
933     struct virtio_dev_state * virtio_state = NULL;
934     char * dev_id = v3_cfg_val(cfg, "ID");
935     char macstr[128];
936     char * str = v3_cfg_val(cfg, "mac");
937     memcpy(macstr, str, strlen(str));
938
939     if (pci_bus == NULL) {
940         PrintError("Virtio NIC: VirtIO devices require a PCI Bus");
941         return -1;
942     }
943
944     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
945     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
946
947     INIT_LIST_HEAD(&(virtio_state->dev_list));
948     virtio_state->pci_bus = pci_bus;
949     virtio_state->vm = vm;
950
951     if (macstr != NULL && !str2mac(macstr, virtio_state->mac)) {
952         PrintDebug("Virtio NIC: Mac specified %s\n", macstr);
953     }else {
954         random_ethaddr(virtio_state->mac);
955     }
956
957     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
958
959     if (dev == NULL) {
960         PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
961         V3_Free(virtio_state);
962         return -1;
963     }
964
965     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
966         PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
967         v3_remove_device(dev);
968         return -1;
969     }
970         
971     return 0;
972 }
973
974 device_register("LNX_VIRTIO_NIC", virtio_init)
975