zebra: rework recursive route resolution
Change the datastructure for recursive routes. This brings the following
benefits:
By using struct nexthop also to store nexthops obtained by recursive
resolution, we can get rid of quite a bit of code duplication in the fib
management. (rt_netlink, rt_socket, ...)
With the new datastructure we can make use of all available paths when
recursive routes are resolved with multipath routes.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index a672d42..e1da7df 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -533,7 +533,8 @@
vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)
{
struct rib *rib;
- struct nexthop *nexthop;
+ struct nexthop *nexthop, *tnexthop;
+ int recursing;
RNODE_FOREACH_RIB (rn, rib)
{
@@ -582,12 +583,13 @@
vty_out (vty, " ago%s", VTY_NEWLINE);
}
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{
char addrstr[32];
- vty_out (vty, " %c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
+ vty_out (vty, " %c%s",
+ CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ',
+ recursing ? " " : "");
switch (nexthop->type)
{
@@ -614,28 +616,8 @@
vty_out (vty, " inactive");
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out (vty, " via %s", inet_ntoa (nexthop->rgate.ipv4));
- if (nexthop->rifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
- vty_out (vty, ")");
+ vty_out (vty, " (recursive)");
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
switch (nexthop->type)
{
case NEXTHOP_TYPE_IPV4:
@@ -672,12 +654,13 @@
static void
vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)
{
- struct nexthop *nexthop;
+ struct nexthop *nexthop, *tnexthop;
+ int recursing;
int len = 0;
char buf[BUFSIZ];
/* Nexthop information. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{
if (nexthop == rib->nexthop)
{
@@ -701,7 +684,7 @@
vty_out (vty, " %c%*c",
CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
? '*' : ' ',
- len - 3, ' ');
+ len - 3 + (2 * recursing), ' ');
switch (nexthop->type)
{
@@ -728,27 +711,8 @@
vty_out (vty, " inactive");
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out (vty, " via %s", inet_ntoa (nexthop->rgate.ipv4));
- if (nexthop->rifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
- vty_out (vty, ")");
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
+ vty_out (vty, " (recursive)");
+
switch (nexthop->type)
{
case NEXTHOP_TYPE_IPV4:
@@ -1058,7 +1022,8 @@
{
rib_cnt[ZEBRA_ROUTE_TOTAL]++;
rib_cnt[rib->type]++;
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+ || nexthop_has_fib_child(nexthop))
{
fib_cnt[ZEBRA_ROUTE_TOTAL]++;
fib_cnt[rib->type]++;
@@ -1067,7 +1032,8 @@
CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
{
rib_cnt[ZEBRA_ROUTE_IBGP]++;
- if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+ || nexthop_has_fib_child(nexthop))
fib_cnt[ZEBRA_ROUTE_IBGP]++;
}
}
@@ -1550,7 +1516,8 @@
vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)
{
struct rib *rib;
- struct nexthop *nexthop;
+ struct nexthop *nexthop, *tnexthop;
+ int recursing;
char buf[BUFSIZ];
RNODE_FOREACH_RIB (rn, rib)
@@ -1601,10 +1568,11 @@
vty_out (vty, " ago%s", VTY_NEWLINE);
}
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{
- vty_out (vty, " %c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ');
+ vty_out (vty, " %c%s",
+ CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ',
+ recursing ? " " : "");
switch (nexthop->type)
{
@@ -1633,29 +1601,8 @@
vty_out (vty, " inactive");
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- vty_out (vty, " via %s)",
- inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
- buf, BUFSIZ));
- if (nexthop->rifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
+ vty_out (vty, " (recursive)");
+
vty_out (vty, "%s", VTY_NEWLINE);
}
vty_out (vty, "%s", VTY_NEWLINE);
@@ -1666,12 +1613,13 @@
vty_show_ipv6_route (struct vty *vty, struct route_node *rn,
struct rib *rib)
{
- struct nexthop *nexthop;
+ struct nexthop *nexthop, *tnexthop;
+ int recursing;
int len = 0;
char buf[BUFSIZ];
/* Nexthop information. */
- for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
{
if (nexthop == rib->nexthop)
{
@@ -1695,7 +1643,7 @@
vty_out (vty, " %c%*c",
CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
? '*' : ' ',
- len - 3, ' ');
+ len - 3 + (2 * recursing), ' ');
switch (nexthop->type)
{
@@ -1724,29 +1672,7 @@
vty_out (vty, " inactive");
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- vty_out (vty, " (recursive");
-
- switch (nexthop->rtype)
- {
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- case NEXTHOP_TYPE_IPV6_IFNAME:
- vty_out (vty, " via %s)",
- inet_ntop (AF_INET6, &nexthop->rgate.ipv6,
- buf, BUFSIZ));
- if (nexthop->rifindex)
- vty_out (vty, ", %s", ifindex2ifname (nexthop->rifindex));
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_IFNAME:
- vty_out (vty, " is directly connected, %s)",
- ifindex2ifname (nexthop->rifindex));
- break;
- default:
- break;
- }
- }
+ vty_out (vty, " (recursive)");
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
vty_out (vty, ", bh");