summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/zebra_rib.c102
-rw-r--r--zebra/zserv.c85
2 files changed, 181 insertions, 6 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 7374f73d..29a8e40b 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -353,6 +353,17 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
break;
}
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
+ zlog_debug("%s: %s/%d: nexthop match %p: %s type=%d sel=%d int=%d",
+ __func__, buf, rn->p.prefixlen, match,
+ match ? zebra_route_string(match->type) : "<?>",
+ match ? match->type : -1,
+ match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED) : -1,
+ match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_INTERNAL) : -1);
+ }
+
/* If there is no selected route or matched route is EGP, go up
tree. */
if (! match
@@ -376,7 +387,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
return 1;
}
- else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
+ else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) ||
+ match->type == ZEBRA_ROUTE_KERNEL)
{
for (newhop = match->nexthop; newhop; newhop = newhop->next)
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
@@ -757,6 +769,43 @@ rib_match_ipv6 (struct in6_addr *addr)
}
#endif /* HAVE_IPV6 */
+static void nexthop_dump(struct nexthop *nexthop,
+ char *type_str_buf,
+ int type_str_buf_size,
+ char *addr_str_buf,
+ int addr_str_buf_size,
+ char *via_str_buf,
+ int via_str_buf_size)
+{
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ snprintf(type_str_buf, type_str_buf_size, "ipv4");
+ snprintf(addr_str_buf, addr_str_buf_size, "%s", inet_ntoa(nexthop->gate.ipv4));
+ snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifindex ? ifindex2ifname(nexthop->ifindex) : "<?>");
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ snprintf(type_str_buf, type_str_buf_size, "connected");
+ snprintf(addr_str_buf, addr_str_buf_size, "<connected>");
+ snprintf(via_str_buf, via_str_buf_size, "%s", ifindex2ifname(nexthop->ifindex));
+ break;
+ case NEXTHOP_TYPE_IFNAME:
+ snprintf(type_str_buf, type_str_buf_size, "connected");
+ snprintf(addr_str_buf, addr_str_buf_size, "<connected>");
+ snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifname);
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ snprintf(type_str_buf, type_str_buf_size, "blackhole");
+ snprintf(addr_str_buf, addr_str_buf_size, "<blackhole>");
+ snprintf(via_str_buf, via_str_buf_size, "Null0");
+ break;
+ default:
+ snprintf(type_str_buf, type_str_buf_size, "unknown");
+ snprintf(addr_str_buf, addr_str_buf_size, "<unknown>");
+ snprintf(via_str_buf, via_str_buf_size, "<?>");
+ }
+}
+
#define RIB_SYSTEM_ROUTE(R) \
((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
@@ -810,10 +859,27 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
family = AFI_IP;
- if (nexthop_active_ipv4 (rib, nexthop, set, rn))
- SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- else
- UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ {
+ int nh_active = nexthop_active_ipv4 (rib, nexthop, set, rn);
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char type_str_buf[100];
+ char addr_str_buf[100];
+ char via_str_buf[100];
+ nexthop_dump(nexthop,
+ type_str_buf, sizeof(type_str_buf),
+ addr_str_buf, sizeof(addr_str_buf),
+ via_str_buf, sizeof(via_str_buf));
+ zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d nexthop_active_ipv4=%d",
+ __func__, rib, nexthop,
+ nexthop->type, type_str_buf,
+ addr_str_buf, via_str_buf, nexthop->ifindex,
+ nh_active);
+ }
+ if (nh_active)
+ SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ else
+ UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ }
break;
#ifdef HAVE_IPV6
case NEXTHOP_TYPE_IPV6:
@@ -893,8 +959,23 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
{
prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
prev_index = nexthop->ifindex;
- if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
+ new_active = nexthop_active_check (rn, rib, nexthop, set);
+ if (new_active)
rib->nexthop_active_num++;
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char type_str_buf[100];
+ char addr_str_buf[100];
+ char via_str_buf[100];
+ nexthop_dump(nexthop,
+ type_str_buf, sizeof(type_str_buf),
+ addr_str_buf, sizeof(addr_str_buf),
+ via_str_buf, sizeof(via_str_buf));
+ zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d act=%d total_act=%d",
+ __func__, rib, nexthop,
+ nexthop->type, type_str_buf,
+ addr_str_buf, via_str_buf, nexthop->ifindex,
+ new_active, rib->nexthop_active_num);
+ }
if (prev_active != new_active ||
prev_index != nexthop->ifindex)
SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
@@ -994,6 +1075,15 @@ rib_process (struct route_node *rn)
* may be passed to rib_unlink() in the middle of iteration.
*/
next = rib->next;
+
+ if (IS_ZEBRA_DEBUG_RIB) {
+ zlog_debug("%s: %s/%d: scan rib %p: type=%d sel=%d rem=%d nh_act=%d dist=%d",
+ __func__, buf, rn->p.prefixlen, rib, rib->type,
+ CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED),
+ CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED),
+ nexthop_active_update(rn, rib, 0),
+ rib->distance);
+ }
/* Currently installed rib. */
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
diff --git a/zebra/zserv.c b/zebra/zserv.c
index e3e15a01..21f24627 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1,5 +1,6 @@
/* Zebra daemon server routine.
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+ * Portions Copyright (c) 2008 Everton da Silva Marques <everton.marques@gmail.com>
*
* This file is part of GNU Zebra.
*
@@ -596,6 +597,77 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr)
return zebra_server_send_message(client);
}
+/*
+ Modified version of zsend_ipv4_nexthop_lookup():
+ 1) Returns both nexthop address and nexthop ifindex
+ (with ZEBRA_NEXTHOP_IPV4_IFINDEX).
+ 2) Returns both route metric and protocol distance.
+*/
+static int
+zsend_ipv4_nexthop_lookup_v2 (struct zserv *client, struct in_addr addr)
+{
+ struct stream *s;
+ struct rib *rib;
+ unsigned long nump;
+ u_char num;
+ struct nexthop *nexthop;
+
+ /* Lookup nexthop. */
+ rib = rib_match_ipv4 (addr);
+
+ /* Get output stream. */
+ s = client->obuf;
+ stream_reset (s);
+
+ /* Fill in result. */
+ zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_V2);
+ stream_put_in_addr (s, &addr);
+
+ if (rib)
+ {
+ stream_putc (s, rib->distance);
+ stream_putl (s, rib->metric);
+ num = 0;
+ nump = stream_get_endp(s); /* remember position for nexthop_num */
+ stream_putc (s, 0); /* reserve room for nexthop_num */
+ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
+ {
+ stream_putc (s, nexthop->type);
+ switch (nexthop->type)
+ {
+ case ZEBRA_NEXTHOP_IPV4:
+ stream_put_in_addr (s, &nexthop->gate.ipv4);
+ break;
+ case ZEBRA_NEXTHOP_IFINDEX:
+ case ZEBRA_NEXTHOP_IFNAME:
+ stream_putl (s, nexthop->ifindex);
+ break;
+ case ZEBRA_NEXTHOP_IPV4_IFINDEX:
+ stream_put_in_addr (s, &nexthop->gate.ipv4);
+ stream_putl (s, nexthop->ifindex);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ num++;
+ }
+
+ stream_putc_at (s, nump, num); /* store nexthop_num */
+ }
+ else
+ {
+ stream_putc (s, 0); /* distance */
+ stream_putl (s, 0); /* metric */
+ stream_putc (s, 0); /* nexthop_num */
+ }
+
+ stream_putw_at (s, 0, stream_get_endp (s));
+
+ return zebra_server_send_message(client);
+}
+
static int
zsend_ipv4_import_lookup (struct zserv *client, struct prefix_ipv4 *p)
{
@@ -892,6 +964,16 @@ zread_ipv4_nexthop_lookup (struct zserv *client, u_short length)
return zsend_ipv4_nexthop_lookup (client, addr);
}
+/* Nexthop lookup v2 for IPv4. */
+static int
+zread_ipv4_nexthop_lookup_v2 (struct zserv *client, u_short length)
+{
+ struct in_addr addr;
+
+ addr.s_addr = stream_get_ipv4 (client->ibuf);
+ return zsend_ipv4_nexthop_lookup_v2 (client, addr);
+}
+
/* Nexthop lookup for IPv4. */
static int
zread_ipv4_import_lookup (struct zserv *client, u_short length)
@@ -1276,6 +1358,9 @@ zebra_client_read (struct thread *thread)
case ZEBRA_IPV4_NEXTHOP_LOOKUP:
zread_ipv4_nexthop_lookup (client, length);
break;
+ case ZEBRA_IPV4_NEXTHOP_LOOKUP_V2:
+ zread_ipv4_nexthop_lookup_v2 (client, length);
+ break;
#ifdef HAVE_IPV6
case ZEBRA_IPV6_NEXTHOP_LOOKUP:
zread_ipv6_nexthop_lookup (client, length);