Zebra: Add IPv6 protocol filtering support & Setting Src of IPv6 routes

Ticket:
Reviewed By: CCR-3335
Testing Done: bgpsmoke, ENHE tests etc.

    Add support for filtering routes from upper layer protocols to zebra
    via route-maps for IPv6. The same functionality already existed for
    IPv4.

    In addition, add support for setting source of routes via IPv6 protocol
    map.

    Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
    Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
    Reviewed-by: Vivek Venkataraman <vivek@cumulusnetworks.com>
    Reviewed-by: Vipin Kumar <vipin@cumulusnetworks.com>
This commit is contained in:
Dinesh G Dutt 2015-09-15 23:48:00 -07:00
parent 3a8c7ba1ec
commit 0aabccc0a8
11 changed files with 345 additions and 113 deletions

View File

@ -257,7 +257,7 @@ if_lookup_by_name_len(const char *name, size_t namelen)
/* Lookup interface by IPv4 address. */
struct interface *
if_lookup_exact_address (struct in_addr src)
if_lookup_exact_address (void *src, int family)
{
struct listnode *node;
struct listnode *cnode;
@ -271,11 +271,19 @@ if_lookup_exact_address (struct in_addr src)
{
p = c->address;
if (p && p->family == AF_INET)
if (p && (p->family == family))
{
if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
if (family == AF_INET)
{
if (IPV4_ADDR_SAME (&p->u.prefix4, (struct in_addr *)src))
return ifp;
}
else if (family == AF_INET6)
{
if (IPV6_ADDR_SAME (&p->u.prefix4, (struct in6_addr *)src))
return ifp;
}
}
}
}
return NULL;
@ -283,7 +291,7 @@ if_lookup_exact_address (struct in_addr src)
/* Lookup interface by IPv4 address. */
struct interface *
if_lookup_address (struct in_addr src)
if_lookup_address (void *matchaddr, int family)
{
struct listnode *node;
struct prefix addr;
@ -293,9 +301,18 @@ if_lookup_address (struct in_addr src)
struct connected *c;
struct interface *match;
if (family == AF_INET)
{
addr.family = AF_INET;
addr.u.prefix4 = src;
addr.u.prefix4 = *((struct in_addr *)matchaddr);
addr.prefixlen = IPV4_MAX_BITLEN;
}
else if (family == AF_INET6)
{
addr.family = AF_INET6;
addr.u.prefix6 = *((struct in6_addr *)matchaddr);
addr.prefixlen = IPV6_MAX_BITLEN;
}
match = NULL;

View File

@ -266,8 +266,8 @@ struct nbr_connected
extern int if_cmp_func (struct interface *, struct interface *);
extern struct interface *if_create (const char *name, int namelen);
extern struct interface *if_lookup_by_index (unsigned int);
extern struct interface *if_lookup_exact_address (struct in_addr);
extern struct interface *if_lookup_address (struct in_addr);
extern struct interface *if_lookup_exact_address (void *matchaddr, int family);
extern struct interface *if_lookup_address (void *matchaddr, int family);
extern struct interface *if_lookup_prefix (struct prefix *prefix);
extern struct connected *if_anchor_lookup_by_address (struct in_addr src);

View File

@ -2811,7 +2811,7 @@ ospf_read (struct thread *thread)
/* Handle cases where the platform does not support retrieving the ifindex,
and also platforms (such as Solaris 8) that claim to support ifindex
retrieval but do not. */
ifp = if_lookup_address (iph->ip_src);
ifp = if_lookup_address ((void *)&iph->ip_src, AF_INET);
if (ifp == NULL)
return 0;

View File

@ -255,7 +255,7 @@ rip2IfLookup (struct variable *v, oid name[], size_t *length,
oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
return if_lookup_exact_address (*addr);
return if_lookup_exact_address ((void *)addr, AF_INET);
}
else
{

View File

@ -1125,7 +1125,7 @@ rip_response_process (struct rip_packet *packet, int size,
/* The datagram's IPv4 source address should be checked to see
whether the datagram is from a valid neighbor; the source of the
datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */
if (if_lookup_address(from->sin_addr) == NULL)
if (if_lookup_address((void *)&from->sin_addr, AF_INET) == NULL)
{
zlog_info ("This datagram doesn't came from a valid neighbor: %s",
inet_ntoa (from->sin_addr));
@ -1211,7 +1211,7 @@ rip_response_process (struct rip_packet *packet, int size,
continue;
}
if (! if_lookup_address (rte->nexthop))
if (! if_lookup_address ((void *)&rte->nexthop, AF_INET))
{
struct route_node *rn;
struct rip_info *rinfo;
@ -1843,7 +1843,7 @@ rip_read (struct thread *t)
}
/* Which interface is this packet comes from. */
ifp = if_lookup_address (from.sin_addr);
ifp = if_lookup_address ((void *)&from.sin_addr, AF_INET);
/* RIP packet received */
if (IS_RIP_DEBUG_EVENT)
@ -2525,7 +2525,7 @@ rip_update_process (int route_type)
{
p = (struct prefix_ipv4 *) &rp->p;
ifp = if_lookup_address (p->prefix);
ifp = if_lookup_address ((void *)&p->prefix, AF_INET);
if (! ifp)
{
zlog_warn ("Neighbor %s doesnt have connected interface!",

View File

@ -62,33 +62,6 @@ is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id)
return 0;
}
int
zebra_check_addr (struct prefix *p)
{
if (p->family == AF_INET)
{
u_int32_t addr;
addr = p->u.prefix4.s_addr;
addr = ntohl (addr);
if (IPV4_NET127 (addr)
|| IN_CLASSD (addr)
|| IPV4_LINKLOCAL(addr))
return 0;
}
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
{
if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6))
return 0;
if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
return 0;
}
#endif /* HAVE_IPV6 */
return 1;
}
static int
is_default (struct prefix *p)
{

View File

@ -46,8 +46,6 @@ extern void zebra_interface_address_add_update (struct interface *,
struct connected *);
extern void zebra_interface_address_delete_update (struct interface *,
struct connected *c);
extern int zebra_check_addr (struct prefix *);
extern int zebra_import_table (afi_t afi, u_int32_t table_id,
u_int32_t metric, int add);

View File

@ -393,6 +393,7 @@ extern struct route_table *vrf_other_route_table (afi_t afi, u_int32_t table_id,
u_int32_t vrf_id);
extern int is_zebra_valid_kernel_table(u_int32_t table_id);
extern int is_zebra_main_routing_table(u_int32_t table_id);
extern int zebra_check_addr (struct prefix *p);
/* NOTE:
* All rib_add_ipv[46]* functions will not just add prefix into RIB, but

View File

@ -1513,12 +1513,15 @@ _netlink_route_build_singlepath(
addattr_l (nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv4, bytelen);
if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
if (cmd == RTM_NEWROUTE)
{
if (nexthop->rmap_src.ipv4.s_addr)
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->rmap_src.ipv4, bytelen);
else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
else if (nexthop->src.ipv4.s_addr)
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->src.ipv4, bytelen);
}
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): "
@ -1535,6 +1538,16 @@ _netlink_route_build_singlepath(
addattr_l (nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen);
if (cmd == RTM_NEWROUTE)
{
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->rmap_src.ipv6, bytelen);
else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->src.ipv6, bytelen);
}
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): "
"nexthop via %s if %u",
@ -1549,12 +1562,15 @@ _netlink_route_build_singlepath(
{
addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
if (cmd == RTM_NEWROUTE)
{
if (nexthop->rmap_src.ipv4.s_addr)
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->rmap_src.ipv4, bytelen);
else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE))
else if (nexthop->src.ipv4.s_addr)
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->src.ipv4, bytelen);
}
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): "
@ -1566,6 +1582,16 @@ _netlink_route_build_singlepath(
{
addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (cmd == RTM_NEWROUTE)
{
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->rmap_src.ipv6, bytelen);
else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->src.ipv6, bytelen);
}
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): "
"nexthop via if %u", routedesc, nexthop->ifindex);
@ -1657,6 +1683,12 @@ _netlink_route_build_multipath(
rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen);
rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
*src = &nexthop->rmap_src;
else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
*src = &nexthop->src;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): "
"nexthop via %s if %u",
@ -1860,8 +1892,9 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
{
/* This only works for IPv4 now */
if (!setsrc)
{
if (family == AF_INET)
{
if (nexthop->rmap_src.ipv4.s_addr != 0)
{
@ -1874,6 +1907,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
setsrc = 1;
}
}
else if (family == AF_INET6)
{
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
{
src.ipv6 = nexthop->rmap_src.ipv6;
setsrc = 1;
}
else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
{
src.ipv6 = nexthop->src.ipv6;
setsrc = 1;
}
}
}
continue;
}
@ -1897,7 +1944,12 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
}
}
if (setsrc && (cmd == RTM_NEWROUTE))
{
if (family == AF_INET)
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
else if (family == AF_INET6)
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
}
}
else
{
@ -1920,6 +1972,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
{
/* This only works for IPv4 now */
if (!setsrc)
{
if (family == AF_INET)
{
if (nexthop->rmap_src.ipv4.s_addr != 0)
{
@ -1932,6 +1986,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
setsrc = 1;
}
}
else if (family == AF_INET6)
{
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
{
src.ipv6 = nexthop->rmap_src.ipv6;
setsrc = 1;
}
else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
{
src.ipv6 = nexthop->src.ipv6;
setsrc = 1;
}
}
}
continue;
}
@ -1954,13 +2022,23 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
if (!setsrc && src1)
{
if (family == AF_INET)
src.ipv4 = src1->ipv4;
else if (family == AF_INET6)
src.ipv6 = src1->ipv6;
setsrc = 1;
}
}
}
if (setsrc && (cmd == RTM_NEWROUTE))
{
if (family == AF_INET)
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen);
else if (family == AF_INET6)
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen);
zlog_debug("Setting source");
}
if (rta->rta_len > RTA_LENGTH (0))
addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta),

