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.


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