2005-09-29 Alain Ritoux <alain.ritoux@6wind.com>
* lib/filer.c: show protocol name in filter_show()
* lib/plist.c: show protocol name in vty_show_prefix_entry()
* routemap.c: show protocol name in vty_show_route_map_entry()
* lib/vty.c: in vty_command(), show protocol name if command unknown
* zebra/zserv.c: Always provide distance fo route add
* ripd/rip_snmp.c: rip2IfConfReceive() sends values in conformance
with RFC. Also PeerDomain is now set to a STRING type.
* ripd/ripd.h: rip_redistribute_add() API includes metric and distance
* ripd/ripd.c: rip_redistribute_add() API i.e. stores metric and distance
Now allows a RIP-route to overcome a redistributed route coming
from a protocol with worse (higher) administrative distance
Metrics from redistribution are shown in show ip rip
* ripd/rip_zebra.c: adapt to the rip_redistribute_add() API, i.e.
provide distance and metric
* ripd/rip_interface.c: adapt to the rip_redistribute_add() API
* ripd/rip_routemap.c: no RMAP_COMPILE_ERROR on (metric > 16) usage
rather a CMD_WARNING, because set metric ius shared with other
protocols using larger values (such as OSPF)
The match metric action takes first external metric if present
(from redistribution) then RIP metric.
diff --git a/ripd/ripd.c b/ripd/ripd.c
index b75e018..13cf9b9 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1,4 +1,5 @@
/* RIP version 1 and 2.
+ * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
* Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of GNU Zebra.
@@ -392,6 +393,8 @@
struct in_addr *nexthop;
u_char oldmetric;
int same = 0;
+ int route_reuse = 0;
+ unsigned char old_dist, new_dist;
/* Make prefix structure. */
memset (&p, 0, sizeof (struct prefix_ipv4));
@@ -480,17 +483,51 @@
if (rinfo)
{
- /* Redistributed route check. */
- if (rinfo->type != ZEBRA_ROUTE_RIP
- && rinfo->metric != RIP_METRIC_INFINITY)
- return;
-
/* Local static route. */
if (rinfo->type == ZEBRA_ROUTE_RIP
&& ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
(rinfo->sub_type == RIP_ROUTE_DEFAULT))
&& rinfo->metric != RIP_METRIC_INFINITY)
- return;
+ {
+ route_unlock_node (rp);
+ return;
+ }
+
+ /* Redistributed route check. */
+ if (rinfo->type != ZEBRA_ROUTE_RIP
+ && rinfo->metric != RIP_METRIC_INFINITY)
+ {
+ /* Fill in a minimaly temporary rip_info structure, for a future
+ rip_distance_apply() use) */
+ memset (&rinfotmp, 0, sizeof (rinfotmp));
+ IPV4_ADDR_COPY (&rinfotmp.from, &from->sin_addr);
+ rinfotmp.rp = rinfo->rp;
+ new_dist = rip_distance_apply (&rinfotmp);
+ new_dist = new_dist ? new_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
+ old_dist = rinfo->distance;
+ old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
+ /* If imported route does not have STRICT precedence,
+ mark it as a ghost */
+ if (new_dist > old_dist
+ || rte->metric == RIP_METRIC_INFINITY)
+ {
+ route_unlock_node (rp);
+ return;
+ }
+ else
+ {
+ RIP_TIMER_OFF (rinfo->t_timeout);
+ RIP_TIMER_OFF (rinfo->t_garbage_collect);
+
+ rp->info = NULL;
+ if (rip_route_rte (rinfo))
+ rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p,
+ &rinfo->nexthop, rinfo->metric);
+ rip_info_free (rinfo);
+ rinfo = NULL;
+ route_reuse = 1;
+ }
+ }
}
if (!rinfo)
@@ -544,6 +581,10 @@
rinfo->distance);
rinfo->flags |= RIP_RTF_FIB;
}
+
+ /* Unlock temporary lock, i.e. same behaviour */
+ if (route_reuse)
+ route_unlock_node (rp);
}
else
{
@@ -1495,7 +1536,8 @@
/* Add redistributed route to RIP table. */
void
rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
- unsigned int ifindex, struct in_addr *nexthop)
+ unsigned int ifindex, struct in_addr *nexthop,
+ unsigned int metric, unsigned char distance)
{
int ret;
struct route_node *rp;
@@ -1551,6 +1593,8 @@
rinfo->sub_type = sub_type;
rinfo->ifindex = ifindex;
rinfo->metric = 1;
+ rinfo->external_metric = metric;
+ rinfo->distance = distance;
rinfo->rp = rp;
if (nexthop)
@@ -2922,7 +2966,7 @@
node->info = (char *)"static";
- rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
+ rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0);
return CMD_SUCCESS;
}
@@ -3467,7 +3511,17 @@
}
else
{
- vty_out (vty, "self ");
+ if (rinfo->external_metric)
+ {
+ len = vty_out (vty, "self (%s:%d)",
+ route_info[rinfo->type].str_long,
+ rinfo->external_metric);
+ len = 16 - len;
+ if (len > 0)
+ vty_out (vty, "%*s", len, " ");
+ }
+ else
+ vty_out (vty, "self ");
vty_out (vty, "%3d", rinfo->tag);
}