/* 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;
{
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));
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),
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;
}
}
-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
{
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. */
}
}