Merge citrix branch into master.
[sliver-openvswitch.git] / ofproto / in-band.c
similarity index 90%
rename from secchan/in-band.c
rename to ofproto/in-band.c
index a2197c6..2b362bc 100644 (file)
@@ -225,12 +225,13 @@ struct in_band {
 
     /* Keep track of local port's information. */
     uint8_t local_mac[ETH_ADDR_LEN];       /* Current MAC. */
-    char local_name[IF_NAMESIZE];          /* Local device name. */
+    struct netdev *local_netdev;           /* Local port's network device. */
     time_t next_local_refresh;
 
     /* Keep track of controller and next hop's information. */
     uint32_t controller_ip;                /* Controller IP, 0 if unknown. */
     uint8_t remote_mac[ETH_ADDR_LEN];      /* Remote MAC. */
+    struct netdev *remote_netdev;
     uint8_t last_remote_mac[ETH_ADDR_LEN]; /* Previous remote MAC. */
     time_t next_remote_refresh;
 
@@ -245,14 +246,17 @@ get_remote_mac(struct in_band *ib)
 {
     int retval;
     bool have_mac;
-    struct in_addr c_in4, r_in4;
-    char *dev_name;
+    struct in_addr c_in4;   /* Controller's IP address. */
+    struct in_addr r_in4;   /* Next hop IP address. */
+    char *next_hop_dev;
     time_t now = time_now();
 
     if (now >= ib->next_remote_refresh) {
+        /* Find the next-hop IP address. */
         c_in4.s_addr = ib->controller_ip;
         memset(ib->remote_mac, 0, sizeof ib->remote_mac);
-        retval = netdev_get_next_hop(&c_in4, &r_in4, &dev_name);
+        retval = netdev_get_next_hop(ib->local_netdev,
+                                     &c_in4, &r_in4, &next_hop_dev);
         if (retval) {
             VLOG_WARN("cannot find route for controller ("IP_FMT"): %s",
                     IP_ARGS(&ib->controller_ip), strerror(retval));
@@ -263,17 +267,34 @@ get_remote_mac(struct in_band *ib)
             r_in4.s_addr = c_in4.s_addr;
         }
 
-        retval = netdev_nodev_arp_lookup(dev_name, r_in4.s_addr, 
-                                         ib->remote_mac);
+        /* Get the next-hop IP and network device. */
+        if (!ib->remote_netdev
+            || strcmp(netdev_get_name(ib->remote_netdev), next_hop_dev))
+        {
+            netdev_close(ib->remote_netdev);
+            retval = netdev_open(next_hop_dev, NETDEV_ETH_TYPE_NONE,
+                                 &ib->remote_netdev);
+            if (retval) {
+                VLOG_WARN_RL(&rl, "cannot open netdev %s (next hop "
+                             "to controller "IP_FMT"): %s",
+                             next_hop_dev, IP_ARGS(&ib->controller_ip),
+                             strerror(retval));
+                ib->next_remote_refresh = now + 1;
+                return NULL;
+            }
+        }
+
+        /* Look up the MAC address of the next-hop IP address. */
+        retval = netdev_arp_lookup(ib->remote_netdev, r_in4.s_addr,
+                                   ib->remote_mac);
         if (retval) {
             VLOG_DBG_RL(&rl, "cannot look up remote MAC address ("IP_FMT"): %s",
                         IP_ARGS(&r_in4.s_addr), strerror(retval));
         }
         have_mac = !eth_addr_is_zero(ib->remote_mac);
-        free(dev_name);
-
-        if (have_mac 
-                && !eth_addr_equals(ib->last_remote_mac, ib->remote_mac)) {
+        free(next_hop_dev);
+        if (have_mac
+            && !eth_addr_equals(ib->last_remote_mac, ib->remote_mac)) {
             VLOG_DBG("remote MAC address changed from "ETH_ADDR_FMT" to "
                      ETH_ADDR_FMT,
                      ETH_ADDR_ARGS(ib->last_remote_mac),
@@ -299,7 +320,7 @@ get_local_mac(struct in_band *ib)
     time_t now = time_now();
     if (now >= ib->next_local_refresh) {
         uint8_t ea[ETH_ADDR_LEN];
-        if (!netdev_nodev_get_etheraddr(ib->local_name, ea)) {
+        if (ib->local_netdev && !netdev_get_etheraddr(ib->local_netdev, ea)) {
             memcpy(ib->local_mac, ea, ETH_ADDR_LEN);
         }
         ib->next_local_refresh = now + 1;
@@ -578,30 +599,44 @@ in_band_flushed(struct in_band *in_band)
     }
 }
 
-void
+int
 in_band_create(struct ofproto *ofproto, struct dpif *dpif,
                struct switch_status *ss, struct rconn *controller, 
                struct in_band **in_bandp)
 {
     struct in_band *in_band;
+    char local_name[IF_NAMESIZE];
+    struct netdev *local_netdev;
     int error;
 
-    in_band = xcalloc(1, sizeof *in_band);
-    error = dpif_port_get_name(dpif, ODPP_LOCAL, in_band->local_name, 
-                               sizeof in_band->local_name);
+    error = dpif_port_get_name(dpif, ODPP_LOCAL,
+                               local_name, sizeof local_name);
     if (error) {
-        free(in_band);
-        return;
+        VLOG_ERR("failed to initialize in-band control: cannot get name "
+                 "of datapath local port (%s)", strerror(error));
+        return error;
     }
 
+    error = netdev_open(local_name, NETDEV_ETH_TYPE_NONE, &local_netdev);
+    if (error) {
+        VLOG_ERR("failed to initialize in-band control: cannot open "
+                 "datapath local port %s (%s)", local_name, strerror(error));
+        return error;
+    }
+
+    in_band = xcalloc(1, sizeof *in_band);
     in_band->ofproto = ofproto;
     in_band->controller = controller;
     in_band->ss_cat = switch_status_register(ss, "in-band",
                                              in_band_status_cb, in_band);
-    in_band->next_remote_refresh = TIME_MIN;
+    in_band->local_netdev = local_netdev;
     in_band->next_local_refresh = TIME_MIN;
+    in_band->remote_netdev = NULL;
+    in_band->next_remote_refresh = TIME_MIN;
 
     *in_bandp = in_band;
+
+    return 0;
 }
 
 void
@@ -609,6 +644,8 @@ in_band_destroy(struct in_band *in_band)
 {
     if (in_band) {
         switch_status_unregister(in_band->ss_cat);
+        netdev_close(in_band->local_netdev);
+        netdev_close(in_band->remote_netdev);
         /* We don't own the rconn. */
     }
 }