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:
David Lamparter 2010-02-05 04:31:56 +01:00 committed by David Lamparter
parent fd36be7e15
commit a830942228
14 changed files with 213 additions and 218 deletions

View file

@ -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 */

View file

@ -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

View file

@ -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) \

View file

@ -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 */

View file

@ -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 *);

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -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)\

View file

@ -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;