/* Handle an interface delete event */ void if_delete_update (struct interface *ifp) { struct listnode *node; struct listnode *next; struct connected *ifc; struct prefix *p; if (if_is_up(ifp)) { zlog_err ("interface %s index %d is still up while being deleted.", ifp->name, ifp->ifindex); return; } /* Mark interface as inactive */ UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); if (IS_ZEBRA_DEBUG_KERNEL) zlog_info ("interface %s index %d is now inactive.", ifp->name, ifp->ifindex); /* Delete connected routes from the kernel. */ if (ifp->connected) { for (node = listhead (ifp->connected); node; node = next) { next = node->next; ifc = getdata (node); p = ifc->address; if (p->family == AF_INET) connected_down_ipv4 (ifp, ifc); #ifdef HAVE_IPV6 else if (p->family == AF_INET6) connected_down_ipv6 (ifp, ifc); #endif /* HAVE_IPV6 */ zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) { listnode_delete (ifp->connected, ifc); connected_free (ifc); } } } zebra_interface_delete_update (ifp); }
/* Handle an interface delete event */ void if_delete_update (struct interface *ifp) { struct connected *ifc; struct prefix *p; struct route_node *rn; struct zebra_if *zebra_if; zebra_if = ifp->info; if (if_is_up(ifp)) { zlog_err ("interface %s index %d is still up while being deleted.", ifp->name, ifp->ifindex); return; } /* Mark interface as inactive */ UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("interface %s index %d is now inactive.", ifp->name, ifp->ifindex); /* Delete connected routes from the kernel. */ if (ifp->connected) { struct listnode *node; struct listnode *last = NULL; while ((node = (last ? last->next : listhead (ifp->connected)))) { ifc = listgetdata (node); p = ifc->address; if (p->family == AF_INET && (rn = route_node_lookup (zebra_if->ipv4_subnets, p))) { struct listnode *anode; struct listnode *next; struct listnode *first; struct list *addr_list; route_unlock_node (rn); addr_list = (struct list *) rn->info; /* Remove addresses, secondaries first. */ first = listhead (addr_list); for (anode = first->next; anode || first; anode = next) { if (!anode) { anode = first; first = NULL; } next = anode->next; ifc = listgetdata (anode); p = ifc->address; connected_down_ipv4 (ifp, ifc); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); /* Remove from subnet chain. */ list_delete_node (addr_list, anode); route_unlock_node (rn); /* Remove from interface address list (unconditionally). */ if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) { listnode_delete (ifp->connected, ifc); connected_free (ifc); } else last = node; } /* Free chain list and respective route node. */ list_delete (addr_list); rn->info = NULL; route_unlock_node (rn); } #ifdef HAVE_IPV6 else if (p->family == AF_INET6) { connected_down_ipv6 (ifp, ifc); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) last = node; else { listnode_delete (ifp->connected, ifc); connected_free (ifc); } } #endif /* HAVE_IPV6 */ else { last = node; } } } zebra_interface_delete_update (ifp); /* Update ifindex after distributing the delete message. This is in case any client needs to have the old value of ifindex available while processing the deletion. Each client daemon is responsible for setting ifindex to IFINDEX_INTERNAL after processing the interface deletion message. */ ifp->ifindex = IFINDEX_INTERNAL; }