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.


8032b13be23266ded91c5e406b562d5d64f39860
[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: Error handling nic operation\n");
305             goto exit_error;
306         }
307         if(buf_desc->next & VIRTIO_NEXT_FLAG){
308             PrintError("Virtio NIC: TX more buffer need to read\n");
309         }
310             
311         q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
312         q->used->ring[q->used->index % q->queue_size].length = buf_desc->length; /* What do we set this to???? */
313         q->used->index ++;
314         
315         q->cur_avail_idx ++;
316         
317         if(++txed >= quote && quote > 0){
318             left = (q->cur_avail_idx != q->avail->index);
319             break;
320         }
321     }
322
323     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
324
325     if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
326         v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 
327                          0, virtio_state->pci_dev);
328         virtio_state->virtio_cfg.pci_isr = 0x1;
329         virtio_state->stats.rx_interrupts ++;
330     }
331
332     if(txed > 0) {
333         V3_Net_Print(2, "Virtio Handle TX: txed pkts: %d, left %d\n", txed, left);
334     }
335
336     return left;
337
338 exit_error:
339         
340     v3_unlock_irqrestore(virtio_state->tx_lock, flags);
341     return -1;
342 }
343
344
345 static int virtio_setup_queue(struct guest_info *core, 
346                               struct virtio_net_state * virtio_state, 
347                               struct virtio_queue * queue, 
348                               addr_t pfn, addr_t page_addr) {
349     queue->pfn = pfn;
350                 
351     queue->ring_desc_addr = page_addr;
352     queue->ring_avail_addr = page_addr + (queue->queue_size * sizeof(struct vring_desc));
353     queue->ring_used_addr = ((queue->ring_avail_addr) + 
354                              (sizeof(struct vring_avail)) + 
355                              (queue->queue_size * sizeof(uint16_t)));
356
357     // round up to next page boundary.
358     queue->ring_used_addr = (queue->ring_used_addr + 0xfff) & ~0xfff;
359     if (v3_gpa_to_hva(core, queue->ring_desc_addr, (addr_t *)&(queue->desc)) == -1) {
360         PrintError("Could not translate ring descriptor address\n");
361          return -1;
362     }
363  
364     if (v3_gpa_to_hva(core, queue->ring_avail_addr, (addr_t *)&(queue->avail)) == -1) {
365         PrintError("Could not translate ring available address\n");
366         return -1;
367     }
368
369     if (v3_gpa_to_hva(core, queue->ring_used_addr, (addr_t *)&(queue->used)) == -1) {
370         PrintError("Could not translate ring used address\n");
371         return -1;
372     }
373
374     PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
375                (void *)(queue->ring_desc_addr),
376                (void *)(queue->ring_avail_addr),
377                (void *)(queue->ring_used_addr));
378     
379     PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
380                queue->desc, queue->avail, queue->used);
381     
382     return 0;
383 }
384
385 static int virtio_io_write(struct guest_info *core, 
386                            uint16_t port, void * src, 
387                            uint_t length, void * private_data) 
388 {
389     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
390     int port_idx = port % virtio->io_range_size;
391
392     PrintDebug("VIRTIO NIC %p Write for port %d (index=%d) len=%d, value=%x\n",
393                private_data, port, port_idx,  
394                length, *(uint32_t *)src);
395
396     switch (port_idx) {
397         case GUEST_FEATURES_PORT:
398             if (length != 4) {
399                 PrintError("Illegal write length for guest features\n");
400                 return -1;
401             }       
402             virtio->virtio_cfg.guest_features = *(uint32_t *)src;
403             break;
404                 
405         case VRING_PG_NUM_PORT:
406             if (length != 4) {
407                 PrintError("Illegal write length for page frame number\n");
408                 return -1;
409             }
410             addr_t pfn = *(uint32_t *)src;
411             addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
412             uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
413             switch (queue_idx) {
414                 case 0:
415                     virtio_setup_queue(core, virtio,
416                                        &virtio->rx_vq, 
417                                        pfn, page_addr);
418                     break;
419                 case 1:
420                     virtio_setup_queue(core, virtio, 
421                                        &virtio->tx_vq, 
422                                        pfn, page_addr);
423                     if(virtio->tx_notify == 0){
424                         disable_cb(&virtio->tx_vq);
425                     }
426                     virtio->status = 1;
427                     break;
428                 case 2:
429                     virtio_setup_queue(core, virtio, 
430                                        &virtio->ctrl_vq, 
431                                        pfn, page_addr);
432                     break;          
433                 default:
434                     break;
435             }
436             break;
437                 
438         case VRING_Q_SEL_PORT:
439             virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
440             if (virtio->virtio_cfg.vring_queue_selector > 2) {
441                 PrintError("Virtio NIC: wrong queue idx: %d\n", 
442                            virtio->virtio_cfg.vring_queue_selector);
443                 return -1;
444             }
445             break;
446                 
447         case VRING_Q_NOTIFY_PORT: 
448             {
449                 uint16_t queue_idx = *(uint16_t *)src;                  
450                 if (queue_idx == 0){
451                     /* receive queue refill */
452                     virtio->stats.tx_interrupts ++;
453                 } else if (queue_idx == 1){
454                     if (handle_pkt_tx(core, virtio, 0) < 0) {
455                         PrintError("Virtio NIC: Error to handle packet TX\n");
456                         return -1;
457                     }
458                     virtio->stats.tx_interrupts ++;
459                 } else if (queue_idx == 2){
460                     /* ctrl */
461                 } else {
462                     PrintError("Virtio NIC: Wrong queue index %d\n", queue_idx);
463                 }       
464                 break;          
465             }
466         
467         case VIRTIO_STATUS_PORT:
468             virtio->virtio_cfg.status = *(uint8_t *)src;
469             if (virtio->virtio_cfg.status == 0) {
470                 virtio_init_state(virtio);
471             }
472             break;
473
474         case VIRTIO_ISR_PORT:
475             virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
476             break;
477                 
478         default:
479             return -1;
480             break;
481     }
482
483     return length;
484 }
485
486 static int virtio_io_read(struct guest_info *core, 
487                           uint16_t port, void * dst, 
488                           uint_t length, void * private_data) 
489 {
490     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
491     int port_idx = port % virtio->io_range_size;
492     uint16_t queue_idx = virtio->virtio_cfg.vring_queue_selector;
493
494     PrintDebug("Virtio NIC %p: Read  for port 0x%x (index =%d), length=%d\n", 
495                private_data, port, port_idx, length);
496         
497     switch (port_idx) {
498         case HOST_FEATURES_PORT:
499             if (length != 4) {
500                 PrintError("Virtio NIC: Illegal read length for host features\n");
501                 //return -1;
502             }
503             *(uint32_t *)dst = virtio->virtio_cfg.host_features;
504             break;
505
506         case VRING_PG_NUM_PORT:
507             if (length != 4) {
508                 PrintError("Virtio NIC: Illegal read length for page frame number\n");
509                 return -1;
510             }
511             switch (queue_idx) {
512                 case 0:
513                     *(uint32_t *)dst = virtio->rx_vq.pfn;
514                     break;
515                 case 1:
516                     *(uint32_t *)dst = virtio->tx_vq.pfn;
517                     break;      
518                 case 2:
519                     *(uint32_t *)dst = virtio->ctrl_vq.pfn;
520                     break;
521                 default:
522                     break;
523             }
524             break;
525
526         case VRING_SIZE_PORT:
527             if (length != 2) {
528                 PrintError("Virtio NIC: Illegal read length for vring size\n");
529                 return -1;
530             }
531             switch (queue_idx) {
532                 case 0:
533                     *(uint16_t *)dst = virtio->rx_vq.queue_size;
534                     break;
535                 case 1:
536                     *(uint16_t *)dst = virtio->tx_vq.queue_size;
537                     break;      
538                 case 2:
539                     *(uint16_t *)dst = virtio->ctrl_vq.queue_size;
540                     break;
541                 default:
542                     break;
543             }
544             break;
545
546         case VIRTIO_STATUS_PORT:
547             if (length != 1) {
548                 PrintError("Virtio NIC: Illegal read length for status\n");
549                 return -1;
550             }
551             *(uint8_t *)dst = virtio->virtio_cfg.status;
552             break;
553                 
554         case VIRTIO_ISR_PORT:
555             *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
556             virtio->virtio_cfg.pci_isr = 0;
557             v3_pci_lower_irq(virtio->virtio_dev->pci_bus, 
558                              0, virtio->pci_dev);
559             break;
560
561         case VIRTIO_NET_CONFIG ... VIRTIO_NET_CONFIG + ETH_ALEN:
562             *(uint8_t *)dst = virtio->net_cfg.mac[port_idx-VIRTIO_NET_CONFIG];
563             break;
564
565         default:
566             PrintError("Virtio NIC: Read of Unhandled Virtio Read:%d\n", 
567                        port_idx);
568             return -1;
569     }
570
571     return length;
572 }
573
574
575 /* receiving raw ethernet pkt from backend */
576 static int virtio_rx(uint8_t * buf, uint32_t size, void * private_data) {
577     struct virtio_net_state * virtio = (struct virtio_net_state *)private_data;
578     struct virtio_queue * q = &(virtio->rx_vq);
579     struct virtio_net_hdr_mrg_rxbuf hdr;
580     unsigned long flags;
581     uint8_t kick_guest = 0;
582
583     V3_Net_Print(2, "Virtio NIC: virtio_rx: size: %d\n", size);
584
585     if (!q->ring_avail_addr) {
586         V3_Net_Print(2, "Virtio NIC: RX Queue not set\n");
587         virtio->stats.rx_dropped ++;
588         
589         return -1;
590     }
591
592     memset(&hdr, 0, sizeof(struct virtio_net_hdr_mrg_rxbuf));
593
594     flags = v3_lock_irqsave(virtio->rx_lock);
595
596     if (q->cur_avail_idx != q->avail->index){
597         uint16_t buf_idx;
598         struct vring_desc * buf_desc;
599         uint32_t hdr_len, len;
600         uint32_t offset = 0;
601
602         hdr_len = (virtio->mergeable_rx_bufs)?
603             sizeof(struct virtio_net_hdr_mrg_rxbuf):
604             sizeof(struct virtio_net_hdr);
605
606         if(virtio->mergeable_rx_bufs){/* merged buffer */
607             struct vring_desc * hdr_desc;
608             uint16_t old_idx = q->cur_avail_idx;
609
610             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
611             hdr_desc = &(q->desc[buf_idx]);
612
613             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
614                                     virtio, hdr_desc, buf, size, hdr_len);
615             if(len < 0){
616                 goto err_exit;
617             }
618             offset += len;
619
620             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
621             q->used->ring[q->used->index % q->queue_size].length = hdr_len + offset;
622             q->cur_avail_idx ++;
623             hdr.num_buffers ++;
624
625             while(offset < size) {
626                 buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
627                 buf_desc = &(q->desc[buf_idx]);
628
629                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
630                                         virtio, buf_desc, buf+offset, size-offset, 0);  
631                 if (len < 0){
632                     V3_Net_Print(2, "Virtio NIC: merged buffer, %d buffer size %d\n", 
633                                  hdr.num_buffers, len);
634                     q->cur_avail_idx = old_idx;
635                     goto err_exit;
636                 }
637                 offset += len;
638                 buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
639
640                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
641                 q->used->ring[(q->used->index + hdr.num_buffers) % q->queue_size].length = len;
642                 q->cur_avail_idx ++;   
643
644                 hdr.num_buffers ++;
645             }
646
647             copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
648                               virtio, hdr_desc, (uchar_t *)&hdr, hdr_len, 0);
649             q->used->index += hdr.num_buffers;
650         }else{
651             buf_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
652             buf_desc = &(q->desc[buf_idx]);
653
654             /* copy header */
655             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
656                                     virtio, buf_desc, (uchar_t *)&(hdr.hdr), hdr_len, 0);
657             if(len < hdr_len){
658                 V3_Net_Print(2, "Virtio NIC: rx copy header error %d, hdr_len %d\n", 
659                              len, hdr_len);
660                 goto err_exit;
661             }
662
663             len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
664                                     virtio, buf_desc, buf, size, hdr_len);
665             if(len < 0){
666                 V3_Net_Print(2, "Virtio NIC: rx copy data error %d\n", len);
667                 goto err_exit;
668             }
669             offset += len;
670
671             /* copy rest of data */
672             while(offset < size && 
673                   (buf_desc->flags & VIRTIO_NEXT_FLAG)){
674                 buf_desc = &(q->desc[buf_desc->next]);
675                 len = copy_data_to_desc(&(virtio->virtio_dev->vm->cores[0]), 
676                                         virtio, buf_desc, buf+offset, size-offset, 0);      
677                 if (len < 0) {
678                     break;
679                 }
680                 offset += len;
681             }
682             buf_desc->flags &= ~VIRTIO_NEXT_FLAG;
683
684             if(offset < size){
685                 V3_Net_Print(2, "Virtio NIC: rx not enough ring buffer, buffer size %d\n", 
686                              len);
687                 goto err_exit;
688             }
689                 
690             q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
691             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) */
692             q->used->index ++;
693             q->cur_avail_idx ++;
694         } 
695
696         virtio->stats.rx_pkts ++;
697         virtio->stats.rx_bytes += size;
698     } else {
699         V3_Net_Print(2, "Virtio NIC: Guest RX queue is full\n");
700         virtio->stats.rx_dropped ++;
701
702         /* kick guest to refill RX queue */
703         kick_guest = 1;
704     }
705
706     v3_unlock_irqrestore(virtio->rx_lock, flags);
707
708     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG) || kick_guest) {
709         V3_Net_Print(2, "Virtio NIC: RX Raising IRQ %d\n",  
710                      virtio->pci_dev->config_header.intr_line);
711
712         virtio->virtio_cfg.pci_isr = 0x1;       
713         v3_pci_raise_irq(virtio->virtio_dev->pci_bus, 0, virtio->pci_dev);
714         virtio->stats.rx_interrupts ++;
715     }
716
717     /* notify guest if it is in guest mode */
718     if((kick_guest || virtio->rx_notify == 1) && 
719         V3_Get_CPU() != virtio->virtio_dev->vm->cores[0].pcpu_id){
720         v3_interrupt_cpu(virtio->virtio_dev->vm, 
721                          virtio->virtio_dev->vm->cores[0].pcpu_id, 
722                          0);
723     }
724
725     return 0;
726
727 err_exit:
728     virtio->stats.rx_dropped ++;
729     v3_unlock_irqrestore(virtio->rx_lock, flags);
730  
731     return -1;
732 }
733
734 static int virtio_free(struct virtio_dev_state * virtio) {
735     struct virtio_net_state * backend = NULL;
736     struct virtio_net_state * tmp = NULL;
737
738
739     list_for_each_entry_safe(backend, tmp, &(virtio->dev_list), dev_link) {
740
741         // unregister from PCI
742
743         list_del(&(backend->dev_link));
744         V3_Free(backend);
745     }
746
747     V3_Free(virtio);
748     return 0;
749 }
750
751
752 static struct v3_device_ops dev_ops = {
753     .free = (int (*)(void *))virtio_free,
754 };
755
756
757 static int virtio_poll(int quote, void * data){
758     struct virtio_net_state * virtio  = (struct virtio_net_state *)data;
759
760     if (virtio->status) {
761
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 #define RATE_UPPER_THRESHOLD 10  /* 10000 pkts per second, around 100Mbits */
844 #define RATE_LOWER_THRESHOLD 1
845 #define PROFILE_PERIOD 10000 /*us*/
846
847 static void virtio_nic_timer(struct guest_info * core, 
848                              uint64_t cpu_cycles, uint64_t cpu_freq, 
849                              void * priv_data) {
850     struct virtio_net_state * net_state = (struct virtio_net_state *)priv_data;
851     uint64_t period_us;
852     static int profile_ms = 0;
853
854     if(!net_state->status){ /* VNIC is not in working status */
855         return;
856     }
857
858     period_us = (1000*cpu_cycles)/cpu_freq;
859     net_state->past_us += period_us;
860
861     if(net_state->past_us > PROFILE_PERIOD){ 
862         uint32_t tx_rate, rx_rate;
863         
864         tx_rate = (net_state->stats.tx_pkts - net_state->tx_pkts)/(net_state->past_us/1000); /* pkts/per ms */
865         rx_rate = (net_state->stats.rx_pkts - net_state->rx_pkts)/(net_state->past_us/1000);
866
867         net_state->tx_pkts = net_state->stats.tx_pkts;
868         net_state->rx_pkts = net_state->stats.rx_pkts;
869
870         if(tx_rate > RATE_UPPER_THRESHOLD && net_state->tx_notify == 1){
871             V3_Print("Virtio NIC: Switch TX to VMM driven mode\n");
872             disable_cb(&(net_state->tx_vq));
873             net_state->tx_notify = 0;
874         }
875
876         if(tx_rate < RATE_LOWER_THRESHOLD && net_state->tx_notify == 0){
877             V3_Print("Virtio NIC: Switch TX to Guest  driven mode\n");
878             enable_cb(&(net_state->tx_vq));
879             net_state->tx_notify = 1;
880         }
881
882         if(rx_rate > RATE_UPPER_THRESHOLD && net_state->rx_notify == 1){
883             V3_Print("Virtio NIC: Switch RX to VMM None notify mode\n");
884             net_state->rx_notify = 0;
885         }
886
887         if(rx_rate < RATE_LOWER_THRESHOLD && net_state->rx_notify == 0){
888             V3_Print("Virtio NIC: Switch RX to VMM notify mode\n");
889             net_state->rx_notify = 1;
890         }
891
892         net_state->past_us = 0;
893     }
894
895     profile_ms += period_us/1000;
896     if(profile_ms > 20000){
897         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",
898                 net_state->stats.tx_pkts, net_state->stats.tx_bytes,
899                 net_state->stats.rx_pkts, net_state->stats.rx_bytes,
900                 net_state->stats.tx_dropped, net_state->stats.rx_dropped,
901                 net_state->stats.tx_interrupts, net_state->stats.rx_interrupts,
902                 net_state->vm->cores[0].num_exits);
903         profile_ms = 0;
904     }
905 }
906
907 static struct v3_timer_ops timer_ops = {
908     .update_timer = virtio_nic_timer,
909 };
910
911
912 static int connect_fn(struct v3_vm_info * info, 
913                       void * frontend_data, 
914                       struct v3_dev_net_ops * ops, 
915                       v3_cfg_tree_t * cfg, 
916                       void * private_data) {
917     struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
918     struct virtio_net_state * net_state  = (struct virtio_net_state *)V3_Malloc(sizeof(struct virtio_net_state));
919
920     memset(net_state, 0, sizeof(struct virtio_net_state));
921     register_dev(virtio, net_state);
922
923     net_state->vm = info;
924     net_state->net_ops = ops;
925     net_state->backend_data = private_data;
926     net_state->virtio_dev = virtio;
927     
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