diff options
author | Feng Lu <lu.feng@6wind.com> | 2015-05-22 11:39:53 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-06-08 21:16:23 +0200 |
commit | c880b6367ec69eeae5ad7ed7527d0cf567918a10 (patch) | |
tree | e0223eb96e2a5864c23f309b6813046dcb573ddc /ripngd/ripng_zebra.c | |
parent | isisd: always print adj->sysid (clang 3.6 warning) (diff) | |
download | frr-c880b6367ec69eeae5ad7ed7527d0cf567918a10.tar.xz frr-c880b6367ec69eeae5ad7ed7527d0cf567918a10.zip |
ripngd: add ECMP support
* Each node in the routing table is changed into a list, holding
the multiple equal-cost paths.
* If one of the multiple entries gets less-preferred (greater
metric or greater distance), it will be directly deleted instead
of starting a garbage-collection timer for it.
The garbage-collection timer is started only when the last entry
in the list gets INFINITY.
* Some new functions are used to maintain the ECMP list. And hence
ripng_route_process(), ripng_redistribute_add() and ripng_timeout()
are significantly simplified.
* ripng_zebra_ipv6_add() and ripng_zebra_ipv6_delete() now can share
the common code. The common part is moved to ripng_zebra_ipv6_send().
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent Jardin <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'ripngd/ripng_zebra.c')
-rw-r--r-- | ripngd/ripng_zebra.c | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index afd658020..1b09b6d7c 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -24,21 +24,32 @@ #include "command.h" #include "prefix.h" +#include "table.h" #include "stream.h" +#include "memory.h" #include "routemap.h" #include "zclient.h" #include "log.h" #include "ripngd/ripngd.h" +#include "ripngd/ripng_debug.h" /* All information about zebra. */ struct zclient *zclient = NULL; -void -ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, - unsigned int ifindex, u_char metric) +/* Send ECMP routes to zebra. */ +static void +ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd) { + static struct in6_addr **nexthops = NULL; + static unsigned int *ifindexes = NULL; + static unsigned int nexthops_len = 0; + + struct list *list = (struct list *)rp->info; struct zapi_ipv6 api; + struct listnode *listnode = NULL; + struct ripng_info *rinfo = NULL; + int count = 0; if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) { @@ -48,42 +59,62 @@ ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, api.flags = 0; api.message = 0; api.safi = SAFI_UNICAST; + + if (nexthops_len < listcount (list)) + { + nexthops_len = listcount (list); + nexthops = XREALLOC (MTYPE_TMP, nexthops, + nexthops_len * sizeof (struct in6_addr *)); + ifindexes = XREALLOC (MTYPE_TMP, ifindexes, + nexthops_len * sizeof (unsigned int)); + } + SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) + { + nexthops[count] = &rinfo->nexthop; + ifindexes[count] = rinfo->ifindex; + count++; + if (cmd == ZEBRA_IPV6_ROUTE_ADD) + SET_FLAG (rinfo->flags, RIPNG_RTF_FIB); + else + UNSET_FLAG (rinfo->flags, RIPNG_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex = ifindexes; + api.ifindex_num = count; + + rinfo = listgetdata (listhead (list)); + SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api); + api.metric = rinfo->metric; + + zapi_ipv6_route (cmd, zclient, + (struct prefix_ipv6 *)&rp->p, &api); + + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug ("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ + "Install into zebra" : "Delete from zebra", + inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen, count); } } +/* Add/update ECMP routes to zebra. */ void -ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, struct in6_addr *nexthop, - unsigned int ifindex) +ripng_zebra_ipv6_add (struct route_node *rp) { - struct zapi_ipv6 api; - - if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIPNG; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; + ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_ADD); +} - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api); - } +/* Delete ECMP routes from zebra. */ +void +ripng_zebra_ipv6_delete (struct route_node *rp) +{ + ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ |