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

View File

@ -266,8 +266,8 @@ struct nbr_connected
extern int if_cmp_func (struct interface *, struct interface *); extern int if_cmp_func (struct interface *, struct interface *);
extern struct interface *if_create (const char *name, int namelen); extern struct interface *if_create (const char *name, int namelen);
extern struct interface *if_lookup_by_index (unsigned int); extern struct interface *if_lookup_by_index (unsigned int);
extern struct interface *if_lookup_exact_address (struct in_addr); extern struct interface *if_lookup_exact_address (void *matchaddr, int family);
extern struct interface *if_lookup_address (struct in_addr); extern struct interface *if_lookup_address (void *matchaddr, int family);
extern struct interface *if_lookup_prefix (struct prefix *prefix); extern struct interface *if_lookup_prefix (struct prefix *prefix);
extern struct connected *if_anchor_lookup_by_address (struct in_addr src); 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, /* Handle cases where the platform does not support retrieving the ifindex,
and also platforms (such as Solaris 8) that claim to support ifindex and also platforms (such as Solaris 8) that claim to support ifindex
retrieval but do not. */ retrieval but do not. */
ifp = if_lookup_address (iph->ip_src); ifp = if_lookup_address ((void *)&iph->ip_src, AF_INET);
if (ifp == NULL) if (ifp == NULL)
return 0; 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); 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 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 /* The datagram's IPv4 source address should be checked to see
whether the datagram is from a valid neighbor; the source of the 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) */ 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", zlog_info ("This datagram doesn't came from a valid neighbor: %s",
inet_ntoa (from->sin_addr)); inet_ntoa (from->sin_addr));
@ -1211,7 +1211,7 @@ rip_response_process (struct rip_packet *packet, int size,
continue; continue;
} }
if (! if_lookup_address (rte->nexthop)) if (! if_lookup_address ((void *)&rte->nexthop, AF_INET))
{ {
struct route_node *rn; struct route_node *rn;
struct rip_info *rinfo; struct rip_info *rinfo;
@ -1843,7 +1843,7 @@ rip_read (struct thread *t)
} }
/* Which interface is this packet comes from. */ /* 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 */ /* RIP packet received */
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
@ -2525,7 +2525,7 @@ rip_update_process (int route_type)
{ {
p = (struct prefix_ipv4 *) &rp->p; p = (struct prefix_ipv4 *) &rp->p;
ifp = if_lookup_address (p->prefix); ifp = if_lookup_address ((void *)&p->prefix, AF_INET);
if (! ifp) if (! ifp)
{ {
zlog_warn ("Neighbor %s doesnt have connected interface!", 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; 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 static int
is_default (struct prefix *p) is_default (struct prefix *p)
{ {

View File

@ -46,8 +46,6 @@ extern void zebra_interface_address_add_update (struct interface *,
struct connected *); struct connected *);
extern void zebra_interface_address_delete_update (struct interface *, extern void zebra_interface_address_delete_update (struct interface *,
struct connected *c); struct connected *c);
extern int zebra_check_addr (struct prefix *);
extern int zebra_import_table (afi_t afi, u_int32_t table_id, extern int zebra_import_table (afi_t afi, u_int32_t table_id,
u_int32_t metric, int add); 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); u_int32_t vrf_id);
extern int is_zebra_valid_kernel_table(u_int32_t table_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 is_zebra_main_routing_table(u_int32_t table_id);
extern int zebra_check_addr (struct prefix *p);
/* NOTE: /* NOTE:
* All rib_add_ipv[46]* functions will not just add prefix into RIB, but * 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, addattr_l (nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv4, bytelen); &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, addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->rmap_src.ipv4, bytelen); &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, addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->src.ipv4, bytelen); &nexthop->src.ipv4, bytelen);
}
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): " zlog_debug("netlink_route_multipath() (%s): "
@ -1535,6 +1538,16 @@ _netlink_route_build_singlepath(
addattr_l (nlmsg, req_size, RTA_GATEWAY, addattr_l (nlmsg, req_size, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen); &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) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): " zlog_debug("netlink_route_multipath() (%s): "
"nexthop via %s if %u", "nexthop via %s if %u",
@ -1549,12 +1562,15 @@ _netlink_route_build_singlepath(
{ {
addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); 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, addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->rmap_src.ipv4, bytelen); &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, addattr_l (nlmsg, req_size, RTA_PREFSRC,
&nexthop->src.ipv4, bytelen); &nexthop->src.ipv4, bytelen);
}
if (IS_ZEBRA_DEBUG_KERNEL) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): " zlog_debug("netlink_route_multipath() (%s): "
@ -1566,6 +1582,16 @@ _netlink_route_build_singlepath(
{ {
addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); 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) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): " zlog_debug("netlink_route_multipath() (%s): "
"nexthop via if %u", routedesc, nexthop->ifindex); "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, rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
&nexthop->gate.ipv6, bytelen); &nexthop->gate.ipv6, bytelen);
rtnh->rtnh_len += sizeof (struct rtattr) + 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) if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("netlink_route_multipath() (%s): " zlog_debug("netlink_route_multipath() (%s): "
"nexthop via %s if %u", "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)) if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
{ {
/* This only works for IPv4 now */
if (!setsrc) if (!setsrc)
{
if (family == AF_INET)
{ {
if (nexthop->rmap_src.ipv4.s_addr != 0) 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; 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; continue;
} }
@ -1897,7 +1944,12 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
} }
} }
if (setsrc && (cmd == RTM_NEWROUTE)) if (setsrc && (cmd == RTM_NEWROUTE))
{
if (family == AF_INET)
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); 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 else
{ {
@ -1920,6 +1972,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
{ {
/* This only works for IPv4 now */ /* This only works for IPv4 now */
if (!setsrc) if (!setsrc)
{
if (family == AF_INET)
{ {
if (nexthop->rmap_src.ipv4.s_addr != 0) 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; 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; continue;
} }
@ -1954,13 +2022,23 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
if (!setsrc && src1) if (!setsrc && src1)
{ {
if (family == AF_INET)
src.ipv4 = src1->ipv4; src.ipv4 = src1->ipv4;
else if (family == AF_INET6)
src.ipv6 = src1->ipv6;
setsrc = 1; setsrc = 1;
} }
} }
} }
if (setsrc && (cmd == RTM_NEWROUTE)) if (setsrc && (cmd == RTM_NEWROUTE))
{
if (family == AF_INET)
addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); 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)) if (rta->rta_len > RTA_LENGTH (0))
addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), 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; 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. */ /* Add nexthop to the end of a nexthop list. */
static void static void
_nexthop_add (struct nexthop **target, struct nexthop *nexthop) _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); UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
} }
return CHECK_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 || prev_index != nexthop->ifindex ||
((nexthop->type >= NEXTHOP_TYPE_IFINDEX && ((nexthop->type >= NEXTHOP_TYPE_IFINDEX &&
nexthop->type < NEXTHOP_TYPE_IPV6) && 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->flags, ZEBRA_FLAG_CHANGED);
SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);

View File

@ -648,21 +648,46 @@ DEFUN (no_match_source_protocol,
DEFUN (set_src, DEFUN (set_src,
set_src_cmd, set_src_cmd,
"set src A.B.C.D", "set src (A.B.C.D|X:X::X:X)",
SET_STR SET_STR
"src address for route\n" "src address for route\n"
"src address\n") "src address\n")
{ {
struct in_addr src; union g_addr src;
struct interface *pif; 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; 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) if (!pif)
{ {
vty_out (vty, "%% not a local address%s", VTY_NEWLINE); vty_out (vty, "%% not a local address%s", VTY_NEWLINE);
@ -673,7 +698,7 @@ DEFUN (set_src,
DEFUN (no_set_src, DEFUN (no_set_src,
no_set_src_cmd, no_set_src_cmd,
"no set src", "no set src {A.B.C.D|X:X::X:X}",
NO_STR NO_STR
SET_STR SET_STR
"Source address for route\n") "Source address for route\n")
@ -684,14 +709,6 @@ DEFUN (no_set_src,
return zebra_route_set_delete (vty, vty->index, "src", argv[0]); 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, DEFUN (zebra_route_map_timer,
zebra_route_map_timer_cmd, zebra_route_map_timer_cmd,
"zebra route-map delay-timer <0-600>", "zebra route-map delay-timer <0-600>",
@ -822,6 +839,112 @@ DEFUN (show_ip_protocol,
return CMD_SUCCESS; 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, DEFUN (ip_protocol_nht_rmap,
ip_protocol_nht_rmap_cmd, ip_protocol_nht_rmap_cmd,
"ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", "ip nht " QUAGGA_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP",
@ -1413,17 +1536,17 @@ route_set_src_compile (const char *arg)
{ {
union g_addr src, *psrc; union g_addr src, *psrc;
if (inet_pton(AF_INET, arg, &src.ipv4) != 1 if (
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
&& inet_pton(AF_INET6, arg, &src.ipv6) != 1 (inet_pton(AF_INET6, arg, &src.ipv6) == 1) ||
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
) (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1)))
return NULL; {
psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr)); psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr));
*psrc = src; *psrc = src;
return psrc; return psrc;
}
return NULL;
} }
/* Free route map's compiled `set src' value. */ /* Free route map's compiled `set src' value. */
@ -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), vty_out (vty, "ip protocol %s route-map %s%s", zebra_route_string(i),
proto_rm[AFI_IP][i], VTY_NEWLINE); 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]) if (nht_rm[AFI_IP][i])
vty_out (vty, "ip nht %s route-map %s%s", zebra_route_string(i), vty_out (vty, "ip nht %s route-map %s%s", zebra_route_string(i),
nht_rm[AFI_IP][i], VTY_NEWLINE); 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", vty_out (vty, "ip protocol %s route-map %s%s", "any",
proto_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE); 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]) if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX])
vty_out (vty, "ip nht %s route-map %s%s", "any", vty_out (vty, "ip nht %s route-map %s%s", "any",
nht_rm[AFI_IP][ZEBRA_ROUTE_MAX], VTY_NEWLINE); 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 (CONFIG_NODE, &no_ip_protocol_val_cmd);
install_element (VIEW_NODE, &show_ip_protocol_cmd); install_element (VIEW_NODE, &show_ip_protocol_cmd);
install_element (ENABLE_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, &ip_protocol_nht_rmap_cmd);
install_element (CONFIG_NODE, &no_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); install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_val_cmd);