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.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[palacios.git] / palacios / src / vnet / vnet_core.c
index 0819adf..7d9942d 100644 (file)
 #define PrintDebug(fmt, args...)
 #endif
 
-#define VNET_NOPROGRESS_LIMIT 1000
-#define VNET_YIELD_USEC       1000
+#define VNET_NUM_TX_KICK_THREADS 1
+
+#define VNET_ADAPTIVE_TX_KICK 0         // set to 1 to try to sleep when there is nothing to do
+#define VNET_NOPROGRESS_LIMIT 1000      //   ... after this many tries
+#define VNET_YIELD_USEC       1000      //   ... and go to sleep for this long
+
 
 int net_debug = 0;
 
@@ -119,9 +123,10 @@ static struct {
    /* device queue that are waiting to be polled */
     struct v3_queue * poll_devs;
 
-    struct vnet_thread * pkt_flush_thread;
+    struct vnet_thread * pkt_flush_thread[VNET_NUM_TX_KICK_THREADS];
 
     struct hashtable * route_cache;
+
 } vnet_state;
        
 
@@ -136,15 +141,15 @@ static void print_route(struct v3_vnet_route * route){
     char str[50];
 
     mac2str(route->src_mac, str);
-    PrintDebug("Src Mac (%s),  src_qual (%d)\n", 
+    PrintDebug(VM_NONE, VCORE_NONE, "Src Mac (%s),  src_qual (%d)\n", 
               str, route->src_mac_qual);
     mac2str(route->dst_mac, str);
-    PrintDebug("Dst Mac (%s),  dst_qual (%d)\n", 
+    PrintDebug(VM_NONE, VCORE_NONE, "Dst Mac (%s),  dst_qual (%d)\n", 
               str, route->dst_mac_qual);
-    PrintDebug("Src dev id (%d), src type (%d)", 
+    PrintDebug(VM_NONE, VCORE_NONE, "Src dev id (%d), src type (%d)", 
               route->src_id, 
               route->src_type);
-    PrintDebug("Dst dev id (%d), dst type (%d)\n", 
+    PrintDebug(VM_NONE, VCORE_NONE, "Dst dev id (%d), dst type (%d)\n", 
               route->dst_id, 
               route->dst_type);
 }
@@ -152,13 +157,13 @@ static void print_route(struct v3_vnet_route * route){
 static void dump_routes(){
     struct vnet_route_info *route;
 
-    PrintDebug("\n========Dump routes starts ============\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "\n========Dump routes starts ============\n");
     list_for_each_entry(route, &(vnet_state.routes), node) {
-       PrintDebug("\nroute %d:\n", route->idx);
+       PrintDebug(VM_NONE, VCORE_NONE, "\nroute %d:\n", route->idx);
                
        print_route(&(route->route_def));
        if (route->route_def.dst_type == LINK_INTERFACE) {
-           PrintDebug("dst_dev (%p), dst_dev_id (%d), dst_dev_ops(%p), dst_dev_data (%p)\n",
+           PrintDebug(VM_NONE, VCORE_NONE, "dst_dev (%p), dst_dev_id (%d), dst_dev_ops(%p), dst_dev_data (%p)\n",
                route->dst_dev,
                route->dst_dev->dev_id,
                (void *)&(route->dst_dev->dev_ops),
@@ -166,7 +171,7 @@ static void dump_routes(){
        }
     }
 
-    PrintDebug("\n========Dump routes end ============\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "\n========Dump routes end ============\n");
 }
 
 #endif
@@ -190,7 +195,7 @@ static int add_route_to_cache(const struct v3_vnet_pkt * pkt, struct route_list
     memcpy(routes->hash_buf, pkt->hash_buf, VNET_HASH_SIZE);    
 
     if (vnet_htable_insert(vnet_state.route_cache, (addr_t)routes->hash_buf, (addr_t)routes) == 0) {
-       PrintError("VNET/P Core: Failed to insert new route entry to the cache\n");
+       PrintError(VM_NONE, VCORE_NONE, "VNET/P Core: Failed to insert new route entry to the cache\n");
        return -1;
     }
     
@@ -237,6 +242,10 @@ static struct vnet_dev * dev_by_mac(uint8_t * mac) {
 }
 
 
+static int start_vnet_kick_threads(void);
+static int stop_vnet_kick_threads(void);
+
+
 int v3_vnet_find_dev(uint8_t  * mac) {
     struct vnet_dev * dev = NULL;
 
@@ -257,14 +266,14 @@ int v3_vnet_add_route(struct v3_vnet_route route) {
     new_route = (struct vnet_route_info *)Vnet_Malloc(sizeof(struct vnet_route_info));
 
     if (!new_route) {
-       PrintError("Cannot allocate new route\n");
+       PrintError(VM_NONE, VCORE_NONE, "Cannot allocate new route\n");
        return -1;
     }
 
     memset(new_route, 0, sizeof(struct vnet_route_info));
 
 #ifdef V3_CONFIG_DEBUG_VNET
-    PrintDebug("VNET/P Core: add_route_entry:\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: add_route_entry:\n");
     print_route(&route);
 #endif
     
@@ -389,7 +398,7 @@ static inline uint8_t match_mac(uint8_t test_mac[ETH_ALEN],
            }
            break;
        default:
-           PrintError("Unknown qualifier %u\n",route_qual);
+           PrintError(VM_NONE, VCORE_NONE, "Unknown qualifier %u\n",route_qual);
            return NONE;
            break;
     }
@@ -496,7 +505,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
        char dst_str[32], src_str[32];
        mac2str(hdr->src_mac, src_str);  
        mac2str(hdr->dst_mac, dst_str);
-       PrintDebug("VNET/P Core: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dst_str);
+       PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: match_route. pkt: SRC(%s), DEST(%s)\n", src_str, dst_str);
     }
 #endif
     
@@ -526,7 +535,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
            mac2str(route_def->src_mac, src_str);  
            mac2str(route_def->dst_mac, dst_str);
            
-           PrintDebug("Tested match against SRC(%s) SRC_QUAL(%s), DEST(%s) DST_QUAL(%s): "
+           PrintDebug(VM_NONE, VCORE_NONE, "Tested match against SRC(%s) SRC_QUAL(%s), DEST(%s) DST_QUAL(%s): "
                       "SRC_MATCH=%s  DEST_MATCH=%s PRIORITY=%d\n", 
                       src_str, QUAL_TO_STR(route_def->src_mac_qual), 
                       dst_str, QUAL_TO_STR(route_def->dst_mac_qual),
@@ -537,12 +546,12 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
 #endif
 
        if (priority<0) { 
-           PrintDebug("No match to this rule\n");
+           PrintDebug(VM_NONE, VCORE_NONE, "No match to this rule\n");
            continue;
        }
 
        if (priority > max_priority) { 
-            PrintDebug("New highest priority match, reseting list\n");
+            PrintDebug(VM_NONE, VCORE_NONE, "New highest priority match, reseting list\n");
            max_priority = priority;
 
            struct vnet_route_info *my_route, *tmp_route;
@@ -555,7 +564,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
            num_matches = 1;                                    
            
        } else if (priority == max_priority) {                      
-            PrintDebug("Equal priority match, adding to list\n");
+            PrintDebug(VM_NONE, VCORE_NONE, "Equal priority match, adding to list\n");
            
            list_add(&(route->match_node), &match_list);        
            num_matches++;                                      
@@ -563,7 +572,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
        
     }
 
-    PrintDebug("VNET/P Core: match_route: Matches=%d\n", num_matches);
+    PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: match_route: Matches=%d\n", num_matches);
 
     if (num_matches <= 0) {
        return NULL;
@@ -574,7 +583,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
 
 
     if (!matches) {
-       PrintError("VNET/P Core: Unable to allocate matches\n");
+       PrintError(VM_NONE, VCORE_NONE, "VNET/P Core: Unable to allocate matches\n");
        return NULL;
     }
 
@@ -584,7 +593,7 @@ static struct route_list * match_route(const struct v3_vnet_pkt * pkt)
     list_for_each_entry(route, &match_list, match_node) {
        if (i==num_matches) { 
            // the list should never have more than num_matches on it...
-           PrintError("Weird list behavior\n");
+           PrintError(VM_NONE, VCORE_NONE, "Weird list behavior\n");
            break;
        } else {
            matches->routes[i++] = route;
@@ -607,15 +616,15 @@ int v3_vnet_query_header(uint8_t src_mac[ETH_ALEN],
 
     p.size=14;
     p.data=p.header;
-    memcpy(p.header,dest_mac,6);
-    memcpy(p.header+6,src_mac,6);
+    memcpy(p.header,dest_mac,ETH_ALEN);
+    memcpy(p.header+ETH_ALEN,src_mac,ETH_ALEN);
     memset(p.header+12,0,2);
 
     p.src_type = LINK_EDGE;
     p.src_id = 0;
 
-    memcpy(header->src_mac,src_mac,6);
-    memcpy(header->dst_mac,dest_mac,6);
+    memcpy(header->src_mac,src_mac,ETH_ALEN);
+    memcpy(header->dst_mac,dest_mac,ETH_ALEN);
 
 
     flags = vnet_lock_irqsave(vnet_state.lock);
@@ -626,7 +635,7 @@ int v3_vnet_query_header(uint8_t src_mac[ETH_ALEN],
        routes = match_route(&p);
        if (!routes) { 
            vnet_unlock_irqrestore(vnet_state.lock,flags);
-           PrintError("Cannot match route\n");
+           PrintError(VM_NONE, VCORE_NONE, "Cannot match route\n");
            header->header_type=VNET_HEADER_NOMATCH;
            header->header_len=0;
            return -1;
@@ -638,14 +647,14 @@ int v3_vnet_query_header(uint8_t src_mac[ETH_ALEN],
     vnet_unlock_irqrestore(vnet_state.lock,flags);
     
     if (routes->num_routes<1) { 
-       PrintError("Less than one route\n");
+       PrintError(VM_NONE, VCORE_NONE, "Less than one route\n");
        header->header_type=VNET_HEADER_NOMATCH;
        header->header_len=0;
        return -1;
     }
 
     if (routes->num_routes>1) { 
-       PrintError("More than one route, building header for the first one only\n");
+       PrintError(VM_NONE, VCORE_NONE, "More than one route, building header for the first one only\n");
     }
 
     r=routes->routes[0];
@@ -681,7 +690,7 @@ int v3_vnet_query_header(uint8_t src_mac[ETH_ALEN],
            break;
 
        default:
-           PrintError("Unknown destination type\n");
+           PrintError(VM_NONE, VCORE_NONE, "Unknown destination type\n");
            return -1;
            break;
 
@@ -715,14 +724,14 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
     look_into_cache(pkt, &matched_routes);
 
     if (matched_routes == NULL) {  
-       PrintDebug("VNET/P Core: sending pkt - matching route\n");
+       PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: sending pkt - matching route\n");
        
        matched_routes = match_route(pkt);
        
        if (matched_routes) {
            add_route_to_cache(pkt, matched_routes);
        } else {
-           PrintDebug("VNET/P Core: Could not find route for packet... discarding packet\n");
+           PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: Could not find route for packet... discarding packet\n");
            vnet_unlock_irqrestore(vnet_state.lock, flags);
            return 0; /* do we return -1 here?*/
        }
@@ -730,7 +739,7 @@ int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data) {
 
     vnet_unlock_irqrestore(vnet_state.lock, flags);
 
-    PrintDebug("VNET/P Core: send pkt route matches %d\n", matched_routes->num_routes);
+    PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: send pkt route matches %d\n", matched_routes->num_routes);
 
     for (i = 0; i < matched_routes->num_routes; i++) {
        struct vnet_route_info * route = matched_routes->routes[i];
@@ -785,7 +794,7 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
        return -1;
     }
    
-    memcpy(new_dev->mac_addr, mac, 6);
+    memcpy(new_dev->mac_addr, mac, ETH_ALEN);
     new_dev->dev_ops.input = ops->input;
     new_dev->dev_ops.poll = ops->poll;
     new_dev->private_data = priv_data;
@@ -794,6 +803,8 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
     new_dev->quote = quote<VNET_MAX_QUOTE ? quote : VNET_MAX_QUOTE;
     new_dev->poll = poll_state;
 
+    stop_vnet_kick_threads();
+
     flags = vnet_lock_irqsave(vnet_state.lock);
 
     if (dev_by_mac(mac) == NULL) {
@@ -805,18 +816,20 @@ int v3_vnet_add_dev(struct v3_vm_info * vm, uint8_t * mac,
            v3_enqueue(vnet_state.poll_devs, (addr_t)new_dev);
        }
     } else {
-       PrintError("VNET/P: Device with the same MAC has already been added\n");
+        PrintError(VM_NONE, VCORE_NONE,"VNET/P: Device with the same MAC has already been added\n");
     }
 
     vnet_unlock_irqrestore(vnet_state.lock, flags);
 
+    start_vnet_kick_threads();
+
     /* if the device was found previosly the id should still be 0 */
     if (new_dev->dev_id == 0) {
        Vnet_Print(0, "VNET/P Core: Device Already exists\n");
        return -1;
     }
 
-    PrintDebug("VNET/P Core: Add Device: dev_id %d\n", new_dev->dev_id);
+    PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: Add Device: dev_id %d\n", new_dev->dev_id);
 
     return new_dev->dev_id;
 }
@@ -826,6 +839,8 @@ int v3_vnet_del_dev(int dev_id){
     struct vnet_dev * dev = NULL;
     vnet_intr_flags_t flags;
 
+    stop_vnet_kick_threads();
+
     flags = vnet_lock_irqsave(vnet_state.lock);
        
     dev = dev_by_id(dev_id);
@@ -837,9 +852,11 @@ int v3_vnet_del_dev(int dev_id){
        
     vnet_unlock_irqrestore(vnet_state.lock, flags);
 
+    start_vnet_kick_threads();
+
     Vnet_Free(dev);
 
-    PrintDebug("VNET/P Core: Removed Device: dev_id %d\n", dev_id);
+    PrintDebug(VM_NONE, VCORE_NONE, "VNET/P Core: Removed Device: dev_id %d\n", dev_id);
 
     return 0;
 }
@@ -889,14 +906,14 @@ int v3_vnet_add_bridge(struct v3_vm_info * vm,
     vnet_unlock_irqrestore(vnet_state.lock, flags);
 
     if (bridge_free == 0) {
-       PrintError("VNET/P Core: Bridge already set\n");
+       PrintError(VM_NONE, VCORE_NONE, "VNET/P Core: Bridge already set\n");
        return -1;
     }
 
     tmp_bridge = (struct vnet_brg_dev *)Vnet_Malloc(sizeof(struct vnet_brg_dev));
 
     if (tmp_bridge == NULL) {
-       PrintError("VNET/P Core: Unable to allocate new bridge\n");
+       PrintError(VM_NONE, VCORE_NONE, "VNET/P Core: Unable to allocate new bridge\n");
        vnet_state.bridge = NULL;
        return -1;
     }
@@ -957,12 +974,12 @@ static int vnet_tx_flush(void * args){
     struct v3_queue * tq = v3_create_queue();
 
     if (!tq) { 
-       PrintError("VNET/P polling thread cannot allocate queue\n");
+       PrintError(VM_NONE, VCORE_NONE, "VNET/P polling thread cannot allocate queue\n");
        return -1;
     }
 
-    noprogress_count=0;
-
+    noprogress_count = 0;
+    
     while (!vnet_thread_should_stop()) {
 
        more=0; // will indicate if any device has more work for us to do
@@ -998,10 +1015,10 @@ static int vnet_tx_flush(void * args){
        }
 
        // adaptively yield 
-       if (noprogress_count < VNET_NOPROGRESS_LIMIT) { 
+       if ((!VNET_ADAPTIVE_TX_KICK) || (noprogress_count < VNET_NOPROGRESS_LIMIT)) { 
            V3_Yield();
        } else {
-           V3_Yield_Timed(VNET_YIELD_USEC);
+           V3_Sleep(VNET_YIELD_USEC);
        }
 
     }
@@ -1013,7 +1030,30 @@ static int vnet_tx_flush(void * args){
     return 0;
 }
 
-int v3_init_vnet() {
+static int start_vnet_kick_threads()
+{
+    int i;
+
+    for (i=0; i<VNET_NUM_TX_KICK_THREADS;i++) { 
+       char name[32];
+       snprintf(name,32,"vnetd-%d",i);
+       vnet_state.pkt_flush_thread[i] = vnet_start_thread(vnet_tx_flush, NULL, name);
+    }
+    return 0;
+}
+
+static int stop_vnet_kick_threads()
+{
+    int i;
+    for (i=0; i<VNET_NUM_TX_KICK_THREADS;i++) { 
+       vnet_thread_stop(vnet_state.pkt_flush_thread[i]);
+    }
+    return 0;
+}
+
+
+int v3_init_vnet() 
+{
     memset(&vnet_state, 0, sizeof(vnet_state));
        
     INIT_LIST_HEAD(&(vnet_state.routes));
@@ -1023,58 +1063,62 @@ int v3_init_vnet() {
     vnet_state.num_routes = 0;
 
     if (vnet_lock_init(&(vnet_state.lock)) == -1){
-        PrintError("VNET/P: Fails to initiate lock\n");
+        PrintError(VM_NONE, VCORE_NONE, "VNET/P: Fails to initiate lock\n");
     }
 
     vnet_state.route_cache = vnet_create_htable(0, &hash_fn, &hash_eq);
     if (vnet_state.route_cache == NULL) {
-        PrintError("VNET/P: Fails to initiate route cache\n");
+        PrintError(VM_NONE, VCORE_NONE, "VNET/P: Fails to initiate route cache\n");
         return -1;
     }
 
     vnet_state.poll_devs = v3_create_queue();
 
-    vnet_state.pkt_flush_thread = vnet_start_thread(vnet_tx_flush, NULL, "vnetd-1");
+    start_vnet_kick_threads();
 
-    PrintDebug("VNET/P is initiated\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "VNET/P is initiated (%d tx kick threads active)\n",VNET_NUM_TX_KICK_THREADS);
 
     return 0;
 }
 
 
-void v3_deinit_vnet() {
+void v3_deinit_vnet() 
+{
 
+    PrintDebug(VM_NONE, VCORE_NONE, "Stopping kick threads\n");
+    stop_vnet_kick_threads();
+
+
+    PrintDebug(VM_NONE, VCORE_NONE, "Deiniting poll devices\n");
     v3_deinit_queue(vnet_state.poll_devs);
     Vnet_Free(vnet_state.poll_devs);
 
-    PrintDebug("Stopping flush thread\n");
-    // This will pause until the flush thread is gone
-    vnet_thread_stop(vnet_state.pkt_flush_thread);
+
     // At this point there should be no lock-holder
 
     Vnet_Free(vnet_state.poll_devs);
 
 
-    PrintDebug("Deiniting Device List\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "Deiniting Device List\n");
     // close any devices we have open
     deinit_devices_list();  
     
-    PrintDebug("Deiniting Route List\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "Deiniting Route List\n");
     // remove any routes we have
     deinit_routes_list();
 
-    PrintDebug("Freeing hash table\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "Freeing hash table\n");
     // remove the hash table
     vnet_free_htable(vnet_state.route_cache, 1, 1);
 
     
-    PrintDebug("Removing Bridge\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "Removing Bridge\n");
     // remove bridge if it was added
     if (vnet_state.bridge) { 
        Vnet_Free(vnet_state.bridge);
     }
 
-    PrintDebug("Deleting lock\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "Deleting lock\n");
     // eliminate the lock
     vnet_lock_deinit(&(vnet_state.lock));