View File

@ -231,6 +231,33 @@ is_zebra_main_routing_table(u_int32_t table_id)
return 0;
}
int
zebra_check_addr (struct prefix *p)
{
if (p->family == AF_INET)
{
u_int32_t addr;
addr = p->u.prefix4.s_addr;
addr = ntohl (addr);
if (IPV4_NET127 (addr)
|| IN_CLASSD (addr)
|| IPV4_LINKLOCAL(addr))
return 0;
}
#ifdef HAVE_IPV6
if (p->family == AF_INET6)
{
if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6))
return 0;
if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
return 0;
}
#endif /* HAVE_IPV6 */
return 1;
}
/* Add nexthop to the end of a nexthop list. */
static void
_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
@ -1298,7 +1325,6 @@ nexthop_active_check (struct route_node *rn, struct rib *rib,
}
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
@ -1336,7 +1362,10 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
prev_index != nexthop->ifindex ||
((nexthop->type >= NEXTHOP_TYPE_IFINDEX &&
nexthop->type < NEXTHOP_TYPE_IPV6) &&
prev_src.ipv4.s_addr != nexthop->rmap_src.ipv4.s_addr))
prev_src.ipv4.s_addr != nexthop->rmap_src.ipv4.s_addr) ||
((nexthop->type >= NEXTHOP_TYPE_IPV6 &&
nexthop->type < NEXTHOP_TYPE_BLACKHOLE) &&
!(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6))))
{
SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);

