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.


Update on VNET-NIC device, and fix vnet & virtio net
[palacios.git] / palacios / src / palacios / vmm_vnet.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) 2009, Lei Xia <lxia@northwestern.edu> 
11  * Copyright (c) 2009, Yuan Tang <ytang@northwestern.edu>  
12  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
13  * All rights reserved.
14  *
15  * Author: Lei Xia <lxia@northwestern.edu>
16  *         Yuan Tang <ytang@northwestern.edu>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21  
22 #include <palacios/vmm_vnet.h>
23 #include <palacios/vmm_hypercall.h>
24 #include <palacios/vm_guest_mem.h>
25 #include <palacios/vmm_lock.h>
26
27 #ifndef CONFIG_DEBUG_VNET
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 #define ETHERNET_HEADER_LEN 14
34 #define ETHERNET_DATA_MIN   46
35 #define ETHERNET_DATA_MAX   1500
36 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_DATA_MAX)
37
38
39 typedef enum {TCP_TYPE, UDP_TYPE, NONE_TYPE} prot_type_t;
40
41 #define VNET_INITAB_HCALL 0xca00
42
43 struct eth_header {
44     uchar_t dest[6];
45     uchar_t src[6];
46     uint16_t type; // indicates layer 3 protocol type
47 }__attribute__((packed));
48
49 struct ip_header {
50     uint8_t version: 4;
51     uint8_t hdr_len: 4;
52     uchar_t tos;
53     uint16_t total_len;
54     uint16_t id;
55     uint8_t flags:     3;
56     uint16_t offset: 13;
57     uchar_t ttl;
58     uchar_t proto;
59     uint16_t cksum;
60     uint32_t src_addr;
61     uint32_t dst_addr;
62 }__attribute__((packed));
63
64 struct udp_header {
65     uint16_t src_port;
66     uint16_t dst_port;
67     uint16_t len;
68     uint16_t csum;//set to zero, disable the xsum
69 }__attribute__((packed));
70
71 struct udp_link_header {
72     struct eth_header eth_hdr;
73     struct ip_header ip_hdr;
74     struct udp_header udp_hdr;
75 }__attribute__((packed));
76
77
78 struct ethernet_pkt {
79     uint32_t size; //size of data field
80     uint16_t type;
81     uint8_t use_header;
82     struct udp_link_header ext_hdr;
83     char data[ETHERNET_PACKET_LEN];
84 }__attribute__((packed));
85
86
87 #define DEVICE_NAME_LEN 20
88 struct vnet_if_device {
89     char name[DEVICE_NAME_LEN];
90     uchar_t mac_addr[6];
91     struct v3_vm_info *vm;
92     
93     int (*input)(struct v3_vm_info *vm, uchar_t *data, uint32_t len, void *private_data);
94     
95     void *private_data;
96 }__attribute__((packed));
97
98 struct vnet_if_link {
99     prot_type_t pro_type; //transport layer protocal type of this link
100     unsigned long dest_ip;
101     uint16_t dest_port;
102
103     struct udp_link_header vnet_header; //header applied to the packet in/out from this link
104
105     int (*input)(uchar_t *data, uint32_t len, void *private_data);
106     
107     void *private_data;
108 }__attribute__((packed));
109
110
111 struct link_entry {
112     link_type_t type;
113   
114     union {
115         struct vnet_if_device *dst_dev;
116         struct vnet_if_link *dst_link;
117     } __attribute__((packed));
118
119     int use;
120 }__attribute__((packed));
121
122 //routing table entry
123 struct routing_entry {
124     char src_mac[6];
125     char dest_mac[6];
126
127     mac_type_t src_mac_qual;
128     mac_type_t dest_mac_qual;
129
130     int link_idx; //link[dest] is the link to be used to send pkt
131     link_type_t link_type; //EDGE|INTERFACE|ANY
132  
133     int src_link_idx;
134     link_type_t src_type; //EDGE|INTERFACE|ANY
135 };
136
137
138 // 14 (ethernet frame) + 20 bytes
139 struct in_pkt_header {
140     uchar_t ethernetdest[6];
141     uchar_t ethernetsrc[6];
142     uchar_t ethernettype[2]; //layer 3 protocol type
143     char ip[20];
144 }__attribute__((packed));
145
146
147 #define MAX_LINKS 10
148 #define MAX_ROUTES 10
149 #define HASH_KEY_LEN 16
150 #define MIN_CACHE_SIZE 100
151 #define HASH_KEY_SIZE 16
152
153 struct link_table {
154     struct link_entry * links[MAX_LINKS];
155     uint16_t size;
156     v3_lock_t lock;
157 }__attribute__((packed));
158
159 struct routing_table {
160     struct routing_entry * routes[MAX_ROUTES];
161     uint16_t size;
162     v3_lock_t lock;
163 }__attribute__((packed));
164
165 typedef char * route_hashkey_t;
166
167 struct route_cache_entry {
168     int num_matched_routes;
169     int * matches; 
170 };
171
172 struct vnet_state_t {
173     struct link_table g_links;
174     struct routing_table g_routes;
175     struct gen_queue * g_inpkt_q;
176     struct hashtable * g_route_cache;
177     v3_lock_t cache_lock;
178 };
179
180 static struct vnet_state_t g_vnet_state;//global state for vnet
181
182 static uint16_t ip_xsum(struct ip_header *ip_hdr, int hdr_len){
183     long sum = 0;
184
185     uint16_t *p = (uint16_t*) ip_hdr;
186     while(hdr_len > 1){
187         sum += *(p++);
188         if(sum & 0x80000000)
189             sum = (sum & 0xFFFF) + (sum >> 16);
190             hdr_len -= 2;
191         }
192  
193     if(hdr_len) 
194         sum += (uint16_t) *(uchar_t *)p;
195           
196     while(sum>>16)
197         sum = (sum & 0xFFFF) + (sum >> 16);
198
199     return (uint16_t)~sum;
200 }
201
202 static void ethernet_packet_init(struct ethernet_pkt *pt, 
203                                                               uchar_t *data, 
204                                                               const size_t size) {
205     pt->size = size;
206     pt->use_header = 0;
207     memset(&pt->ext_hdr, 0, sizeof(struct udp_link_header));
208     memcpy(pt->data, data, size);
209 }
210
211 static inline uint_t hash_from_key_fn(addr_t hashkey) {    
212     return v3_hash_buffer((uint8_t *)hashkey, HASH_KEY_LEN);
213 }
214
215 static inline int hash_key_equal(addr_t key1, addr_t key2) {
216     return (memcmp((uint8_t *)key1, (uint8_t *)key2, HASH_KEY_LEN) == 0);
217 }
218
219 static int init_route_cache(struct vnet_state_t *vnet_state) {  
220     vnet_state->g_route_cache = v3_create_htable(MIN_CACHE_SIZE, 
221                                                                       &hash_from_key_fn, 
222                                                                       &hash_key_equal);
223
224     if (vnet_state->g_route_cache == NULL) {
225         PrintError("Vnet: Route Cache Init Fails\n");
226         return -1;
227     }
228
229     return 0;
230 }
231
232 static void make_hash_key(route_hashkey_t hashkey,
233                                                 char src_addr[6],
234                                                 char dest_addr[6],
235                                                 char src_type,
236                                                 int src_index) {
237     int j;
238
239     for (j = 0; j < 6; j++) {
240         hashkey[j] = src_addr[j];
241         hashkey[j + 6] = dest_addr[j] + 1;
242     }
243
244     hashkey[12] = src_type;
245
246     *(int *)(hashkey + 12) = src_index;
247 }
248
249 static int add_route_to_cache(route_hashkey_t hashkey, 
250                                                         int num_matched_r, 
251                                                         int * matches) {
252     struct route_cache_entry * new_entry = NULL;
253     struct vnet_state_t *vnet_state = &g_vnet_state;
254     int i;
255     
256     new_entry = (struct route_cache_entry *)V3_Malloc(sizeof(struct route_cache_entry));
257     if (new_entry == NULL) {
258         PrintError("Vnet: Malloc fails\n");
259         return -1;
260     }
261     
262     new_entry->num_matched_routes = num_matched_r;
263     new_entry->matches = (int *)V3_Malloc(num_matched_r * sizeof(int));
264     
265     if (new_entry->matches == NULL) {
266         PrintError("Vnet: Malloc fails\n");
267         return -1;
268     }
269     
270     for (i = 0; i < num_matched_r; i++) {
271         new_entry->matches[i] = matches[i];
272     }
273     
274     if (v3_htable_insert(vnet_state->g_route_cache, (addr_t)hashkey, (addr_t)new_entry) == 0) {
275         PrintError("Vnet: Failed to insert new route entry to the cache\n");
276         V3_Free(new_entry->matches);
277         V3_Free(new_entry);
278     }
279     
280     return 0;
281 }
282
283 static int clear_hash_cache() {
284     struct vnet_state_t *vnet_state = &g_vnet_state;
285
286     v3_free_htable(vnet_state->g_route_cache, 1, 1);            
287     vnet_state->g_route_cache = v3_create_htable(MIN_CACHE_SIZE, 
288                                                                         hash_from_key_fn, 
289                                                                         hash_key_equal);
290     
291     if (vnet_state->g_route_cache == NULL) {
292         PrintError("Vnet: Route Cache Create Failurely\n");
293         return -1;
294     }
295
296     return 0;
297 }
298
299 static int look_into_cache(route_hashkey_t hashkey, int * matches) {
300     struct route_cache_entry * found = NULL;
301     int n_matches = -1;
302     int i = 0;
303     struct vnet_state_t *vnet_state = &g_vnet_state;
304     
305     found = (struct route_cache_entry *)v3_htable_search(vnet_state->g_route_cache, 
306                                                                                (addr_t)hashkey);
307    
308     if (found != NULL) {
309         n_matches = found->num_matched_routes;
310
311         for (i = 0; i < n_matches; i++) {
312             matches[i] = found->matches[i];
313         }
314     }
315
316     return n_matches;
317 }
318
319
320 #ifdef CONFIG_DEBUG_VNET
321
322 static void print_packet(uchar_t *pkt, int size) {
323     PrintDebug("Vnet: data_packet: size: %d\n", size);
324     v3_hexdump(pkt, size, NULL, 0);
325 }
326
327 static inline uint8_t hex_nybble_to_nybble(const uint8_t hexnybble) {
328     uint8_t x = toupper(hexnybble);
329
330     if (isdigit(x)) {
331         return x - '0';
332     } else {
333         return 10 + (x - 'A');
334     }
335 }
336
337 static inline uint8_t hex_byte_to_byte(const uint8_t hexbyte[2]) {
338     return ((hex_nybble_to_nybble(hexbyte[0]) << 4) + 
339             (hex_nybble_to_nybble(hexbyte[1]) & 0xf));
340 }
341
342 static inline void string_to_mac(const char *str, uint8_t mac[6]) {
343     int k;
344
345     for (k = 0; k < 6; k++) {
346         mac[k] = hex_byte_to_byte(&(str[(2 * k) + k]));
347     }
348 }
349
350 static inline void mac_to_string(char mac[6], char * buf) {
351     snprintf(buf, 20, "%02x:%02x:%02x:%02x:%02x:%02x", 
352              mac[0], mac[1], mac[2],
353              mac[3], mac[4], mac[5]);
354 }
355
356
357 static void print_route(struct routing_entry *route){
358     char dest_str[18];
359     char src_str[18];
360
361     mac_to_string(route->src_mac, src_str);  
362     mac_to_string(route->dest_mac, dest_str);
363
364     PrintDebug("SRC(%s), DEST(%s), src_mac_qual(%d), dst_mac_qual(%d)\n", 
365                  src_str, 
366                  dest_str, 
367                  route->src_mac_qual, 
368                  route->dest_mac_qual);
369     PrintDebug("Src_Link(%d), src_type(%d), dst_link(%d), dst_type(%d)\n\n", 
370                  route->src_link_idx, 
371                  route->src_type, 
372                  route->link_idx, 
373                  route->link_type);
374 }
375         
376
377 static void dump_routes(struct routing_entry **route_tables) {
378     int i;
379
380     PrintDebug("\nVnet: route table dump start =====\n");
381
382     for(i = 0; i < MAX_ROUTES; i++) {
383         if (route_tables[i] != NULL){
384              print_route(route_tables[i]);
385         }
386     }
387
388     PrintDebug("\nVnet: route table dump end =====\n");
389 }
390
391 #endif
392
393 static int __add_link_entry(struct link_entry * link) {
394     int idx;
395     struct vnet_state_t *vnet_state = &g_vnet_state;
396
397     v3_lock(vnet_state->g_links.lock);
398     for (idx = 0; idx < MAX_LINKS; idx++) {
399         if (vnet_state->g_links.links[idx] == NULL) {
400             vnet_state->g_links.links[idx] = link;
401             vnet_state->g_links.size++;
402             break;
403         }
404     }
405     v3_unlock(vnet_state->g_links.lock);
406
407     if (idx == MAX_LINKS) {
408         PrintDebug("VNET: No available Link entry for new link\n");
409         return -1;
410     }
411
412     return idx;
413 }
414
415 static int __add_route_entry(struct routing_entry * route) {
416     int idx;
417     struct vnet_state_t *vnet_state = &g_vnet_state;
418
419     v3_lock(vnet_state->g_routes.lock);
420     for (idx = 0; idx < MAX_ROUTES; idx++) {
421         if (vnet_state->g_routes.routes[idx] == NULL) {
422             vnet_state->g_routes.routes[idx] = route;
423             vnet_state->g_routes.size++;
424           break;
425         }
426     }
427     v3_unlock(vnet_state->g_routes.lock);
428
429     if(idx == MAX_LINKS){
430         PrintDebug("VNET: No available route entry for new route\n");
431         return -1;
432     }
433
434 #ifdef CONFIG_DEBUG_VNET
435     dump_routes(vnet_state->g_routes.routes);
436 #endif
437
438     return idx;
439 }
440
441 int v3_vnet_add_route(struct v3_vnet_route *route){
442     struct routing_entry * new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
443     int idx = -1;
444
445     PrintDebug("Vnet: vnet_add_route_entry\n");
446         
447     memset(new_route, 0, sizeof(struct routing_entry));
448     if ((route->src_mac_qual != MAC_ANY)) {
449         memcpy(new_route->src_mac, route->src_mac, 6);
450     }
451             
452     if ((route->dest_mac_qual != MAC_ANY)) {
453         memcpy(new_route->dest_mac, route->dest_mac, 6);
454     }
455             
456     new_route->src_mac_qual = route->src_mac_qual;
457     new_route->dest_mac_qual = route->dest_mac_qual;
458     new_route->link_idx= route->link_idx;
459     new_route->link_type = route->link_type;
460     new_route->src_link_idx = route->src_link_idx;
461     new_route->src_type = route->src_type;
462
463     if ((idx = __add_route_entry(new_route)) == -1) {
464         PrintError("Could not add route entry\n");
465         return -1;
466     }
467     
468     clear_hash_cache();
469
470     return idx;
471 }
472
473 static int match_route(uint8_t * src_mac, 
474                        uint8_t * dst_mac, 
475                        link_type_t src_type, 
476                        int src_index, 
477                        int * matches) {
478     struct routing_entry *route = NULL; 
479     struct vnet_state_t *vnet_state = &g_vnet_state;
480     int matched_routes[MAX_ROUTES];
481     int num_matches = 0;
482     int i;
483
484 #ifdef CONFIG_DEBUG_VNET
485     char dest_str[18];
486     char src_str[18];
487
488     mac_to_string(src_mac, src_str);  
489     mac_to_string(dst_mac, dest_str);
490     PrintDebug("Vnet: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dest_str);
491 #endif
492
493     for(i = 0; i < MAX_ROUTES; i++) {
494         if (vnet_state->g_routes.routes[i] != NULL){
495              route = vnet_state->g_routes.routes[i];
496
497             if(src_type == LINK_ANY && src_index == -1) {
498                  if ((route->dest_mac_qual == MAC_ANY) &&
499                        (route->src_mac_qual == MAC_ANY)) {      
500                     matched_routes[num_matches] = i;
501                     num_matches++;
502                  }
503         
504                 if (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0) {
505                      if (route->src_mac_qual !=  MAC_NOT) {
506                           if (route->dest_mac_qual == MAC_ANY) {
507                               matched_routes[num_matches] = i;
508                               num_matches++;
509                           } else if (route->dest_mac_qual != MAC_NOT &&
510                                       memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0) {
511                             matched_routes[num_matches] = i;
512                             num_matches++;
513                         }
514                     }
515                 }
516
517                 if (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0) {
518                     if (route->dest_mac_qual != MAC_NOT) {
519                         if (route->src_mac_qual == MAC_ANY) {
520                             matched_routes[num_matches] = i;
521                             num_matches++;
522                         } else if ((route->src_mac_qual != MAC_NOT) && 
523                                        (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0)) {
524                             matched_routes[num_matches] = i;
525                             num_matches++;
526                         }
527                      }
528                 }
529
530                 if ((route->dest_mac_qual == MAC_NOT) &&
531                        (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) != 0)) {
532                     if (route->src_mac_qual == MAC_ANY) {
533                         matched_routes[num_matches] = i;            
534                         num_matches++;    
535                     } else if ((route->src_mac_qual != MAC_NOT) && 
536                                    (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0)) {     
537                         matched_routes[num_matches] = i;     
538                         num_matches++;
539                       }
540                 }
541
542                 if ((route->src_mac_qual == MAC_NOT) &&
543                        (memcmp((void *)&route->src_mac, (void *)src_mac, 6) != 0)) {
544                     if (route->dest_mac_qual == MAC_ANY) {
545                         matched_routes[num_matches] = i;   
546                         num_matches++;
547                     } else if ((route->dest_mac_qual != MAC_NOT) &&
548                                    (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0)) {
549                         matched_routes[num_matches] = i;
550                         num_matches++;
551                     }
552                 }
553             }//end if src_type == Link_any
554         }       
555     }//end for
556
557     PrintDebug("Vnet: match_route: Matches=%d\n", num_matches);
558         
559     for (i = 0; i < num_matches; i++) {
560         matches[i] = matched_routes[i];
561     }
562     
563     return num_matches;
564 }
565
566 static int handle_one_pkt(struct ethernet_pkt *pkt) {
567     int src_link_index = -1;    //the value of src_link_index of udp always is 0
568     char src_mac[6];
569     char dst_mac[6];
570     int matches[MAX_ROUTES];
571     int num_matched_routes = 0;
572     struct in_pkt_header header;
573     char hash_key[HASH_KEY_SIZE];
574     struct vnet_state_t *vnet_state = &g_vnet_state;
575     int i;
576
577     // get the ethernet and ip headers from the packet
578     memcpy((void *)&header, (void *)pkt->data, sizeof(header));
579     memcpy(src_mac, header.ethernetsrc, 6);
580     memcpy(dst_mac, header.ethernetdest, 6);
581
582 #ifdef CONFIG_DEBUG_VNET
583     char dest_str[18];
584     char src_str[18];
585
586     mac_to_string(src_mac, src_str);  
587     mac_to_string(dst_mac, dest_str);
588     PrintDebug("Vnet: HandleDataOverLink. SRC(%s), DEST(%s)\n", src_str, dest_str);
589 #endif
590
591     make_hash_key(hash_key, src_mac, dst_mac, LINK_EDGE, src_link_index); 
592     num_matched_routes = look_into_cache((route_hashkey_t)hash_key, matches);
593     
594     if (num_matched_routes == -1) {  
595         num_matched_routes = match_route(src_mac, dst_mac, LINK_ANY, src_link_index, matches);  
596         if (num_matched_routes > 0) {
597              add_route_to_cache(hash_key, num_matched_routes,matches);      
598          }
599     }
600     
601     PrintDebug("Vnet: HandleDataOverLink: Matches=%d\n", num_matched_routes);
602
603     if (num_matched_routes == 0) {
604         return -1;
605     }
606     
607     for (i = 0; i < num_matched_routes; i++) {//send packet to all destinations
608         int route_index = -1;
609         int link_index = -1;
610         int pkt_len = 0;
611         struct link_entry * link = NULL;
612
613         route_index = matches[i];
614         link_index = vnet_state->g_routes.routes[route_index]->link_idx;
615
616         if ((link_index < 0) || (link_index > MAX_LINKS) || 
617              (vnet_state->g_links.links[link_index] == NULL)) {
618              continue;
619          }
620         
621         link = vnet_state->g_links.links[link_index];
622         pkt_len = pkt->size;
623         if (link->type == LINK_EDGE) {
624
625               //apply the header in the beginning of the packet to be sent
626             if (link->dst_link->pro_type == UDP_TYPE) {
627                 struct udp_link_header *hdr = &(link->dst_link->vnet_header);
628                 struct ip_header *ip = &hdr->ip_hdr;
629                 struct udp_header *udp = &hdr->udp_hdr;
630                    udp->len = pkt_len + sizeof(struct udp_header);
631                    ip->total_len = pkt_len + sizeof(struct udp_header) + sizeof(struct ip_header);
632                    ip->cksum = ip_xsum(ip, sizeof(struct ip_header));
633                 
634                 int hdr_size = sizeof(struct udp_link_header);
635                 memcpy(&pkt->ext_hdr, hdr, hdr_size);
636
637                 pkt_len += hdr_size;
638                 if ((link->dst_link->input((uchar_t *)&pkt->ext_hdr, pkt_len, link->dst_link->private_data)) != pkt_len) {
639                     PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
640                     continue;
641                 }
642              }else {
643                 PrintDebug("VNET: Link protocol type not support\n");
644                 continue;
645              }
646         } else if (link->type == LINK_INTERFACE) {
647             if ((link->dst_dev->input(link->dst_dev->vm, pkt->data, pkt_len, link->dst_dev->private_data)) != pkt_len) {
648                 PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
649                 continue;
650              }
651         } else {
652             PrintDebug("Vnet: Wrong Edge type of link: %d\n", link_index);
653             continue;
654         }
655
656         PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route entry %d to link %d\n", route_index, link_index);
657     }
658     
659     return 0;
660 }
661
662 static int send_ethernet_pkt(uchar_t *data, int len, void *private_data) {
663     struct ethernet_pkt *pkt;
664     struct vnet_state_t *vnet_state = &g_vnet_state;
665
666     pkt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
667     if(pkt == NULL){
668         PrintError("VNET: Memory allocate fails\n");
669         return -1;
670     }
671
672     memset(pkt, 0, sizeof(struct ethernet_pkt));
673     ethernet_packet_init(pkt, data, len);
674     v3_enqueue(vnet_state->g_inpkt_q, (addr_t)pkt);
675   
676 #ifdef CONFIG_DEBUG_VNET
677     PrintDebug("VNET: send_pkt: transmitting packet: (size:%d)\n", (int)pkt->size);
678     print_packet((char *)data, len);
679 #endif
680
681     return 0;
682 }
683
684 int v3_vnet_send_rawpkt(uchar_t * buf, 
685                                           int len, 
686                                           void *private_data) {
687     PrintDebug("VNET: In v3_vnet_send_rawpkt: pkt length %d\n", len);
688     
689     return send_ethernet_pkt(buf, len, private_data);
690 }
691
692 //sending the packet from Dom0, should remove the link header
693 int v3_vnet_send_udppkt(uchar_t * buf, 
694                                            int len, 
695                                            void *private_data) {
696     uint_t hdr_len = sizeof(struct udp_link_header);
697         
698     PrintDebug("VNET: In v3_vnet_send_udppkt: pkt length %d\n", len);
699    
700     return send_ethernet_pkt((uchar_t *)(buf+hdr_len), len - hdr_len, private_data);
701 }
702
703 static int search_device(char * device_name) {
704     struct vnet_state_t *vnet_state = &g_vnet_state;
705     int i;
706
707     for (i = 0; i < MAX_LINKS; i++) {
708         if ((vnet_state->g_links.links[i] != NULL) && (vnet_state->g_links.links[i]->type == LINK_INTERFACE)) {
709             if (strcmp(device_name, vnet_state->g_links.links[i]->dst_dev->name) == 0) {
710                 return i;
711             }
712         }
713     }
714
715     return -1;
716 }
717
718 int v3_vnet_add_node(struct v3_vm_info *info, 
719                    char * dev_name, 
720                    uchar_t mac[6], 
721                     int (*netif_input)(struct v3_vm_info * vm, uchar_t * pkt, uint_t size, void * private_data), 
722                     void * priv_data){
723     struct vnet_if_device * if_dev;
724
725     int idx = search_device(dev_name);
726     if (idx != -1) {
727         PrintDebug("VNET: register device: Already has device with the name %s\n", dev_name);
728         return -1;
729     }
730     
731     if_dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device)); 
732     if (if_dev == NULL) {
733         PrintError("VNET: Malloc fails\n");
734         return -1;
735     }
736     
737     strcpy(if_dev->name, dev_name);
738     strncpy(if_dev->mac_addr, mac, 6);
739     if_dev->input = netif_input;
740     if_dev->private_data = priv_data;
741     if_dev->vm = info;
742
743     struct link_entry * link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
744     link->type = LINK_INTERFACE;
745     link->dst_dev = if_dev;
746
747     idx = __add_link_entry(link);
748
749     if (idx < 0) return -1;
750
751     return idx;
752 }
753
754 int v3_vnet_pkt_process() {
755     struct ethernet_pkt * pkt;
756     struct vnet_state_t *vnet_state = &g_vnet_state;
757
758     while ((pkt = (struct ethernet_pkt *)v3_dequeue(vnet_state->g_inpkt_q))!= NULL) {
759         if (handle_one_pkt(pkt) != -1) {
760             PrintDebug("VNET: vnet_check: handle one packet! pt length %d, pt type %d\n", (int)pkt->size, (int)pkt->type);  
761         } else {
762             PrintDebug("VNET: vnet_check: Fail to forward one packet, discard it!\n"); 
763         }
764         
765         V3_Free(pkt); // be careful here
766     }
767     
768     return 0;
769 }
770
771 static void vnet_state_init(struct vnet_state_t *vnet_state) {
772     int i;
773
774     /*initial links table */
775     for (i = 0; i < MAX_LINKS; i++) {
776         vnet_state->g_links.links[i] = NULL;
777     }
778     vnet_state->g_links.size = 0;
779     if(v3_lock_init(&(vnet_state->g_links.lock)) == -1){
780         PrintError("VNET: Failure to init lock for links table\n");
781     }
782     PrintDebug("VNET: Links table initiated\n");
783
784     /*initial routes table */
785     for (i = 0; i < MAX_ROUTES; i++) {
786         vnet_state->g_routes.routes[i] = NULL;
787     }
788     vnet_state->g_routes.size = 0;
789     if(v3_lock_init(&(vnet_state->g_routes.lock)) == -1){
790         PrintError("VNET: Failure to init lock for routes table\n");
791     }
792     PrintDebug("VNET: Routes table initiated\n");
793
794     /*initial pkt receiving queue */
795     vnet_state->g_inpkt_q = v3_create_queue();
796     v3_init_queue(vnet_state->g_inpkt_q);
797     PrintDebug("VNET: Receiving queue initiated\n");
798
799     /*initial routing cache */
800     init_route_cache(vnet_state);
801 }
802
803
804 int v3_init_vnet() {
805     vnet_state_init(&g_vnet_state);
806         
807     PrintDebug("VNET Initialized\n");
808
809     return 0;
810 }
811