summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c156
1 files changed, 52 insertions, 104 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 00550fa07d..fab8c3c932 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -261,7 +261,7 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
if (src)
nexthop->src.ipv4 = *src;
nexthop->ifindex = ifindex;
- ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
/*Pending: need to think if null ifp here is ok during bootup?
There was a crash because ifp here was coming to be NULL */
if (ifp)
@@ -417,7 +417,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
* address in the routing table.
*/
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
- ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT);
+ ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
if (ifp && connected_is_unnumbered(ifp)) {
if (if_is_operative(ifp))
return 1;
@@ -2216,23 +2216,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
struct route_entry *same;
struct nexthop *nexthop;
int ret = 0;
- int family;
if (!re)
return 0;
- if (p->family == AF_INET)
- family = AFI_IP;
- else
- family = AFI_IP6;
-
- assert(!src_p || family == AFI_IP6);
+ assert(!src_p || afi == AFI_IP6);
/* Lookup table. */
- table = zebra_vrf_table_with_table_id(family, safi, re->vrf_id,
- re->table);
- if (!table)
+ table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table);
+ if (!table) {
+ XFREE(MTYPE_RE, re);
return 0;
+ }
/* Make it sure prefixlen is applied to the prefix. */
apply_mask(p);
@@ -2258,8 +2253,18 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
continue;
- if (same->type == re->type && same->instance == re->instance
- && same->table == re->table && !RIB_SYSTEM_ROUTE(same))
+ if (same->type != re->type)
+ continue;
+ if (same->instance != re->instance)
+ continue;
+ if (same->type == ZEBRA_ROUTE_KERNEL &&
+ same->metric != re->metric)
+ continue;
+ /*
+ * We should allow duplicate connected routes because of
+ * IPv6 link-local routes and unnumbered interfaces on Linux.
+ */
+ if (same->type != ZEBRA_ROUTE_CONNECT)
break;
}
@@ -2294,7 +2299,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
u_short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
- u_int32_t table_id, u_int32_t metric)
+ u_int32_t table_id, u_int32_t metric, bool fromkernel)
{
struct route_table *table;
struct route_node *rn;
@@ -2375,6 +2380,21 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
/* If same type of route can't be found and this message is from
kernel. */
if (!same) {
+ /*
+ * In the past(HA!) we could get here because
+ * we were receiving a route delete from the
+ * kernel and we're not marking the proto
+ * as coming from it's appropriate originator.
+ * Now that we are properly noticing the fact
+ * that the kernel has deleted our route we
+ * are not going to get called in this path
+ * I am going to leave this here because
+ * this might still work this way on non-linux
+ * platforms as well as some weird state I have
+ * not properly thought of yet.
+ * If we can show that this code path is
+ * dead then we can remove it.
+ */
if (fib && type == ZEBRA_ROUTE_KERNEL
&& CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) {
if (IS_ZEBRA_DEBUG_RIB) {
@@ -2423,8 +2443,17 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
}
- if (same)
+ if (same) {
+ if (fromkernel &&
+ CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) &&
+ !allow_delete) {
+ rib_install_kernel(rn, same, NULL);
+ route_unlock_node(rn);
+
+ return;
+ }
rib_delnode(rn, same);
+ }
route_unlock_node(rn);
return;
@@ -2437,70 +2466,10 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
u_int32_t mtu, u_char distance)
{
struct route_entry *re;
- struct route_entry *same = NULL;
- struct route_table *table;
- struct route_node *rn;
- struct nexthop *rtnh;
-
- assert(!src_p || afi == AFI_IP6);
-
- /* Lookup table. */
- table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id);
- if (!table)
- return 0;
-
- /* Make sure mask is applied. */
- apply_mask(p);
- if (src_p)
- apply_mask_ipv6(src_p);
-
- /* Set default distance by route type. */
- if (distance == 0) {
- distance = route_distance(type);
-
- /* iBGP distance is 200. */
- if (type == ZEBRA_ROUTE_BGP
- && CHECK_FLAG(flags, ZEBRA_FLAG_IBGP))
- distance = 200;
- }
-
- /* Lookup route node.*/
- rn = srcdest_rnode_get(table, p, src_p);
-
- /* If same type of route are installed, treat it as a implicit
- withdraw. */
- RNODE_FOREACH_RE (rn, re) {
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
- continue;
-
- if (re->type != type)
- continue;
- if (re->instance != instance)
- continue;
- if (re->type == ZEBRA_ROUTE_KERNEL &&
- re->metric != metric)
- continue;
- if (!RIB_SYSTEM_ROUTE(re)) {
- same = re;
- break;
- }
- /* Duplicate system route comes in. */
- rtnh = re->nexthop;
- if (nexthop_same_no_recurse(rtnh, nh))
- return 0;
- /*
- * Nexthop is different. Remove the old route unless it's
- * a connected route. This exception is necessary because
- * of IPv6 link-local routes and unnumbered interfaces on
- * Linux.
- */
- else if (type != ZEBRA_ROUTE_CONNECT)
- same = re;
- }
+ struct nexthop *nexthop;
- /* Allocate new re structure. */
+ /* Allocate new route_entry structure. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
-
re->type = type;
re->instance = instance;
re->distance = distance;
@@ -2512,33 +2481,12 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
re->nexthop_num = 0;
re->uptime = time(NULL);
- rtnh = nexthop_new();
- *rtnh = *nh;
- route_entry_nexthop_add(re, rtnh);
-
- /* If this route is kernel route, set FIB flag to the route. */
- if (RIB_SYSTEM_ROUTE(re))
- for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next)
- SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB);
-
- /* Link new rib to node.*/
- if (IS_ZEBRA_DEBUG_RIB) {
- rnode_debug(
- rn, vrf_id,
- "Inserting route rn %p, re %p (type %d) existing %p",
- (void *)rn, (void *)re, re->type, (void *)same);
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- route_entry_dump(p, src_p, re);
- }
- rib_addnode(rn, re, 1);
-
- /* Free implicit route.*/
- if (same)
- rib_delnode(rn, same);
+ /* Add nexthop. */
+ nexthop = nexthop_new();
+ *nexthop = *nh;
+ route_entry_nexthop_add(re, nexthop);
- route_unlock_node(rn);
- return 0;
+ return rib_add_multipath(afi, safi, p, src_p, re);
}
/* Schedule routes of a particular table (address-family) based on event. */