secchan: Get rid of static data in in-band control.
authorBen Pfaff <blp@nicira.com>
Tue, 17 Mar 2009 20:48:49 +0000 (13:48 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 17 Mar 2009 20:48:49 +0000 (13:48 -0700)
The notion of the controller's IP and MAC address in in-band control was
global.  This is incorrect if different switches within a process have
different controller.  Make this data part of "struct in_band" instead.

secchan/in-band.c

index b377f2e38b0e9fc45a64b74215fd87e9ae6a3256..4d1635c56fb5ba99c56b36e2c833dadef7216d26 100644 (file)
@@ -61,47 +61,52 @@ struct in_band {
     struct netdev *netdev;
     struct rconn *controller;
     struct status_category *ss_cat;
+
+    /* Keeping track of controller's MAC address. */
+    uint32_t ip;                /* Current IP, 0 if unknown. */
+    uint32_t last_ip;           /* Last known IP, 0 if never known. */
+    uint8_t mac[ETH_ADDR_LEN];  /* Current MAC, 0 if unknown. */
+    uint8_t last_mac[ETH_ADDR_LEN]; /* Last known MAC, 0 if never known */
+    time_t next_refresh;        /* Next time to refresh MAC address. */
 };
 
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60);
 
 static const uint8_t *
-get_controller_mac(struct in_band *in_band)
+get_controller_mac(struct in_band *ib)
 {
-    static uint32_t ip, last_nonzero_ip;
-    static uint8_t mac[ETH_ADDR_LEN], last_nonzero_mac[ETH_ADDR_LEN];
-    static time_t next_refresh = 0;
-
-    uint32_t last_ip = ip;
-
     time_t now = time_now();
+    uint32_t ip;
 
-    ip = rconn_get_ip(in_band->controller);
-    if (last_ip != ip || !next_refresh || now >= next_refresh) {
+    ip = rconn_get_ip(ib->controller);
+    if (ip != ib->ip || now >= ib->next_refresh) {
         bool have_mac;
 
+        ib->ip = ip;
+
         /* Look up MAC address. */
-        memset(mac, 0, sizeof mac);
-        if (ip) {
-            int retval = netdev_arp_lookup(in_band->netdev, ip, mac);
+        memset(ib->mac, 0, sizeof ib->mac);
+        if (ib->ip) {
+            int retval = netdev_arp_lookup(ib->netdev, ib->ip, ib->mac);
             if (retval) {
                 VLOG_DBG_RL(&rl, "cannot look up controller hw address "
-                            "("IP_FMT"): %s", IP_ARGS(&ip), strerror(retval));
+                            "("IP_FMT"): %s",
+                            IP_ARGS(&ib->ip), strerror(retval));
             }
         }
-        have_mac = !eth_addr_is_zero(mac);
+        have_mac = !eth_addr_is_zero(ib->mac);
 
         /* Log changes in IP, MAC addresses. */
-        if (ip && ip != last_nonzero_ip) {
+        if (ib->ip && ib->ip != ib->last_ip) {
             VLOG_DBG("controller IP address changed from "IP_FMT
-                     " to "IP_FMT, IP_ARGS(&last_nonzero_ip), IP_ARGS(&ip));
-            last_nonzero_ip = ip;
+                     " to "IP_FMT, IP_ARGS(&ib->last_ip), IP_ARGS(&ib->ip));
+            ib->last_ip = ib->ip;
         }
-        if (have_mac && memcmp(last_nonzero_mac, mac, ETH_ADDR_LEN)) {
+        if (have_mac && memcmp(ib->last_mac, ib->mac, ETH_ADDR_LEN)) {
             VLOG_DBG("controller MAC address changed from "ETH_ADDR_FMT" to "
                      ETH_ADDR_FMT,
-                     ETH_ADDR_ARGS(last_nonzero_mac), ETH_ADDR_ARGS(mac));
-            memcpy(last_nonzero_mac, mac, ETH_ADDR_LEN);
+                     ETH_ADDR_ARGS(ib->last_mac), ETH_ADDR_ARGS(ib->mac));
+            memcpy(ib->last_mac, ib->mac, ETH_ADDR_LEN);
         }
 
         /* Schedule next refresh.
@@ -109,9 +114,9 @@ get_controller_mac(struct in_band *in_band)
          * If we have an IP address but not a MAC address, then refresh
          * quickly, since we probably will get a MAC address soon (via ARP).
          * Otherwise, we can afford to wait a little while. */
-        next_refresh = now + (!ip || have_mac ? 10 : 1);
+        ib->next_refresh = now + (!ib->ip || have_mac ? 10 : 1);
     }
-    return !eth_addr_is_zero(mac) ? mac : NULL;
+    return !eth_addr_is_zero(ib->mac) ? ib->mac : NULL;
 }
 
 static bool
@@ -271,6 +276,7 @@ in_band_create(struct dpif *dpif, struct switch_status *ss,
     in_band->controller = controller;
     in_band->ss_cat = switch_status_register(ss, "in-band",
                                              in_band_status_cb, in_band);
+    in_band->next_refresh = TIME_MIN;
 
     *in_bandp = in_band;
     return 0;