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.


Restructure of direct host network bridge.
[palacios-OLD.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 nic_statistics stats;
135
136     struct v3_dev_net_ops * net_ops;
137     v3_lock_t rx_lock, tx_lock;
138
139     uint8_t tx_notify, rx_notify;
140     uint32_t tx_pkts, rx_pkts;
141     uint64_t past_us;
142
143     void * backend_data;
144     struct virtio_dev_state * virtio_dev;
145     struct list_head dev_link;
146 };
147
148
149 static int virtio_init_state(struct virtio_net_state * virtio) 
150 {
151     virtio->rx_vq.queue_size = RX_QUEUE_SIZE;
152     virtio->tx_vq.queue_size = TX_QUEUE_SIZE;
153     virtio->ctrl_vq.queue_size = CTRL_QUEUE_SIZE;
154
155     virtio->rx_vq.ring_desc_addr = 0;
156     virtio->rx_vq.ring_avail_addr = 0;
157     virtio->rx_vq.ring_used_addr = 0;
158     virtio->rx_vq.pfn = 0;
159     virtio->rx_vq.cur_avail_idx = 0;
160
161     virtio->tx_vq.ring_desc_addr = 0;
162     virtio->tx_vq.ring_avail_addr = 0;
163     virtio->tx_vq.ring_used_addr = 0;
164     virtio->tx_vq.pfn = 0;
165     virtio->tx_vq.cur_avail_idx = 0;
166
167     virtio->ctrl_vq.ring_desc_addr = 0;
168     virtio->ctrl_vq.ring_avail_addr = 0;
169     virtio->ctrl_vq.ring_used_addr = 0;
170     virtio->ctrl_vq.pfn = 0;
171     virtio->ctrl_vq.cur_avail_idx = 0;
172
173     virtio->virtio_cfg.pci_isr = 0;
174
175     virtio->mergeable_rx_bufs = 1;
176         
177     virtio->virtio_cfg.host_features = 0 | (1 << VIRTIO_NET_F_MAC);
178     if(virtio->mergeable_rx_bufs) {
179         virtio->virtio_cfg.host_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
180     }
181
182     if ((v3_lock_init(&(virtio->rx_lock)) == -1) ||
183         (v3_lock_init(&(virtio->tx_lock)) == -1)){
184         PrintError("Virtio NIC: Failure to init locks for net_state\n");
185     }
186
187     return 0;
188 }
189
190 static int tx_one_pkt(struct guest_info * core, 
191                       struct virtio_net_state * virtio, 
192                       struct vring_desc * buf_desc) 
193 {
194     uint8_t * buf = NULL;
195     uint32_t len = buf_desc->length;
196
197     if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
198         PrintDebug("Could not translate buffer address\n");
199         return -1;
200     }
201     
202     V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len);
203     if(net_debug >= 4){
204         v3_hexdump(buf, len, NULL, 0);
205     }
206
207     if(virtio->net_ops->send(buf, len, virtio->backend_data) < 0){
208         virtio->stats.tx_dropped ++;
209         return -1;
210     }
211     
212     virtio->stats.tx_pkts ++;
213     virtio->stats.tx_bytes += len;
214     
215     return 0;
216 }
217
218
219 /*copy data into ring buffer */
220 static inline int copy_data_to_desc(struct guest_info * core, 
221                                     struct virtio_net_state * virtio_state, 
222                                     struct vring_desc * desc, 
223                                     uchar_t * buf, 
224                                     uint_t buf_len,
225                                     uint_t dst_offset){
226     uint32_t len;
227     uint8_t * desc_buf = NULL;
228     
229     if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) {
230         PrintDebug("Could not translate buffer address\n");
231         return -1;
232     }
233     len = (desc->length < (buf_len+dst_offset))?(desc->length - dst_offset):buf_len;
234     memcpy(desc_buf + dst_offset, buf, len);
235
236     return len;
237 }
238
239
240 static inline int get_desc_count(struct virtio_queue * q, int index) {
241     struct vring_desc * tmp_desc = &(q->desc[index]);
242     int cnt = 1;
243     
244     while (tmp_desc->flags & VIRTIO_NEXT_FLAG) {
245         tmp_desc = &(q->desc[tmp_desc->next]);
246         cnt++;
247     }
248
249     return cnt;
250 }
251
252 static inline void enable_cb(struct virtio_queue *queue){
253     if(queue->used){
254         queue->used->flags &= ~ VRING_NO_NOTIFY_FLAG;
255     }
256 }
257
258 static inline void disable_cb(struct virtio_queue *queue) {
259     if(queue->used){
260         queue->used->flags |= VRING_NO_NOTIFY_FLAG;
261     }
262 }
263
264 static int handle_pkt_tx(struct guest_info * core, 
265                          struct virtio_net_state * virtio_state,
266                          int quote)
267 {
268     struct virtio_queue *q = &(virtio_state->tx_vq);
269     int txed = 0, left = 0;
270     unsigned long flags;
271
272     if (!q->ring_avail_addr) {
273         return -1;
274     }
275
276     flags = v3_lock_irqsave(virtio_state->tx_lock);
277     while (q->cur_avail_idx != q->avail->index) {
278         struct virtio_net_hdr_mrg_rxbuf * hdr = NULL;
279         struct vring_desc * hdr_desc = NULL;
280         addr_t hdr_addr = 0;
281         uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
282         int desc_cnt = get_desc_count(q, desc_idx);
283
284         if(desc_cnt != 2){
285             PrintError("VNIC: merged rx buffer not supported, desc_cnt %d\n", desc_cnt);
286             goto exit_error;
287         }
288
289         hdr_desc = &(q->desc[desc_idx]);
290         if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
291             PrintError("Could not translate block header address\n");
292             goto exit_error;
293         }
294
295         hdr = (struct virtio_net_hdr_mrg_rxbuf *)hdr_addr;
296         desc_idx = hdr_desc->next;
297
298         V3_Net_Print(2, "Virtio NIC: TX hdr count : %d\n", hdr->num_buffers);
299
300         /* here we assumed that one ethernet pkt is not splitted into multiple buffer */        
301         struct vring_desc * buf_desc = &(q->desc[desc_idx]);
302         if (tx_one_pkt(core, virtio_state, buf_desc) == -1) {
303             PrintError("Virtio NIC: Fails to send packet\n");
304         }
305         if(buf_desc->next & VIRTIO_NEXT_FLAG){
306             PrintError("Virtio NIC: TX more buffer need to read\n");
307         }
308         
309         q->used->ring[q->used->index % q->queue_size].id = 
310             q->avail->ring[q->cur_avail_idx % q->queue_size];
311         
312         q->used->ring[q->used->index % q->queue_size].length = 
313             buf_desc->length; /* What do we set this to???? */
314         
315         q->used->index ++;
316         q->cur_avail_idx ++;
317         
318         if(++txed >= quote && quote > 0){
319             left = (q->cur_avail_idx != q->avail->index);
320             break;
321         }
322     }
323     
324     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
325     
326     if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
327         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 
328                          0, virtio_state->pci_dev);
329         virtio_state->virtio_cfg.pci_isr = 0x1;
330         virtio_state->stats.rx_interrupts ++;
331     }
332
333     if(txed > 0) {
334         V3_Net_Print(2, "Virtio Handle TX: txed pkts: %d, left %d\n", txed, left);
335     }
336
337     return left;
338     
339  exit_error:
340     
341     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
342     return -1;
343 }
344
345
346 static int virtio_setup_queue(struct guest_info *core, 
347                               struct virtio_net_state * virtio_state, 
348                               struct virtio_queue * queue, 
349                               addr_t pfn, addr_t page_addr) {
350     queue->pfn = pfn;
351                 
352     queue->ring_desc_addr = page_addr;
353     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
354     queue->ring_used_addr = ((queue->ring_avail_addr) + 
355                              (sizeof(struct vring_avail)) + 
356                              (queue->queue_size * sizeof(uint16_t)));
357
358     // round up to next page boundary.
359     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
360     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
361         PrintError("Could not translate ring descriptor address\n");
362          return -1;
363     }
364  
365     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
366         PrintError("Could not translate ring available address\n");
367         return -1;
368     }
369
370     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
371         PrintError("Could not translate ring used address\n");
372         return -1;
373     }
374
375     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
376                (void *)(queue->ring_desc_addr),
377                (void *)(queue->ring_avail_addr),
378                (void *)(queue->ring_used_addr));
379     
380     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
381                queue->desc, queue->avail, queue->used);
382     
383     return 0;
384 }
385
386 static int virtio_io_write(struct guest_info *core, 
387                            uint16_t port, void * src, 
388                            uint_t length, void * private_data) 
389 {
390     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
391     int port_idx = port % virtio->io_range_size;
392
393     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n",
394                private_data, port, port_idx,  
395                length, *(uint32_t *)src);
396
397     switch (port_idx) {
398         case GUEST_FEATURES_PORT:
399             if (length != 4) {
400                 PrintError("Illegal write length for guest features\n");
401                 return -1;
402             }       
403             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
404             break;
405                 
406         case VRING_PG_NUM_PORT:
407             if (length != 4) {
408                 PrintError("Illegal write length for page frame number\n");
409                 return -1;
410             }
411             addr_t pfn = *(uint32_t *)src;
412             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
413             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
414             switch (queue_idx) {
415                 case 0:
416                     virtio_setup_queue(core, virtio,
417                                        &virtio->rx_vq, 
418                                        pfn, page_addr);
419                     break;
420                 case 1:
421                     virtio_setup_queue(core, virtio, 
422                                        &virtio->tx_vq, 
423                                        pfn, page_addr);
424                     if(virtio->tx_notify == 0){
425                         disable_cb(&virtio->tx_vq);
426                     }
427                         virtio->status = 1;
428                     break;
429                 case 2:
430                     virtio_setup_queue(core, virtio, 
431                                        &virtio->ctrl_vq, 
432                                        pfn, page_addr);
433                     break;          
434                 default:
435                     break;
436             }
437             break;
438                 
439         case VRING_Q_SEL_PORT:
440             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
441             if (virtio->virtio_cfg.vring_queue_selector > 2) {
442                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
443                            virtio->virtio_cfg.vring_queue_selector);
444                 return -1;
445             }
446             break;
447                 
448         case VRING_Q_NOTIFY_PORT: 
449             {
450                 uint16_t queue_idx = *(uint16_t *)src;                  
451                 if (queue_idx == 0){
452                     /* receive queue refill */
453                     virtio->stats.tx_interrupts ++;
454                 } else if (queue_idx == 1){
455                     if (handle_pkt_tx(core, virtio, 0) < 0) {
456                         PrintError("Virtio NIC: Error to handle packet TX\n");
457                         return -1;
458                     }
459                     virtio->stats.tx_interrupts ++;
460                 } else if (queue_idx == 2){
461                     /* ctrl */
462                 } else {
463                     PrintError("Virtio NIC: Wrong queue index %d\n", queue_idx);
464                 }       
465                 break;          
466             }
467         
468         case VIRTIO_STATUS_PORT:
469             virtio->virtio_cfg.status = *(uint8_t *)src;
470             if (virtio->virtio_cfg.status == 0) {
471                 virtio_init_state(virtio);
472             }
473             break;
474
475         case VIRTIO_ISR_PORT:
476             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
477             break;
478                 
479         default:
480             return -1;
481             break;
482     }
483
484     return length;
485 }
486
487 static int virtio_io_read(struct guest_info *core, 
488                           uint16_t port, void * dst, 
489                           uint_t length, void * private_data) 
490 {
491     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
492     int port_idx = port % virtio->io_range_size;
493     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
494
495     PrintDebug("Virtio NIC %p: Read  for port 0x%x (index =%d), length=%d\n", 
496                private_data, port, port_idx, length);
497         
498     switch (port_idx) {
499         case HOST_FEATURES_PORT:
500             if (length != 4) {
501                 PrintError("Virtio NIC: Illegal read length for host features\n");
502                 //return -1;
503             }
504             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
505             break;
506
507         case VRING_PG_NUM_PORT:
508             if (length != 4) {
509                 PrintError("Virtio NIC: Illegal read length for page frame number\n");
510                 return -1;
511             }
512             switch (queue_idx) {
513                 case 0:
514                     *(uint32_t *)dst = virtio->rx_vq.pfn;
515                     break;
516                 case 1:
517                     *(uint32_t *)dst = virtio->tx_vq.pfn;
518                     break;      
519                 case 2:
520                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
521                     break;
522                 default:
523                     break;
524             }
525             break;
526
527         case VRING_SIZE_PORT:
528             if (length != 2) {
529                 PrintError("Virtio NIC: Illegal read length for vring size\n");
530                 return -1;
531             }
532             switch (queue_idx) {
533                 case 0:
534                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
535                     break;
536                 case 1:
537                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
538                     break;      
539                 case 2:
540                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
541                     break;
542                 default:
543                     break;
544             }
545             break;
546
547         case VIRTIO_STATUS_PORT:
548             if (length != 1) {
549                 PrintError("Virtio NIC: Illegal read length for status\n");
550                 return -1;
551             }
552             *(uint8_t *)dst = virtio->virtio_cfg.status;
553             break;
554                 
555         case VIRTIO_ISR_PORT:
556             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
557             virtio->virtio_cfg.pci_isr = 0;
558             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 
559                              0, virtio->pci_dev);
560             break;
561
562         case VIRTIO_NET_CONFIG ... VIRTIO_NET_CONFIG + ETH_ALEN:
563             *(uint8_t *)dst = virtio->net_cfg.mac[port_idx-VIRTIO_NET_CONFIG];
564             break;
565
566         default:
567             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", 
568                        port_idx);
569             return -1;
570     }
571
572     return length;
573 }
574
575
576 /* receiving raw ethernet pkt from backend */
577 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
578     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
579     struct virtio_queue * q = &(virtio->rx_vq);
580     struct virtio_net_hdr_mrg_rxbuf hdr;
581     unsigned long flags;
582     uint8_t kick_guest = 0;
583
584     V3_Net_Print(2, "Virtio NIC: virtio_rx: size: %d\n", size);
585
586     if (!q->ring_avail_addr) {
587         V3_Net_Print(2, "Virtio NIC: RX Queue not set\n");
588         virtio->stats.rx_dropped ++;
589         
590         return -1;
591     }
592
593     memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
594
595     flags = v3_lock_irqsave(virtio->rx_lock);
596
597     if (q->cur_avail_idx != q->avail->index){
598         uint16_t buf_idx;
599         struct vring_desc * buf_desc;
600         uint32_t hdr_len, len;
601         uint32_t offset = 0;
602
603         hdr_len = (virtio->mergeable_rx_bufs)?
604             sizeof(struct virtio_net_hdr_mrg_rxbuf):
605             sizeof(struct virtio_net_hdr);
606
607         if(virtio->mergeable_rx_bufs){/* merged buffer */
608             struct vring_desc * hdr_desc;
609             uint16_t old_idx = q->cur_avail_idx;
610
611             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
612             hdr_desc = &(q->desc[buf_idx]);
613
614             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
615                                     virtio, hdr_desc, buf, size, hdr_len);
616             if(len < 0){
617                 goto err_exit;
618             }
619             offset += len;
620
621             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
622             q->used->ring[q->used->index % q->queue_size].length = hdr_len + offset;
623             q->cur_avail_idx ++;
624             hdr.num_buffers ++;
625
626             while(offset < size) {
627                 buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
628                 buf_desc = &(q->desc[buf_idx]);
629
630                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
631                                         virtio, buf_desc, buf+offset, size-offset, 0);  
632                 if (len < 0){
633                     V3_Net_Print(2, "Virtio NIC: merged buffer, %d buffer size %d\n", 
634                                  hdr.num_buffers, len);
635                     q->cur_avail_idx = old_idx;
636                     goto err_exit;
637                 }
638                 offset += len;
639                 buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
640
641                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
642                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].length = len;
643                 q->cur_avail_idx ++;   
644
645                 hdr.num_buffers ++;
646             }
647
648             copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
649                               virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
650             q->used->index += hdr.num_buffers;
651         }else{
652             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
653             buf_desc = &(q->desc[buf_idx]);
654
655             /* copy header */
656             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
657                                     virtio, buf_desc, (uchar_t *)&(hdr.hdr), hdr_len, 0);
658             if(len < hdr_len){
659                 V3_Net_Print(2, "Virtio NIC: rx copy header error %d, hdr_len %d\n", 
660                              len, hdr_len);
661                 goto err_exit;
662             }
663
664             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
665                                     virtio, buf_desc, buf, size, hdr_len);
666             if(len < 0){
667                 V3_Net_Print(2, "Virtio NIC: rx copy data error %d\n", len);
668                 goto err_exit;
669             }
670             offset += len;
671
672             /* copy rest of data */
673             while(offset < size && 
674                   (buf_desc->flags & VIRTIO_NEXT_FLAG)){
675                 buf_desc = &(q->desc[buf_desc->next]);
676                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
677                                         virtio, buf_desc, buf+offset, size-offset, 0);      
678                 if (len < 0) {
679                     break;
680                 }
681                 offset += len;
682             }
683             buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
684
685             if(offset < size){
686                 V3_Net_Print(2, "Virtio NIC: rx not enough ring buffer, buffer size %d\n", 
687                              len);
688                 goto err_exit;
689             }
690                 
691             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
692             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) */
693             q->used->index ++;
694             q->cur_avail_idx ++;
695         } 
696
697         virtio->stats.rx_pkts ++;
698         virtio->stats.rx_bytes += size;
699     } else {
700         V3_Net_Print(2, "Virtio NIC: Guest RX queue is full\n");
701         virtio->stats.rx_dropped ++;
702
703         /* kick guest to refill RX queue */
704         kick_guest = 1;
705     }
706
707     v3_unlock_irqrestore(virtio->rx_lock, flags);
708
709     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG) || kick_guest) {
710         V3_Net_Print(2, "Virtio NIC: RX Raising IRQ %d\n",  
711                      virtio->pci_dev->config_header.intr_line);
712
713         virtio->virtio_cfg.pci_isr = 0x1;       
714         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
715         virtio->stats.rx_interrupts ++;
716     }
717
718     /* notify guest if it is in guest mode */
719     if((kick_guest || virtio->rx_notify == 1) && 
720         V3_Get_CPU() != virtio->virtio_dev->vm->cores[0].pcpu_id){
721         v3_interrupt_cpu(virtio->virtio_dev->vm, 
722                          virtio->virtio_dev->vm->cores[0].pcpu_id, 
723                          0);
724     }
725
726     return 0;
727
728 err_exit:
729     virtio->stats.rx_dropped ++;
730     v3_unlock_irqrestore(virtio->rx_lock, flags);
731  
732     return -1;
733 }
734
735 static int virtio_free(struct virtio_dev_state * virtio) {
736     struct virtio_net_state * backend = NULL;
737     struct virtio_net_state * tmp = NULL;
738
739
740     list_for_each_entry_safe(backend, tmp, &(virtio->dev_list), dev_link) {
741
742         // unregister from PCI
743
744         list_del(&(backend->dev_link));
745         V3_Free(backend);
746     }
747
748     V3_Free(virtio);
749     return 0;
750 }
751
752
753 static struct v3_device_ops dev_ops = {
754     .free = (int (*)(void *))virtio_free,
755 };
756
757
758 static int virtio_poll(int quote, void * data){
759     struct virtio_net_state * virtio  = (struct virtio_net_state *)data;
760
761     if(virtio->status) {
762         return handle_pkt_tx(&(virtio->vm->cores[0]), virtio, quote);
763     }
764
765     return 0;
766 }
767
768 static int register_dev(struct virtio_dev_state * virtio, 
769                         struct virtio_net_state * net_state) 
770 {
771     struct pci_device * pci_dev = NULL;
772     struct v3_pci_bar bars[6];
773     int num_ports = sizeof(struct virtio_config);
774     int tmp_ports = num_ports;
775     int i;
776
777     /* This gets the number of ports, rounded up to a power of 2 */
778     net_state->io_range_size = 1;
779     while (tmp_ports > 0) {
780         tmp_ports >>= 1;
781         net_state->io_range_size <<= 1;
782     }
783         
784     /* this is to account for any low order bits being set in num_ports
785      * if there are none, then num_ports was already a power of 2 so we shift right to reset it
786      */
787     if ((num_ports & ((net_state->io_range_size >> 1) - 1)) == 0) {
788         net_state->io_range_size >>= 1;
789     }
790     
791     for (i = 0; i < 6; i++) {
792         bars[i].type = PCI_BAR_NONE;
793     }
794     
795     PrintDebug("Virtio NIC: io_range_size = %d\n", 
796                net_state->io_range_size);
797     
798     bars[0].type = PCI_BAR_IO;
799     bars[0].default_base_port = -1;
800     bars[0].num_ports = net_state->io_range_size;
801     bars[0].io_read = virtio_io_read;
802     bars[0].io_write = virtio_io_write;
803     bars[0].private_data = net_state;
804     
805     pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
806                                      0, PCI_AUTO_DEV_NUM, 0,
807                                      "LNX_VIRTIO_NIC", bars,
808                                      NULL, NULL, NULL, net_state);
809     
810     if (!pci_dev) {
811         PrintError("Virtio NIC: Could not register PCI Device\n");
812         return -1;
813     }
814
815     PrintDebug("Virtio NIC:  registered to PCI bus\n");
816     
817     pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
818     pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
819         
820
821     pci_dev->config_header.device_id = VIRTIO_NET_DEV_ID;
822     pci_dev->config_header.class = PCI_CLASS_NETWORK;
823     pci_dev->config_header.subclass = PCI_NET_SUBCLASS_OTHER;  
824     pci_dev->config_header.subsystem_id = VIRTIO_NET_SUBDEVICE_ID;
825     pci_dev->config_header.intr_pin = 1;
826     pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
827
828     net_state->pci_dev = pci_dev;
829     net_state->virtio_dev = virtio;
830
831     memcpy(net_state->net_cfg.mac, virtio->mac, 6);                           
832         
833     virtio_init_state(net_state);
834
835     V3_Print("Virtio NIC: Registered Intr Line %d\n", pci_dev->config_header.intr_line);
836
837     /* Add backend to list of devices */
838     list_add(&(net_state->dev_link), &(virtio->dev_list));
839
840     return 0;
841 }
842
843
844 #define RATE_UPPER_THRESHOLD 10  /* 10000 pkts per second, around 100Mbits */
845 #define RATE_LOWER_THRESHOLD 1
846 #define PROFILE_PERIOD 10000 /*us*/
847
848 static void virtio_nic_timer(struct guest_info * core, 
849                              uint64_t cpu_cycles, uint64_t cpu_freq, 
850                              void * priv_data) {
851     struct virtio_net_state * net_state = (struct virtio_net_state *)priv_data;
852     uint64_t period_us;
853     static int profile_ms = 0;
854
855     if(!net_state->status){ /* VNIC is not in working status */
856         return;
857     }
858
859     period_us = (1000*cpu_cycles)/cpu_freq;
860     net_state->past_us += period_us;
861
862     if(net_state->past_us > PROFILE_PERIOD){ 
863         uint32_t tx_rate, rx_rate;
864         
865         tx_rate = (net_state->stats.tx_pkts - net_state->tx_pkts)/(net_state->past_us/1000); /* pkts/per ms */
866         rx_rate = (net_state->stats.rx_pkts - net_state->rx_pkts)/(net_state->past_us/1000);
867
868         net_state->tx_pkts = net_state->stats.tx_pkts;
869         net_state->rx_pkts = net_state->stats.rx_pkts;
870
871         if(tx_rate > RATE_UPPER_THRESHOLD && net_state->tx_notify == 1){
872             V3_Print("Virtio NIC: Switch TX to VMM driven mode\n");
873             disable_cb(&(net_state->tx_vq));
874             net_state->tx_notify = 0;
875         }
876
877         if(tx_rate < RATE_LOWER_THRESHOLD && net_state->tx_notify == 0){
878             V3_Print("Virtio NIC: Switch TX to Guest  driven mode\n");
879             enable_cb(&(net_state->tx_vq));
880             net_state->tx_notify = 1;
881         }
882
883         if(rx_rate > RATE_UPPER_THRESHOLD && net_state->rx_notify == 1){
884             V3_Print("Virtio NIC: Switch RX to VMM None notify mode\n");
885             net_state->rx_notify = 0;
886         }
887
888         if(rx_rate < RATE_LOWER_THRESHOLD && net_state->rx_notify == 0){
889             V3_Print("Virtio NIC: Switch RX to VMM notify mode\n");
890             net_state->rx_notify = 1;
891         }
892
893         net_state->past_us = 0;
894     }
895
896     profile_ms += period_us/1000;
897     if(profile_ms > 20000){
898         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",
899                 net_state->stats.tx_pkts, net_state->stats.tx_bytes,
900                 net_state->stats.rx_pkts, net_state->stats.rx_bytes,
901                 net_state->stats.tx_dropped, net_state->stats.rx_dropped,
902                 net_state->stats.tx_interrupts, net_state->stats.rx_interrupts,
903                 net_state->vm->cores[0].num_exits);
904         profile_ms = 0;
905     }
906 }
907
908 static struct v3_timer_ops timer_ops = {
909     .update_timer = virtio_nic_timer,
910 };
911
912
913 static int connect_fn(struct v3_vm_info * info, 
914                       void * frontend_data, 
915                       struct v3_dev_net_ops * ops, 
916                       v3_cfg_tree_t * cfg, 
917                       void * private_data) {
918     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
919     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
920
921     memset(net_state, 0, sizeof(struct virtio_net_state));
922     register_dev(virtio, net_state);
923
924     net_state->vm = info;
925     net_state->net_ops = ops;
926     net_state->backend_data = private_data;
927     net_state->virtio_dev = virtio;
928     net_state->tx_notify = 1;
929     net_state->rx_notify = 1;
930         
931     net_state->timer = v3_add_timer(&(info->cores[0]),
932                                 &timer_ops,net_state);
933
934     ops->recv = virtio_rx;
935     ops->poll = virtio_poll;
936     ops->config.frontend_data = net_state;
937     ops->config.poll = 1;
938     ops->config.quote = 64;
939     ops->config.fnt_mac = V3_Malloc(ETH_ALEN);  
940     memcpy(ops->config.fnt_mac, virtio->mac, ETH_ALEN);
941
942     return 0;
943 }
944
945 static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
946     struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
947     struct virtio_dev_state * virtio_state = NULL;
948     char * dev_id = v3_cfg_val(cfg, "ID");
949     char macstr[128];
950     char * str = v3_cfg_val(cfg, "mac");
951     memcpy(macstr, str, strlen(str));
952
953     if (pci_bus == NULL) {
954         PrintError("Virtio NIC: Virtio device require a PCI Bus");
955         return -1;
956     }
957
958     virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
959     memset(virtio_state, 0, sizeof(struct virtio_dev_state));
960
961     INIT_LIST_HEAD(&(virtio_state->dev_list));
962     virtio_state->pci_bus = pci_bus;
963     virtio_state->vm = vm;
964
965     if (macstr != NULL && !str2mac(macstr, virtio_state->mac)) {
966         PrintDebug("Virtio NIC: Mac specified %s\n", macstr);
967     }else {
968         random_ethaddr(virtio_state->mac);
969     }
970
971     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
972
973     if (dev == NULL) {
974         PrintError("Virtio NIC: Could not attach device %s\n", dev_id);
975         V3_Free(virtio_state);
976         return -1;
977     }
978
979     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
980         PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
981         v3_remove_device(dev);
982         return -1;
983     }
984         
985     return 0;
986 }
987
988 device_register("LNX_VIRTIO_NIC", virtio_init)
989