From: Ben Pfaff Date: Tue, 17 Mar 2009 20:50:13 +0000 (-0700) Subject: secchan: Tolerate local port change in MAC address. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d454e24b22d0e985f86e885bf7f178c2961bf7a;p=openvswitch secchan: Tolerate local port change in MAC address. Before, if the local port's MAC address changed, we would not notice, and continue to set up flows only for the local port's current MAC address, which completely broke in-band control. Now, we notice changes and start to set up flows for the new MAC address instead. Fixes bug #1081. --- diff --git a/secchan/in-band.c b/secchan/in-band.c index 4d1635c5..0379e748 100644 --- a/secchan/in-band.c +++ b/secchan/in-band.c @@ -68,6 +68,10 @@ struct in_band { 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. */ + + /* Keeping track of the local port's MAC address. */ + uint8_t local_mac[ETH_ADDR_LEN]; /* Current MAC. */ + time_t next_local_refresh; /* Next time to refresh MAC address. */ }; static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60); @@ -127,6 +131,27 @@ is_controller_mac(const uint8_t dl_addr[ETH_ADDR_LEN], return mac && eth_addr_equals(mac, dl_addr); } +static const uint8_t * +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(netdev_get_name(ib->netdev), ea)) { + memcpy(ib->local_mac, ea, ETH_ADDR_LEN); + } + ib->next_local_refresh = now + 1; + } + return !eth_addr_is_zero(ib->local_mac) ? ib->local_mac : NULL; +} + +static bool +is_local_mac(const uint8_t dl_addr[ETH_ADDR_LEN], struct in_band *ib) +{ + const uint8_t *local_mac = get_local_mac(ib); + return local_mac && eth_addr_equals(dl_addr, local_mac); +} + static void in_band_learn_mac(struct in_band *in_band, uint16_t in_port, const uint8_t src_mac[ETH_ADDR_LEN]) @@ -151,8 +176,7 @@ in_band_handle_flow_miss(struct in_band *in_band, struct ofproto *ofproto, if (flow->in_port == ODPP_LOCAL) { /* Sent by secure channel. */ out_port = mac_learning_lookup(in_band->mac_learning, flow->dl_dst, 0); - } else if (eth_addr_equals(flow->dl_dst, - netdev_get_etheraddr(in_band->netdev))) { + } else if (is_local_mac(flow->dl_dst, in_band)) { /* Sent to secure channel. */ out_port = ODPP_LOCAL; in_band_learn_mac(in_band, flow->in_port, flow->dl_src); @@ -214,15 +238,18 @@ in_band_status_cb(struct status_reply *sr, void *in_band_) { struct in_band *in_band = in_band_; struct in_addr local_ip; + const uint8_t *local_mac; uint32_t controller_ip; const uint8_t *controller_mac; - const uint8_t *mac; - mac = netdev_get_etheraddr(in_band->netdev); if (netdev_get_in4(in_band->netdev, &local_ip)) { status_reply_put(sr, "local-ip="IP_FMT, IP_ARGS(&local_ip.s_addr)); } - status_reply_put(sr, "local-mac="ETH_ADDR_FMT, ETH_ADDR_ARGS(mac)); + local_mac = get_local_mac(in_band); + if (local_mac) { + status_reply_put(sr, "local-mac="ETH_ADDR_FMT, + ETH_ADDR_ARGS(local_mac)); + } controller_ip = rconn_get_ip(in_band->controller); if (controller_ip) { @@ -277,6 +304,7 @@ in_band_create(struct dpif *dpif, struct switch_status *ss, in_band->ss_cat = switch_status_register(ss, "in-band", in_band_status_cb, in_band); in_band->next_refresh = TIME_MIN; + in_band->next_local_refresh = TIME_MIN; *in_bandp = in_band; return 0;