summaryrefslogtreecommitdiff
path: root/zebra/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/interface.c')
-rw-r--r--zebra/interface.c185
1 files changed, 127 insertions, 58 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 7b19379910..5a47f60fa0 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -54,6 +54,8 @@
const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 };
#endif /* HAVE_RTADV */
+static void if_down_del_nbr_connected (struct interface *ifp);
+
struct zebra_ns *dzns;
/* Called when new interface is added. */
@@ -482,32 +484,64 @@ if_add_update (struct interface *ifp)
}
}
-/* Handle an interface delete event */
-void
-if_delete_update (struct interface *ifp)
+/* Install connected routes corresponding to an interface. */
+static void
+if_install_connected (struct interface *ifp)
{
+ struct listnode *node;
+ struct listnode *next;
struct connected *ifc;
struct prefix *p;
- struct route_node *rn;
- struct zebra_if *zebra_if;
- zebra_if = ifp->info;
+ if (ifp->connected)
+ {
+ for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
+ {
+ p = ifc->address;
- if (if_is_up(ifp))
+ if (p->family == AF_INET)
+ connected_up_ipv4 (ifp, ifc);
+ else if (p->family == AF_INET6)
+ connected_up_ipv6 (ifp, ifc);
+ }
+ }
+}
+
+/* Uninstall connected routes corresponding to an interface. */
+static void
+if_uninstall_connected (struct interface *ifp)
+{
+ struct listnode *node;
+ struct listnode *next;
+ struct connected *ifc;
+ struct prefix *p;
+
+ if (ifp->connected)
{
- zlog_err ("interface %s vrf %u index %d is still up while being deleted.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
- return;
+ for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
+ {
+ p = ifc->address;
+
+ if (p->family == AF_INET)
+ connected_down_ipv4 (ifp, ifc);
+ else if (p->family == AF_INET6)
+ connected_down_ipv6 (ifp, ifc);
+ }
}
+}
- /* Mark interface as inactive */
- UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
-
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("interface %s vrf %u index %d is now inactive.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
+/* Uninstall and delete connected routes corresponding to an interface. */
+/* TODO - Check why IPv4 handling here is different from install or if_down */
+static void
+if_delete_connected (struct interface *ifp)
+{
+ struct connected *ifc;
+ struct prefix *p;
+ struct route_node *rn;
+ struct zebra_if *zebra_if;
+
+ zebra_if = ifp->info;
- /* Delete connected routes from the kernel. */
if (ifp->connected)
{
struct listnode *node;
@@ -571,7 +605,6 @@ if_delete_update (struct interface *ifp)
rn->info = NULL;
route_unlock_node (rn);
}
-#ifdef HAVE_IPV6
else if (p->family == AF_INET6)
{
connected_down_ipv6 (ifp, ifc);
@@ -589,13 +622,36 @@ if_delete_update (struct interface *ifp)
connected_free (ifc);
}
}
-#endif /* HAVE_IPV6 */
else
{
last = node;
}
}
}
+}
+
+/* Handle an interface delete event */
+void
+if_delete_update (struct interface *ifp)
+{
+ if (if_is_up(ifp))
+ {
+ zlog_err ("interface %s vrf %u index %d is still up while being deleted.",
+ ifp->name, ifp->vrf_id, ifp->ifindex);
+ return;
+ }
+
+ /* Mark interface as inactive */
+ UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
+
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ 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_delete_connected (ifp);
+
+ /* Send out notification on interface delete. */
zebra_interface_delete_update (ifp);
if_unlink_per_ns(ifp);
@@ -608,6 +664,55 @@ if_delete_update (struct interface *ifp)
ifp->ifindex = IFINDEX_INTERNAL;
}
+/* VRF change for an interface */
+void
+if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id)
+{
+ vrf_id_t old_vrf_id;
+
+ old_vrf_id = ifp->vrf_id;
+
+ /* Uninstall connected routes. */
+ if_uninstall_connected (ifp);
+
+ /* Delete any IPv4 neighbors created to implement RFC 5549 */
+ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
+
+ /* Delete all neighbor addresses learnt through IPv6 RA */
+ if_down_del_nbr_connected (ifp);
+
+ /* Suppress RAs on this interface, if enabled. */
+ ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS);
+
+ /* Send out notification on interface VRF change. */
+ /* This is to issue an UPDATE or a DELETE, as appropriate. */
+ zebra_interface_vrf_update_del (ifp, vrf_id);
+
+ /* update VRF */
+ if_update_vrf (ifp, ifp->name, strlen (ifp->name), vrf_id);
+
+ /* Send out notification on interface VRF change. */
+ /* This is to issue an ADD, if needed. */
+ zebra_interface_vrf_update_add (ifp, old_vrf_id);
+
+ /* Install connected routes (in new VRF). */
+ if_install_connected (ifp);
+
+ /* Enable RAs on this interface, if IPv6 addresses are present. */
+ if (ipv6_address_configured(ifp))
+ ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
+
+ /* Due to connected route change, schedule RIB processing for both old
+ * and new VRF.
+ */
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug ("%u: IF %s VRF change, scheduling RIB processing",
+ ifp->vrf_id, ifp->name);
+ rib_update (old_vrf_id, RIB_UPDATE_IF_CHANGE);
+ rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
+}
+
+
/* Handle VRF addition */
void
vrf_add_update (struct vrf *vrfp)
@@ -728,11 +833,6 @@ if_down_del_nbr_connected (struct interface *ifp)
void
if_up (struct interface *ifp)
{
- struct listnode *node;
- struct listnode *next;
- struct connected *ifc;
- struct prefix *p;
-
/* Notify the protocol daemons. */
if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
zlog_warn("%s: interface %s hasn't passed ptm check\n", __func__,
@@ -744,20 +844,7 @@ if_up (struct interface *ifp)
if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp);
/* Install connected routes to the kernel. */
- if (ifp->connected)
- {
- for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
- {
- p = ifc->address;
-
- if (p->family == AF_INET)
- connected_up_ipv4 (ifp, ifc);
-#ifdef HAVE_IPV6
- else if (p->family == AF_INET6)
- connected_up_ipv6 (ifp, ifc);
-#endif /* HAVE_IPV6 */
- }
- }
+ if_install_connected (ifp);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug ("%u: IF %s up, scheduling RIB processing",
@@ -770,29 +857,11 @@ if_up (struct interface *ifp)
void
if_down (struct interface *ifp)
{
- struct listnode *node;
- struct listnode *next;
- struct connected *ifc;
- struct prefix *p;
-
/* Notify to the protocol daemons. */
zebra_interface_down_update (ifp);
- /* Delete connected routes from the kernel. */
- if (ifp->connected)
- {
- for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
- {
- 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 */
- }
- }
+ /* Uninstall connected routes from the kernel. */
+ if_uninstall_connected (ifp);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug ("%u: IF %s down, scheduling RIB processing",