zebra: ipv6 multipath support
This patch enables support for multipath for IPV6. The nexthop information
from the protocols have ifindices and nexthop addresses in two different
structures. This patch combines them to ensure that the correct APIs can
be called. Also, given that IPV6 Linux implementation does not support the
rta_XXX APIs for multipath, the communication with the kernel is in terms
of a single nh/ifindex pair.
Signed-off-by: Ayan Banerjee <ayan@cumulusnetworks.com>
Signed-off-by: Dinesh Dutt <ddutt@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 2e15f99..eec2976 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -289,7 +289,7 @@
return nexthop;
}
-static struct nexthop *
+struct nexthop *
nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
ifindex_t ifindex)
{
@@ -2669,6 +2669,86 @@
return 0;
}
+int
+rib_add_ipv6_multipath (struct prefix_ipv6 *p, struct rib *rib, safi_t safi)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *same = NULL;
+ struct nexthop *nexthop;
+ int ret = 0;
+
+ if (!rib)
+ return 0; /* why are we getting called with NULL rib */
+
+ /* Lookup table. */
+ table = zebra_vrf_table (AFI_IP6, safi, rib->vrf_id);
+
+ if (! table)
+ return 0;
+
+ /* Make sure mask is applied. */
+ apply_mask_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->table != rib->table) {
+ continue;
+ }
+ if (same->type != ZEBRA_ROUTE_CONNECT) {
+ break;
+ }
+ }
+
+ /* 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.*/
+ rib_addnode (rn, rib);
+ ret = 1;
+ /* Free implicit route.*/
+ if (same)
+ {
+ if (IS_ZEBRA_DEBUG_RIB)
+ {
+ zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
+ __func__, rn, same);
+ rib_dump ((struct prefix *)p, 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, int flags, struct prefix_ipv6 *p,