forked from Mirror/frr
zebra: cleanup blackhole support
blackhole support was horribly broken. cleanup by removing blackhole stuff from ZEBRA_FLAG_* introduces support for "prohibit" routes (Linux/netlink only) also clean up blackhole options on "ip route" vty commands. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
fd36be7e15
commit
a830942228
|
@ -76,7 +76,10 @@ struct nexthop {
|
||||||
#define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */
|
#define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */
|
||||||
|
|
||||||
/* Nexthop address */
|
/* Nexthop address */
|
||||||
union g_addr gate;
|
union {
|
||||||
|
union g_addr gate;
|
||||||
|
enum blackhole_type bh_type;
|
||||||
|
};
|
||||||
union g_addr src;
|
union g_addr src;
|
||||||
union g_addr rmap_src; /* Src is set via routemap */
|
union g_addr rmap_src; /* Src is set via routemap */
|
||||||
|
|
||||||
|
|
|
@ -404,13 +404,13 @@ extern const char *zserv_command_string(unsigned int command);
|
||||||
/* Zebra message flags */
|
/* Zebra message flags */
|
||||||
#define ZEBRA_FLAG_INTERNAL 0x01
|
#define ZEBRA_FLAG_INTERNAL 0x01
|
||||||
#define ZEBRA_FLAG_SELFROUTE 0x02
|
#define ZEBRA_FLAG_SELFROUTE 0x02
|
||||||
#define ZEBRA_FLAG_BLACKHOLE 0x04
|
|
||||||
#define ZEBRA_FLAG_IBGP 0x08
|
#define ZEBRA_FLAG_IBGP 0x08
|
||||||
#define ZEBRA_FLAG_SELECTED 0x10
|
#define ZEBRA_FLAG_SELECTED 0x10
|
||||||
#define ZEBRA_FLAG_STATIC 0x40
|
#define ZEBRA_FLAG_STATIC 0x40
|
||||||
#define ZEBRA_FLAG_REJECT 0x80
|
|
||||||
#define ZEBRA_FLAG_SCOPE_LINK 0x100
|
#define ZEBRA_FLAG_SCOPE_LINK 0x100
|
||||||
#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
|
#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
|
||||||
|
/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
|
||||||
|
/* ZEBRA_FLAG_REJECT was 0x80 */
|
||||||
|
|
||||||
/* Zebra FEC flags. */
|
/* Zebra FEC flags. */
|
||||||
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
|
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
|
||||||
|
|
|
@ -887,11 +887,15 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||||
if (flags & RTF_STATIC)
|
if (flags & RTF_STATIC)
|
||||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
|
SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
|
||||||
|
|
||||||
|
memset(&nh, 0, sizeof(nh));
|
||||||
/* This is a reject or blackhole route */
|
/* This is a reject or blackhole route */
|
||||||
if (flags & RTF_REJECT)
|
if (flags & RTF_REJECT) {
|
||||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_REJECT);
|
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
||||||
if (flags & RTF_BLACKHOLE)
|
nh.bh_type = BLACKHOLE_REJECT;
|
||||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_BLACKHOLE);
|
} else if (flags & RTF_BLACKHOLE) {
|
||||||
|
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
||||||
|
nh.bh_type = BLACKHOLE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (dest.sa.sa_family == AF_INET) {
|
if (dest.sa.sa_family == AF_INET) {
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
|
@ -1017,11 +1021,12 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||||
if (rtm->rtm_type == RTM_CHANGE)
|
if (rtm->rtm_type == RTM_CHANGE)
|
||||||
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
|
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
|
||||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
|
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
|
||||||
NULL, 0, 0);
|
NULL, NULL, 0, 0);
|
||||||
|
|
||||||
memset(&nh, 0, sizeof(nh));
|
if (!nh.type) {
|
||||||
nh.type = NEXTHOP_TYPE_IPV4;
|
nh.type = NEXTHOP_TYPE_IPV4;
|
||||||
nh.gate.ipv4 = gate.sin;
|
nh.gate.ipv4 = gate.sin.sin_addr;
|
||||||
|
}
|
||||||
|
|
||||||
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
||||||
|| rtm->rtm_type == RTM_CHANGE)
|
|| rtm->rtm_type == RTM_CHANGE)
|
||||||
|
@ -1064,11 +1069,12 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
|
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
|
||||||
NULL, NULL, 0, 0);
|
NULL, NULL, 0, 0);
|
||||||
|
|
||||||
memset(&nh, 0, sizeof(nh));
|
if (!nh.type) {
|
||||||
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
|
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
|
||||||
: NEXTHOP_TYPE_IPV6;
|
: NEXTHOP_TYPE_IPV6;
|
||||||
nh.gate.ipv6 = gate.sin6;
|
nh.gate.ipv6 = gate.sin6.sin6_addr;
|
||||||
nh.ifindex = ifindex;
|
nh.ifindex = ifindex;
|
||||||
|
}
|
||||||
|
|
||||||
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
||||||
|| rtm->rtm_type == RTM_CHANGE)
|
|| rtm->rtm_type == RTM_CHANGE)
|
||||||
|
@ -1088,7 +1094,7 @@ void rtm_read(struct rt_msghdr *rtm)
|
||||||
*/
|
*/
|
||||||
int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
||||||
union sockunion *gate, union sockunion *mpls, unsigned int index,
|
union sockunion *gate, union sockunion *mpls, unsigned int index,
|
||||||
int zebra_flags, int metric)
|
enum blackhole_type bh_type, int metric)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
caddr_t pnt;
|
caddr_t pnt;
|
||||||
|
@ -1178,11 +1184,16 @@ int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
||||||
/* Tagging route with flags */
|
/* Tagging route with flags */
|
||||||
msg.rtm.rtm_flags |= (RTF_PROTO1);
|
msg.rtm.rtm_flags |= (RTF_PROTO1);
|
||||||
|
|
||||||
/* Additional flags. */
|
switch (bh_type) {
|
||||||
if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
|
case BLACKHOLE_UNSPEC:
|
||||||
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
break;
|
||||||
if (zebra_flags & ZEBRA_FLAG_REJECT)
|
case BLACKHOLE_REJECT:
|
||||||
msg.rtm.rtm_flags |= RTF_REJECT;
|
msg.rtm.rtm_flags |= RTF_REJECT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define SOCKADDRSET(X, R) \
|
#define SOCKADDRSET(X, R) \
|
||||||
|
|
|
@ -34,8 +34,8 @@ extern void rtm_read(struct rt_msghdr *);
|
||||||
extern int ifam_read(struct ifa_msghdr *);
|
extern int ifam_read(struct ifa_msghdr *);
|
||||||
extern int ifm_read(struct if_msghdr *);
|
extern int ifm_read(struct if_msghdr *);
|
||||||
extern int rtm_write(int, union sockunion *, union sockunion *,
|
extern int rtm_write(int, union sockunion *, union sockunion *,
|
||||||
union sockunion *, union sockunion *, unsigned int, int,
|
union sockunion *, union sockunion *, unsigned int,
|
||||||
int);
|
enum blackhole_type, int);
|
||||||
extern const struct message rtm_type_str[];
|
extern const struct message rtm_type_str[];
|
||||||
|
|
||||||
#endif /* __ZEBRA_KERNEL_SOCKET_H */
|
#endif /* __ZEBRA_KERNEL_SOCKET_H */
|
||||||
|
|
|
@ -231,7 +231,8 @@ typedef enum {
|
||||||
|
|
||||||
extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *,
|
extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *,
|
||||||
ifindex_t);
|
ifindex_t);
|
||||||
extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *);
|
extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *,
|
||||||
|
enum blackhole_type);
|
||||||
extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *,
|
extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *,
|
||||||
struct in_addr *,
|
struct in_addr *,
|
||||||
struct in_addr *);
|
struct in_addr *);
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
|
||||||
struct sockaddr_nl snl;
|
struct sockaddr_nl snl;
|
||||||
struct nexthop *nexthop = NULL;
|
struct nexthop *nexthop = NULL;
|
||||||
unsigned int nexthop_num;
|
unsigned int nexthop_num;
|
||||||
int discard;
|
int discard = 0;
|
||||||
int family = PREFIX_FAMILY(p);
|
int family = PREFIX_FAMILY(p);
|
||||||
const char *routedesc;
|
const char *routedesc;
|
||||||
int setsrc = 0;
|
int setsrc = 0;
|
||||||
|
@ -1252,24 +1252,23 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
|
||||||
req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
|
req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
|
||||||
req.r.rtm_protocol = get_rt_proto(re->type);
|
req.r.rtm_protocol = get_rt_proto(re->type);
|
||||||
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||||
|
req.r.rtm_type = RTN_UNICAST;
|
||||||
|
|
||||||
if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
|
if (re->nexthop_num == 1
|
||||||
|| (re->flags & ZEBRA_FLAG_REJECT))
|
&& re->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
|
||||||
discard = 1;
|
discard = 1;
|
||||||
else
|
|
||||||
discard = 0;
|
|
||||||
|
|
||||||
if (cmd == RTM_NEWROUTE) {
|
switch (re->nexthop->bh_type) {
|
||||||
if (discard) {
|
case BLACKHOLE_ADMINPROHIB:
|
||||||
if (re->flags & ZEBRA_FLAG_BLACKHOLE)
|
req.r.rtm_type = RTN_PROHIBIT;
|
||||||
req.r.rtm_type = RTN_BLACKHOLE;
|
break;
|
||||||
else if (re->flags & ZEBRA_FLAG_REJECT)
|
case BLACKHOLE_REJECT:
|
||||||
req.r.rtm_type = RTN_UNREACHABLE;
|
req.r.rtm_type = RTN_UNREACHABLE;
|
||||||
else
|
break;
|
||||||
assert(RTN_BLACKHOLE
|
default:
|
||||||
!= RTN_UNREACHABLE); /* false */
|
req.r.rtm_type = RTN_BLACKHOLE;
|
||||||
} else
|
break;
|
||||||
req.r.rtm_type = RTN_UNICAST;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
|
addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
|
||||||
|
@ -1294,6 +1293,9 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
|
||||||
addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
|
addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (discard)
|
||||||
|
goto skip;
|
||||||
|
|
||||||
if (re->mtu || re->nexthop_mtu) {
|
if (re->mtu || re->nexthop_mtu) {
|
||||||
char buf[NL_PKT_BUF_SIZE];
|
char buf[NL_PKT_BUF_SIZE];
|
||||||
struct rtattr *rta = (void *)buf;
|
struct rtattr *rta = (void *)buf;
|
||||||
|
@ -1307,21 +1309,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
|
||||||
RTA_PAYLOAD(rta));
|
RTA_PAYLOAD(rta));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discard) {
|
|
||||||
if (cmd == RTM_NEWROUTE)
|
|
||||||
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
|
|
||||||
/* We shouldn't encounter recursive nexthops on
|
|
||||||
* discard routes,
|
|
||||||
* but it is probably better to handle that case
|
|
||||||
* correctly anyway.
|
|
||||||
*/
|
|
||||||
if (CHECK_FLAG(nexthop->flags,
|
|
||||||
NEXTHOP_FLAG_RECURSIVE))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count overall nexthops so we can decide whether to use singlepath
|
/* Count overall nexthops so we can decide whether to use singlepath
|
||||||
* or multipath case. */
|
* or multipath case. */
|
||||||
nexthop_num = 0;
|
nexthop_num = 0;
|
||||||
|
|
|
@ -42,11 +42,6 @@
|
||||||
|
|
||||||
extern struct zebra_privs_t zserv_privs;
|
extern struct zebra_privs_t zserv_privs;
|
||||||
|
|
||||||
/* kernel socket export */
|
|
||||||
extern int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
|
||||||
union sockunion *gate, union sockunion *mpls,
|
|
||||||
unsigned int index, int zebra_flags, int metric);
|
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||||
/* Adjust netmask socket length. Return value is a adjusted sin_len
|
/* Adjust netmask socket length. Return value is a adjusted sin_len
|
||||||
value. */
|
value. */
|
||||||
|
@ -108,6 +103,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
|
||||||
int gate = 0;
|
int gate = 0;
|
||||||
int error;
|
int error;
|
||||||
char prefix_buf[PREFIX_STRLEN];
|
char prefix_buf[PREFIX_STRLEN];
|
||||||
|
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
prefix2str(p, prefix_buf, sizeof(prefix_buf));
|
prefix2str(p, prefix_buf, sizeof(prefix_buf));
|
||||||
|
@ -155,6 +151,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
|
||||||
struct in_addr loopback;
|
struct in_addr loopback;
|
||||||
loopback.s_addr = htonl(INADDR_LOOPBACK);
|
loopback.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
sin_gate.sin_addr = loopback;
|
sin_gate.sin_addr = loopback;
|
||||||
|
bh_type = nexthop->bh_type;
|
||||||
gate = 1;
|
gate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +179,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
|
||||||
cmd, (union sockunion *)&sin_dest,
|
cmd, (union sockunion *)&sin_dest,
|
||||||
(union sockunion *)mask,
|
(union sockunion *)mask,
|
||||||
gate ? (union sockunion *)&sin_gate : NULL,
|
gate ? (union sockunion *)&sin_gate : NULL,
|
||||||
smplsp, ifindex, re->flags, re->metric);
|
smplsp, ifindex, bh_type, re->metric);
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB) {
|
if (IS_ZEBRA_DEBUG_RIB) {
|
||||||
if (!gate) {
|
if (!gate) {
|
||||||
|
@ -292,6 +289,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
|
||||||
ifindex_t ifindex = 0;
|
ifindex_t ifindex = 0;
|
||||||
int gate = 0;
|
int gate = 0;
|
||||||
int error;
|
int error;
|
||||||
|
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
||||||
|
|
||||||
memset(&sin_dest, 0, sizeof(struct sockaddr_in6));
|
memset(&sin_dest, 0, sizeof(struct sockaddr_in6));
|
||||||
sin_dest.sin6_family = AF_INET6;
|
sin_dest.sin6_family = AF_INET6;
|
||||||
|
@ -331,6 +329,9 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
|
||||||
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
|
||||||
ifindex = nexthop->ifindex;
|
ifindex = nexthop->ifindex;
|
||||||
|
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
|
||||||
|
bh_type = nexthop->bh_type;
|
||||||
|
|
||||||
if (cmd == RTM_ADD)
|
if (cmd == RTM_ADD)
|
||||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
|
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||||
}
|
}
|
||||||
|
@ -369,7 +370,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
|
||||||
error = rtm_write(cmd, (union sockunion *)&sin_dest,
|
error = rtm_write(cmd, (union sockunion *)&sin_dest,
|
||||||
(union sockunion *)mask,
|
(union sockunion *)mask,
|
||||||
gate ? (union sockunion *)&sin_gate : NULL,
|
gate ? (union sockunion *)&sin_gate : NULL,
|
||||||
smplsp, ifindex, re->flags, re->metric);
|
smplsp, ifindex, bh_type, re->metric);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (error)
|
if (error)
|
||||||
|
|
|
@ -222,7 +222,6 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
|
||||||
rib_dest_t *dest, struct route_entry *re)
|
rib_dest_t *dest, struct route_entry *re)
|
||||||
{
|
{
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
int discard;
|
|
||||||
|
|
||||||
memset(ri, 0, sizeof(*ri));
|
memset(ri, 0, sizeof(*ri));
|
||||||
|
|
||||||
|
@ -247,30 +246,9 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
ri->rtm_protocol = netlink_proto_from_route_type(re->type);
|
ri->rtm_protocol = netlink_proto_from_route_type(re->type);
|
||||||
|
ri->rtm_type = RTN_UNICAST;
|
||||||
if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
|
|
||||||
|| (re->flags & ZEBRA_FLAG_REJECT))
|
|
||||||
discard = 1;
|
|
||||||
else
|
|
||||||
discard = 0;
|
|
||||||
|
|
||||||
if (cmd == RTM_NEWROUTE) {
|
|
||||||
if (discard) {
|
|
||||||
if (re->flags & ZEBRA_FLAG_BLACKHOLE)
|
|
||||||
ri->rtm_type = RTN_BLACKHOLE;
|
|
||||||
else if (re->flags & ZEBRA_FLAG_REJECT)
|
|
||||||
ri->rtm_type = RTN_UNREACHABLE;
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
} else
|
|
||||||
ri->rtm_type = RTN_UNICAST;
|
|
||||||
}
|
|
||||||
|
|
||||||
ri->metric = &re->metric;
|
ri->metric = &re->metric;
|
||||||
|
|
||||||
if (discard)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
|
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
|
||||||
if (ri->num_nhs >= multipath_num)
|
if (ri->num_nhs >= multipath_num)
|
||||||
break;
|
break;
|
||||||
|
@ -278,6 +256,22 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
|
||||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
|
||||||
|
switch (nexthop->bh_type) {
|
||||||
|
case BLACKHOLE_ADMINPROHIB:
|
||||||
|
ri->rtm_type = RTN_PROHIBIT;
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_REJECT:
|
||||||
|
ri->rtm_type = RTN_UNREACHABLE;
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_NULL:
|
||||||
|
default:
|
||||||
|
ri->rtm_type = RTN_BLACKHOLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((cmd == RTM_NEWROUTE
|
if ((cmd == RTM_NEWROUTE
|
||||||
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
||||||
|| (cmd == RTM_DELROUTE
|
|| (cmd == RTM_DELROUTE
|
||||||
|
|
|
@ -141,7 +141,6 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
|
||||||
struct route_entry *re)
|
struct route_entry *re)
|
||||||
{
|
{
|
||||||
Fpm__AddRoute *msg;
|
Fpm__AddRoute *msg;
|
||||||
int discard;
|
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
uint num_nhs, u;
|
uint num_nhs, u;
|
||||||
struct nexthop *nexthops[MULTIPATH_NUM];
|
struct nexthop *nexthops[MULTIPATH_NUM];
|
||||||
|
@ -164,26 +163,7 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
|
||||||
msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
|
msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
|
||||||
msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
|
msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
|
||||||
qpb_protocol_set(&msg->protocol, re->type);
|
qpb_protocol_set(&msg->protocol, re->type);
|
||||||
|
msg->route_type = FPM__ROUTE_TYPE__NORMAL;
|
||||||
if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
|
|
||||||
|| (re->flags & ZEBRA_FLAG_REJECT))
|
|
||||||
discard = 1;
|
|
||||||
else
|
|
||||||
discard = 0;
|
|
||||||
|
|
||||||
if (discard) {
|
|
||||||
if (re->flags & ZEBRA_FLAG_BLACKHOLE) {
|
|
||||||
msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
|
|
||||||
} else if (re->flags & ZEBRA_FLAG_REJECT) {
|
|
||||||
msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
|
|
||||||
} else {
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
} else {
|
|
||||||
msg->route_type = FPM__ROUTE_TYPE__NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->metric = re->metric;
|
msg->metric = re->metric;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -197,6 +177,19 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
|
||||||
if (num_nhs >= ZEBRA_NUM_OF(nexthops))
|
if (num_nhs >= ZEBRA_NUM_OF(nexthops))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
|
||||||
|
switch (nexthop->bh_type) {
|
||||||
|
case BLACKHOLE_REJECT:
|
||||||
|
msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_NULL:
|
||||||
|
default:
|
||||||
|
msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -291,13 +291,14 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
|
||||||
return nexthop;
|
return nexthop;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re)
|
struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re,
|
||||||
|
enum blackhole_type bh_type)
|
||||||
{
|
{
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
|
|
||||||
nexthop = nexthop_new();
|
nexthop = nexthop_new();
|
||||||
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
|
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
|
||||||
SET_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE);
|
nexthop->bh_type = bh_type;
|
||||||
|
|
||||||
route_entry_nexthop_add(re, nexthop);
|
route_entry_nexthop_add(re, nexthop);
|
||||||
|
|
||||||
|
@ -471,12 +472,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the longest prefix match for the nexthop yields
|
|
||||||
* a blackhole, mark it as inactive. */
|
|
||||||
if (CHECK_FLAG(match->flags, ZEBRA_FLAG_BLACKHOLE)
|
|
||||||
|| CHECK_FLAG(match->flags, ZEBRA_FLAG_REJECT))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (match->type == ZEBRA_ROUTE_CONNECT) {
|
if (match->type == ZEBRA_ROUTE_CONNECT) {
|
||||||
/* Directly point connected route. */
|
/* Directly point connected route. */
|
||||||
newhop = match->nexthop;
|
newhop = match->nexthop;
|
||||||
|
@ -488,41 +483,46 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||||
return 1;
|
return 1;
|
||||||
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) {
|
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) {
|
||||||
resolved = 0;
|
resolved = 0;
|
||||||
for (ALL_NEXTHOPS(match->nexthop, newhop))
|
for (ALL_NEXTHOPS(match->nexthop, newhop)) {
|
||||||
if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB)
|
if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
|
||||||
&& !CHECK_FLAG(newhop->flags,
|
continue;
|
||||||
NEXTHOP_FLAG_RECURSIVE)) {
|
if (!CHECK_FLAG(newhop->flags,
|
||||||
if (set) {
|
NEXTHOP_FLAG_FIB))
|
||||||
SET_FLAG(
|
continue;
|
||||||
nexthop->flags,
|
if (CHECK_FLAG(newhop->flags,
|
||||||
NEXTHOP_FLAG_RECURSIVE);
|
NEXTHOP_FLAG_RECURSIVE))
|
||||||
SET_FLAG(
|
continue;
|
||||||
re->status,
|
|
||||||
ROUTE_ENTRY_NEXTHOPS_CHANGED);
|
|
||||||
|
|
||||||
nexthop_set_resolved(
|
if (set) {
|
||||||
afi, newhop, nexthop);
|
SET_FLAG(nexthop->flags,
|
||||||
}
|
NEXTHOP_FLAG_RECURSIVE);
|
||||||
resolved = 1;
|
SET_FLAG(re->status,
|
||||||
|
ROUTE_ENTRY_NEXTHOPS_CHANGED);
|
||||||
|
nexthop_set_resolved(afi, newhop,
|
||||||
|
nexthop);
|
||||||
}
|
}
|
||||||
|
resolved = 1;
|
||||||
|
}
|
||||||
if (resolved && set)
|
if (resolved && set)
|
||||||
re->nexthop_mtu = match->mtu;
|
re->nexthop_mtu = match->mtu;
|
||||||
return resolved;
|
return resolved;
|
||||||
} else if (re->type == ZEBRA_ROUTE_STATIC) {
|
} else if (re->type == ZEBRA_ROUTE_STATIC) {
|
||||||
resolved = 0;
|
resolved = 0;
|
||||||
for (ALL_NEXTHOPS(match->nexthop, newhop))
|
for (ALL_NEXTHOPS(match->nexthop, newhop)) {
|
||||||
if (CHECK_FLAG(newhop->flags,
|
if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
|
||||||
NEXTHOP_FLAG_FIB)) {
|
continue;
|
||||||
if (set) {
|
if (!CHECK_FLAG(newhop->flags,
|
||||||
SET_FLAG(
|
NEXTHOP_FLAG_FIB))
|
||||||
nexthop->flags,
|
continue;
|
||||||
NEXTHOP_FLAG_RECURSIVE);
|
|
||||||
|
|
||||||
nexthop_set_resolved(
|
if (set) {
|
||||||
afi, newhop, nexthop);
|
SET_FLAG(nexthop->flags,
|
||||||
}
|
NEXTHOP_FLAG_RECURSIVE);
|
||||||
resolved = 1;
|
nexthop_set_resolved(afi, newhop,
|
||||||
|
nexthop);
|
||||||
}
|
}
|
||||||
|
resolved = 1;
|
||||||
|
}
|
||||||
if (resolved && set)
|
if (resolved && set)
|
||||||
re->nexthop_mtu = match->mtu;
|
re->nexthop_mtu = match->mtu;
|
||||||
return resolved;
|
return resolved;
|
||||||
|
|
|
@ -91,7 +91,8 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||||
si->ifindex);
|
si->ifindex);
|
||||||
break;
|
break;
|
||||||
case STATIC_BLACKHOLE:
|
case STATIC_BLACKHOLE:
|
||||||
nexthop = route_entry_nexthop_blackhole_add(re);
|
nexthop = route_entry_nexthop_blackhole_add(re,
|
||||||
|
si->bh_type);
|
||||||
break;
|
break;
|
||||||
case STATIC_IPV6_GATEWAY:
|
case STATIC_IPV6_GATEWAY:
|
||||||
nexthop = route_entry_nexthop_ipv6_add(re,
|
nexthop = route_entry_nexthop_ipv6_add(re,
|
||||||
|
@ -166,7 +167,8 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||||
si->ifindex);
|
si->ifindex);
|
||||||
break;
|
break;
|
||||||
case STATIC_BLACKHOLE:
|
case STATIC_BLACKHOLE:
|
||||||
nexthop = route_entry_nexthop_blackhole_add(re);
|
nexthop = route_entry_nexthop_blackhole_add(re,
|
||||||
|
si->bh_type);
|
||||||
break;
|
break;
|
||||||
case STATIC_IPV6_GATEWAY:
|
case STATIC_IPV6_GATEWAY:
|
||||||
nexthop = route_entry_nexthop_ipv6_add(re,
|
nexthop = route_entry_nexthop_ipv6_add(re,
|
||||||
|
@ -187,9 +189,6 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||||
si->snh_label.num_labels,
|
si->snh_label.num_labels,
|
||||||
&si->snh_label.label[0]);
|
&si->snh_label.label[0]);
|
||||||
|
|
||||||
/* Save the flags of this static routes (reject, blackhole) */
|
|
||||||
re->flags = si->flags;
|
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB) {
|
if (IS_ZEBRA_DEBUG_RIB) {
|
||||||
char buf[INET6_ADDRSTRLEN];
|
char buf[INET6_ADDRSTRLEN];
|
||||||
if (IS_ZEBRA_DEBUG_RIB) {
|
if (IS_ZEBRA_DEBUG_RIB) {
|
||||||
|
@ -364,7 +363,7 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||||
|
|
||||||
int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
|
int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
|
||||||
struct prefix_ipv6 *src_p, union g_addr *gate,
|
struct prefix_ipv6 *src_p, union g_addr *gate,
|
||||||
const char *ifname, u_char flags,
|
const char *ifname, enum blackhole_type bh_type,
|
||||||
route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
|
route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
|
||||||
struct static_nh_label *snh_label)
|
struct static_nh_label *snh_label)
|
||||||
{
|
{
|
||||||
|
@ -405,7 +404,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
|
||||||
if ((distance == si->distance) && (tag == si->tag)
|
if ((distance == si->distance) && (tag == si->tag)
|
||||||
&& !memcmp(&si->snh_label, snh_label,
|
&& !memcmp(&si->snh_label, snh_label,
|
||||||
sizeof(struct static_nh_label))
|
sizeof(struct static_nh_label))
|
||||||
&& si->flags == flags) {
|
&& si->bh_type == bh_type) {
|
||||||
route_unlock_node(rn);
|
route_unlock_node(rn);
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
|
@ -424,7 +423,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
|
||||||
|
|
||||||
si->type = type;
|
si->type = type;
|
||||||
si->distance = distance;
|
si->distance = distance;
|
||||||
si->flags = flags;
|
si->bh_type = bh_type;
|
||||||
si->tag = tag;
|
si->tag = tag;
|
||||||
si->vrf_id = zvrf_id(zvrf);
|
si->vrf_id = zvrf_id(zvrf);
|
||||||
if (ifname)
|
if (ifname)
|
||||||
|
|
|
@ -61,18 +61,12 @@ struct static_route {
|
||||||
/*
|
/*
|
||||||
* Nexthop value.
|
* Nexthop value.
|
||||||
*/
|
*/
|
||||||
|
enum blackhole_type bh_type;
|
||||||
union g_addr addr;
|
union g_addr addr;
|
||||||
ifindex_t ifindex;
|
ifindex_t ifindex;
|
||||||
|
|
||||||
char ifname[INTERFACE_NAMSIZ + 1];
|
char ifname[INTERFACE_NAMSIZ + 1];
|
||||||
|
|
||||||
/* bit flags */
|
|
||||||
u_char flags;
|
|
||||||
/*
|
|
||||||
see ZEBRA_FLAG_REJECT
|
|
||||||
ZEBRA_FLAG_BLACKHOLE
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Label information */
|
/* Label information */
|
||||||
struct static_nh_label snh_label;
|
struct static_nh_label snh_label;
|
||||||
};
|
};
|
||||||
|
@ -86,7 +80,7 @@ extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
|
||||||
|
|
||||||
extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p,
|
extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p,
|
||||||
struct prefix_ipv6 *src_p, union g_addr *gate,
|
struct prefix_ipv6 *src_p, union g_addr *gate,
|
||||||
const char *ifname, u_char flags,
|
const char *ifname, enum blackhole_type bh_type,
|
||||||
route_tag_t tag, u_char distance,
|
route_tag_t tag, u_char distance,
|
||||||
struct zebra_vrf *zvrf,
|
struct zebra_vrf *zvrf,
|
||||||
struct static_nh_label *snh_label);
|
struct static_nh_label *snh_label);
|
||||||
|
|
|
@ -74,7 +74,7 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
|
||||||
union g_addr gate;
|
union g_addr gate;
|
||||||
union g_addr *gatep = NULL;
|
union g_addr *gatep = NULL;
|
||||||
struct in_addr mask;
|
struct in_addr mask;
|
||||||
u_char flag = 0;
|
enum blackhole_type bh_type = 0;
|
||||||
route_tag_t tag = 0;
|
route_tag_t tag = 0;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
u_char type;
|
u_char type;
|
||||||
|
@ -165,28 +165,18 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Null0 static route. */
|
|
||||||
if ((ifname != NULL)
|
|
||||||
&& (strncasecmp(ifname, "Null0", strlen(ifname)) == 0)) {
|
|
||||||
if (flag_str) {
|
|
||||||
vty_out(vty, "%% can not have flag %s with Null0\n",
|
|
||||||
flag_str);
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
|
|
||||||
ifname = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Route flags */
|
/* Route flags */
|
||||||
if (flag_str) {
|
if (flag_str) {
|
||||||
switch (flag_str[0]) {
|
switch (flag_str[0]) {
|
||||||
case 'r':
|
case 'r':
|
||||||
case 'R': /* XXX */
|
case 'R': /* XXX */
|
||||||
SET_FLAG(flag, ZEBRA_FLAG_REJECT);
|
bh_type = BLACKHOLE_REJECT;
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
case 'N' /* XXX */:
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B': /* XXX */
|
case 'B': /* XXX */
|
||||||
SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
|
bh_type = BLACKHOLE_NULL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vty_out(vty, "%% Malformed flag %s \n", flag_str);
|
vty_out(vty, "%% Malformed flag %s \n", flag_str);
|
||||||
|
@ -221,7 +211,7 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
|
||||||
|
|
||||||
if (!negate)
|
if (!negate)
|
||||||
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
|
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
|
||||||
flag, tag, distance, zvrf, &snh_label);
|
bh_type, tag, distance, zvrf, &snh_label);
|
||||||
else
|
else
|
||||||
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
|
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
|
||||||
tag, distance, zvrf, &snh_label);
|
tag, distance, zvrf, &snh_label);
|
||||||
|
@ -346,8 +336,7 @@ DEFPY (ip_route,
|
||||||
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\
|
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\
|
||||||
<\
|
<\
|
||||||
{A.B.C.D$gate|INTERFACE$ifname}\
|
{A.B.C.D$gate|INTERFACE$ifname}\
|
||||||
|null0$ifname\
|
|<null0|reject|blackhole>$flag\
|
||||||
|<reject|blackhole>$flag\
|
|
||||||
>\
|
>\
|
||||||
[{\
|
[{\
|
||||||
tag (1-4294967295)\
|
tag (1-4294967295)\
|
||||||
|
@ -417,10 +406,6 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
|
||||||
vty_out(vty, ", best");
|
vty_out(vty, ", best");
|
||||||
if (re->refcnt)
|
if (re->refcnt)
|
||||||
vty_out(vty, ", refcnt %ld", re->refcnt);
|
vty_out(vty, ", refcnt %ld", re->refcnt);
|
||||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
|
|
||||||
vty_out(vty, ", blackhole");
|
|
||||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
|
|
||||||
vty_out(vty, ", reject");
|
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
|
|
||||||
if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
|
if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
|
||||||
|
@ -485,7 +470,20 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
|
||||||
re->vrf_id));
|
re->vrf_id));
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
vty_out(vty, " directly connected, Null0");
|
vty_out(vty, " unreachable");
|
||||||
|
switch (nexthop->bh_type) {
|
||||||
|
case BLACKHOLE_REJECT:
|
||||||
|
vty_out(vty, " (ICMP unreachable)");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_ADMINPROHIB:
|
||||||
|
vty_out(vty, " (ICMP admin-prohibited)");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_NULL:
|
||||||
|
vty_out(vty, " (blackhole)");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_UNSPEC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -580,12 +578,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||||
json_object_int_add(json_route, "metric", re->metric);
|
json_object_int_add(json_route, "metric", re->metric);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
|
|
||||||
json_object_boolean_true_add(json_route, "blackhole");
|
|
||||||
|
|
||||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
|
|
||||||
json_object_boolean_true_add(json_route, "reject");
|
|
||||||
|
|
||||||
if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
|
if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
|
||||||
|| re->type == ZEBRA_ROUTE_ISIS
|
|| re->type == ZEBRA_ROUTE_ISIS
|
||||||
|| re->type == ZEBRA_ROUTE_NHRP
|
|| re->type == ZEBRA_ROUTE_NHRP
|
||||||
|
@ -671,7 +663,26 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
json_object_boolean_true_add(json_nexthop,
|
json_object_boolean_true_add(json_nexthop,
|
||||||
"blackhole");
|
"unreachable");
|
||||||
|
switch (nexthop->bh_type) {
|
||||||
|
case BLACKHOLE_REJECT:
|
||||||
|
json_object_boolean_true_add(
|
||||||
|
json_nexthop,
|
||||||
|
"reject");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_ADMINPROHIB:
|
||||||
|
json_object_boolean_true_add(
|
||||||
|
json_nexthop,
|
||||||
|
"admin-prohibited");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_NULL:
|
||||||
|
json_object_boolean_true_add(
|
||||||
|
json_nexthop,
|
||||||
|
"blackhole");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_UNSPEC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -796,7 +807,20 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||||
ifindex2ifname(nexthop->ifindex, re->vrf_id));
|
ifindex2ifname(nexthop->ifindex, re->vrf_id));
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
vty_out(vty, " is directly connected, Null0");
|
vty_out(vty, " unreachable");
|
||||||
|
switch (nexthop->bh_type) {
|
||||||
|
case BLACKHOLE_REJECT:
|
||||||
|
vty_out(vty, " (ICMP unreachable)");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_ADMINPROHIB:
|
||||||
|
vty_out(vty, " (ICMP admin-prohibited)");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_NULL:
|
||||||
|
vty_out(vty, " (blackhole)");
|
||||||
|
break;
|
||||||
|
case BLACKHOLE_UNSPEC:
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -839,11 +863,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
||||||
sizeof buf, 1));
|
sizeof buf, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
|
|
||||||
vty_out(vty, ", bh");
|
|
||||||
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
|
|
||||||
vty_out(vty, ", rej");
|
|
||||||
|
|
||||||
if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
|
if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
|
||||||
|| re->type == ZEBRA_ROUTE_ISIS
|
|| re->type == ZEBRA_ROUTE_ISIS
|
||||||
|| re->type == ZEBRA_ROUTE_NHRP
|
|| re->type == ZEBRA_ROUTE_NHRP
|
||||||
|
@ -1693,12 +1712,15 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
|
||||||
case STATIC_IFNAME:
|
case STATIC_IFNAME:
|
||||||
vty_out(vty, " %s", si->ifname);
|
vty_out(vty, " %s", si->ifname);
|
||||||
break;
|
break;
|
||||||
/* blackhole and Null0 mean the same thing */
|
|
||||||
case STATIC_BLACKHOLE:
|
case STATIC_BLACKHOLE:
|
||||||
if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
|
switch (si->bh_type) {
|
||||||
|
case BLACKHOLE_REJECT:
|
||||||
vty_out(vty, " reject");
|
vty_out(vty, " reject");
|
||||||
else
|
break;
|
||||||
vty_out(vty, " Null0");
|
default:
|
||||||
|
vty_out(vty, " blackhole");
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||||
vty_out(vty, " %s %s",
|
vty_out(vty, " %s %s",
|
||||||
|
@ -1716,19 +1738,6 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flags are incompatible with STATIC_BLACKHOLE
|
|
||||||
*/
|
|
||||||
if (si->type != STATIC_BLACKHOLE) {
|
|
||||||
if (CHECK_FLAG(si->flags,
|
|
||||||
ZEBRA_FLAG_REJECT))
|
|
||||||
vty_out(vty, " %s", "reject");
|
|
||||||
|
|
||||||
if (CHECK_FLAG(si->flags,
|
|
||||||
ZEBRA_FLAG_BLACKHOLE))
|
|
||||||
vty_out(vty, " %s",
|
|
||||||
"blackhole");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (si->tag)
|
if (si->tag)
|
||||||
vty_out(vty, " tag %" ROUTE_TAG_PRI,
|
vty_out(vty, " tag %" ROUTE_TAG_PRI,
|
||||||
si->tag);
|
si->tag);
|
||||||
|
@ -1763,8 +1772,7 @@ DEFPY (ipv6_route,
|
||||||
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
|
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
|
||||||
<\
|
<\
|
||||||
{X:X::X:X$gate|INTERFACE$ifname}\
|
{X:X::X:X$gate|INTERFACE$ifname}\
|
||||||
|null0$ifname\
|
|<null0|reject|blackhole>$flag\
|
||||||
|<reject|blackhole>$flag\
|
|
||||||
>\
|
>\
|
||||||
[{\
|
[{\
|
||||||
tag (1-4294967295)\
|
tag (1-4294967295)\
|
||||||
|
|
|
@ -1051,6 +1051,7 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||||
struct route_entry *re;
|
struct route_entry *re;
|
||||||
struct nexthop *nexthop = NULL;
|
struct nexthop *nexthop = NULL;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||||
|
|
||||||
s = client->ibuf;
|
s = client->ibuf;
|
||||||
if (zapi_route_decode(s, &api) < 0)
|
if (zapi_route_decode(s, &api) < 0)
|
||||||
|
@ -1093,7 +1094,7 @@ static int zread_route_add(struct zserv *client, u_short length,
|
||||||
api_nh->ifindex);
|
api_nh->ifindex);
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
route_entry_nexthop_blackhole_add(re);
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,7 +1164,7 @@ static int zread_route_del(struct zserv *client, u_short length,
|
||||||
src_p = &api.src_prefix;
|
src_p = &api.src_prefix;
|
||||||
|
|
||||||
rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||||
api.flags, &api.prefix, src_p, NULL, 0, zvrf->table_id,
|
api.flags, &api.prefix, src_p, NULL, zvrf->table_id,
|
||||||
api.metric);
|
api.metric);
|
||||||
|
|
||||||
/* Stats */
|
/* Stats */
|
||||||
|
@ -1201,6 +1202,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
|
||||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||||
mpls_label_t label;
|
mpls_label_t label;
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||||
|
|
||||||
/* Get input stream. */
|
/* Get input stream. */
|
||||||
s = client->ibuf;
|
s = client->ibuf;
|
||||||
|
@ -1264,7 +1266,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
|
||||||
stream_forward_getp(s, IPV6_MAX_BYTELEN);
|
stream_forward_getp(s, IPV6_MAX_BYTELEN);
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
route_entry_nexthop_blackhole_add(re);
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1329,7 +1331,7 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
|
||||||
table_id = zvrf->table_id;
|
table_id = zvrf->table_id;
|
||||||
|
|
||||||
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||||
api.flags, &p, NULL, NULL, 0, table_id, 0);
|
api.flags, &p, NULL, NULL, table_id, 0);
|
||||||
client->v4_route_del_cnt++;
|
client->v4_route_del_cnt++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1367,6 +1369,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||||
mpls_label_t label;
|
mpls_label_t label;
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||||
|
|
||||||
/* Get input stream. */
|
/* Get input stream. */
|
||||||
s = client->ibuf;
|
s = client->ibuf;
|
||||||
|
@ -1434,7 +1437,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
route_entry_nexthop_blackhole_add(re);
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1516,6 +1519,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||||
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
enum lsp_types_t label_type = ZEBRA_LSP_NONE;
|
||||||
mpls_label_t label;
|
mpls_label_t label;
|
||||||
struct nexthop *nexthop;
|
struct nexthop *nexthop;
|
||||||
|
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||||
|
|
||||||
/* Get input stream. */
|
/* Get input stream. */
|
||||||
s = client->ibuf;
|
s = client->ibuf;
|
||||||
|
@ -1594,7 +1598,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
route_entry_nexthop_blackhole_add(re);
|
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1689,7 +1693,7 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
|
||||||
src_pp = NULL;
|
src_pp = NULL;
|
||||||
|
|
||||||
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
|
||||||
api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0);
|
api.flags, &p, src_pp, NULL, client->rtm_table, 0);
|
||||||
|
|
||||||
client->v6_route_del_cnt++;
|
client->v6_route_del_cnt++;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue