--- embedaddon/quagga/zebra/interface.c 2013/07/21 23:54:41 1.1.1.3 +++ embedaddon/quagga/zebra/interface.c 2016/11/02 10:09:10 1.1.1.4 @@ -32,6 +32,7 @@ #include "connected.h" #include "log.h" #include "zclient.h" +#include "vrf.h" #include "zebra/interface.h" #include "zebra/rtadv.h" @@ -41,11 +42,11 @@ #include "zebra/debug.h" #include "zebra/irdp.h" -#ifdef RTADV +#if defined (HAVE_RTADV) /* Order is intentional. Matches RFC4191. This array is also used for command matching, so only modify with care. */ const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; -#endif /* RTADV */ +#endif /* HAVE_RTADV */ /* Called when new interface is added. */ static int @@ -56,9 +57,9 @@ if_zebra_new_hook (struct interface *ifp) zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if)); zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; - zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC; + zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; -#ifdef RTADV +#if defined (HAVE_RTADV) { /* Set default router advertise values. */ struct rtadvconf *rtadv; @@ -84,7 +85,7 @@ if_zebra_new_hook (struct interface *ifp) rtadv->AdvPrefixList = list_new (); } -#endif /* RTADV */ +#endif /* HAVE_RTADV */ /* Initialize installed address chains tree. */ zebra_if->ipv4_subnets = route_table_init (); @@ -161,11 +162,26 @@ if_subnet_delete (struct interface *ifp, struct connec /* Get address derived subnet node. */ rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address); if (! (rn && rn->info)) - return -1; + { + zlog_warn("Trying to remove an address from an unknown subnet." + " (please report this bug)"); + return -1; + } route_unlock_node (rn); /* Untie address from subnet's address list. */ addr_list = rn->info; + + /* Deleting an address that is not registered is a bug. + * In any case, we shouldn't decrement the lock counter if the address + * is unknown. */ + if (!listnode_lookup(addr_list, ifc)) + { + zlog_warn("Trying to remove an address from a subnet where it is not" + " currently registered. (please report this bug)"); + return -1; + } + listnode_delete (addr_list, ifc); route_unlock_node (rn); @@ -178,6 +194,9 @@ if_subnet_delete (struct interface *ifp, struct connec ifc = listgetdata (listhead (addr_list)); zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); + /* XXX: Linux kernel removes all the secondary addresses when the primary + * address is removed. We could try to work around that, though this is + * non-trivial. */ zebra_interface_address_add_update (ifp, ifc); } @@ -274,23 +293,30 @@ if_addr_wakeup (struct interface *ifp) p = ifc->address; if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED) - && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)) { /* Address check. */ if (p->family == AF_INET) { if (! if_is_up (ifp)) { - /* XXX: WTF is it trying to set flags here? - * caller has just gotten a new interface, has been - * handed the flags already. This code has no business - * trying to override administrative status of the interface. - * The only call path to here which doesn't originate from - * kernel event is irdp - what on earth is it trying to do? - * - * further RUNNING is not a settable flag on any system - * I (paulj) am aware of. - */ + /* Assume zebra is configured like following: + * + * interface gre0 + * ip addr 192.0.2.1/24 + * ! + * + * As soon as zebra becomes first aware that gre0 exists in the + * kernel, it will set gre0 up and configure its addresses. + * + * (This may happen at startup when the interface already exists + * or during runtime when the interface is added to the kernel) + * + * XXX: IRDP code is calling here via if_add_update - this seems + * somewhat weird. + * XXX: RUNNING is not a settable flag on any system + * I (paulj) am aware of. + */ if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); } @@ -303,22 +329,17 @@ if_addr_wakeup (struct interface *ifp) continue; } - /* Add to subnet chain list. */ - if_subnet_add (ifp, ifc); - - SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - - zebra_interface_address_add_update (ifp, ifc); - - if (if_is_operative(ifp)) - connected_up_ipv4 (ifp, ifc); + SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the notification + * from the kernel has been received. + * It will also be added to the interface's subnet list then. */ } #ifdef HAVE_IPV6 if (p->family == AF_INET6) { if (! if_is_up (ifp)) { - /* XXX: See long comment above */ + /* See long comment above */ if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); } @@ -330,12 +351,10 @@ if_addr_wakeup (struct interface *ifp) safe_strerror(errno)); continue; } - SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - zebra_interface_address_add_update (ifp, ifc); - - if (if_is_operative(ifp)) - connected_up_ipv6 (ifp, ifc); + SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the notification + * from the kernel has been received. */ } #endif /* HAVE_IPV6 */ } @@ -349,6 +368,8 @@ if_add_update (struct interface *ifp) struct zebra_if *if_data; if_data = ifp->info; + assert(if_data); + if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) if_set_flags (ifp, IFF_MULTICAST); else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) @@ -360,16 +381,26 @@ if_add_update (struct interface *ifp) { SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); + if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("interface %s vrf %u index %d is shutdown. " + "Won't wake it up.", + ifp->name, ifp->vrf_id, ifp->ifindex); + return; + } + if_addr_wakeup (ifp); if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s index %d becomes active.", - ifp->name, ifp->ifindex); + zlog_debug ("interface %s vrf %u index %d becomes active.", + ifp->name, ifp->vrf_id, ifp->ifindex); } else { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s index %d is added.", ifp->name, ifp->ifindex); + zlog_debug ("interface %s vrf %u index %d is added.", + ifp->name, ifp->vrf_id, ifp->ifindex); } } @@ -386,8 +417,8 @@ if_delete_update (struct interface *ifp) if (if_is_up(ifp)) { - zlog_err ("interface %s index %d is still up while being deleted.", - ifp->name, ifp->ifindex); + zlog_err ("interface %s vrf %u index %d is still up while being deleted.", + ifp->name, ifp->vrf_id, ifp->ifindex); return; } @@ -395,8 +426,8 @@ if_delete_update (struct interface *ifp) 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); + zlog_debug ("interface %s vrf %u index %d is now inactive.", + ifp->name, ifp->vrf_id, ifp->ifindex); /* Delete connected routes from the kernel. */ if (ifp->connected) @@ -433,12 +464,15 @@ if_delete_update (struct interface *ifp) ifc = listgetdata (anode); p = ifc->address; - connected_down_ipv4 (ifp, ifc); + /* XXX: We have to send notifications here explicitly, because we destroy + * the ifc before receiving the notification about the address being deleted. + */ zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); /* Remove from subnet chain. */ list_delete_node (addr_list, anode); @@ -467,6 +501,7 @@ if_delete_update (struct interface *ifp) zebra_interface_address_delete_update (ifp, ifc); UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) last = node; @@ -522,7 +557,7 @@ if_up (struct interface *ifp) } /* Examine all static routes. */ - rib_update (); + rib_update (ifp->vrf_id); } /* Interface goes down. We have to manage different behavior of based @@ -555,7 +590,7 @@ if_down (struct interface *ifp) } /* Examine all static routes which direct to the interface. */ - rib_update (); + rib_update (ifp->vrf_id); } void @@ -603,7 +638,7 @@ connected_dump_vty (struct vty *vty, struct connected vty_out (vty, "%s", VTY_NEWLINE); } -#ifdef RTADV +#if defined (HAVE_RTADV) /* Dump interface ND information to vty. */ static void nd_dump_vty (struct vty *vty, struct interface *ifp) @@ -664,15 +699,12 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) VTY_NEWLINE); } } -#endif /* RTADV */ +#endif /* HAVE_RTADV */ /* Interface's information print out to vty interface. */ static void if_dump_vty (struct vty *vty, struct interface *ifp) { -#ifdef HAVE_STRUCT_SOCKADDR_DL - struct sockaddr_dl *sdl; -#endif /* HAVE_STRUCT_SOCKADDR_DL */ struct connected *connected; struct listnode *node; struct route_node *rn; @@ -696,6 +728,8 @@ if_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, "down%s", VTY_NEWLINE); } + vty_out (vty, " vrf: %u%s", ifp->vrf_id, VTY_NEWLINE); + if (ifp->desc) vty_out (vty, " Description: %s%s", ifp->desc, VTY_NEWLINE); @@ -722,19 +756,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) if_flag_dump (ifp->flags), VTY_NEWLINE); /* Hardware address. */ -#ifdef HAVE_STRUCT_SOCKADDR_DL - sdl = &ifp->sdl; - if (sdl != NULL && sdl->sdl_alen != 0) - { - int i; - u_char *ptr; - - vty_out (vty, " HWaddr: "); - for (i = 0, ptr = (u_char *)LLADDR (sdl); i < sdl->sdl_alen; i++, ptr++) - vty_out (vty, "%s%02x", i == 0 ? "" : ":", *ptr); - vty_out (vty, "%s", VTY_NEWLINE); - } -#else + vty_out (vty, " Type: %s%s", if_link_type_str (ifp->ll_type), VTY_NEWLINE); if (ifp->hw_addr_len != 0) { int i; @@ -744,7 +766,6 @@ if_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]); vty_out (vty, "%s", VTY_NEWLINE); } -#endif /* HAVE_STRUCT_SOCKADDR_DL */ /* Bandwidth in kbps */ if (ifp->bandwidth != 0) @@ -769,9 +790,9 @@ if_dump_vty (struct vty *vty, struct interface *ifp) connected_dump_vty (vty, connected); } -#ifdef RTADV +#if defined (HAVE_RTADV) nd_dump_vty (vty, ifp); -#endif /* RTADV */ +#endif /* HAVE_RTADV */ #ifdef HAVE_PROC_NET_DEV /* Statistics print out using proc file system. */ @@ -806,24 +827,29 @@ if_dump_vty (struct vty *vty, struct interface *ifp) #ifdef HAVE_NET_RT_IFLIST #if defined (__bsdi__) || defined (__NetBSD__) /* Statistics print out using sysctl (). */ - vty_out (vty, " input packets %qu, bytes %qu, dropped %qu," - " multicast packets %qu%s", - ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes, - ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts, - VTY_NEWLINE); + vty_out (vty, " input packets %llu, bytes %llu, dropped %llu," + " multicast packets %llu%s", + (unsigned long long)ifp->stats.ifi_ipackets, + (unsigned long long)ifp->stats.ifi_ibytes, + (unsigned long long)ifp->stats.ifi_iqdrops, + (unsigned long long)ifp->stats.ifi_imcasts, + VTY_NEWLINE); - vty_out (vty, " input errors %qu%s", - ifp->stats.ifi_ierrors, VTY_NEWLINE); + vty_out (vty, " input errors %llu%s", + (unsigned long long)ifp->stats.ifi_ierrors, VTY_NEWLINE); - vty_out (vty, " output packets %qu, bytes %qu, multicast packets %qu%s", - ifp->stats.ifi_opackets, ifp->stats.ifi_obytes, - ifp->stats.ifi_omcasts, VTY_NEWLINE); + vty_out (vty, " output packets %llu, bytes %llu," + " multicast packets %llu%s", + (unsigned long long)ifp->stats.ifi_opackets, + (unsigned long long)ifp->stats.ifi_obytes, + (unsigned long long)ifp->stats.ifi_omcasts, + VTY_NEWLINE); - vty_out (vty, " output errors %qu%s", - ifp->stats.ifi_oerrors, VTY_NEWLINE); + vty_out (vty, " output errors %llu%s", + (unsigned long long)ifp->stats.ifi_oerrors, VTY_NEWLINE); - vty_out (vty, " collisions %qu%s", - ifp->stats.ifi_collisions, VTY_NEWLINE); + vty_out (vty, " collisions %llu%s", + (unsigned long long)ifp->stats.ifi_collisions, VTY_NEWLINE); #else /* Statistics print out using sysctl (). */ vty_out (vty, " input packets %lu, bytes %lu, dropped %lu," @@ -875,6 +901,13 @@ DEFUN_NOSH (zebra_interface, return ret; } +ALIAS (zebra_interface, + zebra_interface_vrf_cmd, + "interface IFNAME " VRF_CMD_STR, + "Select an interface to configure\n" + "Interface's name\n" + VRF_CMD_HELP_STR) + struct cmd_node interface_node = { INTERFACE_NODE, @@ -882,16 +915,53 @@ struct cmd_node interface_node = 1 }; -/* Show all or specified interface to vty. */ +/* Show all interfaces to vty. */ DEFUN (show_interface, show_interface_cmd, - "show interface [IFNAME]", + "show interface", SHOW_STR + "Interface status and configuration\n") +{ + struct listnode *node; + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; + +#ifdef HAVE_PROC_NET_DEV + /* If system has interface statistics via proc file system, update + statistics. */ + ifstat_update_proc (); +#endif /* HAVE_PROC_NET_DEV */ +#ifdef HAVE_NET_RT_IFLIST + ifstat_update_sysctl (); +#endif /* HAVE_NET_RT_IFLIST */ + + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + /* All interface print. */ + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) + if_dump_vty (vty, ifp); + + return CMD_SUCCESS; +} + +ALIAS (show_interface, + show_interface_vrf_cmd, + "show interface " VRF_CMD_STR, + SHOW_STR "Interface status and configuration\n" - "Inteface name\n") + VRF_CMD_HELP_STR) + +/* Show all interfaces to vty. */ +DEFUN (show_interface_vrf_all, show_interface_vrf_all_cmd, + "show interface " VRF_ALL_CMD_STR, + SHOW_STR + "Interface status and configuration\n" + VRF_ALL_CMD_HELP_STR) { struct listnode *node; struct interface *ifp; - + vrf_iter_t iter; + #ifdef HAVE_PROC_NET_DEV /* If system has interface statistics via proc file system, update statistics. */ @@ -901,39 +971,107 @@ DEFUN (show_interface, show_interface_cmd, ifstat_update_sysctl (); #endif /* HAVE_NET_RT_IFLIST */ + /* All interface print. */ + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp)) + if_dump_vty (vty, ifp); + + return CMD_SUCCESS; +} + +/* Show specified interface to vty. */ +DEFUN (show_interface_name, show_interface_name_cmd, + "show interface IFNAME", + SHOW_STR + "Interface status and configuration\n" + "Inteface name\n") +{ + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; + +#ifdef HAVE_PROC_NET_DEV + /* If system has interface statistics via proc file system, update + statistics. */ + ifstat_update_proc (); +#endif /* HAVE_PROC_NET_DEV */ +#ifdef HAVE_NET_RT_IFLIST + ifstat_update_sysctl (); +#endif /* HAVE_NET_RT_IFLIST */ + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + /* Specified interface print. */ - if (argc != 0) + ifp = if_lookup_by_name_vrf (argv[0], vrf_id); + if (ifp == NULL) { - ifp = if_lookup_by_name (argv[0]); - if (ifp == NULL) - { - vty_out (vty, "%% Can't find interface %s%s", argv[0], - VTY_NEWLINE); - return CMD_WARNING; - } - if_dump_vty (vty, ifp); - return CMD_SUCCESS; + vty_out (vty, "%% Can't find interface %s%s", argv[0], + VTY_NEWLINE); + return CMD_WARNING; } + if_dump_vty (vty, ifp); - /* All interface print. */ - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) - if_dump_vty (vty, ifp); - return CMD_SUCCESS; } -DEFUN (show_interface_desc, - show_interface_desc_cmd, - "show interface description", +ALIAS (show_interface_name, + show_interface_name_vrf_cmd, + "show interface IFNAME " VRF_CMD_STR, SHOW_STR "Interface status and configuration\n" - "Interface description\n") + "Inteface name\n" + VRF_CMD_HELP_STR) + +/* Show specified interface to vty. */ +DEFUN (show_interface_name_vrf_all, show_interface_name_vrf_all_cmd, + "show interface IFNAME " VRF_ALL_CMD_STR, + SHOW_STR + "Interface status and configuration\n" + "Inteface name\n" + VRF_ALL_CMD_HELP_STR) { + struct interface *ifp; + vrf_iter_t iter; + int found = 0; + +#ifdef HAVE_PROC_NET_DEV + /* If system has interface statistics via proc file system, update + statistics. */ + ifstat_update_proc (); +#endif /* HAVE_PROC_NET_DEV */ +#ifdef HAVE_NET_RT_IFLIST + ifstat_update_sysctl (); +#endif /* HAVE_NET_RT_IFLIST */ + + /* All interface print. */ + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + /* Specified interface print. */ + ifp = if_lookup_by_name_vrf (argv[0], vrf_iter2id (iter)); + if (ifp) + { + if_dump_vty (vty, ifp); + found++; + } + } + + if (!found) + { + vty_out (vty, "%% Can't find interface %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +static void +if_show_description (struct vty *vty, vrf_id_t vrf_id) +{ struct listnode *node; struct interface *ifp; vty_out (vty, "Interface Status Protocol Description%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { int len; @@ -964,9 +1102,55 @@ DEFUN (show_interface_desc, vty_out (vty, "%s", ifp->desc); vty_out (vty, "%s", VTY_NEWLINE); } +} + +DEFUN (show_interface_desc, + show_interface_desc_cmd, + "show interface description", + SHOW_STR + "Interface status and configuration\n" + "Interface description\n") +{ + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + if_show_description (vty, vrf_id); + return CMD_SUCCESS; } +ALIAS (show_interface_desc, + show_interface_desc_vrf_cmd, + "show interface description " VRF_CMD_STR, + SHOW_STR + "Interface status and configuration\n" + "Interface description\n" + VRF_CMD_HELP_STR) + +DEFUN (show_interface_desc_vrf_all, + show_interface_desc_vrf_all_cmd, + "show interface description " VRF_ALL_CMD_STR, + SHOW_STR + "Interface status and configuration\n" + "Interface description\n" + VRF_ALL_CMD_HELP_STR) +{ + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if (!list_isempty (vrf_iter2iflist (iter))) + { + vty_out (vty, "%s\tVRF %u%s%s", VTY_NEWLINE, + vrf_iter2id (iter), + VTY_NEWLINE, VTY_NEWLINE); + if_show_description (vty, vrf_iter2id (iter)); + } + + return CMD_SUCCESS; +} + DEFUN (multicast, multicast_cmd, "multicast", @@ -1073,13 +1257,16 @@ DEFUN (shutdown_if, struct zebra_if *if_data; ifp = (struct interface *) vty->index; - ret = if_unset_flags (ifp, IFF_UP); - if (ret < 0) + if (ifp->ifindex != IFINDEX_INTERNAL) { - vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE); - return CMD_WARNING; + ret = if_unset_flags (ifp, IFF_UP); + if (ret < 0) + { + vty_out (vty, "Can't shutdown interface%s", VTY_NEWLINE); + return CMD_WARNING; + } + if_refresh (ifp); } - if_refresh (ifp); if_data = ifp->info; if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; @@ -1097,13 +1284,23 @@ DEFUN (no_shutdown_if, struct zebra_if *if_data; ifp = (struct interface *) vty->index; - ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if (ret < 0) + + if (ifp->ifindex != IFINDEX_INTERNAL) { - vty_out (vty, "Can't up interface%s", VTY_NEWLINE); - return CMD_WARNING; + ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING); + if (ret < 0) + { + vty_out (vty, "Can't up interface%s", VTY_NEWLINE); + return CMD_WARNING; + } + if_refresh (ifp); + + /* Some addresses (in particular, IPv6 addresses on Linux) get + * removed when the interface goes down. They need to be readded. + */ + if_addr_wakeup(ifp); } - if_refresh (ifp); + if_data = ifp->info; if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; @@ -1163,17 +1360,20 @@ ALIAS (no_bandwidth_if, NO_STR "Set bandwidth informational parameter\n" "Bandwidth in kilobits\n") - + static int ip_address_install (struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, const char *label) { + struct zebra_if *if_data; struct prefix_ipv4 cp; struct connected *ifc; struct prefix_ipv4 *p; int ret; + if_data = ifp->info; + ret = str2prefix_ipv4 (addr_str, &cp); if (ret <= 0) { @@ -1214,8 +1414,9 @@ ip_address_install (struct vty *vty, struct interface SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); /* In case of this route need to install kernel. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL) - && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { /* Some system need to up the interface to set IP address. */ if (! if_is_up (ifp)) @@ -1232,18 +1433,10 @@ ip_address_install (struct vty *vty, struct interface return CMD_WARNING; } - /* Add to subnet chain list (while marking secondary attribute). */ - if_subnet_add (ifp, ifc); - - /* IP address propery set. */ - SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - - /* Update interface address information to protocol daemon. */ - zebra_interface_address_add_update (ifp, ifc); - - /* If interface is up register connected route. */ - if (if_is_operative(ifp)) - connected_up_ipv4 (ifp, ifc); + SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the notification + * from the kernel has been received. + * It will also be added to the subnet chain list, then. */ } return CMD_SUCCESS; @@ -1281,7 +1474,7 @@ ip_address_uninstall (struct vty *vty, struct interfac UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); /* This is not real address or interface is not active. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL) + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { listnode_delete (ifp->connected, ifc); @@ -1297,34 +1490,9 @@ ip_address_uninstall (struct vty *vty, struct interfac safe_strerror(errno), VTY_NEWLINE); return CMD_WARNING; } - /* success! call returned that the address deletion went through. - * this is a synchronous operation, so we know it succeeded and can - * now update all internal state. */ - - /* the HAVE_NETLINK check is only here because, on BSD, although the - * call above is still synchronous, we get a second confirmation later - * through the route socket, and we don't want to touch that behaviour - * for now. It should work without the #ifdef, but why take the risk... - * -- equinox 2012-07-13 */ -#ifdef HAVE_NETLINK - - /* Remove connected route. */ - connected_down_ipv4 (ifp, ifc); - - /* Redistribute this information. */ - zebra_interface_address_delete_update (ifp, ifc); - - /* IP address propery set. */ - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - - /* remove from interface, remark secondaries */ - if_subnet_delete (ifp, ifc); - - /* Free address information. */ - listnode_delete (ifp->connected, ifc); - connected_free (ifc); -#endif - + UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); + /* we will receive a kernel notification about this route being removed. + * this will trigger its removal from the connected list. */ return CMD_SUCCESS; } @@ -1382,11 +1550,14 @@ ipv6_address_install (struct vty *vty, struct interfac const char *addr_str, const char *peer_str, const char *label, int secondary) { + struct zebra_if *if_data; struct prefix_ipv6 cp; struct connected *ifc; struct prefix_ipv6 *p; int ret; + if_data = ifp->info; + ret = str2prefix_ipv6 (addr_str, &cp); if (ret <= 0) { @@ -1422,8 +1593,9 @@ ipv6_address_install (struct vty *vty, struct interfac SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); /* In case of this route need to install kernel. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL) - && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { /* Some system need to up the interface to set IP address. */ if (! if_is_up (ifp)) @@ -1441,15 +1613,9 @@ ipv6_address_install (struct vty *vty, struct interfac return CMD_WARNING; } - /* IP address propery set. */ - SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - - /* Update interface address information to protocol daemon. */ - zebra_interface_address_add_update (ifp, ifc); - - /* If interface is up register connected route. */ - if (if_is_operative(ifp)) - connected_up_ipv6 (ifp, ifc); + SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the notification + * from the kernel has been received. */ } return CMD_SUCCESS; @@ -1484,8 +1650,10 @@ ipv6_address_uninstall (struct vty *vty, struct interf if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) return CMD_WARNING; + UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); + /* This is not real address or interface is not active. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL) + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { listnode_delete (ifp->connected, ifc); @@ -1502,16 +1670,9 @@ ipv6_address_uninstall (struct vty *vty, struct interf return CMD_WARNING; } - /* Redistribute this information. */ - zebra_interface_address_delete_update (ifp, ifc); - - /* Remove connected route. */ - connected_down_ipv6 (ifp, ifc); - - /* Free address information. */ - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - + UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); + /* This information will be propagated to the zclients when the + * kernel notification is received. */ return CMD_SUCCESS; } @@ -1542,8 +1703,10 @@ if_config_write (struct vty *vty) { struct listnode *node; struct interface *ifp; + vrf_iter_t iter; - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), node, ifp)) { struct zebra_if *if_data; struct listnode *addrnode; @@ -1551,10 +1714,19 @@ if_config_write (struct vty *vty) struct prefix *p; if_data = ifp->info; - - vty_out (vty, "interface %s%s", ifp->name, - VTY_NEWLINE); + if (ifp->vrf_id == VRF_DEFAULT) + vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE); + else + vty_out (vty, "interface %s vrf %u%s", ifp->name, ifp->vrf_id, + VTY_NEWLINE); + + if (if_data) + { + if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) + vty_out (vty, " shutdown%s", VTY_NEWLINE); + } + if (ifp->desc) vty_out (vty, " description %s%s", ifp->desc, VTY_NEWLINE); @@ -1566,6 +1738,8 @@ if_config_write (struct vty *vty) if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) vty_out(vty, " link-detect%s", VTY_NEWLINE); + else + vty_out(vty, " no link-detect%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc)) { @@ -1573,10 +1747,9 @@ if_config_write (struct vty *vty) { char buf[INET6_ADDRSTRLEN]; p = ifc->address; - vty_out (vty, " ip%s address %s/%d", + vty_out (vty, " ip%s address %s", p->family == AF_INET ? "" : "v6", - inet_ntop (p->family, &p->u.prefix, buf, sizeof(buf)), - p->prefixlen); + prefix2str (p, buf, sizeof(buf))); if (ifc->label) vty_out (vty, " label %s", ifc->label); @@ -1587,18 +1760,15 @@ if_config_write (struct vty *vty) if (if_data) { - if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) - vty_out (vty, " shutdown%s", VTY_NEWLINE); - if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC) vty_out (vty, " %smulticast%s", if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no ", VTY_NEWLINE); } -#ifdef RTADV +#if defined (HAVE_RTADV) rtadv_config_write (vty, ifp); -#endif /* RTADV */ +#endif /* HAVE_RTADV */ #ifdef HAVE_IRDP irdp_config_write (vty, ifp); @@ -1614,7 +1784,6 @@ void zebra_if_init (void) { /* Initialize interface and new hook. */ - if_init (); if_add_hook (IF_NEW_HOOK, if_zebra_new_hook); if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook); @@ -1622,10 +1791,24 @@ zebra_if_init (void) install_node (&interface_node, if_config_write); install_element (VIEW_NODE, &show_interface_cmd); + install_element (VIEW_NODE, &show_interface_vrf_cmd); + install_element (VIEW_NODE, &show_interface_vrf_all_cmd); + install_element (VIEW_NODE, &show_interface_name_cmd); + install_element (VIEW_NODE, &show_interface_name_vrf_cmd); + install_element (VIEW_NODE, &show_interface_name_vrf_all_cmd); install_element (ENABLE_NODE, &show_interface_cmd); + install_element (ENABLE_NODE, &show_interface_vrf_cmd); + install_element (ENABLE_NODE, &show_interface_vrf_all_cmd); + install_element (ENABLE_NODE, &show_interface_name_cmd); + install_element (ENABLE_NODE, &show_interface_name_vrf_cmd); + install_element (ENABLE_NODE, &show_interface_name_vrf_all_cmd); install_element (ENABLE_NODE, &show_interface_desc_cmd); + install_element (ENABLE_NODE, &show_interface_desc_vrf_cmd); + install_element (ENABLE_NODE, &show_interface_desc_vrf_all_cmd); install_element (CONFIG_NODE, &zebra_interface_cmd); + install_element (CONFIG_NODE, &zebra_interface_vrf_cmd); install_element (CONFIG_NODE, &no_interface_cmd); + install_element (CONFIG_NODE, &no_interface_vrf_cmd); install_default (INTERFACE_NODE); install_element (INTERFACE_NODE, &interface_desc_cmd); install_element (INTERFACE_NODE, &no_interface_desc_cmd);