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.


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