Palacios Public Git Repository

To checkout Palacios execute

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


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