+\f
+/* name_table . */
+
+static void
+name_table_init(void)
+{
+ hmap_init(&name_map);
+ name_notifier = rtnetlink_link_notifier_create(name_table_change, NULL);
+ name_table_valid = false;
+}
+
+static void
+name_table_uninit(void)
+{
+ rtnetlink_link_notifier_destroy(name_notifier);
+ name_notifier = NULL;
+ name_map_clear();
+ hmap_destroy(&name_map);
+}
+
+static int
+name_table_reset(void)
+{
+ struct nl_dump dump;
+ struct rtgenmsg *rtmsg;
+ uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
+ struct ofpbuf request, reply, buf;
+
+ name_table_valid = true;
+ name_map_clear();
+
+ ofpbuf_init(&request, 0);
+ nl_msg_put_nlmsghdr(&request, sizeof *rtmsg, RTM_GETLINK, NLM_F_REQUEST);
+ rtmsg = ofpbuf_put_zeros(&request, sizeof *rtmsg);
+ rtmsg->rtgen_family = AF_INET;
+
+ nl_dump_start(&dump, NETLINK_ROUTE, &request);
+ ofpbuf_uninit(&request);
+
+ ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub);
+ while (nl_dump_next(&dump, &reply, &buf)) {
+ struct rtnetlink_link_change change;
+
+ if (rtnetlink_link_parse(&reply, &change)
+ && change.nlmsg_type == RTM_NEWLINK
+ && !name_node_lookup(change.ifi_index)) {
+ struct name_node *nn;
+
+ nn = xzalloc(sizeof *nn);
+ nn->ifi_index = change.ifi_index;
+ ovs_strlcpy(nn->ifname, change.ifname, IFNAMSIZ);
+ hmap_insert(&name_map, &nn->node, hash_int(nn->ifi_index, 0));
+ }
+ }
+ ofpbuf_uninit(&buf);
+ return nl_dump_done(&dump);
+}
+
+static void
+name_table_change(const struct rtnetlink_link_change *change OVS_UNUSED,
+ void *aux OVS_UNUSED)
+{
+ /* Changes to interface status can cause routing table changes that some
+ * versions of the linux kernel do not advertise for some reason. */
+ route_table_valid = false;
+ name_table_valid = false;
+}
+
+static struct name_node *
+name_node_lookup(int ifi_index)
+{
+ struct name_node *nn;
+
+ HMAP_FOR_EACH_WITH_HASH(nn, node, hash_int(ifi_index, 0), &name_map) {
+ if (nn->ifi_index == ifi_index) {
+ return nn;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+name_map_clear(void)
+{
+ struct name_node *nn, *nn_next;
+
+ HMAP_FOR_EACH_SAFE(nn, nn_next, node, &name_map) {
+ hmap_remove(&name_map, &nn->node);
+ free(nn);
+ }
+}