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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
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
22 * This is free software. You are permitted to use,
23 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
26 #include <palacios/vmm_vnet.h>
27 #include <palacios/vmm_hypercall.h>
28 #include <palacios/vm_guest_mem.h>
30 #ifndef CONFIG_DEBUG_VNET
32 #define PrintDebug(fmt, args...)
37 uint32_t size; //size of data
39 struct udp_link_header ext_hdr; //possible externel header to applied to data before sent
40 char data[ETHERNET_PACKET_LEN];
41 }__attribute__((packed));
44 // 14 (ethernet frame) + 20 bytes
45 struct in_pkt_header {
46 uchar_t ethernetdest[6];
47 uchar_t ethernetsrc[6];
48 uchar_t ethernettype[2]; //layer 3 protocol type
50 }__attribute__((packed));
52 #define VNET_INITAB_HCALL 0xca00 // inital hypercall id
56 #define HASH_KEY_LEN 16
57 #define MIN_CACHE_SIZE 100
58 static const uint_t hash_key_size = 16;
61 struct link_entry * links[MAX_LINKS];
63 }__attribute__((packed));
65 struct routing_table {
66 struct routing_entry * routes[MAX_ROUTES];
68 }__attribute__((packed));
70 static struct link_table g_links;
71 static struct routing_table g_routes;
72 static struct gen_queue * g_inpkt_q;
80 typedef char * route_hashkey_t;
82 // This is the hash value, Format: 0: num_matched_routes, 1...n: matches[] -- TY
83 struct route_cache_entry {
84 int num_matched_routes;
89 static struct hashtable * g_route_cache;
91 static uint16_t ip_xsum(struct ip_header *ip_hdr, int hdr_len){
94 uint16_t *p = (uint16_t*) ip_hdr;
98 sum = (sum & 0xFFFF) + (sum >> 16);
103 sum += (uint16_t) *(uchar_t *)p;
106 sum = (sum & 0xFFFF) + (sum >> 16);
108 return (uint16_t)~sum;
111 static inline void ethernet_packet_init(struct ethernet_pkt *pt, uchar_t *data, const size_t size) {
113 memcpy(pt->data, data, size);
116 static uint_t hash_from_key_fn(addr_t hashkey) {
117 uint8_t * key = (uint8_t *)hashkey;
118 return v3_hash_buffer(key, HASH_KEY_LEN);
121 static int hash_key_equal(addr_t key1, addr_t key2) {
122 uint8_t * buf1 = (uint8_t *)key1;
123 uint8_t * buf2 = (uint8_t *)key2;
124 return (memcmp(buf1, buf2, HASH_KEY_LEN) == 0);
127 static int init_route_cache() {
128 g_route_cache = v3_create_htable(MIN_CACHE_SIZE, &hash_from_key_fn, &hash_key_equal);
130 if (g_route_cache == NULL) {
131 PrintError("Vnet: Route Cache Initiate Failurely\n");
138 static void make_hash_key(route_hashkey_t hashkey,
145 for (j = 0; j < 6; j++) {
146 hashkey[j] = src_addr[j];
147 hashkey[j + 6] = dest_addr[j] + 1;
150 hashkey[12] = src_type;
152 *(int *)(hashkey + 12) = src_index;
155 static int add_route_to_cache(route_hashkey_t hashkey, int num_matched_r, int * matches) {
156 struct route_cache_entry * new_entry = NULL;
159 new_entry = (struct route_cache_entry *)V3_Malloc(sizeof(struct route_cache_entry));
160 if (new_entry == NULL) {
161 PrintError("Vnet: Malloc fails\n");
165 new_entry->num_matched_routes = num_matched_r;
167 new_entry->matches = (int *)V3_Malloc(num_matched_r * sizeof(int));
169 if (new_entry->matches == NULL) {
170 PrintError("Vnet: Malloc fails\n");
174 for (i = 0; i < num_matched_r; i++) {
175 new_entry->matches[i] = matches[i];
178 // here, when v3_htable_insert return 0, it means insert fails
179 if (v3_htable_insert(g_route_cache, (addr_t)hashkey, (addr_t)new_entry) == 0) {
180 PrintError("Vnet: Insert new route entry to cache failed\n");
181 V3_Free(new_entry->matches);
188 static int clear_hash_cache() {
189 v3_free_htable(g_route_cache, 1, 1);
191 g_route_cache = v3_create_htable(MIN_CACHE_SIZE, hash_from_key_fn, hash_key_equal);
193 if (g_route_cache == NULL) {
194 PrintError("Vnet: Route Cache Create Failurely\n");
201 static int look_into_cache(route_hashkey_t hashkey, int * matches) {
202 struct route_cache_entry * found = NULL;
206 found = (struct route_cache_entry *)v3_htable_search(g_route_cache, (addr_t)hashkey);
209 n_matches = found->num_matched_routes;
211 for (i = 0; i < n_matches; i++) {
212 matches[i] = found->matches[i];
219 #ifdef CONFIG_DEBUG_VNET
221 static void print_packet(uchar_t *pkt, int size) {
222 PrintDebug("Vnet: print_data_packet: size: %d\n", size);
223 v3_hexdump(pkt, size, NULL, 0);
226 static inline uint8_t hex_nybble_to_nybble(const uint8_t hexnybble) {
227 uint8_t x = toupper(hexnybble);
232 return 10 + (x - 'A');
236 static inline uint8_t hex_byte_to_byte(const uint8_t hexbyte[2]) {
237 return ((hex_nybble_to_nybble(hexbyte[0]) << 4) +
238 (hex_nybble_to_nybble(hexbyte[1]) & 0xf));
241 static inline void string_to_mac(const char *str, uint8_t mac[6]) {
244 for (k = 0; k < 6; k++) {
245 mac[k] = hex_byte_to_byte(&(str[(2 * k) + k]));
249 static inline void mac_to_string(char mac[6], char * buf) {
250 snprintf(buf, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
251 mac[0], mac[1], mac[2],
252 mac[3], mac[4], mac[5]);
255 static void dump_routes(struct routing_entry **route_tables) {
258 struct routing_entry *route = NULL;
261 PrintDebug("\nVnet: route table dump start =====\n");
263 for(i = 0; i < MAX_ROUTES; i++) {
264 if (route_tables[i] != NULL){
265 route = route_tables[i];
267 mac_to_string(route->src_mac, src_str);
268 mac_to_string(route->dest_mac, dest_str);
270 PrintDebug("route: %d\n", i);
271 PrintDebug("SRC(%s), DEST(%s), src_mac_qual(%d), dst_mac_qual(%d)\n", src_str, dest_str, route->src_mac_qual, route->dest_mac_qual);
272 PrintDebug("Src_Link(%d), src_type(%d), dst_link(%d), dst_type(%d)\n\n", route->src_link_idx, route->src_type, route->link_idx, route->link_type);
276 PrintDebug("\nVnet: route table dump end =====\n");
281 static int __add_link_entry(struct link_entry * link) {
284 for (idx = 0; idx < MAX_LINKS; idx++) {
285 if (g_links.links[idx] == NULL) {
286 g_links.links[idx] = link;
293 PrintError("No available Link entry\n");
297 static int __add_route_entry(struct routing_entry * route) {
300 for (idx = 0; idx < MAX_ROUTES; idx++) {
301 if (g_routes.routes[idx] == NULL) {
302 g_routes.routes[idx] = route;
309 PrintError("No available route entry\n");
314 int vnet_add_route_entry(char src_mac[6],
319 link_type_t link_type,
321 link_type_t src_link_type) {
322 struct routing_entry * new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
325 memset(new_route, 0, sizeof(struct routing_entry));
327 if ((src_mac_qual != MAC_ANY)) {
328 memcpy(new_route->src_mac, src_mac, 6);
331 if ((dest_mac_qual != MAC_ANY)) {
332 memcpy(new_route->dest_mac, dest_mac, 6);
335 new_route->src_mac_qual = src_mac_qual;
336 new_route->dest_mac_qual = dest_mac_qual;
337 new_route->link_idx= link_idx;
338 new_route->link_type = link_type;
339 new_route->src_link_idx = src_link_idx;
340 new_route->src_type = src_link_type;
342 if ((idx = __add_route_entry(new_route)) == -1) {
343 PrintError("Could not add route entry\n");
353 static void * __delete_link_entry(int index) {
354 struct link_entry * link = NULL;
358 if ((index >= MAX_LINKS) || (g_links.links[index] == NULL)) {
362 link = g_links.links[index];
363 type = g_links.links[index]->type;
365 if (type == LINK_INTERFACE) {
366 ret = (void *)g_links.links[index]->dst_dev;
367 } else if (type == LINK_EDGE) {
368 ret = (void *)g_links.links[index]->dst_link;
371 g_links.links[index] = NULL;
379 static int find_route_entry(char src_mac[6],
384 link_type_t link_type,
386 link_type_t src_type) {
388 char temp_src_mac[6];
389 char temp_dest_mac[6];
391 if ((src_mac_qual != MAC_ANY) && (src_mac_qual != MAC_NONE)) {
392 memcpy(temp_src_mac, src_mac, 6);
394 memset(temp_src_mac, 0, 6);
397 if ((dest_mac_qual != MAC_ANY) && (dest_mac_qual != MAC_NONE)) {
398 memcpy(temp_dest_mac, dest_mac, 6);
400 memset(temp_dest_mac, 0, 6);
403 for (i = 0; i < MAX_ROUTES; i++) {
404 if (g_routes.routes[i] != NULL) {
405 if ((memcmp(temp_src_mac, g_routes.routes[i]->src_mac, 6) == 0) &&
406 (memcmp(temp_dest_mac, g_routes.routes[i]->dest_mac, 6) == 0) &&
407 (g_routes.routes[i]->src_mac_qual == src_mac_qual) &&
408 (g_routes.routes[i]->dest_mac_qual == dest_mac_qual) &&
409 ( (link_type == LINK_ANY) ||
410 ((link_type == g_routes.routes[i]->link_type) && (g_routes.routes[i]->link_idx == link_idx))) &&
411 ( (src_type == LINK_ANY) ||
412 ((src_type == g_routes.routes[i]->src_type) && (g_routes.routes[i]->src_link_idx == src)))) {
421 static int __delete_route_entry(int index) {
422 struct routing_entry * route;
424 if ((index >= MAX_ROUTES) || (g_routes.routes[index] == NULL)) {
425 PrintDebug("VNET: wrong index in delete route entry %d\n", index);
429 route = g_routes.routes[index];
430 g_routes.routes[index] = NULL;
440 static int vnet_delete_route_entry_by_addr(char src_mac[6],
447 link_type_t src_type) {
448 int index = find_route_entry(src_mac, dest_mac, src_mac_qual,
449 dest_mac_qual, link_idx, type, src, src_type);
452 PrintDebug("VNET: wrong in delete route entry %d\n", index);
456 return __delete_route_entry(index);
460 static int match_route(uint8_t * src_mac,
462 link_type_t src_type,
465 int matched_routes[MAX_ROUTES];
468 struct routing_entry *route = NULL;
470 #ifdef CONFIG_DEBUG_VNET
474 mac_to_string(src_mac, src_str);
475 mac_to_string(dst_mac, dest_str);
477 PrintDebug("Vnet: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dest_str);
479 dump_routes(g_routes.routes);
482 for(i = 0; i < MAX_ROUTES; i++) {
483 if (g_routes.routes[i] != NULL){
484 route = g_routes.routes[i];
486 if(src_type == LINK_ANY && src_index == -1) {
487 if ((route->dest_mac_qual == MAC_ANY) &&
488 (route->src_mac_qual == MAC_ANY)) {
489 matched_routes[num_matches] = i;
493 if (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0) {
494 if (route->src_mac_qual != MAC_NOT) {
495 if (route->dest_mac_qual == MAC_ANY) {
496 matched_routes[num_matches] = i;
498 } else if (route->dest_mac_qual != MAC_NOT &&
499 memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0) {
500 matched_routes[num_matches] = i;
506 if (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0) {
507 if (route->dest_mac_qual != MAC_NOT) {
508 if (route->src_mac_qual == MAC_ANY) {
509 matched_routes[num_matches] = i;
511 } else if ((route->src_mac_qual != MAC_NOT) &&
512 (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0)) {
513 matched_routes[num_matches] = i;
519 if ((route->dest_mac_qual == MAC_NOT) &&
520 (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) != 0)) {
521 if (route->src_mac_qual == MAC_ANY) {
522 matched_routes[num_matches] = i;
524 } else if ((route->src_mac_qual != MAC_NOT) &&
525 (memcmp((void *)&route->src_mac, (void *)src_mac, 6) == 0)) {
526 matched_routes[num_matches] = i;
531 if ((route->src_mac_qual == MAC_NOT) &&
532 (memcmp((void *)&route->src_mac, (void *)src_mac, 6) != 0)) {
533 if (route->dest_mac_qual == MAC_ANY) {
534 matched_routes[num_matches] = i;
536 } else if ((route->dest_mac_qual != MAC_NOT) &&
537 (memcmp((void *)&route->dest_mac, (void *)dst_mac, 6) == 0)) {
538 matched_routes[num_matches] = i;
542 }//end if src_type == Link_any
546 PrintDebug("Vnet: match_route: Matches=%d\n", num_matches);
548 for (i = 0; i < num_matches; i++) {
549 matches[i] = matched_routes[i];
555 static int handle_one_pkt(struct ethernet_pkt *pkt) {
556 int src_link_index = -1; //the value of src_link_index of udp always is 0
561 int matches[MAX_ROUTES];
562 int num_matched_routes = 0;
564 struct in_pkt_header header;
566 char hash_key[hash_key_size];
568 // get the ethernet and ip headers from the packet
569 memcpy((void *)&header, (void *)pkt->data, sizeof(header));
570 memcpy(src_mac, header.ethernetsrc, 6);
571 memcpy(dst_mac, header.ethernetdest, 6);
573 #ifdef CONFIG_DEBUG_VNET
577 mac_to_string(src_mac, src_str);
578 mac_to_string(dst_mac, dest_str);
580 PrintDebug("Vnet: HandleDataOverLink. SRC(%s), DEST(%s)\n", src_str, dest_str);
583 // link_edge -> pt->type???
584 make_hash_key(hash_key, src_mac, dst_mac, LINK_EDGE, src_link_index);
586 num_matched_routes = look_into_cache((route_hashkey_t)hash_key, matches);
588 if (num_matched_routes == -1) {
589 // no match in the cache
590 num_matched_routes = match_route(src_mac, dst_mac, LINK_ANY, src_link_index, matches);
592 if (num_matched_routes > 0) {
593 add_route_to_cache(hash_key, num_matched_routes,matches);
597 PrintDebug("Vnet: HandleDataOverLink: Matches=%d\n", num_matched_routes);
599 if (num_matched_routes == 0) {
603 for (i = 0; i < num_matched_routes; i++) {//send packet to all destinations
604 int route_index = -1;
607 struct link_entry * link = NULL;
609 route_index = matches[i];
610 link_index = g_routes.routes[route_index]->link_idx;
612 if ((link_index < 0) || (link_index > MAX_LINKS) ||
613 (g_links.links[link_index] == NULL)) {
617 link = g_links.links[link_index];
619 if (link->type == LINK_EDGE) {
621 //apply the header in the beginning of the packet to be sent
622 if (link->dst_link->pro_type == UDP_TYPE) {
623 struct udp_link_header *hdr = &(link->dst_link->vnet_header);
624 struct ip_header *ip = &hdr->ip_hdr;
625 struct udp_header *udp = &hdr->udp_hdr;
626 udp->len = pkt_len + sizeof(struct udp_header);
627 ip->total_len = pkt_len + sizeof(struct udp_header) + sizeof(struct ip_header);
628 ip->cksum = ip_xsum(ip, sizeof(struct ip_header));
630 int hdr_size = sizeof(struct udp_link_header);
631 memcpy(&pkt->ext_hdr, hdr, hdr_size);
634 if ((link->dst_link->input((uchar_t *)&pkt->ext_hdr, pkt_len, link->dst_link->private_data)) != pkt_len) {
635 PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
639 PrintDebug("VNET: Link protocol type not support\n");
642 } else if (link->type == LINK_INTERFACE) {
643 if ((link->dst_dev->input(pkt->data, pkt_len, link->dst_dev->private_data)) != pkt_len) {
644 PrintDebug("VNET: Packet not sent properly to link: %d\n", link_index);
648 PrintDebug("Vnet: Wrong Edge type of link: %d\n", link_index);
652 PrintDebug("Vnet: HandleDataOverLink: Forward packet according to Route entry %d to link %d\n", route_index, link_index);
658 static int send_ethernet_pkt(uchar_t *data, int len) {
659 struct ethernet_pkt *pkt;
661 pkt = (struct ethernet_pkt *)V3_Malloc(sizeof(struct ethernet_pkt));
662 memset(pkt, 0, sizeof(struct ethernet_pkt));
665 PrintError("VNET: Memory allocate fails\n");
669 ethernet_packet_init(pkt, data, len); //====here we copy sending data once
671 PrintDebug("VNET: vm_send_pkt: transmitting packet: (size:%d)\n", (int)pkt->size);
673 #ifdef CONFIG_DEBUG_VNET
674 print_packet((char *)data, len);
677 v3_enqueue(g_inpkt_q, (addr_t)pkt);
682 //send raw ethernet packet
683 int v3_vnet_send_rawpkt(uchar_t * buf, int len, void *private_data) {
684 PrintDebug("VNET: In V3_Send_pkt: pkt length %d\n", len);
686 return send_ethernet_pkt(buf, len);
689 //sending the packet from Dom0, should remove the link header
690 int v3_vnet_send_udppkt(uchar_t * buf, int len, void *private_data) {
691 PrintDebug("VNET: In V3_Send_pkt: pkt length %d\n", len);
693 uint_t hdr_len = sizeof(struct udp_link_header);
695 return send_ethernet_pkt((uchar_t *)(buf+hdr_len), len - hdr_len);
698 static int search_device(char * device_name) {
701 for (i = 0; i < MAX_LINKS; i++) {
702 if ((g_links.links[i] != NULL) && (g_links.links[i]->type == LINK_INTERFACE)) {
703 if (strcmp(device_name, g_links.links[i]->dst_dev->name) == 0) {
712 int vnet_register_device(struct vm_device * vdev,
715 int (*netif_input)(uchar_t * pkt, uint_t size, void * private_data),
717 struct vnet_if_device * if_dev;
719 int idx = search_device(dev_name);
721 PrintDebug("VNET: register device: Already has device with the name %s\n", dev_name);
725 if_dev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device));
726 if (if_dev == NULL) {
727 PrintError("VNET: Malloc fails\n");
731 strcpy(if_dev->name, dev_name);
732 strncpy(if_dev->mac_addr, mac, 6);
734 if_dev->input = netif_input;
735 if_dev->private_data = data;
737 struct link_entry * link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
738 link->type = LINK_INTERFACE;
739 link->dst_dev = if_dev;
741 idx = __add_link_entry(link);
747 static int vnet_unregister_device(char * dev_name) {
750 idx = search_device(dev_name);
753 PrintDebug("VNET: No device with name %s found\n", dev_name);
757 struct vnet_if_device * device = (struct vnet_if_device *)__delete_link_entry(idx);
758 if (device == NULL) {
759 PrintError("VNET: Device %s not in the link table %d, something may be wrong in link table\n", dev_name, idx);
770 int v3_vnet_pkt_process() {
771 struct ethernet_pkt * pkt;
773 while ((pkt = (struct ethernet_pkt *)v3_dequeue(g_inpkt_q)) != NULL) {
774 PrintDebug("VNET: In vnet_check: pt length %d, pt type %d\n", (int)pkt->size, (int)pkt->type);
776 if (handle_one_pkt(pkt) != -1) {
777 PrintDebug("VNET: vnet_check: handle one packet!\n");
779 PrintDebug("VNET: vnet_check: Fail to forward one packet, discard it!\n");
782 V3_Free(pkt); // be careful here
788 static void init_empty_link_table() {
791 for (i = 0; i < MAX_LINKS; i++) {
792 g_links.links[i] = NULL;
798 static void init_empty_route_table() {
801 for (i = 0; i < MAX_ROUTES; i++) {
802 g_routes.routes[i] = NULL;
808 static void init_tables() {
809 init_empty_link_table();
810 init_empty_route_table();
814 static void init_pkt_queue() {
815 PrintDebug("VNET Init package receiving queue\n");
817 g_inpkt_q = v3_create_queue();
818 v3_init_queue(g_inpkt_q);
821 static void free_link_mem(struct link_entry *link){
822 V3_Free(link->dst_dev);
827 static int addto_routing_link_tables(struct routing_entry *route_tab,
829 struct link_entry *link_tab,
831 struct routing_entry *route, *new_route;
832 struct link_entry *link, *new_link;
835 int link_idxs[MAX_LINKS];
837 //add all of the links first, record their new indexs
838 for (i = 0; i < num_links; i++) {
841 new_link = (struct link_entry *)V3_Malloc(sizeof(struct link_entry));
843 if (new_link == NULL){
844 PrintError("VNET: Memory allocate error\n");
848 new_link->type = link->type;
850 //TODO: how to set the input parameters here
851 if (link->type == LINK_EDGE){
852 struct vnet_if_device *ifdev = (struct vnet_if_device *)V3_Malloc(sizeof(struct vnet_if_device));
855 PrintError("VNET: Memory allocate fails\n");
859 memcpy(ifdev->name, link->dst_dev->name, DEVICE_NAME_LEN);
864 //ifdev->private_data
866 new_link->dst_dev = ifdev;
867 }else if (link->type == LINK_INTERFACE){
868 struct vnet_if_link *iflink = (struct vnet_if_link *)V3_Malloc(sizeof(struct vnet_if_link));
871 PrintError("VNET: Memory allocate fails\n");
874 iflink->pro_type = link->dst_link->pro_type;
875 iflink->dest_ip = link->dst_link->dest_ip;
876 iflink->dest_port = link->dst_link->dest_port;
877 memcpy(&iflink->vnet_header, &link->dst_link->vnet_header, sizeof(struct udp_link_header));
881 //iflink->private_data =
883 new_link->dst_link = iflink;
885 PrintDebug("VNET: invalid link type\n");
890 new_idx = __add_link_entry(new_link);
892 PrintError("VNET: Adding link fails\n");
893 free_link_mem(new_link);
896 link_idxs[i] = new_idx;
899 //add all of routes, replace with new link indexs
900 for (i = 0; i < num_routes; i++) {
901 route = &route_tab[i];
902 if (route->link_idx < 0 || route->link_idx >= num_links ||
903 ((route->src_link_idx != -1) &&
904 (route->src_link_idx < 0 || route->src_link_idx >= num_links))){
905 PrintError("VNET: There is error in the intial tables data from guest\n");
909 new_route = (struct routing_entry *)V3_Malloc(sizeof(struct routing_entry));
911 if (new_route == NULL){
912 PrintError("VNET: Memory allocate fails\n");
915 memcpy(new_route, route, sizeof(struct routing_entry));
917 new_route->link_idx = link_idxs[new_route->link_idx];
919 if (route->src_link_idx != -1)
920 new_route->src_link_idx = link_idxs[new_route->src_link_idx];
922 if((__add_route_entry(new_route)) == -1){
923 PrintDebug("VNET: Adding route fails");
932 struct table_init_info {
933 addr_t routing_table_start;
934 uint16_t routing_table_size;
935 addr_t link_table_start;
936 uint16_t link_table_size;
939 //add the guest specified routes and links to the tables
940 static int handle_init_tables_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
941 addr_t guest_addr = (addr_t)info->vm_regs.rcx;
942 addr_t info_addr, route_addr, link_addr;
943 struct table_init_info *init_info;
944 struct link_entry *link_array;
945 struct routing_entry *route_array;
947 PrintDebug("Vnet: In handle_init_tables_hcall\n");
949 if (guest_va_to_host_va(info, guest_addr, &info_addr) == -1) {
950 PrintError("VNET: Could not translate guest address\n");
953 init_info = (struct table_init_info *)info_addr;
955 if (guest_va_to_host_va(info, init_info->routing_table_start, &route_addr) == -1) {
956 PrintError("VNET: Could not translate guest address\n");
959 route_array = (struct routing_entry *)route_addr;
961 if (guest_va_to_host_va(info, init_info->link_table_start, &link_addr) == -1) {
962 PrintError("VNET: Could not translate guest address\n");
965 link_array = (struct link_entry *)link_addr;
967 addto_routing_link_tables(route_array, init_info->routing_table_size, link_array, init_info->link_table_size);
972 void v3_vnet_init(struct guest_info * vm) {
976 v3_register_hypercall(vm, VNET_INITAB_HCALL, handle_init_tables_hcall, NULL);
978 PrintDebug("VNET Initialized\n");