si->tag = tag;
si->vrf_id = zvrf_id(zvrf);
si->nh_vrf_id = zvrf_id(nh_zvrf);
+ strcpy(si->nh_vrfname, nh_zvrf->vrf->name);
if (ifname)
strlcpy(si->ifname, ifname, sizeof(si->ifname));
}
}
+/*
+ * This function looks at a zvrf's stable and notices if any of the
+ * nexthops we are using are part of the vrf coming up.
+ * If we are using them then cleanup the nexthop vrf id
+ * to be the new value and then re-installs them
+ *
+ *
+ * stable -> The table we are looking at.
+ * zvrf -> The newly changed vrf.
+ * afi -> The afi to look at
+ * safi -> the safi to look at
+ */
+static void static_fixup_vrf(struct zebra_vrf *zvrf,
+ struct route_table *stable, afi_t afi, safi_t safi)
+{
+ struct route_node *rn;
+ struct static_route *si;
+ struct interface *ifp;
+
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ for (si = rn->info; si; si = si->next) {
+ if (strcmp(zvrf->vrf->name, si->nh_vrfname) != 0)
+ continue;
+
+ si->nh_vrf_id = zvrf->vrf->vrf_id;
+ if (si->ifindex) {
+ ifp = if_lookup_by_name(si->ifname,
+ si->nh_vrf_id);
+ if (ifp)
+ si->ifindex = ifp->ifindex;
+ else
+ continue;
+ }
+ static_install_route(afi, safi, &rn->p, NULL, si);
+ }
+ }
+}
+
+/*
+ * This function enables static routes in a zvrf as it
+ * is coming up. It sets the new vrf_id as appropriate.
+ *
+ * zvrf -> The zvrf that is being brought up and enabled by the kernel
+ * stable -> The stable we are looking at.
+ * afi -> the afi in question
+ * safi -> the safi in question
+ */
+static void static_enable_vrf(struct zebra_vrf *zvrf,
+ struct route_table *stable,
+ afi_t afi, safi_t safi)
+{
+ struct route_node *rn;
+ struct static_route *si;
+ struct interface *ifp;
+ struct vrf *vrf = zvrf->vrf;
+
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ for (si = rn->info; si; si = si->next) {
+ si->vrf_id = vrf->vrf_id;
+ if (si->ifindex) {
+ ifp = if_lookup_by_name(si->ifname,
+ si->nh_vrf_id);
+ if (ifp)
+ si->ifindex = ifp->ifindex;
+ else
+ continue;
+ }
+ static_install_route(afi, safi, &rn->p, NULL, si);
+ }
+ }
+}
+
+/*
+ * When a vrf is being enabled by the kernel, go through all the
+ * static routes in the system that use this vrf (both nexthops vrfs
+ * and the routes vrf )
+ *
+ * enable_zvrf -> the vrf being enabled
+ */
+void static_fixup_vrf_ids(struct zebra_vrf *enable_zvrf)
+{
+ struct route_table *stable;
+ struct vrf *vrf;
+ afi_t afi;
+ safi_t safi;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ struct zebra_vrf *zvrf;
+
+ zvrf = vrf->info;
+ /* Install any static routes configured for this VRF. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ stable = zvrf->stable[afi][safi];
+ if (!stable)
+ continue;
+
+ static_fixup_vrf(enable_zvrf, stable,
+ afi, safi);
+
+ if (enable_zvrf == zvrf)
+ static_enable_vrf(zvrf, stable,
+ afi, safi);
+ }
+ }
+ }
+}
+
+/*
+ * Look at the specified stable and if any of the routes in
+ * this table are using the zvrf as the nexthop, uninstall
+ * those routes.
+ *
+ * zvrf -> the vrf being disabled
+ * stable -> the table we need to look at.
+ * afi -> the afi in question
+ * safi -> the safi in question
+ */
+static void static_cleanup_vrf(struct zebra_vrf *zvrf,
+ struct route_table *stable,
+ afi_t afi, safi_t safi)
+{
+ struct route_node *rn;
+ struct static_route *si;
+
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ for (si = rn->info; si; si = si->next) {
+ if (strcmp(zvrf->vrf->name, si->nh_vrfname) != 0)
+ continue;
+
+ static_uninstall_route(afi, safi, &rn->p, NULL, si);
+ }
+ }
+}
+
+/*
+ * Look at all static routes in this table and uninstall
+ * them.
+ *
+ * stable -> The table to uninstall from
+ * afi -> The afi in question
+ * safi -> the safi in question
+ */
+static void static_disable_vrf(struct route_table *stable,
+ afi_t afi, safi_t safi)
+{
+ struct route_node *rn;
+ struct static_route *si;
+
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ for (si = rn->info; si; si = si->next) {
+ static_uninstall_route(afi, safi, &rn->p, NULL, si);
+ }
+ }
+}
+
+/*
+ * When the disable_zvrf is shutdown by the kernel, we call
+ * this function and it cleans up all static routes using
+ * this vrf as a nexthop as well as all static routes
+ * in it's stables.
+ *
+ * disable_zvrf - The vrf being disabled
+ */
+void static_cleanup_vrf_ids(struct zebra_vrf *disable_zvrf)
+{
+ struct vrf *vrf;
+ afi_t afi;
+ safi_t safi;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ struct zebra_vrf *zvrf;
+
+ zvrf = vrf->info;
+
+ /* Uninstall any static routes configured for this VRF. */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ struct route_table *stable;
+
+ stable = zvrf->stable[afi][safi];
+ if (!stable)
+ continue;
+
+ static_cleanup_vrf(disable_zvrf, stable,
+ afi, safi);
+
+ if (disable_zvrf == zvrf)
+ static_disable_vrf(stable, afi, safi);
+ }
+ }
+ }
+}
+
/* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
void static_ifindex_update(struct interface *ifp, bool up)
{
static int zebra_vrf_enable(struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
- struct route_table *stable;
- struct route_node *rn;
- struct static_route *si;
struct route_table *table;
- struct interface *ifp;
afi_t afi;
safi_t safi;
zvrf->import_check_table[afi] = table;
}
- /* Install any static routes configured for this VRF. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- stable = zvrf->stable[afi][safi];
- if (!stable)
- continue;
-
- for (rn = route_top(stable); rn; rn = route_next(rn))
- for (si = rn->info; si; si = si->next) {
- si->vrf_id = vrf->vrf_id;
- if (si->ifindex) {
- ifp = if_lookup_by_name(
- si->ifname, si->vrf_id);
- if (ifp)
- si->ifindex =
- ifp->ifindex;
- else
- continue;
- }
- static_install_route(afi, safi, &rn->p,
- NULL, si);
- }
- }
+ static_fixup_vrf_ids(zvrf);
/*
* We may have static routes that are now possible to
static int zebra_vrf_disable(struct vrf *vrf)
{
struct zebra_vrf *zvrf = vrf->info;
- struct route_table *stable;
- struct route_node *rn;
- struct static_route *si;
struct route_table *table;
struct interface *ifp;
afi_t afi;
zlog_debug("VRF %s id %u is now inactive", zvrf_name(zvrf),
zvrf_id(zvrf));
- /* Uninstall any static routes configured for this VRF. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- stable = zvrf->stable[afi][safi];
- if (!stable)
- continue;
-
- for (rn = route_top(stable); rn; rn = route_next(rn))
- for (si = rn->info; si; si = si->next)
- static_uninstall_route(
- afi, safi, &rn->p, NULL, si);
- }
+ static_cleanup_vrf_ids(zvrf);
/* Stop any VxLAN-EVPN processing. */
zebra_vxlan_vrf_disable(zvrf);