+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
ripd_SOURCES = \
rip_main.c $(librip_a_SOURCES)
-ripd_LDADD = ../lib/libzebra.a
+ripd_LDADD = -L../lib -lzebra
sysconf_DATA = ripd.conf.sample
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[] =
{
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;
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);
}
/* rip_request_neighbor_all (); */
+ /* Check interface routemap. */
+ rip_if_rmap_update_interface (ifp);
+
return 0;
}
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;
}
}
+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)
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);
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)
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);
}
\f
/* 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;
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)
else
node->info = "enabled";
+ /* XXX: One should find a better solution than a generic one */
+ rip_enable_apply_all();
+
return 1;
}
/* 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;
vector_set (rip_enable_interface, strdup (ifname));
+ rip_enable_apply_all(); /* TODOVJ */
+
return 1;
}
free (str);
vector_unset (rip_enable_interface, index);
+ rip_enable_apply_all(); /* TODOVJ */
+
return 1;
}
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);
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)
/* 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);
{
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);
}
}
return CMD_WARNING;
}
- rip_enable_apply_all ();
-
return CMD_SUCCESS;
}
return CMD_WARNING;
}
- rip_enable_apply_all ();
-
return CMD_SUCCESS;
}
"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;
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;
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",
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);
/* 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. */
rip_interface_delete_hook (struct interface *ifp)
{
XFREE (MTYPE_RIP_INTERFACE, ifp->info);
+ ifp->info = NULL;
return 0;
}
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);
}
#include "plist.h"
#include "ripd/ripd.h"
+\f
+struct rip_metric_modifier
+{
+ enum
+ {
+ metric_increment,
+ metric_decrement,
+ metric_absolute
+ } type;
+
+ u_char metric;
+};
/* Add rip route map rule. */
int
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
+};
\f
/* `set metric METRIC' */
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;
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. */
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
+};
\f
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
"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]);
}
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,
"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 ()
{
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);
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);
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);
}
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",
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;
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;
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);
#include "filter.h"
#include "sockunion.h"
#include "routemap.h"
+#include "if_rmap.h"
#include "plist.h"
#include "distribute.h"
#include "md5-gnu.h"
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
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;
}
/* 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;
}
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);
/* 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
/* 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;
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);
}
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);
}
}
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)
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);
/* 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 ||
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)
{
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)
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);
}
}
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")
+
\f
struct route_table *rip_distance_table;
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)
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, " ");
(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);
}
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;
/* 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);
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 ()
/* 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);
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);
/* Debug related init. */
rip_debug_init ();
- /* Filter related init. */
- rip_route_map_init ();
- rip_offset_init ();
-
/* SNMP init. */
#ifdef HAVE_SNMP
rip_snmp_init ();
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 ();
}
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;
#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
{
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
/* 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;
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 *);