View File

@ -648,21 +648,46 @@ DEFUN (no_match_source_protocol,
DEFUN (set_src,
set_src_cmd,
"set src A.B.C.D",
"set src (A.B.C.D|X:X::X:X)",
SET_STR
"src address for route\n"
"src address\n")
{
struct in_addr src;
struct interface *pif;
union g_addr src;
struct interface *pif = NULL;
int family;
struct prefix p;
if (inet_pton(AF_INET, argv[0], &src) <= 0)
if (inet_pton(AF_INET, argv[0], &src.ipv4) != 1)
{
vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
if (inet_pton(AF_INET6, argv[0], &src.ipv6) != 1)
{
vty_out (vty, "%% not a valid IPv4/v6 address%s", VTY_NEWLINE);
return CMD_WARNING;
}
pif = if_lookup_exact_address (src);
p.family = family = AF_INET6;
p.u.prefix6 = src.ipv6;
p.prefixlen = IPV6_MAX_BITLEN;
}
else
{
p.family = family = AF_INET;
p.u.prefix4 = src.ipv4;
p.prefixlen = IPV4_MAX_BITLEN;
}
if (!zebra_check_addr(&p))
{
vty_out (vty, "%% not a valid source IPv4/v6 address%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (family == AF_INET)
pif = if_lookup_exact_address ((void *)&src.ipv4, AF_INET);
else if (family == AF_INET6)
pif = if_lookup_exact_address ((void *)&src.ipv6, AF_INET6);
if (!pif)
{
vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
@ -673,7 +698,7 @@ DEFUN (set_src,
DEFUN (no_set_src,
no_set_src_cmd,
"no set src",
"no set src {A.B.C.D|X:X::X:X}",
NO_STR
SET_STR
"Source address for route\n")
@ -684,14 +709,6 @@ DEFUN (no_set_src,
return zebra_route_set_delete (vty, vty->index, "src", argv[0]);
}
ALIAS (no_set_src,
no_set_src_val_cmd,
"no set src (A.B.C.D)",
NO_STR
SET_STR
"src address for route\n"
"src address\n")
DEFUN (zebra_route_map_timer,
zebra_route_map_timer_cmd,
"zebra route-map delay-timer <0-600>",
@ -822,6 +839,112 @@ DEFUN (show_ip_protocol,
return CMD_SUCCESS;
}
DEFUN (ipv6_protocol,
ipv6_protocol_cmd,
"ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
IP6_STR
"Filter IPv6 routing info exchanged between zebra and protocol\n"
QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"Route map name\n")
{
int i;
u_int32_t table_id;
if (strcasecmp(argv[0], "any") == 0)
i = ZEBRA_ROUTE_MAX;
else
i = proto_name2num(argv[0]);
if (i < 0)
{
vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
VTY_NEWLINE);
return CMD_WARNING;
}
if (proto_rm[AFI_IP6][i])
{
if (strcmp(proto_rm[AFI_IP6][i], argv[1]) == 0)
return CMD_SUCCESS;
XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
}
proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]);
rib_update();
return CMD_SUCCESS;
}
DEFUN (no_ipv6_protocol,
no_ipv6_protocol_cmd,
"no ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA,
NO_STR
IP6_STR
"Stop filtering IPv6 routing info between zebra and protocol\n"
QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"Protocol from which to stop filtering routes\n")
{
int i;
u_int32_t table_id;
if (strcasecmp(argv[0], "any") == 0)
i = ZEBRA_ROUTE_MAX;
else
i = proto_name2num(argv[0]);
if (i < 0)
{
vty_out (vty, "invalid protocol name \"%s\"%s", argv[0] ? argv[0] : "",
VTY_NEWLINE);
return CMD_WARNING;
}
if (!proto_rm[AFI_IP6][i])
return CMD_SUCCESS;
if ((argc == 2 && strcmp(argv[1], proto_rm[AFI_IP6][i]) == 0) ||
(argc < 2))
{
XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]);
proto_rm[AFI_IP6][i] = NULL;
rib_update();
}
return CMD_SUCCESS;
}
ALIAS (no_ipv6_protocol,
no_ipv6_protocol_val_cmd,
"no ipv6 protocol " QUAGGA_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
NO_STR
IP6_STR
"Stop filtering IPv6 routing info between zebra and protocol\n"
QUAGGA_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
"route map name")
DEFUN (show_ipv6_protocol,
show_ipv6_protocol_cmd,
"show ipv6 protocol",
SHOW_STR
IP6_STR
"IPv6 protocol filtering status\n")
{
int i;
vty_out(vty, "Protocol : route-map %s", VTY_NEWLINE);
vty_out(vty, "------------------------%s", VTY_NEWLINE);
for (i=0;i<ZEBRA_ROUTE_MAX;i++)
{
if (proto_rm[AFI_IP6][i])
vty_out (vty, "%-10s : %-10s%s", zebra_route_string(i),
proto_rm[AFI_IP6][i],
VTY_NEWLINE);
else
vty_out (vty, "%-10s : none%s", zebra_route_string(i), VTY_NEWLINE);
}
if (proto_rm[AFI_IP6][i])
vty_out (vty, "%-10s : %-10s%s", "any", proto_rm[AFI_IP6][i],
VTY_NEWLINE);
else
vty_out (vty, "%-10s : none%s", "any", VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN (ip_protocol_nht_rmap,
ip_protocol_nht_rmap_cmd,
"ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
@ -1413,18 +1536,18 @@ route_set_src_compile (const char *arg)
{
union g_addr src, *psrc;
if (inet_pton(AF_INET, arg, &src.ipv4) != 1
if (
#ifdef HAVE_IPV6
&& inet_pton(AF_INET6, arg, &src.ipv6) != 1
(inet_pton(AF_INET6, arg, &src.ipv6) == 1) ||
#endif /* HAVE_IPV6 */
)
return NULL;
(src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1)))
{
psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
*psrc = src;
return psrc;
}
return NULL;
}
/* Free route map's compiled `set src' value. */
static void
@ -1570,6 +1693,10 @@ zebra_routemap_config_write_protocol (struct vty *vty)
vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
proto_rm[AFI_IP][i], VTY_NEWLINE);
if (proto_rm[AFI_IP6][i])
vty_out (vty, "ipv6 protocol %s route-map %s%s", zebra_route_string(i),
proto_rm[AFI_IP6][i], VTY_NEWLINE);
if (nht_rm[AFI_IP][i])
vty_out (vty, "ip nht %s route-map %s%s", zebra_route_string(i),
nht_rm[AFI_IP][i], VTY_NEWLINE);
@ -1583,6 +1710,10 @@ zebra_routemap_config_write_protocol (struct vty *vty)
vty_out (vty, "ip protocol %s route-map %s%s", "any",
proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX])
vty_out (vty, "ipv6 protocol %s route-map %s%s", "any",
proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
vty_out (vty, "ip nht %s route-map %s%s", "any",
nht_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE);
@ -1604,6 +1735,11 @@ zebra_route_map_init ()
install_element (CONFIG_NODE, &no_ip_protocol_val_cmd);
install_element (VIEW_NODE, &show_ip_protocol_cmd);
install_element (ENABLE_NODE, &show_ip_protocol_cmd);
install_element (CONFIG_NODE, &ipv6_protocol_cmd);
install_element (CONFIG_NODE, &no_ipv6_protocol_cmd);
install_element (CONFIG_NODE, &no_ipv6_protocol_val_cmd);
install_element (VIEW_NODE, &show_ipv6_protocol_cmd);
install_element (ENABLE_NODE, &show_ipv6_protocol_cmd);
install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_val_cmd);