#include "queue.h"
#include "nexthop.h"
#include "vrf.h"
+#include "if.h"
#define DISTANCE_INFINITY 255
#define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */
union g_addr addr;
unsigned int ifindex;
+ char ifname[INTERFACE_NAMSIZ + 1];
+
/* bit flags */
u_char flags;
/*
extern unsigned long rib_score_proto (u_char proto, u_short instance);
extern void rib_queue_add (struct route_node *rn);
+extern void
+static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
+extern void
+static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si);
extern int
static_add_ipv4 (struct prefix *p, struct in_addr *gate, unsigned int ifindex,
}
/* Install static route into rib. */
-static void
+void
static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
{
struct rib *rib;
}
/* Uninstall static route from RIB. */
-static void
+void
static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
{
struct route_node *rn;
si->tag = tag;
si->vrf_id = zvrf->vrf_id;
si->ifindex = ifindex;
+ if (si->ifindex)
+ strcpy(si->ifname, ifindex2ifname_vrf (si->ifindex, si->vrf_id));
if (gate)
si->addr.ipv4 = *gate;
return 0;
}
+/*
+ * Moving an interface amongst different vrf's
+ * causes the interface to get a new ifindex
+ * so we need to find static routes with
+ * the old ifindex and replace with new
+ * ifindex to insert back into the table
+ */
+void
+zebra_vrf_static_route_interface_fixup (struct interface *ifp)
+{
+ afi_t afi;
+ safi_t safi;
+ struct zebra_vrf *zvrf = zebra_vrf_lookup (ifp->vrf_id);
+ struct route_table *stable = NULL;
+ struct route_node *rn = NULL;
+ struct static_route *si = NULL;
+
+ if (!zvrf)
+ return;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ {
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ stable = zvrf->stable[afi][safi];
+ if (stable)
+ for (rn = route_top (stable); rn; rn = route_next (rn))
+ {
+ if (rn->info)
+ {
+ si = rn->info;
+ if ((strcmp (si->ifname, ifp->name) == 0) &&
+ (si->ifindex != ifp->ifindex))
+ {
+ si->ifindex = ifp->ifindex;
+ static_install_route (afi, safi, &rn->p, si);
+ }
+ }
+ }
+ }
+ }
+
+}
+
/* Callback upon enabling a VRF. */
static int
zebra_vrf_enable (vrf_id_t vrf_id, const char *name, void **info)
{
struct zebra_vrf *zvrf = (struct zebra_vrf *) (*info);
+ struct route_table *stable = NULL;
+ struct route_node *rn = NULL;
+ struct static_route *si = NULL;
+ struct interface *ifp = NULL;
+ afi_t afi;
+ safi_t safi;
assert (zvrf);
zebra_vrf_add_update (zvrf);
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ {
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ stable = zvrf->stable[afi][safi];
+ if (stable)
+ {
+ for (rn = route_top (stable); rn; rn = route_next (rn))
+ {
+ if (rn->info)
+ {
+ si = rn->info;
+ si->vrf_id = vrf_id;
+ if (si->ifindex)
+ {
+ ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id);
+ if (ifp)
+ si->ifindex = ifp->ifindex;
+ else
+ continue;
+ }
+ static_install_route (afi, safi, &rn->p, si);
+ }
+ }
+ }
+ }
+ }
return 0;
}
zebra_vrf_disable (vrf_id_t vrf_id, const char *name, void **info)
{
struct zebra_vrf *zvrf = (struct zebra_vrf *)(*info);
+ struct route_table *stable = NULL;
+ struct route_node *rn = NULL;
+ afi_t afi;
+ safi_t safi;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug ("VRF %s id %u is now disabled.",
zvrf->name, zvrf->vrf_id);
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ {
+ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+ {
+ stable = zvrf->stable[afi][safi];
+ if (stable)
+ {
+ for (rn = route_top (stable); rn; rn = route_next (rn))
+ {
+ if (rn->info)
+ static_uninstall_route(afi, safi, &rn->p, rn->info);
+ }
+ }
+ }
+ }
return 0;
}
vty_out (vty, " %s", inet_ntoa (si->addr.ipv4));
break;
case STATIC_IFINDEX:
- vty_out (vty, " %s", ifindex2ifname_vrf(si->ifindex, si->vrf_id));
+ vty_out (vty, " %s", si->ifname);
break;
case STATIC_IPV4_BLACKHOLE:
vty_out (vty, " Null0");
vty_out (vty, " %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ));
break;
case STATIC_IFINDEX:
- vty_out (vty, " %s", ifindex2ifname_vrf (si->ifindex, si->vrf_id));
+ vty_out (vty, " %s", si->ifname);
break;
case STATIC_IPV6_GATEWAY_IFINDEX:
vty_out (vty, " %s %s",