diff options
Diffstat (limited to 'ripd')
-rw-r--r-- | ripd/ChangeLog | 19 | ||||
-rw-r--r-- | ripd/rip_interface.c | 8 | ||||
-rw-r--r-- | ripd/rip_routemap.c | 18 | ||||
-rw-r--r-- | ripd/rip_snmp.c | 21 | ||||
-rw-r--r-- | ripd/rip_zebra.c | 10 | ||||
-rw-r--r-- | ripd/ripd.c | 72 | ||||
-rw-r--r-- | ripd/ripd.h | 6 |
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); |