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.c1334
1 files changed, 181 insertions, 1153 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index d70f528f5a..3812101431 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -21,12 +21,12 @@
#include <zebra.h>
+#include "if.h"
#include "prefix.h"
#include "table.h"
#include "memory.h"
#include "str.h"
#include "command.h"
-#include "if.h"
#include "log.h"
#include "sockunion.h"
#include "linklist.h"
@@ -119,13 +119,17 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int prior
int
is_zebra_valid_kernel_table(u_int32_t table_id)
{
- if ((table_id > ZEBRA_KERNEL_TABLE_MAX) ||
- (table_id == RT_TABLE_UNSPEC) ||
+ if ((table_id > ZEBRA_KERNEL_TABLE_MAX))
+ return 0;
+
+#ifdef linux
+ if ((table_id == RT_TABLE_UNSPEC) ||
(table_id == RT_TABLE_LOCAL) ||
(table_id == RT_TABLE_COMPAT))
return 0;
- else
- return 1;
+#endif
+
+ return 1;
}
int
@@ -191,7 +195,7 @@ rib_copy_nexthops (struct rib *rib, struct nexthop *nh)
}
/* Delete specified nexthop from the list. */
-static void
+void
rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop)
{
if (nexthop->next)
@@ -206,7 +210,7 @@ rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop)
struct nexthop *
-rib_nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
+rib_nexthop_ifindex_add (struct rib *rib, ifindex_t ifindex)
{
struct nexthop *nexthop;
@@ -237,7 +241,7 @@ rib_nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src
struct nexthop *
rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
- struct in_addr *src, unsigned int ifindex)
+ struct in_addr *src, ifindex_t ifindex)
{
struct nexthop *nexthop;
struct interface *ifp;
@@ -277,7 +281,7 @@ rib_nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
struct nexthop *
rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
- unsigned int ifindex)
+ ifindex_t ifindex)
{
struct nexthop *nexthop;
@@ -348,6 +352,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
zebra_deregister_rnh_static_nexthops(rib->vrf_id, nexthop->resolved, top);
nexthops_free(nexthop->resolved);
nexthop->resolved = NULL;
+ rib->nexthop_mtu = 0;
}
/* Skip nexthops that have been filtered out due to route-map */
@@ -405,6 +410,10 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
{
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
continue;
+
+ /* if the next hop is imported from another table, skip it */
+ if (match->type == ZEBRA_ROUTE_TABLE)
+ continue;
if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
break;
}
@@ -537,6 +546,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
}
resolved = 1;
}
+ if (resolved && set)
+ rib->nexthop_mtu = match->mtu;
return resolved;
}
else
@@ -736,10 +747,10 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
}
struct rib *
-rib_match_ipv4 (struct in_addr addr, safi_t safi, vrf_id_t vrf_id,
- struct route_node **rn_out)
+rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id,
+ union g_addr *addr, struct route_node **rn_out)
{
- struct prefix_ipv4 p;
+ struct prefix p;
struct route_table *table;
struct route_node *rn;
struct rib *match;
@@ -747,14 +758,18 @@ rib_match_ipv4 (struct in_addr addr, safi_t safi, vrf_id_t vrf_id,
int recursing;
/* Lookup table. */
- table = zebra_vrf_table (AFI_IP, safi, vrf_id);
+ table = zebra_vrf_table (afi, safi, vrf_id);
if (! table)
return 0;
- memset (&p, 0, sizeof (struct prefix_ipv4));
- p.family = AF_INET;
+ memset (&p, 0, sizeof (struct prefix));
+ p.family = afi;
+ p.u.prefix = *(u_char *)addr;
p.prefixlen = IPV4_MAX_PREFIXLEN;
- p.prefix = addr;
+ if (afi == AFI_IP)
+ p.prefixlen = IPV4_MAX_PREFIXLEN;
+ else
+ p.prefixlen = IPV6_MAX_PREFIXLEN;
rn = route_node_match (table, (struct prefix *) &p);
@@ -809,23 +824,23 @@ rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
{
struct rib *rib = NULL, *mrib = NULL, *urib = NULL;
struct route_node *m_rn = NULL, *u_rn = NULL;
- int skip_bgp = 0; /* bool */
+ union g_addr gaddr = { .ipv4 = addr };
switch (ipv4_multicast_mode)
{
case MCAST_MRIB_ONLY:
- return rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, rn_out);
+ return rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, rn_out);
case MCAST_URIB_ONLY:
- return rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, rn_out);
+ return rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, rn_out);
case MCAST_NO_CONFIG:
case MCAST_MIX_MRIB_FIRST:
- rib = mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
+ rib = mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn);
if (!mrib)
- rib = urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn);
+ rib = urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn);
break;
case MCAST_MIX_DISTANCE:
- mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
- urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn);
+ mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn);
+ urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn);
if (mrib && urib)
rib = urib->distance < mrib->distance ? urib : mrib;
else if (mrib)
@@ -834,8 +849,8 @@ rib_match_ipv4_multicast (struct in_addr addr, struct route_node **rn_out)
rib = urib;
break;
case MCAST_MIX_PFXLEN:
- mrib = rib_match_ipv4 (addr, SAFI_MULTICAST, skip_bgp, &m_rn);
- urib = rib_match_ipv4 (addr, SAFI_UNICAST, skip_bgp, &u_rn);
+ mrib = rib_match (AFI_IP, SAFI_MULTICAST, VRF_DEFAULT, &gaddr, &m_rn);
+ urib = rib_match (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, &gaddr, &u_rn);
if (mrib && urib)
rib = u_rn->p.prefixlen > m_rn->p.prefixlen ? urib : mrib;
else if (mrib)
@@ -998,68 +1013,6 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
return ZEBRA_RIB_NOTFOUND;
}
-struct rib *
-rib_match_ipv6 (struct in6_addr *addr, vrf_id_t vrf_id)
-{
- struct prefix_ipv6 p;
- struct route_table *table;
- struct route_node *rn;
- struct rib *match;
- struct nexthop *newhop, *tnewhop;
- int recursing;
-
- /* Lookup table. */
- table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
- if (! table)
- return 0;
-
- memset (&p, 0, sizeof (struct prefix_ipv6));
- p.family = AF_INET6;
- p.prefixlen = IPV6_MAX_PREFIXLEN;
- IPV6_ADDR_COPY (&p.prefix, addr);
-
- rn = route_node_match (table, (struct prefix *) &p);
-
- while (rn)
- {
- route_unlock_node (rn);
-
- /* Pick up selected route. */
- RNODE_FOREACH_RIB (rn, match)
- {
- if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
- break;
- }
-
- /* If there is no selected route or matched route is EGP, go up
- tree. */
- if (! match)
- {
- do {
- rn = rn->parent;
- } while (rn && rn->info == NULL);
- if (rn)
- route_lock_node (rn);
- }
- else
- {
- if (match->type == ZEBRA_ROUTE_CONNECT)
- /* Directly point connected route. */
- return match;
- else
- {
- for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
- if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
- return match;
- return NULL;
- }
- }
- }
- return NULL;
-}
-
#define RIB_SYSTEM_ROUTE(R) \
((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
@@ -1180,7 +1133,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
/* Iterate over all nexthops of the given RIB entry and refresh their
* ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
* nexthop is found to toggle the ACTIVE flag, the whole rib structure
- * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
+ * is flagged with RIB_ENTRY_CHANGED. The 4th 'set' argument is
* transparently passed to nexthop_active_check().
*
* Return value is the new number of active nexthops.
@@ -1191,12 +1144,12 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
{
struct nexthop *nexthop;
union g_addr prev_src;
- unsigned int prev_active, prev_index, new_active, old_num_nh;
-
+ unsigned int prev_active, new_active, old_num_nh;
+ ifindex_t prev_index;
old_num_nh = rib->nexthop_active_num;
rib->nexthop_active_num = 0;
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
{
@@ -1216,15 +1169,15 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
nexthop->type < NEXTHOP_TYPE_BLACKHOLE) &&
!(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6))))
{
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+ SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
}
}
if (old_num_nh != rib->nexthop_active_num)
- SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+ SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_CHANGED))
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_CHANGED))
{
SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
}
@@ -1237,7 +1190,7 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
/* Update flag indicates whether this is a "replace" or not. Currently, this
* is only used for IPv4.
*/
-static int
+int
rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
{
int ret = 0;
@@ -1292,7 +1245,7 @@ rib_install_kernel (struct route_node *rn, struct rib *rib, int update)
}
/* Uninstall the route from kernel. */
-static int
+int
rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
{
int ret = 0;
@@ -1421,7 +1374,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn,
/* Update real nexthop. This may actually determine if nexthop is active or not. */
if (!nexthop_active_update (rn, select, 1))
{
- UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(select->status, RIB_ENTRY_CHANGED);
return;
}
@@ -1447,7 +1400,7 @@ rib_process_add_route (struct zebra_vrf *zvrf, struct route_node *rn,
/* Update for redistribution. */
if (installed)
redistribute_update (&rn->p, select, NULL);
- UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(select->status, RIB_ENTRY_CHANGED);
}
static void
@@ -1474,7 +1427,7 @@ rib_process_del_route (struct zebra_vrf *zvrf, struct route_node *rn,
/* Update nexthop for route, reset changed flag. */
nexthop_active_update (rn, fib, 1);
- UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED);
}
static void
@@ -1495,7 +1448,7 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn,
* something has changed.
*/
if (select != fib ||
- CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
+ CHECK_FLAG (select->status, RIB_ENTRY_CHANGED))
{
zfpm_trigger_update (rn, "updating existing route");
@@ -1544,7 +1497,6 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn,
for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
}
-
}
/* Update for redistribution. */
@@ -1615,11 +1567,53 @@ rib_process_update_route (struct zebra_vrf *zvrf, struct route_node *rn,
/* Set real nexthop. */
nexthop_active_update (rn, fib, 1);
- UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED);
}
/* Clear changed flag. */
- UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(select->status, RIB_ENTRY_CHANGED);
+}
+
+/* Check if 'alternate' RIB entry is better than 'current'. */
+static struct rib *
+rib_choose_best (struct rib *current, struct rib *alternate)
+{
+ if (current == NULL)
+ return alternate;
+
+ /* filter route selection in following order:
+ * - connected beats other types
+ * - lower distance beats higher
+ * - lower metric beats higher for equal distance
+ * - last, hence oldest, route wins tie break.
+ */
+
+ /* Connected routes. Pick the last connected
+ * route of the set of lowest metric connected routes.
+ */
+ if (alternate->type == ZEBRA_ROUTE_CONNECT)
+ {
+ if (current->type != ZEBRA_ROUTE_CONNECT
+ || alternate->metric <= current->metric)
+ return alternate;
+
+ return current;
+ }
+
+ if (current->type == ZEBRA_ROUTE_CONNECT)
+ return current;
+
+ /* higher distance loses */
+ if (alternate->distance < current->distance)
+ return alternate;
+ if (current->distance < alternate->distance)
+ return current;
+
+ /* metric tie-breaks equal distance */
+ if (alternate->metric <= current->metric)
+ return alternate;
+
+ return current;
}
/* Core function for processing routing information base. */
@@ -1631,6 +1625,7 @@ rib_process (struct route_node *rn)
struct rib *fib = NULL;
struct rib *select = NULL;
struct rib *del = NULL;
+ struct rib *best = NULL;
char buf[INET6_ADDRSTRLEN];
rib_dest_t *dest;
struct zebra_vrf *zvrf = NULL;
@@ -1699,7 +1694,7 @@ rib_process (struct route_node *rn)
* the nexthop_active_update() code. Thus, we might miss changes to
* recursive NHs.
*/
- if (!CHECK_FLAG(rib->flags, ZEBRA_FLAG_CHANGED) &&
+ if (!CHECK_FLAG(rib->status, RIB_ENTRY_CHANGED) &&
! nexthop_active_update (rn, rib, 0))
{
if (rib->type == ZEBRA_ROUTE_TABLE)
@@ -1727,66 +1722,16 @@ rib_process (struct route_node *rn)
/* Infinite distance. */
if (rib->distance == DISTANCE_INFINITY)
{
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
continue;
}
- /* Newly selected rib, the common case. */
- if (!select)
- {
- select = rib;
- continue;
- }
-
- /* filter route selection in following order:
- * - connected beats other types
- * - lower distance beats higher
- * - lower metric beats higher for equal distance
- * - last, hence oldest, route wins tie break.
- */
-
- /* Connected routes. Pick the last connected
- * route of the set of lowest metric connected routes.
- */
- if (rib->type == ZEBRA_ROUTE_CONNECT)
- {
- if (select->type != ZEBRA_ROUTE_CONNECT
- || rib->metric <= select->metric)
- {
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
- select = rib;
- }
- else
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- continue;
- }
- else if (select->type == ZEBRA_ROUTE_CONNECT)
- {
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- continue;
- }
-
- /* higher distance loses */
- if (rib->distance > select->distance)
- {
- UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
- continue;
- }
-
- /* lower wins */
- if (rib->distance < select->distance)
- {
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
- select = rib;
- continue;
- }
-
- /* metric tie-breaks equal distance */
- if (rib->metric <= select->metric)
- {
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
- select = rib;
- }
+ best = rib_choose_best(select, rib);
+ if (select && best != select)
+ UNSET_FLAG (select->status, RIB_ENTRY_CHANGED);
+ if (best != rib)
+ UNSET_FLAG (rib->status, RIB_ENTRY_CHANGED);
+ select = best;
} /* RNODE_FOREACH_RIB_SAFE */
/* After the cycle is finished, the following pointers will be set:
@@ -1815,7 +1760,7 @@ rib_process (struct route_node *rn)
if (IS_ZEBRA_DEBUG_RIB)
rnode_debug (rn, vrf_id, "Updating existing route, select %p, fib %p",
(void *)select, (void *)fib);
- if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
+ if (CHECK_FLAG (select->status, RIB_ENTRY_CHANGED))
{
if (info->safi == SAFI_UNICAST)
zfpm_trigger_update (rn, "updating existing route");
@@ -1857,7 +1802,7 @@ rib_process (struct route_node *rn)
rib_uninstall_kernel (rn, select);
UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
}
- UNSET_FLAG (select->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG (select->status, RIB_ENTRY_CHANGED);
}
else if (! RIB_SYSTEM_ROUTE (select))
{
@@ -1910,7 +1855,7 @@ rib_process (struct route_node *rn)
/* Set real nexthop. */
nexthop_active_update (rn, fib, 1);
- UNSET_FLAG(fib->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED);
}
/* Regardless of some RIB entry being SELECTED or not before, now we can
@@ -1980,7 +1925,7 @@ rib_process (struct route_node *rn)
redistribute_delete(&rn->p, fib);
}
}
- UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED);
+ UNSET_FLAG(select->status, RIB_ENTRY_CHANGED);
}
#endif
@@ -2313,7 +2258,7 @@ rib_link (struct route_node *rn, struct rib *rib, int process)
rib_queue_add (rn);
}
-static void
+void
rib_addnode (struct route_node *rn, struct rib *rib, int process)
{
/* RIB node has been un-removed before route-node is processed.
@@ -2368,7 +2313,7 @@ rib_unlink (struct route_node *rn, struct rib *rib)
}
-static void
+void
rib_delnode (struct route_node *rn, struct rib *rib)
{
afi_t afi;
@@ -2402,123 +2347,6 @@ rib_delnode (struct route_node *rn, struct rib *rib)
}
}
-int
-rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, struct in_addr *src,
- unsigned int ifindex, vrf_id_t vrf_id, u_int32_t table_id,
- u_int32_t metric, u_char distance, safi_t safi)
-{
- struct rib *rib;
- struct rib *same = NULL;
- struct route_table *table;
- struct route_node *rn;
- struct nexthop *nexthop;
-
- /* Lookup table. */
- table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id);
- if (! table)
- return 0;
-
- /* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 (p);
-
- /* Set default distance by route type. */
- if (distance == 0)
- {
- if ((unsigned)type >= array_size(route_info))
- distance = 150;
- else
- distance = route_info[type].distance;
-
- /* iBGP distance is 200. */
- if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
- distance = 200;
- }
-
- /* Lookup route node.*/
- rn = route_node_get (table, (struct prefix *) p);
-
- /* If same type of route are installed, treat it as a implicit
- withdraw. */
- RNODE_FOREACH_RIB (rn, rib)
- {
- if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
- continue;
-
- if (rib->type != type)
- continue;
- if (rib->instance != instance)
- continue;
-
- if (rib->type != ZEBRA_ROUTE_CONNECT)
- {
- same = rib;
- break;
- }
- /* Duplicate connected route comes in. */
- else if ((nexthop = rib->nexthop) &&
- nexthop->type == NEXTHOP_TYPE_IFINDEX &&
- nexthop->ifindex == ifindex &&
- !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
- {
- rib->refcnt++;
- return 0 ;
- }
- }
-
- /* Allocate new rib structure. */
- rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
- rib->type = type;
- rib->instance = instance;
- rib->distance = distance;
- rib->flags = flags;
- rib->metric = metric;
- rib->table = table_id;
- rib->vrf_id = vrf_id;
- rib->nexthop_num = 0;
- rib->uptime = time (NULL);
-
- /* Nexthop settings. */
- if (gate)
- {
- if (ifindex)
- rib_nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
- else
- rib_nexthop_ipv4_add (rib, gate, src);
- }
- else
- rib_nexthop_ifindex_add (rib, ifindex);
-
- /* If this route is kernel route, set FIB flag to the route. */
- if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- /* Link new rib to node.*/
- if (IS_ZEBRA_DEBUG_RIB)
- {
- char buf[INET6_ADDRSTRLEN];
- if (IS_ZEBRA_DEBUG_RIB)
- {
- inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) "
- "existing %p",
- vrf_id, buf, p->prefixlen, (void *)rn, (void *)rib, rib->type, (void *)same);
- }
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- rib_dump ((struct prefix *)p, rib);
- }
- rib_addnode (rn, rib, 1);
-
- /* Free implicit route.*/
- if (same)
- rib_delnode (rn, same);
-
- route_unlock_node (rn);
- return 0;
-}
-
/* This function dumps the contents of a given RIB entry into
* standard debug log. Calling function name and IP prefix in
* question are passed as 1st and 2nd arguments.
@@ -2546,9 +2374,10 @@ void _rib_dump (const char * func,
);
zlog_debug
(
- "%s: metric == %u, distance == %u, flags == %u, status == %u",
+ "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
func,
rib->metric,
+ rib->mtu,
rib->distance,
rib->flags,
rib->status
@@ -2681,21 +2510,31 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id)
}
int
-rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
+rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p,
+ struct rib *rib)
{
struct route_table *table;
struct route_node *rn;
struct rib *same;
struct nexthop *nexthop;
int ret = 0;
-
+ int family;
+
+ if (!rib)
+ return 0;
+
+ if (p->family == AF_INET)
+ family = AFI_IP;
+ else
+ family = AFI_IP6;
+
/* Lookup table. */
- table = zebra_vrf_table_with_table_id (AFI_IP, safi, rib->vrf_id, rib->table);
+ table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table);
if (! table)
return 0;
/* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 (p);
+ apply_mask (p);
/* Set default distance by route type. */
if (rib->distance == 0)
@@ -2709,7 +2548,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
}
/* Lookup route node.*/
- rn = route_node_get (table, (struct prefix *) p);
+ rn = route_node_get (table, p);
/* If same type of route are installed, treat it as a implicit
withdraw. */
@@ -2735,7 +2574,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
char buf[INET6_ADDRSTRLEN];
if (IS_ZEBRA_DEBUG_RIB)
{
- inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN);
+ inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) "
"existing %p",
rib->vrf_id, buf, p->prefixlen, (void *)rn,
@@ -2759,11 +2598,10 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)
return ret;
}
-/* XXX factor with rib_delete_ipv6 */
int
-rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
- struct in_addr *gate, unsigned int ifindex, vrf_id_t vrf_id,
- u_int32_t table_id, safi_t safi)
+rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
+ int flags, struct prefix *p, union g_addr *gate, ifindex_t ifindex,
+ u_int32_t table_id)
{
struct route_table *table;
struct route_node *rn;
@@ -2776,15 +2614,15 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
char buf2[INET6_ADDRSTRLEN];
/* Lookup table. */
- table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id);
+ table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id);
if (! table)
return 0;
/* Apply mask. */
- apply_mask_ipv4 (p);
+ apply_mask (p);
/* Lookup route node. */
- rn = route_node_lookup (table, (struct prefix *) p);
+ rn = route_node_lookup (table, p);
if (! rn)
{
if (IS_ZEBRA_DEBUG_RIB)
@@ -2830,7 +2668,8 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
break;
}
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
- if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate))
+ if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
+ IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
{
same = rib;
break;
@@ -2848,10 +2687,10 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
{
if (IS_ZEBRA_DEBUG_RIB)
{
- zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted "
+ zlog_debug ("%u:%s: rn %p, rib %p (type %d) was deleted "
"from kernel, adding",
- vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN),
- p->prefixlen, rn, fib, fib->type);
+ vrf_id, prefix2str(p, buf1, INET6_ADDRSTRLEN),
+ rn, fib, fib->type);
}
if (allow_delete)
{
@@ -2876,7 +2715,7 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
zlog_debug ("%u:%s: via %s ifindex %d type %d "
"doesn't exist in rib",
vrf_id, prefix2str (p, buf1, sizeof(buf1)),
- inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
+ inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN),
ifindex,
type);
else
@@ -2897,444 +2736,14 @@ rib_delete_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
return 0;
}
-/* Install static route into rib. */
-void
-static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
-{
- struct rib *rib;
- struct route_node *rn;
- struct route_table *table;
- struct prefix nh_p;
- /* Lookup table. */
- table = zebra_vrf_table (afi, safi, si->vrf_id);
- if (! table)
- return;
-
- /* Lookup existing route */
- rn = route_node_get (table, p);
- RNODE_FOREACH_RIB (rn, rib)
- {
- if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
- continue;
-
- if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
- break;
- }
-
- if (rib)
- {
- /* if tag value changed , update old value in RIB */
- if (rib->tag != si->tag)
- rib->tag = si->tag;
-
- /* Same distance static route is there. Update it with new
- nexthop. */
- route_unlock_node (rn);
- switch (si->type)
- {
- case STATIC_IPV4_GATEWAY:
- rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
- nh_p.family = AF_INET;
- nh_p.prefixlen = IPV4_MAX_BITLEN;
- nh_p.u.prefix4 = si->addr.ipv4;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
- break;
- case STATIC_IFINDEX:
- rib_nexthop_ifindex_add (rib, si->ifindex);
- break;
- case STATIC_IPV4_BLACKHOLE:
- rib_nexthop_blackhole_add (rib);
- break;
- case STATIC_IPV6_GATEWAY:
- rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
- nh_p.family = AF_INET6;
- nh_p.prefixlen = IPV6_MAX_BITLEN;
- nh_p.u.prefix6 = si->addr.ipv6;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
- break;
- case STATIC_IPV6_GATEWAY_IFINDEX:
- rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
- break;
- }
-
- if (IS_ZEBRA_DEBUG_RIB)
- {
- char buf[INET6_ADDRSTRLEN];
- if (IS_ZEBRA_DEBUG_RIB)
- {
- inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
- si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
- }
- }
- /* Schedule route for processing or invoke NHT, as appropriate. */
- if (si->type == STATIC_IPV4_GATEWAY ||
- si->type == STATIC_IPV6_GATEWAY)
- zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p);
- else
- rib_queue_add (rn);
- }
- else
- {
- /* This is new static route. */
- rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-
- rib->type = ZEBRA_ROUTE_STATIC;
- rib->instance = 0;
- rib->distance = si->distance;
- rib->metric = 0;
- rib->vrf_id = si->vrf_id;
- rib->table = si->vrf_id ? (zebra_vrf_lookup(si->vrf_id))->table_id : zebrad.rtm_table_default;
- rib->nexthop_num = 0;
- rib->tag = si->tag;
-
- switch (si->type)
- {
- case STATIC_IPV4_GATEWAY:
- rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
- nh_p.family = AF_INET;
- nh_p.prefixlen = IPV4_MAX_BITLEN;
- nh_p.u.prefix4 = si->addr.ipv4;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
- break;
- case STATIC_IFINDEX:
- rib_nexthop_ifindex_add (rib, si->ifindex);
- break;
- case STATIC_IPV4_BLACKHOLE:
- rib_nexthop_blackhole_add (rib);
- break;
- case STATIC_IPV6_GATEWAY:
- rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
- nh_p.family = AF_INET6;
- nh_p.prefixlen = IPV6_MAX_BITLEN;
- nh_p.u.prefix6 = si->addr.ipv6;
- zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
- break;
- case STATIC_IPV6_GATEWAY_IFINDEX:
- rib_nexthop_ipv6_ifindex_add (rib, &si->addr.ipv6, si->ifindex);
- break;
- }
-
- /* Save the flags of this static routes (reject, blackhole) */
- rib->flags = si->flags;
-
- if (IS_ZEBRA_DEBUG_RIB)
- {
- char buf[INET6_ADDRSTRLEN];
- if (IS_ZEBRA_DEBUG_RIB)
- {
- inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)",
- si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
- }
- }
- /* Link this rib to the tree. Schedule for processing or invoke NHT,
- * as appropriate.
- */
- if (si->type == STATIC_IPV4_GATEWAY ||
- si->type == STATIC_IPV6_GATEWAY)
- {
- rib_addnode (rn, rib, 0);
- zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p);
- }
- else
- rib_addnode (rn, rib, 1);
- }
-}
-
-static int
-static_nexthop_same (struct nexthop *nexthop, struct static_route *si)
-{
- if (nexthop->type == NEXTHOP_TYPE_IPV4
- && si->type == STATIC_IPV4_GATEWAY
- && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4))
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_IFINDEX
- && si->type == STATIC_IFINDEX
- && nexthop->ifindex == si->ifindex)
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
- && si->type == STATIC_IPV4_BLACKHOLE)
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_IPV6
- && si->type == STATIC_IPV6_GATEWAY
- && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6))
- return 1;
- if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
- && si->type == STATIC_IPV6_GATEWAY_IFINDEX
- && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)
- && nexthop->ifindex == si->ifindex)
- return 1;
- return 0;
-}
-
-/* Uninstall static route from RIB. */
-void
-static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si)
-{
- struct route_node *rn;
- struct rib *rib;
- struct nexthop *nexthop;
- struct route_table *table;
- struct prefix nh_p;
-
- /* Lookup table. */
- table = zebra_vrf_table (afi, safi, si->vrf_id);
- if (! table)
- return;
-
- /* Lookup existing route with type and distance. */
- rn = route_node_lookup (table, p);
- if (! rn)
- return;
-
- RNODE_FOREACH_RIB (rn, rib)
- {
- if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
- continue;
-
- if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance &&
- rib->tag == si->tag)
- break;
- }
-
- if (! rib)
- {
- route_unlock_node (rn);
- return;
- }
-
- /* Lookup nexthop. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
- if (static_nexthop_same (nexthop, si))
- break;
-
- /* Can't find nexthop. */
- if (! nexthop)
- {
- route_unlock_node (rn);
- return;
- }
-
- /* Check nexthop. */
- if (rib->nexthop_num == 1)
- rib_delnode (rn, rib);
- else
- {
- /* Mark this nexthop as inactive and reinstall the route. Then, delete
- * the nexthop. There is no need to re-evaluate the route for this
- * scenario.
- */
- if (IS_ZEBRA_DEBUG_RIB)
- {
- char buf[INET6_ADDRSTRLEN];
- if (IS_ZEBRA_DEBUG_RIB)
- {
- inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
- si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
- }
- }
- UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
- {
- /* If there are other active nexthops, do an update. */
- if (rib->nexthop_active_num > 1)
- {
- rib_install_kernel (rn, rib, 1);
- redistribute_update (&rn->p, rib, NULL);
- }
- else
- {
- redistribute_delete (&rn->p, rib);
- rib_uninstall_kernel (rn, rib);
- }
- }
-
- if (afi == AFI_IP)
- {
- /* Delete the nexthop and dereg from NHT */
- nh_p.family = AF_INET;
- nh_p.prefixlen = IPV4_MAX_BITLEN;
- nh_p.u.prefix4 = nexthop->gate.ipv4;
- }
- else
- {
- nh_p.family = AF_INET6;
- nh_p.prefixlen = IPV6_MAX_BITLEN;
- nh_p.u.prefix6 = nexthop->gate.ipv6;
- }
- rib_nexthop_delete (rib, nexthop);
- zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn);
- nexthop_free (nexthop);
- }
- /* Unlock node. */
- route_unlock_node (rn);
-}
int
-static_add_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex,
- const char *ifname, u_char flags, u_short tag,
- u_char distance, struct zebra_vrf *zvrf)
-{
- u_char type = 0;
- struct route_node *rn;
- struct static_route *si;
- struct static_route *pp;
- struct static_route *cp;
- struct static_route *update = NULL;
- struct route_table *stable = zvrf->stable[AFI_IP][safi];
-
- if (! stable)
- return -1;
-
- /* Lookup static route prefix. */
- rn = route_node_get (stable, p);
-
- /* Make flags. */
- if (gate)
- type = STATIC_IPV4_GATEWAY;
- else if (ifindex)
- type = STATIC_IFINDEX;
- else
- type = STATIC_IPV4_BLACKHOLE;
-
- /* Do nothing if there is a same static route. */
- for (si = rn->info; si; si = si->next)
- {
- if (type == si->type
- && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
- && (! ifindex || ifindex == si->ifindex))
- {
- if ((distance == si->distance) && (tag == si->tag))
- {
- route_unlock_node (rn);
- return 0;
- }
- else
- update = si;
- }
- }
-
- /* Distance or tag changed. */
- if (update)
- static_delete_ipv4 (safi, p, gate, ifindex, update->tag, update->distance, zvrf);
-
- /* Make new static route structure. */
- si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
-
- si->type = type;
- si->distance = distance;
- si->flags = flags;
- si->tag = tag;
- si->vrf_id = zvrf->vrf_id;
- si->ifindex = ifindex;
- if (si->ifindex)
- strcpy(si->ifname, ifname);
-
- if (gate)
- si->addr.ipv4 = *gate;
-
- /* Add new static route information to the tree with sort by
- distance value and gateway address. */
- for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
- {
- if (si->distance < cp->distance)
- break;
- if (si->distance > cp->distance)
- continue;
- if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
- {
- if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr))
- break;
- if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr))
- continue;
- }
- }
-
- /* Make linked list. */
- if (pp)
- pp->next = si;
- else
- rn->info = si;
- if (cp)
- cp->prev = si;
- si->prev = pp;
- si->next = cp;
-
- /* Install into rib. */
- static_install_route (AFI_IP, safi, p, si);
-
- return 1;
-}
-
-int
-static_delete_ipv4 (safi_t safi, struct prefix *p, struct in_addr *gate, unsigned int ifindex,
- u_short tag, u_char distance, struct zebra_vrf *zvrf)
-{
- u_char type = 0;
- struct route_node *rn;
- struct static_route *si;
- struct route_table *stable;
-
- /* Lookup table. */
- stable = zebra_vrf_static_table (AFI_IP, safi, zvrf);
- if (! stable)
- return -1;
-
- /* Lookup static route prefix. */
- rn = route_node_lookup (stable, p);
- if (! rn)
- return 0;
-
- /* Make flags. */
- if (gate)
- type = STATIC_IPV4_GATEWAY;
- else if (ifindex)
- type = STATIC_IFINDEX;
- else
- type = STATIC_IPV4_BLACKHOLE;
-
- /* Find same static route is the tree */
- for (si = rn->info; si; si = si->next)
- if (type == si->type
- && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
- && (! ifindex || ifindex == si->ifindex)
- && (! tag || (tag == si->tag)))
- break;
-
- /* Can't find static route. */
- if (! si)
- {
- route_unlock_node (rn);
- return 0;
- }
-
- /* Install into rib. */
- static_uninstall_route (AFI_IP, safi, p, si);
-
- /* Unlink static route from linked list. */
- if (si->prev)
- si->prev->next = si->next;
- else
- rn->info = si->next;
- if (si->next)
- si->next->prev = si->prev;
- route_unlock_node (rn);
-
- /* Free static route configuration. */
- XFREE (MTYPE_STATIC_ROUTE, si);
-
- route_unlock_node (rn);
-
- return 1;
-}
-
-int
-rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id,
- u_int32_t table_id, u_int32_t metric, u_char distance, safi_t safi)
+rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
+ u_short instance, int flags, struct prefix *p,
+ union g_addr *gate, union g_addr *src, ifindex_t ifindex,
+ u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+ u_char distance)
{
struct rib *rib;
struct rib *same = NULL;
@@ -3343,22 +2752,28 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
struct nexthop *nexthop;
/* Lookup table. */
- table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id);
+ table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id);
if (! table)
return 0;
/* Make sure mask is applied. */
- apply_mask_ipv6 (p);
+ apply_mask (p);
/* Set default distance by route type. */
- if (!distance)
- distance = route_info[type].distance;
-
- if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
- distance = 200;
+ if (distance == 0)
+ {
+ if ((unsigned)type >= array_size(route_info))
+ distance = 150;
+ else
+ distance = route_info[type].distance;
+
+ /* iBGP distance is 200. */
+ if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
+ distance = 200;
+ }
/* Lookup route node.*/
- rn = route_node_get (table, (struct prefix *) p);
+ rn = route_node_get (table, p);
/* If same type of route are installed, treat it as a implicit
withdraw. */
@@ -3376,12 +2791,14 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
same = rib;
break;
}
+ /* Duplicate connected route comes in. */
else if ((nexthop = rib->nexthop) &&
nexthop->type == NEXTHOP_TYPE_IFINDEX &&
- nexthop->ifindex == ifindex)
+ nexthop->ifindex == ifindex &&
+ !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
{
rib->refcnt++;
- return 0;
+ return 0 ;
}
}
@@ -3393,6 +2810,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
rib->distance = distance;
rib->flags = flags;
rib->metric = metric;
+ rib->mtu = mtu;
rib->table = table_id;
rib->vrf_id = vrf_id;
rib->nexthop_num = 0;
@@ -3401,10 +2819,20 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
/* Nexthop settings. */
if (gate)
{
- if (ifindex)
- rib_nexthop_ipv6_ifindex_add (rib, gate, ifindex);
+ if (afi == AFI_IP6)
+ {
+ if (ifindex)
+ rib_nexthop_ipv6_ifindex_add (rib, &gate->ipv6, ifindex);
+ else
+ rib_nexthop_ipv6_add (rib, &gate->ipv6);
+ }
else
- rib_nexthop_ipv6_add (rib, gate);
+ {
+ if (ifindex)
+ rib_nexthop_ipv4_ifindex_add (rib, &gate->ipv4, &src->ipv4, ifindex);
+ else
+ rib_nexthop_ipv4_add (rib, &gate->ipv4, &src->ipv4);
+ }
}
else
rib_nexthop_ifindex_add (rib, ifindex);
@@ -3420,7 +2848,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
char buf[INET6_ADDRSTRLEN];
if (IS_ZEBRA_DEBUG_RIB)
{
- inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN);
+ inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) "
"existing %p",
vrf_id, buf, p->prefixlen, (void *)rn,
@@ -3428,7 +2856,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
}
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- rib_dump ((struct prefix *)p, rib);
+ rib_dump (p, rib);
}
rib_addnode (rn, rib, 1);
@@ -3440,406 +2868,6 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
return 0;
}
-int
-rib_add_ipv6_multipath (struct prefix *p, struct rib *rib, safi_t safi,
- unsigned long ifindex)
-{
- struct route_table *table;
- struct route_node *rn;
- struct rib *same = NULL;
- struct nexthop *nexthop;
- int ret = 0;
- int family;
-
- if (!rib)
- return 0;
-
- if (p->family == AF_INET)
- family = AFI_IP;
- else
- family = AFI_IP6;
-
- /* Lookup table. */
- table = zebra_vrf_table_with_table_id (family, safi, rib->vrf_id, rib->table);
- if (! table)
- return 0;
-
- if (p->family == AF_INET)
- {
- /* Make it sure prefixlen is applied to the prefix. */
- apply_mask_ipv4 ((struct prefix_ipv4 *)p);
- }
- else
- {
- /* Make sure mask is applied. */
- apply_mask_ipv6 ((struct prefix_ipv6 *)p);
- }
-
- /* Set default distance by route type. */
- if (rib->distance == 0)
- {
- rib->distance = route_info[rib->type].distance;
-
- /* iBGP distance is 200. */
- if (rib->type == ZEBRA_ROUTE_BGP
- && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
- rib->distance = 200;
- }
-
- /* Lookup route node.*/
- rn = route_node_get (table, (struct prefix *) p);
-
- /* If same type of route are installed, treat it as a implicit
- withdraw. */
- RNODE_FOREACH_RIB (rn, same) {
- if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED)) {
- continue;
- }
- if (same->type != rib->type) {
- continue;
- }
-
- if (same->instance != rib->instance) {
- continue;
- }
-
- if (same->table != rib->table) {
- continue;
- }
- if (same->type != ZEBRA_ROUTE_CONNECT) {
- break;
- }
- else if ((nexthop = same->nexthop) &&
- nexthop->type == NEXTHOP_TYPE_IFINDEX &&
- nexthop->ifindex == ifindex) {
- same->refcnt++;
- return 0;
- }
- }
-
- /* If this route is kernel route, set FIB flag to the route. */
- if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT) {
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) {
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
- }
- }
-
- /* Link new rib to node.*/
- if (IS_ZEBRA_DEBUG_RIB)
- {
- char buf[INET6_ADDRSTRLEN];
- if (IS_ZEBRA_DEBUG_RIB)
- {
- inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) "
- "existing %p",
- rib->vrf_id, buf, p->prefixlen, rn, rib, rib->type, same);
- }
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- rib_dump ((struct prefix *)p, rib);
- }
- rib_addnode (rn, rib, 1);
- ret = 1;
-
- /* Free implicit route.*/
- if (same)
- {
- rib_delnode (rn, same);
- ret = -1;
- }
-
- route_unlock_node (rn);
- return ret;
-}
-
-/* XXX factor with rib_delete_ipv6 */
-
-int
-rib_delete_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
- struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id,
- u_int32_t table_id, safi_t safi)
-{
- struct route_table *table;
- struct route_node *rn;
- struct rib *rib;
- struct rib *fib = NULL;
- struct rib *same = NULL;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
- char buf1[PREFIX_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
-
- /* Apply mask. */
- apply_mask_ipv6 (p);
-
- /* Lookup table. */
- table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id);
- if (! table)
- return 0;
-
- /* Lookup route node. */
- rn = route_node_lookup (table, (struct prefix *) p);
- if (! rn)
- {
- if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug ("%u:%s: doesn't exist in rib",
- vrf_id, prefix2str (p, buf1, sizeof(buf1)));
- return ZEBRA_ERR_RTNOEXIST;
- }
-
- /* Lookup same type route. */
- RNODE_FOREACH_RIB (rn, rib)
- {
- if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
- continue;
-
- if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
- fib = rib;
-
- if (rib->type != type)
- continue;
- if (rib->instance != instance)
- continue;
- if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
- nexthop->type == NEXTHOP_TYPE_IFINDEX)
- {
- if (nexthop->ifindex != ifindex)
- continue;
- if (rib->refcnt)
- {
- rib->refcnt--;
- route_unlock_node (rn);
- route_unlock_node (rn);
- return 0;
- }
- same = rib;
- break;
- }
- /* Make sure that the route found has the same gateway. */
- else
- {
- if (gate == NULL)
- {
- same = rib;
- break;
- }
- for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
- if (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
- {
- same = rib;
- break;
- }
- if (same)
- break;
- }
- }
-
- /* If same type of route can't be found and this message is from
- kernel. */
- if (! same)
- {
- if (fib && type == ZEBRA_ROUTE_KERNEL &&
- CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE))
- {
- if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted "
- "from kernel, adding",
- vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN),
- p->prefixlen, rn, fib, fib->type);
- if (allow_delete)
- {
- /* Unset flags. */
- for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
- UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
- }
- else
- {
- /* This means someone else, other than Zebra, has deleted a Zebra
- * route from the kernel. We will add it back */
- rib_install_kernel(rn, fib, 0);
- }
- }
- else
- {
- if (IS_ZEBRA_DEBUG_KERNEL)
- {
- if (gate)
- zlog_debug ("%s: vrf %u via %s ifindex %d type %d "
- "doesn't exist in rib",
- prefix2str (p, buf1, sizeof(buf1)), vrf_id,
- inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
- ifindex,
- type);
- else
- zlog_debug ("%s: vrf %u ifindex %d type %d doesn't exist in rib",
- prefix2str (p, buf1, sizeof(buf1)), vrf_id,
- ifindex,
- type);
- }
- route_unlock_node (rn);
- return ZEBRA_ERR_RTNOEXIST;
- }
- }
-
- if (same)
- rib_delnode (rn, same);
-
- route_unlock_node (rn);
- return 0;
-}
-
-/* Add static route into static route configuration. */
-int
-static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- unsigned int ifindex, const char *ifname, u_char flags,
- u_short tag, u_char distance, struct zebra_vrf *zvrf)
-{
- struct route_node *rn;
- struct static_route *si;
- struct static_route *pp;
- struct static_route *cp;
- struct static_route *update = NULL;
- struct route_table *stable = zvrf->stable[AFI_IP6][SAFI_UNICAST];
-
- if (! stable)
- return -1;
-
- if (!gate &&
- (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFINDEX))
- return -1;
-
- if (!ifindex &&
- (type == STATIC_IPV6_GATEWAY_IFINDEX || type == STATIC_IFINDEX))
- return -1;
-
- /* Lookup static route prefix. */
- rn = route_node_get (stable, p);
-
- /* Do nothing if there is a same static route. */
- for (si = rn->info; si; si = si->next)
- {
- if (type == si->type
- && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
- && (! ifindex || ifindex == si->ifindex))
- {
- if ((distance == si->distance) && (tag == si->tag))
- {
- route_unlock_node (rn);
- return 0;
- }
- else
- update = si;
- }
- }
-
- /* Distance or tag changed. */
- if (update)
- static_delete_ipv6 (p, type, gate, ifindex, update->tag, update->distance, zvrf);
-
- /* Make new static route structure. */
- si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
-
- si->type = type;
- si->distance = distance;
- si->flags = flags;
- si->tag = tag;
- si->vrf_id = zvrf->vrf_id;
- si->ifindex = ifindex;
- if (si->ifindex)
- strcpy (si->ifname, ifname);
-
- switch (type)
- {
- case STATIC_IPV6_GATEWAY:
- si->addr.ipv6 = *gate;
- break;
- case STATIC_IPV6_GATEWAY_IFINDEX:
- si->addr.ipv6 = *gate;
- break;
- }
-
- /* Add new static route information to the tree with sort by
- distance value and gateway address. */
- for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
- {
- if (si->distance < cp->distance)
- break;
- if (si->distance > cp->distance)
- continue;
- }
-
- /* Make linked list. */
- if (pp)
- pp->next = si;
- else
- rn->info = si;
- if (cp)
- cp->prev = si;
- si->prev = pp;
- si->next = cp;
-
- /* Install into rib. */
- static_install_route (AFI_IP6, SAFI_UNICAST, p, si);
-
- return 1;
-}
-
-/* Delete static route from static route configuration. */
-int
-static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
- unsigned int ifindex, u_short tag, u_char distance,
- struct zebra_vrf *zvrf)
-{
- struct route_node *rn;
- struct static_route *si;
- struct route_table *stable;
-
- /* Lookup table. */
- stable = zebra_vrf_static_table (AFI_IP6, SAFI_UNICAST, zvrf);
- if (! stable)
- return -1;
-
- /* Lookup static route prefix. */
- rn = route_node_lookup (stable, p);
- if (! rn)
- return 0;
-
- /* Find same static route is the tree */
- for (si = rn->info; si; si = si->next)
- if (distance == si->distance
- && type == si->type
- && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
- && (! ifindex || ifindex == si->ifindex)
- && (! tag || (tag == si->tag)))
- break;
-
- /* Can't find static route. */
- if (! si)
- {
- route_unlock_node (rn);
- return 0;
- }
-
- /* Install into rib. */
- static_uninstall_route (AFI_IP6, SAFI_UNICAST, p, si);
-
- /* Unlink static route from linked list. */
- if (si->prev)
- si->prev->next = si->next;
- else
- rn->info = si->next;
- if (si->next)
- si->next->prev = si->prev;
-
- /* Free static route configuration. */
- XFREE (MTYPE_STATIC_ROUTE, si);
-
- return 1;
-}
-
/* Schedule routes of a particular table (address-family) based on event. */
static void
rib_update_table (struct route_table *table, rib_update_event_t event)