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