summaryrefslogtreecommitdiff
path: root/ripd
diff options
context:
space:
mode:
Diffstat (limited to 'ripd')
-rw-r--r--ripd/ChangeLog19
-rw-r--r--ripd/rip_interface.c8
-rw-r--r--ripd/rip_routemap.c18
-rw-r--r--ripd/rip_snmp.c21
-rw-r--r--ripd/rip_zebra.c10
-rw-r--r--ripd/ripd.c72
-rw-r--r--ripd/ripd.h6
7 files changed, 128 insertions, 26 deletions
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index 3a9b5516..6aecebd4 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,22 @@
+2005-09-29 Alain Ritoux <alain.ritoux@6wind.com>
+
+ * rip_snmp.c: rip2IfConfReceive() sends values in conformance
+ with RFC. Also PeerDomain is now set to a STRING type.
+ * ripd.h: rip_redistribute_add() API includes metric and distance
+ added field external_metric in routes.
+ * 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
+ * rip_zebra.c: adapt to the rip_redistribute_add() API, i.e.
+ provide distance and metric
+ * rip_interface.c: adapt to the rip_redistribute_add() API
+ * 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.
+
2005-09-28 Alain Ritoux <alain.ritoux@6wind.com>
* ripd.c: use new md5 API
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 5fa4b7d3..85bf3c5a 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -717,7 +717,7 @@ rip_apply_address_add (struct connected *ifc) {
if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) ||
(rip_enable_network_lookup2(ifc) >= 0))
rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
- &address, ifc->ifp->ifindex, NULL);
+ &address, ifc->ifp->ifindex, NULL, 0, 0);
}
@@ -1029,14 +1029,16 @@ rip_connect_set (struct interface *ifp, int set)
if ((rip_enable_if_lookup(connected->ifp->name) >= 0) ||
(rip_enable_network_lookup2(connected) >= 0))
rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
- &address, connected->ifp->ifindex, NULL);
+ &address, connected->ifp->ifindex,
+ NULL, 0, 0);
} else
{
rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, connected->ifp->ifindex);
if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT))
rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE,
- &address, connected->ifp->ifindex, NULL);
+ &address, connected->ifp->ifindex,
+ NULL, 0, 0);
}
}
}
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index e7692be0..2a2f264f 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -1,4 +1,5 @@
/* RIPv2 routemap.
+ * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
* Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
*
* This file is part of GNU Zebra.
@@ -106,8 +107,14 @@ rip_route_set_add (struct vty *vty, struct route_map_index *index,
vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
return CMD_WARNING;
case RMAP_COMPILE_ERROR:
- vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
- return CMD_WARNING;
+ /* rip, ripng and other protocols share the set metric command
+ but only values from 0 to 16 are valid for rip and ripng
+ if metric is out of range for rip and ripng, it is not for
+ other protocols. Do not return an error */
+ if (strcmp(command, "metric")) {
+ vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
}
return CMD_SUCCESS;
@@ -161,6 +168,7 @@ route_match_metric (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
u_int32_t *metric;
+ u_int32_t check;
struct rip_info *rinfo;
if (type == RMAP_RIP)
@@ -168,7 +176,11 @@ route_match_metric (void *rule, struct prefix *prefix,
metric = rule;
rinfo = object;
- if (rinfo->metric == *metric)
+ /* If external metric is available, the route-map should
+ work on this one (for redistribute purpose) */
+ check = (rinfo->external_metric) ? rinfo->external_metric :
+ rinfo->metric;
+ if (check == *metric)
return RMAP_MATCH;
else
return RMAP_NOMATCH;
diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c
index 93773bc5..c1bec762 100644
--- a/ripd/rip_snmp.c
+++ b/ripd/rip_snmp.c
@@ -136,7 +136,7 @@ struct variable rip_variables[] =
{RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
/* RIP Peer Table. */
3, {4, 1, 1}},
- {RIP2PEERDOMAIN, INTEGER, RONLY, rip2PeerTable,
+ {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
3, {4, 1, 2}},
{RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
3, {4, 1, 3}},
@@ -419,15 +419,19 @@ rip2IfConfReceive (struct rip_interface *ri)
#define rip1OrRip2 3
#define doNotReceive 4
+ int recvv;
+
if (! ri->running)
return doNotReceive;
- if (ri->ri_receive == RI_RIP_VERSION_1_AND_2)
+ recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
+ ri->ri_receive;
+ if (recvv == RI_RIP_VERSION_1_AND_2)
return rip1OrRip2;
- else if (ri->ri_receive & RIPv2)
- return ripVersion2;
- else if (ri->ri_receive & RIPv1)
- return ripVersion1;
+ else if (recvv & RIPv2)
+ return rip2;
+ else if (recvv & RIPv1)
+ return rip1;
else
return doNotReceive;
}
@@ -508,6 +512,7 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length,
int exact, size_t *val_len, WriteMethod **write_method)
{
static struct in_addr addr;
+ static int domain = 0;
static int version;
/* static time_t uptime; */
@@ -527,8 +532,8 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length,
return (u_char *) &peer->addr;
case RIP2PEERDOMAIN:
- *val_len = sizeof (int);
- return (u_char *) &peer->domain;
+ *val_len = 2;
+ return (u_char *) &domain;
case RIP2PEERLASTUPDATE:
#if 0
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index 734555b7..570b5281 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -134,12 +134,17 @@ rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
}
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
api.distance = stream_getc (s);
+ else
+ api.distance = 255;
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
api.metric = stream_getl (s);
+ else
+ api.metric = 0;
/* Then fetch IPv4 prefixes. */
if (command == ZEBRA_IPV4_ROUTE_ADD)
- rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
+ rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex,
+ &nexthop, api.metric, api.distance);
else
rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex);
@@ -597,7 +602,8 @@ DEFUN (rip_default_information_originate,
rip->default_information = 1;
- rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, NULL);
+ rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0,
+ NULL, 0, 0);
}
return CMD_SUCCESS;
diff --git a/ripd/ripd.c b/ripd/ripd.c
index b75e018b..13cf9b9b 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 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
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 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
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 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,
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 @@ rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
/* 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 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,
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 @@ DEFUN (rip_route,
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 @@ DEFUN (show_ip_rip,
}
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);
}
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 7874871e..6ddd52d5 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -200,6 +200,10 @@ struct rip_info
/* Metric of this route. */
u_int32_t metric;
+ /* External metric of this route.
+ if learnt from an externalm proto */
+ u_int32_t external_metric;
+
/* Tag information of this route. */
u_int16_t tag;
@@ -393,7 +397,7 @@ int rip_request_send (struct sockaddr_in *, struct interface *, u_char,
struct connected *);
int rip_neighbor_lookup (struct sockaddr_in *);
void rip_redistribute_add (int, int, struct prefix_ipv4 *, unsigned int,
- struct in_addr *);
+ struct in_addr *, unsigned int, unsigned char);
void rip_redistribute_delete (int, int, struct prefix_ipv4 *, unsigned int);
void rip_redistribute_withdraw (int);
void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_char);