Ripngd part of 6Wind patch.
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index 369c3d6..b4299eb 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -49,6 +49,9 @@
/* Static utility function. */
static void ripng_enable_apply (struct interface *);
static void ripng_passive_interface_apply (struct interface *);
+int ripng_enable_if_lookup (char *ifname);
+int ripng_enable_network_lookup2 (struct connected *connected);
+void ripng_enable_apply_all ();
/* Join to the all rip routers multicast group. */
int
@@ -57,19 +60,23 @@
int ret;
struct ipv6_mreq mreq;
- memset (&mreq, 0, sizeof (mreq));
- inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
- mreq.ipv6mr_interface = ifp->ifindex;
+ if (if_is_up (ifp) && if_is_multicast (ifp)) {
+ memset (&mreq, 0, sizeof (mreq));
+ inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
+ mreq.ipv6mr_interface = ifp->ifindex;
- ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- (char *) &mreq, sizeof (mreq));
- if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno));
+ ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (char *) &mreq, sizeof (mreq));
+ if (ret < 0)
+ zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", strerror (errno));
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng %s join to all-rip-routers multicast group", ifp->name);
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_info ("RIPng %s join to all-rip-routers multicast group", ifp->name);
- return ret;
+ if (ret < 0)
+ return -1;
+ }
+ return 0;
}
/* Leave from the all rip routers multicast group. */
@@ -79,20 +86,46 @@
int ret;
struct ipv6_mreq mreq;
- memset (&mreq, 0, sizeof (mreq));
- inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
- mreq.ipv6mr_interface = ifp->ifindex;
+ if (if_is_up (ifp) && if_is_multicast (ifp)) {
+ memset (&mreq, 0, sizeof (mreq));
+ inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
+ mreq.ipv6mr_interface = ifp->ifindex;
- ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- (char *) &mreq, sizeof (mreq));
- if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", strerror (errno));
+ ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ (char *) &mreq, sizeof (mreq));
+ if (ret < 0)
+ zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", strerror (errno));
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng %s leave from all-rip-routers multicast group",
- ifp->name);
+ if (IS_RIPNG_DEBUG_EVENT)
+ zlog_info ("RIPng %s leave from all-rip-routers multicast group",
+ ifp->name);
- return ret;
+ if (ret < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* How many link local IPv6 address could be used on the interface ? */
+int
+ripng_if_ipv6_lladdress_check (struct interface *ifp)
+{
+ struct listnode *nn;
+ struct connected *connected;
+ int count = 0;
+
+ for (nn = listhead (ifp->connected); nn; nextnode (nn))
+ if ((connected = getdata (nn)) != NULL) {
+ struct prefix *p;
+ p = connected->address;
+
+ if ((p->family == AF_INET6) &&
+ IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
+ count++;
+ }
+
+ return count;
}
/* Check max mtu size. */
@@ -120,7 +153,7 @@
struct ripng_info *rinfo;
struct ripng_interface *ri;
- if (ripng->table)
+ if (ripng)
{
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
if ((rinfo = rp->info) != NULL)
@@ -134,18 +167,17 @@
&rinfo->nexthop,
rinfo->ifindex);
- RIPNG_TIMER_OFF (rinfo->t_timeout);
- RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
-
- rp->info = NULL;
- route_unlock_node (rp);
-
- ripng_info_free (rinfo);
+ ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
+ (struct prefix_ipv6 *)&rp->p,
+ rinfo->ifindex);
}
else
{
- /* All redistributed routes got through this interface. */
- if (rinfo->ifindex == ifp->ifindex)
+ /* All redistributed routes got through this interface,
+ * but the static and system ones are kept. */
+ if ((rinfo->ifindex == ifp->ifindex) &&
+ (rinfo->type != ZEBRA_ROUTE_STATIC) &&
+ (rinfo->type != ZEBRA_ROUTE_SYSTEM))
ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
(struct prefix_ipv6 *) &rp->p,
rinfo->ifindex);
@@ -155,7 +187,7 @@
ri = ifp->info;
- if (ripng && ri->running)
+ if (ri->running)
{
if (IS_RIPNG_DEBUG_EVENT)
zlog_info ("turn off %s", ifp->name);
@@ -251,16 +283,121 @@
ripng_interface_delete (int command, struct zclient *zclient,
zebra_size_t length)
{
+ struct interface *ifp;
+ struct stream *s;
+
+ s = zclient->ibuf;
+ /* zebra_interface_state_read() updates interface structure in iflist */
+ ifp = zebra_interface_state_read(s);
+
+ if (ifp == NULL)
+ return 0;
+
+ if (if_is_up (ifp)) {
+ ripng_if_down(ifp);
+ }
+
+ zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
+ ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+
+ /* To support pseudo interface do not free interface structure. */
+ /* if_delete(ifp); */
+
return 0;
}
+void
+ripng_interface_clean ()
+{
+ listnode node;
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ for (node = listhead (iflist); node; nextnode (node))
+ {
+ ifp = getdata (node);
+ ri = ifp->info;
+
+ ri->enable_network = 0;
+ ri->enable_interface = 0;
+ ri->running = 0;
+
+ if (ri->t_wakeup)
+ {
+ thread_cancel (ri->t_wakeup);
+ ri->t_wakeup = NULL;
+ }
+ }
+}
+
+void
+ripng_interface_reset () {
+ listnode node;
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ for (node = listhead (iflist); node; nextnode (node))
+ {
+ ifp = getdata (node);
+ ri = ifp->info;
+
+ ri->enable_network = 0;
+ ri->enable_interface = 0;
+ ri->running = 0;
+
+ ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
+ ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
+
+ ri->list[RIPNG_FILTER_IN] = NULL;
+ ri->list[RIPNG_FILTER_OUT] = NULL;
+
+ ri->prefix[RIPNG_FILTER_IN] = NULL;
+ ri->prefix[RIPNG_FILTER_OUT] = NULL;
+
+ if (ri->t_wakeup)
+ {
+ thread_cancel (ri->t_wakeup);
+ ri->t_wakeup = NULL;
+ }
+
+ ri->passive = 0;
+ }
+}
+
+static void
+ripng_apply_address_add (struct connected *ifc) {
+ struct prefix_ipv6 address;
+ struct prefix *p;
+
+ if (!ripng)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv6(&address);
+
+ /* Check if this interface is RIP enabled or not
+ or Check if this address's prefix is RIP enabled */
+ if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
+ (ripng_enable_network_lookup2(ifc) >= 0))
+ ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex, NULL);
+
+}
+
int
ripng_interface_address_add (int command, struct zclient *zclient,
zebra_size_t length)
{
struct connected *c;
struct prefix *p;
- char buf[INET6_ADDRSTRLEN];
c = zebra_interface_address_add_read (zclient->ibuf);
@@ -273,16 +410,56 @@
{
if (IS_RIPNG_DEBUG_ZEBRA)
zlog_info ("RIPng connected address %s/%d add",
- inet_ntop (AF_INET6, &p->u.prefix6, buf, INET6_ADDRSTRLEN),
+ inet6_ntop(&p->u.prefix6),
p->prefixlen);
- /* Check is this interface is RIP enabled or not.*/
- ripng_enable_apply (c->ifp);
+ /* Check is this prefix needs to be redistributed. */
+ ripng_apply_address_add(c);
+
+ /* Let's try once again whether the interface could be activated */
+ if (c->ifp) {
+ struct ripng_interface *ri = c->ifp->info;
+
+ if (!ri->running) {
+ /* Check if this interface is RIP enabled or not.*/
+ ripng_enable_apply (c->ifp);
+
+ /* Apply distribute list to the interface. */
+ ripng_distribute_update_interface (c->ifp);
+
+ /* Check interface routemap. */
+ ripng_if_rmap_update_interface (c->ifp);
+ }
+ }
+
}
return 0;
}
+static void
+ripng_apply_address_del (struct connected *ifc) {
+ struct prefix_ipv6 address;
+ struct prefix *p;
+
+ if (!ripng)
+ return;
+
+ if (! if_is_up(ifc->ifp))
+ return;
+
+ p = ifc->address;
+
+ memset (&address, 0, sizeof (address));
+ address.family = p->family;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv6(&address);
+
+ ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, ifc->ifp->ifindex);
+}
+
int
ripng_interface_address_delete (int command, struct zclient *zclient,
zebra_size_t length)
@@ -305,8 +482,8 @@
INET6_ADDRSTRLEN),
p->prefixlen);
- /* Check is this interface is RIP enabled or not.*/
- ripng_enable_apply (ifc->ifp);
+ /* Check wether this prefix needs to be removed. */
+ ripng_apply_address_del(ifc);
}
connected_free (ifc);
}
@@ -321,11 +498,14 @@
struct route_table *ripng_enable_network;
/* Lookup RIPng enable network. */
+/* Check wether the interface has at least a connected prefix that
+ * is within the ripng_enable_network table. */
int
-ripng_enable_network_lookup (struct interface *ifp)
+ripng_enable_network_lookup_if (struct interface *ifp)
{
listnode listnode;
struct connected *connected;
+ struct prefix_ipv6 address;
for (listnode = listhead (ifp->connected); listnode; nextnode (listnode))
if ((connected = getdata (listnode)) != NULL)
@@ -337,7 +517,12 @@
if (p->family == AF_INET6)
{
- node = route_node_match (ripng_enable_network, p);
+ address.family = AF_INET6;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = IPV6_MAX_BITLEN;
+
+ node = route_node_match (ripng_enable_network,
+ (struct prefix *)&address);
if (node)
{
route_unlock_node (node);
@@ -348,6 +533,35 @@
return -1;
}
+/* Check wether connected is within the ripng_enable_network table. */
+int
+ripng_enable_network_lookup2 (struct connected *connected)
+{
+ struct prefix_ipv6 address;
+ struct prefix *p;
+
+ p = connected->address;
+
+ if (p->family == AF_INET6) {
+ struct route_node *node;
+
+ address.family = p->family;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = IPV6_MAX_BITLEN;
+
+ /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
+ node = route_node_match (ripng_enable_network,
+ (struct prefix *)&address);
+
+ if (node) {
+ route_unlock_node (node);
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
/* Add RIPng enable network. */
int
ripng_enable_network_add (struct prefix *p)
@@ -364,6 +578,9 @@
else
node->info = "enabled";
+ /* XXX: One should find a better solution than a generic one */
+ ripng_enable_apply_all();
+
return 1;
}
@@ -415,6 +632,8 @@
vector_set (ripng_enable_if, strdup (ifname));
+ ripng_enable_apply_all();
+
return 1;
}
@@ -433,6 +652,8 @@
free (str);
vector_unset (ripng_enable_if, index);
+ ripng_enable_apply_all();
+
return 1;
}
@@ -450,7 +671,13 @@
ri->t_wakeup = NULL;
/* Join to multicast group. */
- ripng_multicast_join (ifp);
+ if (ripng_multicast_join (ifp) < 0) {
+ zlog_err ("multicast join failed, interface %s not running", ifp->name);
+ return 0;
+ }
+
+ /* Set running flag. */
+ ri->running = 1;
/* Send RIP request to the interface. */
ripng_request (ifp);
@@ -458,6 +685,44 @@
return 0;
}
+int ripng_redistribute_check (int);
+
+void
+ripng_connect_set (struct interface *ifp, int set)
+{
+ struct listnode *nn;
+ struct connected *connected;
+ struct prefix_ipv6 address;
+
+ for (nn = listhead (ifp->connected); nn; nextnode (nn))
+ if ((connected = getdata (nn)) != NULL) {
+ struct prefix *p;
+ p = connected->address;
+
+ if (p->family != AF_INET6)
+ continue;
+
+ address.family = AF_INET6;
+ address.prefix = p->u.prefix6;
+ address.prefixlen = p->prefixlen;
+ apply_mask_ipv6 (&address);
+
+ if (set) {
+ /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
+ if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
+ (ripng_enable_network_lookup2(connected) >= 0))
+ ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, connected->ifp->ifindex, NULL);
+ } else {
+ ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
+ &address, connected->ifp->ifindex);
+ if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
+ ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
+ &address, connected->ifp->ifindex, NULL);
+ }
+ }
+}
+
/* Check RIPng is enabed on this interface. */
void
ripng_enable_apply (struct interface *ifp)
@@ -466,16 +731,13 @@
struct ripng_interface *ri = NULL;
/* Check interface. */
- if (if_is_loopback (ifp))
- return;
-
if (! if_is_up (ifp))
return;
ri = ifp->info;
- /* Check network configuration. */
- ret = ripng_enable_network_lookup (ifp);
+ /* Is this interface a candidate for RIPng ? */
+ ret = ripng_enable_network_lookup_if (ifp);
/* If the interface is matched. */
if (ret > 0)
@@ -490,10 +752,18 @@
else
ri->enable_interface = 0;
+ /* any candidate interface MUST have a link-local IPv6 address */
+ if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
+ (ri->enable_network || ri->enable_interface)) {
+ ri->enable_network = 0;
+ ri->enable_interface = 0;
+ zlog_warn("Interface %s does not have any link-local address",
+ ifp->name);
+ }
+
/* Update running status of the interface. */
if (ri->enable_network || ri->enable_interface)
{
- if (! ri->running)
{
if (IS_RIPNG_DEBUG_EVENT)
zlog_info ("RIPng turn on %s", ifp->name);
@@ -502,34 +772,26 @@
if (! ri->t_wakeup)
ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
ifp, 1);
-#if 0
- /* Join to multicast group. */
- ripng_multicast_join (ifp);
- /* Send RIP request to the interface. */
- ripng_request (ifp);
-#endif /* 0 */
-
- ri->running = 1;
+ ripng_connect_set (ifp, 1);
}
}
else
{
if (ri->running)
{
- if (IS_RIPNG_DEBUG_EVENT)
- zlog_info ("RIPng turn off %s", ifp->name);
+ /* Might as well clean up the route table as well
+ * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
+ **/
+ ripng_if_down(ifp);
- /* Leave from multicast group. */
- ripng_multicast_leave (ifp);
-
- ri->running = 0;
+ ripng_connect_set (ifp, 0);
}
}
}
/* Set distribute list to all interfaces. */
-static void
+void
ripng_enable_apply_all ()
{
struct interface *ifp;
@@ -542,6 +804,29 @@
}
}
+/* Clear all network and neighbor configuration */
+void
+ripng_clean_network ()
+{
+ int i;
+ char *str;
+ struct route_node *rn;
+
+ /* ripng_enable_network */
+ for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
+ if (rn->info) {
+ rn->info = NULL;
+ route_unlock_node(rn);
+ }
+
+ /* ripng_enable_if */
+ for (i = 0; i < vector_max (ripng_enable_if); i++)
+ if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
+ free (str);
+ vector_slot (ripng_enable_if, i) = NULL;
+ }
+}
+
/* Vector to store passive-interface name. */
vector Vripng_passive_interface;
@@ -638,10 +923,9 @@
/* Write RIPng enable network and interface to the vty. */
int
-ripng_network_write (struct vty *vty)
+ripng_network_write (struct vty *vty, int config_mode)
{
int i;
- char *str;
char *ifname;
struct route_node *node;
char buf[BUFSIZ];
@@ -651,7 +935,8 @@
if (node->info)
{
struct prefix *p = &node->p;
- vty_out (vty, " network %s/%d%s",
+ vty_out (vty, "%s%s/%d%s",
+ config_mode ? " network " : " ",
inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
p->prefixlen,
VTY_NEWLINE);
@@ -660,14 +945,17 @@
/* Write enable interface. */
for (i = 0; i < vector_max (ripng_enable_if); i++)
- if ((str = vector_slot (ripng_enable_if, i)) != NULL)
- vty_out (vty, " network %s%s", str,
+ if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
+ vty_out (vty, "%s%s%s",
+ config_mode ? " network " : " ",
+ ifname,
VTY_NEWLINE);
/* Write passive interface. */
- for (i = 0; i < vector_max (Vripng_passive_interface); i++)
- if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
- vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
+ if (config_mode)
+ for (i = 0; i < vector_max (Vripng_passive_interface); i++)
+ if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
+ vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
return 0;
}
@@ -697,8 +985,6 @@
return CMD_WARNING;
}
- ripng_enable_apply_all ();
-
return CMD_SUCCESS;
}
@@ -728,11 +1014,71 @@
return CMD_WARNING;
}
- ripng_enable_apply_all ();
-
return CMD_SUCCESS;
}
+DEFUN (ipv6_ripng_split_horizon,
+ ipv6_ripng_split_horizon_cmd,
+ "ipv6 ripng split-horizon",
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n")
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIPNG_SPLIT_HORIZON;
+ return CMD_SUCCESS;
+}
+
+DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
+ ipv6_ripng_split_horizon_poisoned_reverse_cmd,
+ "ipv6 ripng split-horizon poisoned-reverse",
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_ripng_split_horizon,
+ no_ipv6_ripng_split_horizon_cmd,
+ "no ipv6 ripng split-horizon",
+ NO_STR
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n")
+{
+ struct interface *ifp;
+ struct ripng_interface *ri;
+
+ ifp = vty->index;
+ ri = ifp->info;
+
+ ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_ipv6_ripng_split_horizon,
+ no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
+ "no ipv6 ripng split-horizon poisoned-reverse",
+ NO_STR
+ IPV6_STR
+ "Routing Information Protocol\n"
+ "Perform split horizon\n"
+ "With poisoned-reverse\n")
+
DEFUN (ripng_passive_interface,
ripng_passive_interface_cmd,
"passive-interface IFNAME",
@@ -757,6 +1103,14 @@
{
struct ripng_interface *ri;
ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
+
+ /* Set default split-horizon behavior. If the interface is Frame
+ 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 = RIPNG_SPLIT_HORIZON;
+ ri->split_horizon = ri->split_horizon_default;
+
return ri;
}
@@ -767,6 +1121,15 @@
return 0;
}
+/* Called when interface structure deleted. */
+int
+ripng_if_delete_hook (struct interface *ifp)
+{
+ XFREE (MTYPE_IF, ifp->info);
+ ifp->info = NULL;
+ return 0;
+}
+
/* Configuration write function for ripngd. */
int
interface_config_write (struct vty *vty)
@@ -781,12 +1144,37 @@
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))
+ continue;
+
vty_out (vty, "interface %s%s", ifp->name,
VTY_NEWLINE);
if (ifp->desc)
vty_out (vty, " description %s%s", ifp->desc,
VTY_NEWLINE);
+ /* Split horizon. */
+ if (ri->split_horizon != ri->split_horizon_default)
+ {
+ switch (ri->split_horizon) {
+ case RIPNG_SPLIT_HORIZON:
+ vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
+ break;
+ case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
+ vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
+ VTY_NEWLINE);
+ break;
+ case RIPNG_NO_SPLIT_HORIZON:
+ default:
+ vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
+ break;
+ }
+ }
+
vty_out (vty, "!%s", VTY_NEWLINE);
write++;
@@ -799,6 +1187,7 @@
{
INTERFACE_NODE,
"%s(config-if)# ",
+ 1 /* VTYSH */
};
/* Initialization of interface. */
@@ -808,6 +1197,7 @@
/* Interface initialize. */
iflist = list_new ();
if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
+ if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
/* RIPng enable network init. */
ripng_enable_network = route_table_init ();
@@ -820,12 +1210,11 @@
/* Install interface node. */
install_node (&interface_node, interface_config_write);
-
+
+ /* Install commands. */
install_element (CONFIG_NODE, &interface_cmd);
install_element (CONFIG_NODE, &no_interface_cmd);
- install_element (INTERFACE_NODE, &config_end_cmd);
- install_element (INTERFACE_NODE, &config_exit_cmd);
- install_element (INTERFACE_NODE, &config_help_cmd);
+ install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
@@ -833,4 +1222,9 @@
install_element (RIPNG_NODE, &no_ripng_network_cmd);
install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
+
+ install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
}