Palacios Public Git Repository

To checkout Palacios execute

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


Restructure of Vnet
[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, Jack Lange <jarusl@cs.northwestern.edu> 
13  * Copyright (c) 2009, Peter Dinda <pdinda@northwestern.edu>
14  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
15  * All rights reserved.
16  *
17  * Author: Lei Xia <lxia@northwestern.edu>
18  *         Yuan Tang <ytang@northwestern.edu>
19  *         Jack Lange <jarusl@cs.northwestern.edu> 
20  *         Peter Dinda <pdinda@northwestern.edu
21  *
22  * This is free software.  You are permitted to use,
23  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
24  */
25  
26 #include <palacios/vmm_vnet.h>
27 #include <palacios/vmm_hypercall.h>
28 #include <palacios/vm_guest_mem.h>
29
30 #ifndef CONFIG_DEBUG_VNET
31 #undef PrintDebug
32 #define PrintDebug(fmt, args...)
33 #endif
34
35
36 struct ethernet_pkt {
37   uint32_t size;
38   uint16_t type;
39   char data[ETHERNET_PACKET_LEN];
40 };
41
42
43 // 14 (ethernet frame) + 20 bytes
44 struct in_pkt_header {
45     char ethernetdest[6];
46     char ethernetsrc[6];
47     unsigned char ethernettype[2]; // indicates layer 3 protocol type
48     char ip[20];
49 };
50
51 #define VNET_INITAB_HCALL 0xca00  // inital hypercall id
52
53 #define MAX_LINKS 10
54 #define MAX_ROUTES 10
55 #define HASH_KEY_LEN 16
56 #define MIN_CACHE_SIZE 100
57 static const uint_t hash_key_size = 16;
58
59 struct link_table {
60     struct link_entry *links[MAX_LINKS];
61     uint16_t size;
62 };
63
64 struct routing_table {
65     struct routing_entry *routes[MAX_ROUTES];
66     uint16_t size;
67 };
68
69 static struct link_table g_links;
70 static struct routing_table g_routes;
71 static struct gen_queue *g_inpkt_q;
72
73 /* Hash key format:
74  * 0-5:     src_eth_addr
75  * 6-11:    dest_eth_addr
76  * 12:      src type
77  * 13-16:   src index
78  */
79 typedef char *route_hashkey_t;
80
81 // This is the hash value, Format: 0: num_matched_routes, 1...n: matches[] -- TY
82 struct route_cache_entry {
83     int num_matched_routes;
84     int * matches; 
85 };
86
87 //the route cache
88 static struct hashtable *g_route_cache; 
89
90
91 static void print_packet(char *pkt, int size) {
92     PrintDebug("Vnet: print_data_packet: size: %d\n", size);
93     v3_hexdump(pkt, size, NULL, 0);
94 }
95
96 #if 0
97 static void print_packet_addr(char *pkt) {
98     PrintDebug("Vnet: print_packet_destination_addr: ");
99     v3_hexdump(pkt + 8, 6, NULL, 0);
100     
101     PrintDebug("Vnet: print_packet_source_addr: ");
102     v3_hexdump(pkt + 14, 6, NULL, 0);
103 }
104
105 static void print_device_addr(char *ethaddr) {
106     PrintDebug("Vnet: print_device_addr: ");
107     v3_hexdump(ethaddr, 6, NULL, 0);
108
109 #endif
110
111
112 //network connection functions 
113 static inline void ethernet_packet_init(struct ethernet_pkt *pt, const char *data, const size_t size) 
114 {
115     pt->size = size;
116     memcpy(pt->data, data, size);
117 }
118
119 static uint_t hash_from_key_fn(addr_t hashkey) 
120 {    
121     uint8_t * key = (uint8_t *)hashkey;
122     return v3_hash_buffer(key, HASH_KEY_LEN);
123 }
124
125 static int hash_key_equal(addr_t key1, addr_t key2) 
126 {
127     uint8_t * buf1 = (uint8_t *)key1;
128     uint8_t * buf2 = (uint8_t *)key2;
129     return (memcmp(buf1, buf2, HASH_KEY_LEN) == 0);
130 }
131
132 static int init_route_cache() 
133 {
134     g_route_cache = v3_create_htable(MIN_CACHE_SIZE, &hash_from_key_fn, &hash_key_equal);
135
136     if (g_route_cache == NULL){
137         PrintError("Vnet: Route Cache Initiate Failurely\n");
138         return -1;
139     }
140
141     return 0;
142 }
143
144 static void make_hash_key(route_hashkey_t hashkey,
145                                                       char src_addr[6],
146                                                       char dest_addr[6],
147                                                       char src_type,
148                                                       int src_index) 
149 {
150     int j;
151
152     for (j = 0; j < 6; j++) {
153         hashkey[j] = src_addr[j];
154         hashkey[j + 6] = dest_addr[j] + 1;
155     }
156
157     hashkey[12] = src_type;
158
159     *(int *)(hashkey + 12) = src_index;
160 }
161
162 static int add_route_to_cache(route_hashkey_t hashkey, int num_matched_r, int *matches) 
163 {
164     struct route_cache_entry * new_entry = NULL;
165     int i;
166     
167     new_entry = (struct route_cache_entry *)V3_Malloc(sizeof(struct route_cache_entry));
168     if (new_entry == NULL){
169         PrintError("Vnet: Malloc fails\n");
170         return -1;
171     }
172     
173     new_entry->num_matched_routes = num_matched_r;
174
175     new_entry->matches = (int *)V3_Malloc(num_matched_r * sizeof(int));
176     
177     if (new_entry->matches == NULL){
178         PrintError("Vnet: Malloc fails\n");
179         return -1;
180     }
181     
182     for (i = 0; i < num_matched_r; i++) {
183         new_entry->matches[i] = matches[i];
184     }
185     
186     //here, when v3_htable_insert return 0, it means insert fails
187     if (v3_htable_insert(g_route_cache, (addr_t)hashkey, (addr_t)new_entry) == 0){
188         PrintError("Vnet: Insert new route entry to cache failed\n");
189         V3_Free(new_entry->matches);
190         V3_Free(new_entry);
191     }
192     
193     return 0;
194 }
195
196 static int clear_hash_cache() 
197 {
198     v3_free_htable(g_route_cache, 1, 1);
199                 
200     g_route_cache = v3_create_htable(MIN_CACHE_SIZE, hash_from_key_fn, hash_key_equal);
201     
202     if (g_route_cache == NULL){
203         PrintError("Vnet: Route Cache Create Failurely\n");
204         return -1;
205     }
206
207     return 0;
208 }
209
210 static int look_into_cache(route_hashkey_t hashkey, int *matches) 
211 {
212     int n_matches = -1;
213     int i = 0;
214     struct route_cache_entry * found = NULL;
215     
216     found = (struct route_cache_entry *)v3_htable_search(g_route_cache, (addr_t)hashkey);
217    
218     if (found != NULL) {
219         n_matches = found->num_matched_routes;
220
221         for (i = 0; i < n_matches; i++) {
222             matches[i] = found->matches[i];
223         }
224     }
225
226     return n_matches;
227 }
228
229 static inline uint8_t hex_nybble_to_nybble(const uint8_t hexnybble) 
230 {
231     uint8_t x = toupper(hexnybble);
232
233     if (isdigit(x)) {
234         return x - '0';
235     } else {
236         return 10 + (x - 'A');
237     }
238 }
239
240 static inline uint8_t hex_byte_to_byte(const uint8_t hexbyte[2]) 
241 {
242     return ((hex_nybble_to_nybble(hexbyte[0]) << 4) + 
243             (hex_nybble_to_nybble(hexbyte[1]) & 0xf));
244 }
245
246 static inline void string_to_mac(const char *str, uint8_t mac[6]) 
247 {
248     int k;
249
250     for (k = 0; k < 6; k++) {
251         mac[k] = hex_byte_to_byte(&(str[(2 * k) + k]));
252     }
253 }
254
255 static inline void mac_to_string(char mac[6], char * buf) 
256 {
257     snprintf(buf, 20, "%x:%x:%x:%x:%x:%x", 
258              mac[0], mac[1], mac[2],
259              mac[3], mac[4], mac[5]);
260 }
261
262 static int add_link_entry(struct link_entry *link)
263
264     int idx;
265     
266     for (idx = 0; idx < MAX_LINKS; idx++) {
267         if (g_links.links[idx] == NULL) {
268             g_links.links[idx] = link;
269             g_links.size ++;
270             
271             return idx;
272         }
273     }
274     
275     return -1;
276 }
277
278 static int add_route_entry(struct routing_entry *route)
279
280     int idx;
281     
282     for (idx = 0; idx < MAX_ROUTES; idx++) {
283         if (g_routes.routes[idx] == NULL) {
284             g_routes.routes[idx] = route;
285             g_routes.size ++;
286             
287             return idx;
288         }
289     }
290     
291     return -1;
292 }
293
294
295 int vnet_add_route_entry(char src_mac[6],
296                                                         char dest_mac[6],
297                                                         int src_mac_qual,
298                                                         int dest_mac_qual,
299                                                         int link_idx,
300                                                         link_type_t link_type,
301                                                         int src,
302                                                         link_type_t src_type)
303 {
304     struct routing_entry *new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
305
306     memset(new_route, 0, sizeof(struct routing_entry));
307
308     if ((src_mac_qual != MAC_ANY) && (src_mac_qual != MAC_NONE)) {
309         memcpy(new_route->src_mac, src_mac, 6);
310     }
311             
312     if ((dest_mac_qual != MAC_ANY) && (dest_mac_qual != MAC_NONE)) {
313         memcpy(new_route->dest_mac, dest_mac, 6);
314     }
315             
316     new_route->src_mac_qual = src_mac_qual;
317     new_route->dest_mac_qual = dest_mac_qual;
318     new_route->link_idx= link_idx;
319     new_route->link_type = link_type;
320     new_route->src_link_idx = src;
321     new_route->src_type = src_type;
322
323     int idx = -1;
324     if ((idx = add_route_entry(new_route)) == -1)
325         return -1;
326     
327     clear_hash_cache();
328     
329     return idx;
330 }
331
332 static void * delete_link_entry(int index) 
333 {
334     struct link_entry *link = NULL;
335     void *ret = NULL;
336     link_type_t type;
337   
338     if (index >= MAX_LINKS || g_links.links[index] == NULL) {
339         return NULL;
340     }
341
342     link = g_links.links[index];
343     type = g_links.links[index]->type;
344
345     if (type == LINK_INTERFACE) 
346         ret = (void *)g_links.links[index]->dst_dev;
347     else if (type == LINK_EDGE)
348         ret = (void *)g_links.links[index]->dst_link;
349
350     g_links.links[index] = NULL;
351     g_links.size --;
352
353     V3_Free(link);
354         
355     return ret;
356 }
357
358 static int find_route_entry(char src_mac[6], 
359                             char dest_mac[6], 
360                             int src_mac_qual, 
361                             int dest_mac_qual, 
362                             int link_idx, 
363                             link_type_t link_type, 
364                             int src, 
365                             link_type_t src_type) 
366 {
367     int i;
368     char temp_src_mac[6];
369     char temp_dest_mac[6];
370   
371     if ((src_mac_qual != MAC_ANY) && (src_mac_qual != MAC_NONE)) {
372         memcpy(temp_src_mac, src_mac, 6);
373     } else {
374         memset(temp_src_mac, 0, 6);
375     }
376     
377     if ((dest_mac_qual != MAC_ANY) && (dest_mac_qual != MAC_NONE)) {
378         memcpy(temp_dest_mac, dest_mac, 6);
379     } else {
380         memset(temp_dest_mac, 0, 6);
381     }
382     
383     for (i = 0; i<MAX_ROUTES; i++) {
384         if (g_routes.routes[i] != NULL) {
385             if ((memcmp(temp_src_mac, g_routes.routes[i]->src_mac, 6) == 0) && 
386                   (memcmp(temp_dest_mac, g_routes.routes[i]->dest_mac, 6) == 0) &&
387                   (g_routes.routes[i]->src_mac_qual == src_mac_qual) &&
388                   (g_routes.routes[i]->dest_mac_qual == dest_mac_qual)  &&
389                   ((link_type == LINK_ANY) || 
390                   ((link_type == g_routes.routes[i]->link_type) && (g_routes.routes[i]->link_idx == link_idx))) &&
391                   ((src_type == LINK_ANY) || 
392                   ((src_type == g_routes.routes[i]->src_type) && (g_routes.routes[i]->src_link_idx == src)))) {
393                 return i;
394             }
395         } 
396      }
397     
398     return -1;
399 }
400
401 static int delete_route_entry(int index) 
402 {
403     struct routing_entry *route;
404
405     if (index >= MAX_ROUTES || g_routes.routes[index] == NULL)
406                 return -1;
407
408     route = g_routes.routes[index];
409     g_routes.routes[index] = NULL;
410     g_routes.size --;
411
412     V3_Free(route);
413
414     clear_hash_cache();
415     
416     return 0;
417 }
418
419 int vnet_delete_route_entry_by_addr(char src_mac[6], 
420                                     char dest_mac[6], 
421                                     int src_mac_qual, 
422                                     int dest_mac_qual, 
423                                     int link_idx, 
424                                     link_type_t type, 
425                                     int src, 
426                                     link_type_t src_type) 
427 {
428     int index = find_route_entry(src_mac, dest_mac, src_mac_qual, 
429                                  dest_mac_qual, link_idx, type, src, src_type);
430     
431     if (index == -1) {
432         return -1;
433     }
434     
435     return delete_route_entry(index);
436 }
437
438 static int match_route(uint8_t *src_mac, uint8_t *dst_mac, link_type_t src_type, int src_index, int *matches)
439
440     int values[MAX_ROUTES];
441     int matched_routes[MAX_ROUTES];
442     
443     int num_matches = 0;
444     int i;
445     int max = 0;
446     int no = 0;
447     int exact_match = 0;
448
449     for(i = 0; i<MAX_ROUTES; i++) {
450         if (g_routes.routes[i] != NULL){
451             if ((g_routes.routes[i]->src_type != LINK_ANY) &&
452                  ((g_routes.routes[i]->src_type != src_type) ||
453                  ((g_routes.routes[i]->src_link_idx != src_index) &&
454                    (g_routes.routes[i]->src_link_idx != -1)))) {
455                 PrintDebug("Vnet: MatchRoute: Source route is on and does not match\n");
456                 continue;
457             }
458         
459             if ((g_routes.routes[i]->dest_mac_qual == MAC_ANY) &&
460                  (g_routes.routes[i]->src_mac_qual == MAC_ANY)) {      
461                   matched_routes[num_matches] = i;
462                   values[num_matches] = 3;
463                   num_matches++;
464             }
465         
466             if (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) {
467                 if (g_routes.routes[i]->src_mac_qual !=  MAC_NOT) {
468                     if (g_routes.routes[i]->dest_mac_qual == MAC_ANY) {
469                         matched_routes[num_matches] = i;
470                         values[num_matches] = 6;
471                     
472                         num_matches++;
473                     } else if (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) == 0) {
474                         if (g_routes.routes[i]->dest_mac_qual != MAC_NOT) {   
475                              matched_routes[num_matches] = i;
476                              values[num_matches] = 8;    
477                              exact_match = 1;
478                              num_matches++;
479                         }
480                     }
481                 }
482             }
483         
484             if (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) == 0) {
485                 if (g_routes.routes[i]->dest_mac_qual != MAC_NOT) {
486                     if (g_routes.routes[i]->src_mac_qual == MAC_ANY) {
487                         matched_routes[num_matches] = i;
488                         values[num_matches] = 6;
489                     
490                         num_matches++;
491                     } else if (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) {
492                         if (g_routes.routes[i]->src_mac_qual != MAC_NOT) {
493                             if (exact_match == 0) {
494                                 matched_routes[num_matches] = i;
495                                 values[num_matches] = 8;
496                                 num_matches++;
497                             }
498                         }
499                     }
500                 }
501             }
502         
503             if ((g_routes.routes[i]->dest_mac_qual == MAC_NOT) &&
504                   (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) != 0)) {
505                 if (g_routes.routes[i]->src_mac_qual == MAC_ANY) {
506                      matched_routes[num_matches] = i;
507                      values[num_matches] = 5;               
508                      num_matches++;    
509                 } else if (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) {
510                      if (g_routes.routes[i]->src_mac_qual != MAC_NOT) {      
511                          matched_routes[num_matches] = i;
512                          values[num_matches] = 7;                     
513                          num_matches++;
514                      }
515                 }
516             }
517         
518             if ((g_routes.routes[i]->src_mac_qual == MAC_NOT) &&
519                 (memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) != 0)) {
520                  if (g_routes.routes[i]->dest_mac_qual == MAC_ANY) {
521                       matched_routes[num_matches] = i;
522                       values[num_matches] = 5;      
523                       num_matches++;
524                  } else if (memcmp((void *)&g_routes.routes[i]->dest_mac, (void *)dst_mac, 6) == 0) {
525                       if (g_routes.routes[i]->dest_mac_qual != MAC_NOT) { 
526                           matched_routes[num_matches] = i;
527                           values[num_matches] = 7;
528                           num_matches++;
529                       }
530                  }
531             }
532        }
533     }//end for
534     
535     for(i = 0; i<MAX_ROUTES; i++) {
536         if ((memcmp((void *)&g_routes.routes[i]->src_mac, (void *)src_mac, 6) == 0) &&
537              (g_routes.routes[i]->dest_mac_qual == MAC_NONE) &&
538              ((g_routes.routes[i]->src_type == LINK_ANY) ||
539              ((g_routes.routes[i]->src_type == src_type) &&
540              ((g_routes.routes[i]->src_link_idx == src_index) ||
541               (g_routes.routes[i]->src_link_idx == -1))))) {
542             matched_routes[num_matches] = i;
543             values[num_matches] = 4;
544             PrintDebug("Vnet: MatchRoute: We matched a default route (%d)\n", i);
545             num_matches++;
546         }
547     }
548     
549     //If many rules have been matched, we choose one which has the highest value rating
550     if (num_matches == 0) {
551         return 0;
552     }
553     
554     for (i = 0; i < num_matches; i++) {
555         if (values[i] > max) {
556             no = 0;
557             max = values[i];
558             matches[no] = matched_routes[i];
559             no++;
560         } else if (values[i] == max) {
561             matches[no] = matched_routes[i];
562             no++;
563         }
564     }
565     
566     return no;
567 }
568
569 #if 0
570 // TODO: To be removed
571 static int process_udpdata() 
572 {
573     struct ethernet_pkt * pt;
574
575     uint32_t dest = 0;
576     uint16_t remote_port = 0;
577     SOCK link_sock = g_udp_sockfd;
578     int length = sizeof(struct ethernet_pkt) - (2 * sizeof(int));   //minus the "size" and "type" 
579
580     //run in a loop to get packets from outside network, adding them to the incoming packet queue
581     while (1) {
582         pt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
583
584         if (pt == NULL){
585             PrintError("Vnet: process_udp: Malloc fails\n");
586             continue;
587         }
588         
589         PrintDebug("Vnet: route_thread: socket: [%d]. ready to receive from ip [%x], port [%d] or from VMs\n", link_sock, (uint_t)dest, remote_port);
590         pt->size = V3_RecvFrom_IP( link_sock, dest, remote_port, pt->data, length);
591         PrintDebug("Vnet: route_thread: socket: [%d] receive from ip [%x], port [%d]\n", link_sock, (uint_t)dest, remote_port);
592         
593         if (pt->size <= 0) {
594             PrintDebug("Vnet: process_udp: receiving packet from UDP fails\n");
595             V3_Free(pt);
596             return -1;
597         }
598         
599         PrintDebug("Vnet: process_udp: get packet\n");
600         print_packet(pt->data, pt->size);
601     }
602 }
603
604 // TODO: To be removed
605 static int indata_handler( )
606 {
607       if (!use_tcp)
608            process_udpdata();     
609
610       return 0;   
611 }
612
613 // TODO: To be removed
614 static int start_recv_data()
615 {
616         if (use_tcp){
617                 
618         } else {
619                 SOCK udp_data_socket;
620   
621                 if ((udp_data_socket = V3_Create_UDP_Socket()) < 0){
622                         PrintError("VNET: Can't setup udp socket\n");
623                         return -1; 
624                 }
625                 PrintDebug("Vnet: vnet_setup_udp: get socket: %d\n", udp_data_socket);
626                 g_udp_sockfd = udp_data_socket;
627
628                 store_topologies(udp_data_socket);
629
630                 if (V3_Bind_Socket(udp_data_socket, vnet_udp_port) < 0){ 
631                         PrintError("VNET: Can't bind socket\n");
632                         return -1;
633                 }
634                 PrintDebug("VNET: vnet_setup_udp: bind socket successful\n");
635         }
636
637         V3_CREATE_THREAD(&indata_handler, NULL, "VNET_DATA_HANDLER");
638         return 0;
639 }
640
641 static void store_test_topologies(SOCK fd) 
642 {
643     int i;
644     int src_mac_qual = MAC_ANY;
645     int dest_mac_qual = MAC_ANY;
646     uint_t dest;
647 #ifndef VNET_SERVER
648     dest = (0 | 172 << 24 | 23 << 16 | 1 );
649     PrintDebug("VNET: store_topologies. NOT VNET_SERVER, dest = %x\n", dest);
650 #else
651     dest = (0 | 172 << 24 | 23 << 16 | 2 );
652     PrintDebug("VNET: store_topologies. VNET_SERVER, dest = %x\n", dest);
653 #endif
654
655     int type = UDP_TYPE;
656     int src = 0;
657     int src_type= LINK_ANY; //ANY_SRC_TYPE
658     int data_port = 22;
659 }
660
661 #endif
662
663 static int handle_one_pkt(struct ethernet_pkt * pkt) 
664 {
665     int src_link_index = -1;    //the value of src_link_index of udp always is 0
666     int i;
667     char src_mac[6];
668     char dst_mac[6];
669
670     int matches[MAX_ROUTES];
671     int num_matched_routes = 0;
672
673     struct in_pkt_header header;
674   
675     // get the ethernet and ip headers from the packet
676     memcpy((void *)&header, (void *)pkt->data, sizeof(header));
677     memcpy(src_mac, header.ethernetsrc, 6);
678     memcpy(dst_mac, header.ethernetdest, 6);
679
680 #ifdef CONFIG_DEBUG_VNET
681     char dest_str[18];
682     char src_str[18];
683     
684     mac_to_string(src_mac, src_str);  
685     mac_to_string(dst_mac, dest_str);
686     
687     PrintDebug("Vnet: HandleDataOverLink. SRC(%s), DEST(%s)\n", src_str, dest_str);
688 #endif
689     
690     char hash_key[hash_key_size];
691     make_hash_key(hash_key, src_mac, dst_mac, LINK_EDGE, src_link_index);//link_edge -> pt->type???
692     
693     num_matched_routes = look_into_cache((route_hashkey_t)hash_key, matches);
694     
695     if (num_matched_routes == -1) {  //no match
696         num_matched_routes = match_route(src_mac, dst_mac, LINK_ANY, src_link_index, matches);
697         
698          if (num_matched_routes > 0) {
699              add_route_to_cache(hash_key, num_matched_routes,matches);      
700          }
701     }
702     
703     PrintDebug("Vnet: HandleDataOverLink: Matches=%d\n", num_matched_routes);
704     
705     for (i = 0; i < num_matched_routes; i++) {
706         int route_index = -1;
707         int link_index = -1;
708          int pkt_len = 0;
709         
710         route_index = matches[i];
711         
712         PrintDebug("Vnet: HandleDataOverLink: Forward packet from link according to Route entry %d\n", route_index);
713
714          link_index = g_routes.routes[route_index]->link_idx;
715          if (link_index < 0 || link_index > MAX_LINKS)
716              continue;
717          
718          struct link_entry *link = g_links.links[link_index];
719          if (link == NULL)
720              continue;
721          
722          pkt_len = pkt->size;
723         if (g_routes.routes[route_index]->link_type == LINK_EDGE) {
724
725             // TODO: apply the header in the beginning of the packet to be sent
726              if ((link->dst_link->input(pkt->data, pkt_len, NULL)) != pkt_len)
727                  return -1;
728         } else if (g_routes.routes[route_index]->link_type == LINK_INTERFACE) {
729           
730       
731             if ((link->dst_link->input(pkt->data, pkt_len, NULL)) != pkt_len)
732                  return -1;
733         } else {
734             PrintError("Vnet: Wrong Edge type\n");
735              return -1;
736         }
737     }
738
739      return 0;
740 }
741
742 static int send_ethernet_pkt(char *buf, int length) 
743 {
744         struct ethernet_pkt *pt;
745
746         pt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
747         ethernet_packet_init(pt, buf, length);  //====here we copy sending data once 
748         
749         PrintDebug("VNET: vm_send_pkt: transmitting packet: (size:%d)\n", (int)pt->size);
750         print_packet((char *)buf, length);
751         
752         v3_enqueue(g_inpkt_q, (addr_t)pt);
753
754         return 0;
755 }
756
757 int v3_vnet_send_pkt(uchar_t *buf, int length) 
758 {
759     PrintDebug("VNET: In V3_Send_pkt: pkt length %d\n", length);
760     
761     return send_ethernet_pkt((char *)buf, length);
762 }
763
764 static int search_device(char *device_name) 
765 {
766     int i;
767
768     for (i = 0; i < MAX_LINKS; i++) {
769         if (g_links.links[i] != NULL && g_links.links[i]->type == LINK_INTERFACE) {
770             if (!strcmp(device_name, g_links.links[i]->dst_dev->name)) {
771                 return i;
772             }
773         }
774     }
775     
776     return -1;
777 }
778
779 int vnet_register_device(struct vm_device *vdev, 
780                                                    char *dev_name, 
781                                                    uchar_t mac[6], 
782                                                    int (*netif_input)(uchar_t * pkt, uint_t size, void *private_data), 
783                                                    void *data) 
784 {
785     struct vnet_if_device *if_dev;
786
787     int idx = search_device(dev_name);
788     if (idx != -1)
789         return -1;
790     
791     if_dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device));
792     
793     if (if_dev == NULL){
794         PrintError("VNET: Malloc fails\n");
795         return -1;
796     }
797     
798     strcpy(if_dev->name, dev_name);
799     strncpy(if_dev->mac_addr, mac, 6);
800     if_dev->dev = vdev;
801     if_dev->input = netif_input;
802     if_dev->private_data = data;
803
804     struct link_entry *link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
805
806     link->type = LINK_INTERFACE;
807     link->dst_dev = if_dev;
808
809     idx = add_link_entry(link);
810     
811     return idx;
812 }
813
814 int vnet_unregister_device(char *dev_name) 
815 {
816     int idx;
817
818     idx = search_device(dev_name);
819     
820     if (idx == -1) {
821         return -1;
822     }
823
824     struct vnet_if_device *device = (struct vnet_if_device *)delete_link_entry(idx);
825     if (device == NULL) {
826         return -1;
827     }
828
829     V3_Free(device);
830
831     return idx;
832 }
833
834 int v3_vnet_pkt_process() 
835 {
836     struct ethernet_pkt *pt;
837
838     PrintDebug("VNET: In vnet_check\n");
839         
840     while ((pt = (struct ethernet_pkt *)v3_dequeue(g_inpkt_q)) != NULL) {
841         PrintDebug("VNET: In vnet_check: pt length %d, pt type %d\n", (int)pt->size, (int)pt->type);
842         v3_hexdump(pt->data, pt->size, NULL, 0);
843         
844         if(handle_one_pkt(pt)) {
845             PrintDebug("VNET: vnet_check: handle one packet!\n");  
846         }else {
847             PrintError("VNET: vnet_check: fail to forward one packet, discard it!\n"); 
848         }
849         
850         V3_Free(pt); //be careful here
851     }
852     
853     return 0;
854 }
855
856
857 static void init_empty_link_table() 
858 {
859     int i;
860
861     for (i = 0; i < MAX_LINKS; i++)
862         g_links.links[i] = NULL;
863
864         
865     g_links.size = 0;
866 }
867
868 static void init_empty_route_table() 
869 {       
870     int i;
871
872     for (i = 0; i < MAX_ROUTES; i++) 
873         g_routes.routes[i] = NULL;
874
875     g_links.size = 0;
876 }
877
878 static void init_tables() {
879     init_empty_link_table();
880     init_empty_route_table();
881     init_route_cache();
882 }
883
884 static void init_pkt_queue()
885 {
886     PrintDebug("VNET Init package receiving queue\n");
887
888     g_inpkt_q = v3_create_queue();
889     v3_init_queue(g_inpkt_q);
890 }
891
892 #if 0
893 // TODO: 
894 static int init_routing_tables(struct routing_entry *route_tab, uint16_t size)
895 {
896     //struct routing_entry *route;
897
898
899     return 0;
900 }
901
902
903 // TODO: 
904 static int init_link_tables(struct link_entry *link_tab, uint16_t size)
905 {
906     //struct link_entry *link;
907
908     return 0;
909 }
910
911 #endif
912
913 struct table_init_info {
914     addr_t routing_table_start;
915     uint16_t routing_table_size;
916     addr_t link_table_start;
917     uint16_t link_table_size;
918 };
919
920 static int handle_init_tables_hcall(struct guest_info * info, uint_t hcall_id, void *priv_data) 
921 {
922     uint8_t *buf = NULL;
923     addr_t info_addr =  (addr_t)info->vm_regs.rcx;
924
925     if (guest_va_to_host_va(info, info_addr, (addr_t *)&(buf)) == -1) {
926         PrintError("Could not translate buffer address\n");
927         return -1;
928     }
929
930     //struct table_init_info *init_info = (struct table_init_info *)buf;
931     
932     
933     return 0;
934 }
935
936
937 void v3_vnet_init(struct guest_info *vm) 
938 {
939     init_tables();
940     init_pkt_queue();
941         
942     v3_register_hypercall(vm, VNET_INITAB_HCALL, handle_init_tables_hcall, NULL);
943
944     //store_test_topologies(udp_data_socket); 
945
946     PrintDebug("VNET Initied\n");
947 }
948
949