Merge RIP part of 6Wind patch.
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index 4950169..c80338d 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,7 @@
+2003-05-25 Vincent Jardin <vjardin@wanadoo.fr>
+
+ * 6Wind patch merge.
+
2003-04-19 Hasso Tepper <hasso@estpak.ee>
* rip_routemap.c: sync daemon's route-map commands to have same
diff --git a/ripd/Makefile.am b/ripd/Makefile.am
index fd25485..df9a0af 100644
--- a/ripd/Makefile.am
+++ b/ripd/Makefile.am
@@ -17,7 +17,7 @@
ripd_SOURCES = \
rip_main.c $(librip_a_SOURCES)
-ripd_LDADD = ../lib/libzebra.a
+ripd_LDADD = -L../lib -lzebra
sysconf_DATA = ripd.conf.sample
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 23c9cb0..8ec96ae 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -43,6 +43,10 @@
void rip_enable_apply (struct interface *);
void rip_passive_interface_apply (struct interface *);
int rip_if_down(struct interface *ifp);
+int rip_enable_if_lookup (char *ifname);
+int rip_enable_network_lookup2 (struct connected *connected);
+void rip_enable_apply_all ();
+
struct message ri_version_msg[] =
{
@@ -122,7 +126,7 @@
Relay or SMDS is enabled, the default value for split-horizon is
off. But currently Zebra does detect Frame Relay or SMDS
interface. So all interface is set to split horizon. */
- ri->split_horizon_default = 1;
+ ri->split_horizon_default = RIP_SPLIT_HORIZON;
ri->split_horizon = ri->split_horizon_default;
return ri;
@@ -226,10 +230,8 @@
to.sin_port = htons (RIP_PORT_DEFAULT);
to.sin_addr = p->prefix;
-#if 0
if (IS_RIP_DEBUG_EVENT)
zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
-#endif /* 0 */
rip_request_send (&to, ifp, version);
}
@@ -466,6 +468,9 @@
/* rip_request_neighbor_all (); */
+ /* Check interface routemap. */
+ rip_if_rmap_update_interface (ifp);
+
return 0;
}
@@ -554,8 +559,8 @@
ri->key_chain = NULL;
}
- ri->split_horizon = 0;
- ri->split_horizon_default = 0;
+ ri->split_horizon = RIP_NO_SPLIT_HORIZON;
+ ri->split_horizon_default = RIP_NO_SPLIT_HORIZON;
ri->list[RIP_FILTER_IN] = NULL;
ri->list[RIP_FILTER_OUT] = NULL;
@@ -644,6 +649,34 @@
}
}
+static void
+rip_apply_address_add (struct connected *ifc) {
+ struct prefix_ipv4 address;
+ struct prefix *p;
+
+ if (!rip)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix4;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv4(&address);
+
+ /* Check if this interface is RIP enabled or not
+ or Check if this address's prefix is RIP enabled */
+ 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);
+
+}
+
int
rip_interface_address_add (int command, struct zclient *zclient,
zebra_size_t length)
@@ -663,9 +696,9 @@
if (IS_RIP_DEBUG_ZEBRA)
zlog_info ("connected address %s/%d is added",
inet_ntoa (p->u.prefix4), p->prefixlen);
-
- /* Check is this interface is RIP enabled or not.*/
- rip_enable_apply (ifc->ifp);
+
+ /* Check if this prefix needs to be redistributed */
+ rip_apply_address_add(ifc);
#ifdef HAVE_SNMP
rip_ifaddr_add (ifc->ifp, ifc);
@@ -675,6 +708,29 @@
return 0;
}
+static void
+rip_apply_address_del (struct connected *ifc) {
+ struct prefix_ipv4 address;
+ struct prefix *p;
+
+ if (!rip)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix4;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv4(&address);
+
+ rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex);
+}
+
int
rip_interface_address_delete (int command, struct zclient *zclient,
zebra_size_t length)
@@ -698,8 +754,9 @@
rip_ifaddr_delete (ifc->ifp, ifc);
#endif /* HAVE_SNMP */
- /* Check if this interface is RIP enabled or not.*/
- rip_enable_apply (ifc->ifp);
+ /* Chech wether this prefix needs to be removed */
+ rip_apply_address_del(ifc);
+
}
connected_free (ifc);
@@ -710,8 +767,10 @@
}
/* Check interface is enabled by network statement. */
+/* Check wether the interface has at least a connected prefix that
+ * is within the ripng_enable_network table. */
int
-rip_enable_network_lookup (struct interface *ifp)
+rip_enable_network_lookup_if (struct interface *ifp)
{
struct listnode *nn;
struct connected *connected;
@@ -743,6 +802,34 @@
return -1;
}
+/* Check wether connected is within the ripng_enable_network table. */
+int
+rip_enable_network_lookup2 (struct connected *connected)
+{
+ struct prefix_ipv4 address;
+ struct prefix *p;
+
+ p = connected->address;
+
+ if (p->family == AF_INET) {
+ struct route_node *node;
+
+ address.family = p->family;
+ address.prefix = p->u.prefix4;
+ address.prefixlen = IPV4_MAX_BITLEN;
+
+ /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */
+ node = route_node_match (rip_enable_network,
+ (struct prefix *)&address);
+
+ if (node) {
+ route_unlock_node (node);
+ return 1;
+ }
+ }
+
+ return -1;
+}
/* Add RIP enable network. */
int
rip_enable_network_add (struct prefix *p)
@@ -759,6 +846,9 @@
else
node->info = "enabled";
+ /* XXX: One should find a better solution than a generic one */
+ rip_enable_apply_all();
+
return 1;
}
@@ -779,6 +869,9 @@
/* Unlock lookup lock. */
route_unlock_node (node);
+ /* XXX: One should find a better solution than a generic one */
+ rip_enable_apply_all ();
+
return 1;
}
return -1;
@@ -810,6 +903,8 @@
vector_set (rip_enable_interface, strdup (ifname));
+ rip_enable_apply_all(); /* TODOVJ */
+
return 1;
}
@@ -828,6 +923,8 @@
free (str);
vector_unset (rip_enable_interface, index);
+ rip_enable_apply_all(); /* TODOVJ */
+
return 1;
}
@@ -883,10 +980,13 @@
address.prefixlen = p->prefixlen;
apply_mask_ipv4 (&address);
- if (set)
- rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
- &address, connected->ifp->ifindex, NULL);
- else
+ if (set) {
+ /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
+ 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);
+ } else
{
rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
&address, connected->ifp->ifindex);
@@ -905,16 +1005,13 @@
struct rip_interface *ri = NULL;
/* Check interface. */
- if (if_is_loopback (ifp))
- return;
-
if (! if_is_operative (ifp))
return;
ri = ifp->info;
/* Check network configuration. */
- ret = rip_enable_network_lookup (ifp);
+ ret = rip_enable_network_lookup_if (ifp);
/* If the interface is matched. */
if (ret > 0)
@@ -939,7 +1036,6 @@
/* Update running status of the interface. */
if (ri->enable_network || ri->enable_interface)
{
- if (! ri->running)
{
if (IS_RIP_DEBUG_EVENT)
zlog_info ("turn on %s", ifp->name);
@@ -955,13 +1051,11 @@
{
if (ri->running)
{
- if (IS_RIP_DEBUG_EVENT)
- zlog_info ("turn off %s", ifp->name);
-
- /* Might as well clean up the route table as well */
+ /* Might as well clean up the route table as well
+ * rip_if_down sets to 0 ri->running, and displays "turn off %s"
+ **/
rip_if_down(ifp);
- ri->running = 0;
rip_connect_set (ifp, 0);
}
}
@@ -1181,8 +1275,6 @@
return CMD_WARNING;
}
- rip_enable_apply_all ();
-
return CMD_SUCCESS;
}
@@ -1212,8 +1304,6 @@
return CMD_WARNING;
}
- rip_enable_apply_all ();
-
return CMD_SUCCESS;
}
@@ -1661,10 +1751,15 @@
"Authentication key-chain\n"
"name of key-chain\n")
-DEFUN (rip_split_horizon,
- rip_split_horizon_cmd,
- "ip split-horizon",
+/* CHANGED: ip rip split-horizon
+ Cisco and Zebra's command is
+ ip split-horizon
+ */
+DEFUN (ip_rip_split_horizon,
+ ip_rip_split_horizon_cmd,
+ "ip rip split-horizon",
IP_STR
+ "Routing Information Protocol\n"
"Perform split horizon\n")
{
struct interface *ifp;
@@ -1673,15 +1768,38 @@
ifp = vty->index;
ri = ifp->info;
- ri->split_horizon = 1;
+ ri->split_horizon = RIP_SPLIT_HORIZON;
return CMD_SUCCESS;
}
-DEFUN (no_rip_split_horizon,
- no_rip_split_horizon_cmd,
- "no ip split-horizon",
+DEFUN (ip_rip_split_horizon_poisoned_reverse,
+ ip_rip_split_horizon_poisoned_reverse_cmd,
+ "ip rip split-horizon poisoned-reverse",
+ IP_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+{
+ struct interface *ifp;
+ struct rip_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE;
+ return CMD_SUCCESS;
+}
+
+/* CHANGED: no ip rip split-horizon
+ Cisco and Zebra's command is
+ no ip split-horizon
+ */
+DEFUN (no_ip_rip_split_horizon,
+ no_ip_rip_split_horizon_cmd,
+ "no ip rip split-horizon",
NO_STR
IP_STR
+ "Routing Information Protocol\n"
"Perform split horizon\n")
{
struct interface *ifp;
@@ -1690,10 +1808,19 @@
ifp = vty->index;
ri = ifp->info;
- ri->split_horizon = 0;
+ ri->split_horizon = RIP_NO_SPLIT_HORIZON;
return CMD_SUCCESS;
}
+ALIAS (no_ip_rip_split_horizon,
+ no_ip_rip_split_horizon_poisoned_reverse_cmd,
+ "no ip rip split-horizon poisoned-reverse",
+ NO_STR
+ IP_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+
DEFUN (rip_passive_interface,
rip_passive_interface_cmd,
"passive-interface IFNAME",
@@ -1727,6 +1854,18 @@
ifp = getdata (node);
ri = ifp->info;
+ /* Do not display the interface if there is no
+ * configuration about it.
+ **/
+ if ((!ifp->desc) &&
+ (ri->split_horizon == ri->split_horizon_default) &&
+ (ri->ri_send == RI_RIP_UNSPEC) &&
+ (ri->ri_receive == RI_RIP_UNSPEC) &&
+ (ri->auth_type != RIP_AUTH_MD5) &&
+ (!ri->auth_str) &&
+ (!ri->key_chain) )
+ continue;
+
vty_out (vty, "interface %s%s", ifp->name,
VTY_NEWLINE);
@@ -1737,10 +1876,19 @@
/* Split horizon. */
if (ri->split_horizon != ri->split_horizon_default)
{
- if (ri->split_horizon)
- vty_out (vty, " ip split-horizon%s", VTY_NEWLINE);
- else
- vty_out (vty, " no ip split-horizon%s", VTY_NEWLINE);
+ switch (ri->split_horizon) {
+ case RIP_SPLIT_HORIZON:
+ vty_out (vty, " ip rip split-horizon%s", VTY_NEWLINE);
+ break;
+ case RIP_SPLIT_HORIZON_POISONED_REVERSE:
+ vty_out (vty, " ip rip split-horizon poisoned-reverse%s",
+ VTY_NEWLINE);
+ break;
+ case RIP_NO_SPLIT_HORIZON:
+ default:
+ vty_out (vty, " no ip rip split-horizon%s", VTY_NEWLINE);
+ break;
+ }
}
/* RIP version setting. */
@@ -1837,6 +1985,7 @@
rip_interface_delete_hook (struct interface *ifp)
{
XFREE (MTYPE_RIP_INTERFACE, ifp->info);
+ ifp->info = NULL;
return 0;
}
@@ -1897,6 +2046,8 @@
install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd);
install_element (INTERFACE_NODE, &no_ip_rip_authentication_string2_cmd);
- install_element (INTERFACE_NODE, &rip_split_horizon_cmd);
- install_element (INTERFACE_NODE, &no_rip_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd);
+ install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd);
}
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index 8262f50..b354a89 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -31,6 +31,18 @@
#include "plist.h"
#include "ripd/ripd.h"
+
+struct rip_metric_modifier
+{
+ enum
+ {
+ metric_increment,
+ metric_decrement,
+ metric_absolute
+ } type;
+
+ u_char metric;
+};
/* Add rip route map rule. */
int
@@ -439,6 +451,57 @@
route_match_ip_address_prefix_list_compile,
route_match_ip_address_prefix_list_free
};
+
+/* `match tag TAG' */
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct rip_info *rinfo;
+
+ if (type == RMAP_RIP)
+ {
+ tag = rule;
+ rinfo = object;
+
+ /* The information stored by rinfo is host ordered. */
+ if (rinfo->tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+ }
+ return RMAP_NOMATCH;
+}
+
+/* Route map `match tag' match statement. `arg' is TAG value */
+void *
+route_match_tag_compile (char *arg)
+{
+ u_short *tag;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+ *tag = atoi (arg);
+
+ return tag;
+}
+
+/* Free route map's compiled `match tag' value. */
+void
+route_match_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for tag matching. */
+struct route_map_rule_cmd route_match_tag_cmd =
+{
+ "tag",
+ route_match_tag,
+ route_match_tag_compile,
+ route_match_tag_free
+};
/* `set metric METRIC' */
@@ -447,17 +510,26 @@
route_set_metric (void *rule, struct prefix *prefix,
route_map_object_t type, void *object)
{
- u_int32_t *metric;
- struct rip_info *rinfo;
-
if (type == RMAP_RIP)
{
- /* Fetch routemap's rule information. */
- metric = rule;
+ struct rip_metric_modifier *mod;
+ struct rip_info *rinfo;
+
+ mod = rule;
rinfo = object;
-
- /* Set metric out value. */
- rinfo->metric_out = *metric;
+
+ if (mod->type == metric_increment)
+ rinfo->metric_out += mod->metric;
+ else if (mod->type == metric_decrement)
+ rinfo->metric_out -= mod->metric;
+ else if (mod->type == metric_absolute)
+ rinfo->metric_out = mod->metric;
+
+ if (rinfo->metric_out < 1)
+ rinfo->metric_out = 1;
+ if (rinfo->metric_out > RIP_METRIC_INFINITY)
+ rinfo->metric_out = RIP_METRIC_INFINITY;
+
rinfo->metric_set = 1;
}
return RMAP_OKAY;
@@ -467,22 +539,51 @@
void *
route_set_metric_compile (char *arg)
{
- u_int32_t *metric;
+ int len;
+ char *pnt;
+ int type;
+ long metric;
+ char *endptr = NULL;
+ struct rip_metric_modifier *mod;
- metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
- *metric = atoi (arg);
+ len = strlen (arg);
+ pnt = arg;
- return metric;
+ if (len == 0)
+ return NULL;
-#if 0
- /* To make it consistent to other daemon, metric check is commented
- out.*/
- if (*metric >= 0 && *metric <= 16)
- return metric;
+ /* Examine first character. */
+ if (arg[0] == '+')
+ {
+ type = metric_increment;
+ pnt++;
+ }
+ else if (arg[0] == '-')
+ {
+ type = metric_decrement;
+ pnt++;
+ }
+ else
+ type = metric_absolute;
- XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
- return NULL;
-#endif /* 0 */
+ /* Check beginning with digit string. */
+ if (*pnt < '0' || *pnt > '9')
+ return NULL;
+
+ /* Convert string to integer. */
+ metric = strtol (pnt, &endptr, 10);
+
+ if (metric == LONG_MAX || *endptr != '\0')
+ return NULL;
+ if (metric < 0 || metric > RIP_METRIC_INFINITY)
+ return NULL;
+
+ mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+ sizeof (struct rip_metric_modifier));
+ mod->type = type;
+ mod->metric = metric;
+
+ return mod;
}
/* Free route map's compiled `set metric' value. */
@@ -560,6 +661,58 @@
route_set_ip_nexthop_compile,
route_set_ip_nexthop_free
};
+
+/* `set tag TAG' */
+
+/* Set tag to object. ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_tag (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_short *tag;
+ struct rip_info *rinfo;
+
+ if(type == RMAP_RIP)
+ {
+ /* Fetch routemap's rule information. */
+ tag = rule;
+ rinfo = object;
+
+ /* Set next hop value. */
+ rinfo->tag_out = *tag;
+ }
+
+ return RMAP_OKAY;
+}
+
+/* Route map `tag' compile function. Given string is converted
+ to u_short. */
+void *
+route_set_tag_compile (char *arg)
+{
+ u_short *tag;
+
+ tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
+ *tag = atoi (arg);
+
+ return tag;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_tag_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for tag set. */
+struct route_map_rule_cmd route_set_tag_cmd =
+{
+ "tag",
+ route_set_tag,
+ route_set_tag_compile,
+ route_set_tag_free
+};
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
@@ -777,14 +930,46 @@
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
+DEFUN (match_tag,
+ match_tag_cmd,
+ "match tag <0-65535>",
+ MATCH_STR
+ "Match tag of route\n"
+ "Metric value\n")
+{
+ return rip_route_match_add (vty, vty->index, "tag", argv[0]);
+}
+
+DEFUN (no_match_tag,
+ no_match_tag_cmd,
+ "no match tag",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n")
+{
+ if (argc == 0)
+ return rip_route_match_delete (vty, vty->index, "tag", NULL);
+
+ return rip_route_match_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_match_tag,
+ no_match_tag_val_cmd,
+ "no match tag <0-65535>",
+ NO_STR
+ MATCH_STR
+ "Match tag of route\n"
+ "Metric value\n")
+
/* set functions */
DEFUN (set_metric,
set_metric_cmd,
- "set metric <0-4294967295>",
+ "set metric (<0-4294967295>|<+/-metric>)",
SET_STR
"Metric value for destination routing protocol\n"
- "Metric value\n")
+ "Metric value\n"
+ "Add or subtract metric\n")
{
return rip_route_set_add (vty, vty->index, "metric", argv[0]);
}
@@ -804,11 +989,12 @@
ALIAS (no_set_metric,
no_set_metric_val_cmd,
- "no set metric <0-4294967295>",
+ "no set metric (<0-4294967295>|<+/-metric>)",
NO_STR
SET_STR
"Metric value for destination routing protocol\n"
- "Metric value\n")
+ "Metric value\n"
+ "Add or subtract metric\n")
DEFUN (set_ip_nexthop,
set_ip_nexthop_cmd,
@@ -854,6 +1040,37 @@
"Next hop address\n"
"IP address of next hop\n")
+DEFUN (set_tag,
+ set_tag_cmd,
+ "set tag <0-65535>",
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+{
+ return rip_route_set_add (vty, vty->index, "tag", argv[0]);
+}
+
+DEFUN (no_set_tag,
+ no_set_tag_cmd,
+ "no set tag",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n")
+{
+ if (argc == 0)
+ return rip_route_set_delete (vty, vty->index, "tag", NULL);
+
+ return rip_route_set_delete (vty, vty->index, "tag", argv[0]);
+}
+
+ALIAS (no_set_tag,
+ no_set_tag_val_cmd,
+ "no set tag <0-65535>",
+ NO_STR
+ SET_STR
+ "Tag value for routing protocol\n"
+ "Tag value\n")
+
void
rip_route_map_reset ()
{
@@ -875,9 +1092,11 @@
route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match (&route_match_ip_address_cmd);
route_map_install_match (&route_match_ip_address_prefix_list_cmd);
+ route_map_install_match (&route_match_tag_cmd);
route_map_install_set (&route_set_metric_cmd);
route_map_install_set (&route_set_ip_nexthop_cmd);
+ route_map_install_set (&route_set_tag_cmd);
install_element (RMAP_NODE, &match_metric_cmd);
install_element (RMAP_NODE, &no_match_metric_cmd);
@@ -897,6 +1116,9 @@
install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
+ install_element (RMAP_NODE, &match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_cmd);
+ install_element (RMAP_NODE, &no_match_tag_val_cmd);
install_element (RMAP_NODE, &set_metric_cmd);
install_element (RMAP_NODE, &no_set_metric_cmd);
@@ -904,4 +1126,7 @@
install_element (RMAP_NODE, &set_ip_nexthop_cmd);
install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
+ install_element (RMAP_NODE, &set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_cmd);
+ install_element (RMAP_NODE, &no_set_tag_val_cmd);
}
diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c
index b6caf3b..67d7b8b 100644
--- a/ripd/rip_zebra.c
+++ b/ripd/rip_zebra.c
@@ -502,6 +502,43 @@
return CMD_WARNING;
}
+DEFUN (rip_redistribute_type_metric_routemap,
+ rip_redistribute_type_metric_routemap_cmd,
+ "redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
+ "Redistribute information from another routing protocol\n"
+ "Kernel routes\n"
+ "Connected\n"
+ "Static routes\n"
+ "Open Shortest Path First (OSPF)\n"
+ "Border Gateway Protocol (BGP)\n"
+ "Metric\n"
+ "Metric value\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ int i;
+ int metric;
+
+ metric = atoi (argv[1]);
+
+ for (i = 0; redist_type[i].str; i++) {
+ if (strncmp(redist_type[i].str, argv[0],
+ redist_type[i].str_min_len) == 0)
+ {
+ rip_redistribute_metric_set (redist_type[i].type, metric);
+ rip_routemap_set (redist_type[i].type, argv[2]);
+ zclient_redistribute_set (zclient, redist_type[i].type);
+ return CMD_SUCCESS;
+ }
+ }
+
+ vty_out(vty, "Invalid type %s%s", argv[0],
+ VTY_NEWLINE);
+
+ return CMD_WARNING;
+}
+
+
DEFUN (no_rip_redistribute_type_metric_routemap,
no_rip_redistribute_type_metric_routemap_cmd,
"no redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
@@ -559,7 +596,7 @@
rip->default_information = 1;
- rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
+ rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, NULL);
}
return CMD_SUCCESS;
@@ -581,7 +618,7 @@
rip->default_information = 0;
- rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
+ rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0);
}
return CMD_SUCCESS;
@@ -682,6 +719,7 @@
install_element (RIP_NODE, &rip_redistribute_type_cmd);
install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);
install_element (RIP_NODE, &rip_redistribute_type_metric_cmd);
+ install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);
install_element (RIP_NODE, &no_rip_redistribute_type_cmd);
install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd);
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 62ebd47..c5d4553 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -32,6 +32,7 @@
#include "filter.h"
#include "sockunion.h"
#include "routemap.h"
+#include "if_rmap.h"
#include "plist.h"
#include "distribute.h"
#include "md5-gnu.h"
@@ -404,6 +405,40 @@
if (ret < 0)
return;
+ /* Modify entry according to the interface routemap. */
+ if (ri->routemap[RIP_FILTER_IN])
+ {
+ int ret;
+ struct rip_info newinfo;
+
+ memset (&newinfo, 0, sizeof (newinfo));
+ newinfo.type = ZEBRA_ROUTE_RIP;
+ newinfo.sub_type = RIP_ROUTE_RTE;
+ newinfo.nexthop= rte->nexthop;
+ newinfo.from = from->sin_addr;
+ newinfo.ifindex= ifp->ifindex;
+ newinfo.metric = rte->metric;
+ newinfo.metric_out = rte->metric; /* XXX */
+ newinfo.tag = ntohs(rte->tag); /* XXX */
+
+ /* The object should be of the type of rip_info */
+ ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
+ (struct prefix *)&p, RMAP_RIP, &newinfo);
+
+ if (ret == RMAP_DENYMATCH)
+ {
+ if (IS_RIP_DEBUG_PACKET)
+ zlog_info ("RIP %s/%d is filtered by route-map in",
+ inet_ntoa (p.prefix), p.prefixlen);
+ return;
+ }
+
+ /* Get back the object */
+ rte->nexthop = newinfo.nexthop_out;
+ rte->tag = htons(newinfo.tag_out); /* XXX */
+ rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
+ }
+
/* Once the entry has been validated, update the metric by
adding the cost of the network on wich the message
arrived. If the result is greater than infinity, use infinity
@@ -425,11 +460,11 @@
else
nexthop = &rte->nexthop;
- /* Check nexthop address. */
+ /* Check if nexthop address is myself, then do nothing. */
if (rip_nexthop_check (nexthop) < 0)
{
if (IS_RIP_DEBUG_PACKET)
- zlog_info ("Nexthop address %s is invalid", inet_ntoa (*nexthop));
+ zlog_info ("Nexthop address %s is myself", inet_ntoa (*nexthop));
return;
}
@@ -448,7 +483,8 @@
/* Local static route. */
if (rinfo->type == ZEBRA_ROUTE_RIP
- && rinfo->sub_type == RIP_ROUTE_STATIC
+ && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
+ (rinfo->sub_type == RIP_ROUTE_DEFAULT))
&& rinfo->metric != RIP_METRIC_INFINITY)
return;
}
@@ -514,7 +550,8 @@
to the address of the router from which the datagram came.
If this datagram is from the same router as the existing
route, reinitialize the timeout. */
- same = IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr);
+ same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
+ && (rinfo->ifindex == ifp->ifindex));
if (same)
rip_timeout_update (rinfo);
@@ -522,9 +559,10 @@
/* Next, compare the metrics. If the datagram is from the same
router as the existing route, and the new metric is different
than the old one; or, if the new metric is lower than the old
- one; do the following actions: */
+ one, or if the tag has been changed; do the following actions: */
if ((same && rinfo->metric != rte->metric) ||
- rte->metric < rinfo->metric)
+ (rte->metric < rinfo->metric) ||
+ (same && (rinfo->metric == rte->metric) && ntohs(rte->tag) != rinfo->tag))
{
/* - Adopt the route from the datagram. That is, put the
new metric in, and adjust the next hop address (if
@@ -1275,9 +1313,11 @@
/* Manually configured RIP route check. */
if (rinfo->type == ZEBRA_ROUTE_RIP
- && rinfo->sub_type == RIP_ROUTE_STATIC)
+ && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
+ (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
{
- if (type != ZEBRA_ROUTE_RIP || sub_type != RIP_ROUTE_STATIC)
+ if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
+ (sub_type != RIP_ROUTE_DEFAULT)))
{
route_unlock_node (rp);
return;
@@ -1312,6 +1352,18 @@
rinfo->flags |= RIP_RTF_CHANGED;
+ if (IS_RIP_DEBUG_EVENT) {
+ if (!nexthop)
+ zlog_info ("Redistribute new prefix %s/%d on the interface %s",
+ inet_ntoa(p->prefix), p->prefixlen,
+ ifindex2ifname(ifindex));
+ else
+ zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
+ inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
+ ifindex2ifname(ifindex));
+ }
+
+
rip_event (RIP_TRIGGERED_UPDATE, 0);
}
@@ -1345,6 +1397,11 @@
RIP_TIMER_OFF (rinfo->t_timeout);
rinfo->flags |= RIP_RTF_CHANGED;
+ if (IS_RIP_DEBUG_EVENT)
+ zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
+ inet_ntoa(p->prefix), p->prefixlen,
+ ifindex2ifname(ifindex));
+
rip_event (RIP_TRIGGERED_UPDATE, 0);
}
}
@@ -1362,7 +1419,14 @@
struct rip_info *rinfo;
struct rip_interface *ri;
+ /* Does not reponse to the requests on the loopback interfaces */
+ if (if_is_loopback (ifp))
+ return;
+
+ /* Check RIPng process is enabled on this interface. */
ri = ifp->info;
+ if (! ri->running)
+ return;
/* When passive interface is specified, suppress responses */
if (ri->passive)
@@ -1907,7 +1971,7 @@
masklen2ip (p->prefixlen, &mask);
stream_putw (s, AF_INET);
- stream_putw (s, rinfo->tag);
+ stream_putw (s, rinfo->tag_out);
stream_put_ipv4 (s, p->prefix.s_addr);
stream_put_ipv4 (s, mask.s_addr);
stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
@@ -2054,7 +2118,7 @@
/* Split horizon. */
/* if (split_horizon == rip_split_horizon) */
- if (ri->split_horizon)
+ if (ri->split_horizon == RIP_SPLIT_HORIZON)
{
/* We perform split horizon for RIP and connected route. */
if ((rinfo->type == ZEBRA_ROUTE_RIP ||
@@ -2067,23 +2131,36 @@
rinfo->metric_set = 0;
rinfo->nexthop_out.s_addr = 0;
rinfo->metric_out = rinfo->metric;
+ rinfo->tag_out = rinfo->tag;
rinfo->ifindex_out = ifp->ifindex;
- /* In order to avoid some local loops, if the RIP route has a
- nexthop via this interface, keep the nexthop, otherwise set
- it to 0. The nexthop should not be propagated beyond the
- local broadcast/multicast area in order to avoid an IGP
- multi-level recursive look-up. For RIP and connected
- route, we don't set next hop value automatically. For
- settting next hop to those routes, please use
- route-map. */
-
- if (rinfo->type != ZEBRA_ROUTE_RIP
- && rinfo->type != ZEBRA_ROUTE_CONNECT
- && rinfo->ifindex == ifp->ifindex)
+ /* In order to avoid some local loops,
+ * if the RIP route has a nexthop via this interface, keep the nexthop,
+ * otherwise set it to 0. The nexthop should not be propagated
+ * beyond the local broadcast/multicast area in order
+ * to avoid an IGP multi-level recursive look-up.
+ * see (4.4)
+ */
+ if (rinfo->ifindex == ifp->ifindex)
rinfo->nexthop_out = rinfo->nexthop;
+
+ /* Interface route-map */
+ if (ri->routemap[RIP_FILTER_OUT])
+ {
+ ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],
+ (struct prefix *) p, RMAP_RIP,
+ rinfo);
+
+ if (ret == RMAP_DENYMATCH)
+ {
+ if (IS_RIP_DEBUG_PACKET)
+ zlog_info ("RIP %s/%d is filtered by route-map out",
+ inet_ntoa (p->prefix), p->prefixlen);
+ continue;
+ }
+ }
- /* Apply route map - continue, if deny */
+ /* Apply redistribute route map - continue, if deny */
if (rip->route_map[rinfo->type].name
&& rinfo->sub_type != RIP_ROUTE_INTERFACE)
{
@@ -2125,7 +2202,17 @@
if (rinfo->metric_out > RIP_METRIC_INFINITY)
rinfo->metric_out = RIP_METRIC_INFINITY;
-
+
+ /* Perform split-horizon with poisoned reverse
+ * for RIP and connected routes.
+ **/
+ if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
+ if ((rinfo->type == ZEBRA_ROUTE_RIP ||
+ rinfo->type == ZEBRA_ROUTE_CONNECT) &&
+ rinfo->ifindex == ifp->ifindex)
+ rinfo->metric_out = RIP_METRIC_INFINITY;
+ }
+
/* Write RTE to the stream. */
num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);
if (num == rtemax)
@@ -2419,6 +2506,14 @@
RIP_TIMER_OFF (rinfo->t_timeout);
rinfo->flags |= RIP_RTF_CHANGED;
+ if (IS_RIP_DEBUG_EVENT) {
+ struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
+
+ zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
+ inet_ntoa(p->prefix), p->prefixlen,
+ ifindex2ifname(rinfo->ifindex));
+ }
+
rip_event (RIP_TRIGGERED_UPDATE, 0);
}
}
@@ -2775,6 +2870,17 @@
return CMD_SUCCESS;
}
+
+ALIAS (no_rip_timers,
+ no_rip_timers_val_cmd,
+ "no timers basic <0-65535> <0-65535> <0-65535>",
+ NO_STR
+ "Adjust routing timers\n"
+ "Basic routing protocol update timers\n"
+ "Routing table update timer value in second. Default is 30.\n"
+ "Routing information timeout timer. Default is 180.\n"
+ "Garbage collection timer. Default is 120.\n")
+
struct route_table *rip_distance_table;
@@ -3109,11 +3215,12 @@
if (! rip)
return CMD_SUCCESS;
- vty_out (vty, "Codes: R - RIP, C - connected, O - OSPF, B - BGP%s"
- " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
+ vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
+ "Sub-codes:%s"
+ " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
" (i) - interface%s%s"
- " Network Next Hop Metric From Time%s",
- VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
+ " Network Next Hop Metric From Tag Time%s",
+ VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
for (np = route_top (rip->table); np; np = route_next (np))
if ((rinfo = np->info) != NULL)
@@ -3126,7 +3233,7 @@
rip_route_type_print (rinfo->sub_type),
inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
- len = 24 - len;
+ len = 21 - len;
if (len > 0)
vty_out (vty, "%*s", len, " ");
@@ -3142,15 +3249,20 @@
(rinfo->sub_type == RIP_ROUTE_RTE))
{
vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
+ vty_out (vty, "%3d ", rinfo->tag);
rip_vty_out_uptime (vty, rinfo);
}
else if (rinfo->metric == RIP_METRIC_INFINITY)
{
vty_out (vty, "self ");
+ vty_out (vty, "%3d ", rinfo->tag);
rip_vty_out_uptime (vty, rinfo);
}
else
- vty_out (vty, "self");
+ {
+ vty_out (vty, "self ");
+ vty_out (vty, "%3d", rinfo->tag);
+ }
vty_out (vty, "%s", VTY_NEWLINE);
}
@@ -3168,11 +3280,13 @@
return thread->u.sands.tv_sec - timer_now.tv_sec;
}
-DEFUN (show_ip_protocols_rip,
- show_ip_protocols_rip_cmd,
- "show ip protocols",
+/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
+DEFUN (show_ip_rip_status,
+ show_ip_rip_status_cmd,
+ "show ip rip status",
SHOW_STR
IP_STR
+ "Show RIP routes\n"
"IP routing protocol process parameters and statistics\n")
{
listnode node;
@@ -3307,6 +3421,9 @@
/* Distribute configuration. */
write += config_write_distribute (vty);
+ /* Interface routemap configuration */
+ write += config_write_if_rmap (vty);
+
/* Distance configuration. */
if (rip->distance)
vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE);
@@ -3538,6 +3655,83 @@
rip_zclient_reset ();
}
+void
+rip_if_rmap_update (struct if_rmap *if_rmap)
+{
+ struct interface *ifp;
+ struct rip_interface *ri;
+ struct route_map *rmap;
+
+ ifp = if_lookup_by_name (if_rmap->ifname);
+ if (ifp == NULL)
+ return;
+
+ ri = ifp->info;
+
+ if (if_rmap->routemap[IF_RMAP_IN])
+ {
+ rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
+ if (rmap)
+ ri->routemap[IF_RMAP_IN] = rmap;
+ else
+ ri->routemap[IF_RMAP_IN] = NULL;
+ }
+ else
+ ri->routemap[RIP_FILTER_IN] = NULL;
+
+ if (if_rmap->routemap[IF_RMAP_OUT])
+ {
+ rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
+ if (rmap)
+ ri->routemap[IF_RMAP_OUT] = rmap;
+ else
+ ri->routemap[IF_RMAP_OUT] = NULL;
+ }
+ else
+ ri->routemap[RIP_FILTER_OUT] = NULL;
+}
+
+void
+rip_if_rmap_update_interface (struct interface *ifp)
+{
+ struct if_rmap *if_rmap;
+
+ if_rmap = if_rmap_lookup (ifp->name);
+ if (if_rmap)
+ rip_if_rmap_update (if_rmap);
+}
+
+void
+rip_routemap_update_redistribute (void)
+{
+ int i;
+
+ if (rip)
+ {
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ {
+ if (rip->route_map[i].name)
+ rip->route_map[i].map =
+ route_map_lookup_by_name (rip->route_map[i].name);
+ }
+ }
+}
+
+void
+rip_routemap_update ()
+{
+ struct interface *ifp;
+ listnode node;
+
+ for (node = listhead (iflist); node; nextnode (node))
+ {
+ ifp = getdata (node);
+ rip_if_rmap_update_interface (ifp);
+ }
+
+ rip_routemap_update_redistribute ();
+}
+
/* Allocate new rip structure and set default value. */
void
rip_init ()
@@ -3550,9 +3744,9 @@
/* Install rip commands. */
install_element (VIEW_NODE, &show_ip_rip_cmd);
- install_element (VIEW_NODE, &show_ip_protocols_rip_cmd);
+ install_element (VIEW_NODE, &show_ip_rip_status_cmd);
install_element (ENABLE_NODE, &show_ip_rip_cmd);
- install_element (ENABLE_NODE, &show_ip_protocols_rip_cmd);
+ install_element (ENABLE_NODE, &show_ip_rip_status_cmd);
install_element (CONFIG_NODE, &router_rip_cmd);
install_element (CONFIG_NODE, &no_router_rip_cmd);
@@ -3565,6 +3759,7 @@
install_element (RIP_NODE, &no_rip_default_metric_val_cmd);
install_element (RIP_NODE, &rip_timers_cmd);
install_element (RIP_NODE, &no_rip_timers_cmd);
+ install_element (RIP_NODE, &no_rip_timers_val_cmd);
install_element (RIP_NODE, &rip_route_cmd);
install_element (RIP_NODE, &no_rip_route_cmd);
install_element (RIP_NODE, &rip_distance_cmd);
@@ -3577,10 +3772,6 @@
/* Debug related init. */
rip_debug_init ();
- /* Filter related init. */
- rip_route_map_init ();
- rip_offset_init ();
-
/* SNMP init. */
#ifdef HAVE_SNMP
rip_snmp_init ();
@@ -3601,6 +3792,17 @@
distribute_list_add_hook (rip_distribute_update);
distribute_list_delete_hook (rip_distribute_update);
+ /* Route-map */
+ rip_route_map_init ();
+ rip_offset_init ();
+
+ route_map_add_hook (rip_routemap_update);
+ route_map_delete_hook (rip_routemap_update);
+
+ if_rmap_init (RIP_NODE);
+ if_rmap_hook_add (rip_if_rmap_update);
+ if_rmap_hook_delete (rip_if_rmap_update);
+
/* Distance control. */
rip_distance_table = route_table_init ();
}
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 112e1cb..260ea46 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -199,6 +199,7 @@
struct in_addr nexthop_out;
u_char metric_set;
u_int32_t metric_out;
+ u_short tag_out;
unsigned int ifindex_out;
struct route_node *rp;
@@ -211,6 +212,12 @@
#endif /* NEW_RIP_TABLE */
};
+typedef enum {
+ RIP_NO_SPLIT_HORIZON = 0,
+ RIP_SPLIT_HORIZON,
+ RIP_SPLIT_HORIZON_POISONED_REVERSE
+} split_horizon_policy_t;
+
/* RIP specific interface configuration. */
struct rip_interface
{
@@ -239,8 +246,8 @@
char *key_chain;
/* Split horizon flag. */
- int split_horizon;
- int split_horizon_default;
+ split_horizon_policy_t split_horizon;
+ split_horizon_policy_t split_horizon_default;
/* For filter type slot. */
#define RIP_FILTER_IN 0
@@ -253,6 +260,9 @@
/* Prefix-list. */
struct prefix_list *prefix[RIP_FILTER_MAX];
+ /* Route-map. */
+ struct route_map *routemap[RIP_FILTER_MAX];
+
/* Wake up thread. */
struct thread *t_wakeup;
@@ -369,6 +379,7 @@
void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t);
void rip_interface_multicast_set (int, struct interface *);
void rip_distribute_update_interface (struct interface *);
+void rip_if_rmap_update_interface (struct interface *);
int config_write_rip_network (struct vty *, int);
int config_write_rip_offset_list (struct vty *);