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 */
|
||||
|
||||
/* Nexthop address */
|
||||
union g_addr gate;
|
||||
union {
|
||||
union g_addr gate;
|
||||
enum blackhole_type bh_type;
|
||||
};
|
||||
union g_addr src;
|
||||
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 */
|
||||
#define ZEBRA_FLAG_INTERNAL 0x01
|
||||
#define ZEBRA_FLAG_SELFROUTE 0x02
|
||||
#define ZEBRA_FLAG_BLACKHOLE 0x04
|
||||
#define ZEBRA_FLAG_IBGP 0x08
|
||||
#define ZEBRA_FLAG_SELECTED 0x10
|
||||
#define ZEBRA_FLAG_STATIC 0x40
|
||||
#define ZEBRA_FLAG_REJECT 0x80
|
||||
#define ZEBRA_FLAG_SCOPE_LINK 0x100
|
||||
#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
|
||||
/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
|
||||
/* ZEBRA_FLAG_REJECT was 0x80 */
|
||||
|
||||
/* Zebra FEC flags. */
|
||||
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
|
||||
|
|
|
@ -887,11 +887,15 @@ void rtm_read(struct rt_msghdr *rtm)
|
|||
if (flags & RTF_STATIC)
|
||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
|
||||
|
||||
memset(&nh, 0, sizeof(nh));
|
||||
/* This is a reject or blackhole route */
|
||||
if (flags & RTF_REJECT)
|
||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_REJECT);
|
||||
if (flags & RTF_BLACKHOLE)
|
||||
SET_FLAG(zebra_flags, ZEBRA_FLAG_BLACKHOLE);
|
||||
if (flags & RTF_REJECT) {
|
||||
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
nh.bh_type = BLACKHOLE_REJECT;
|
||||
} else if (flags & RTF_BLACKHOLE) {
|
||||
nh.type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
nh.bh_type = BLACKHOLE_NULL;
|
||||
}
|
||||
|
||||
if (dest.sa.sa_family == AF_INET) {
|
||||
struct prefix p;
|
||||
|
@ -1017,11 +1021,12 @@ void rtm_read(struct rt_msghdr *rtm)
|
|||
if (rtm->rtm_type == RTM_CHANGE)
|
||||
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
|
||||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
|
||||
NULL, 0, 0);
|
||||
NULL, NULL, 0, 0);
|
||||
|
||||
memset(&nh, 0, sizeof(nh));
|
||||
nh.type = NEXTHOP_TYPE_IPV4;
|
||||
nh.gate.ipv4 = gate.sin;
|
||||
if (!nh.type) {
|
||||
nh.type = NEXTHOP_TYPE_IPV4;
|
||||
nh.gate.ipv4 = gate.sin.sin_addr;
|
||||
}
|
||||
|
||||
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
||||
|| rtm->rtm_type == RTM_CHANGE)
|
||||
|
@ -1064,11 +1069,12 @@ void rtm_read(struct rt_msghdr *rtm)
|
|||
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p,
|
||||
NULL, NULL, 0, 0);
|
||||
|
||||
memset(&nh, 0, sizeof(nh));
|
||||
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
|
||||
: NEXTHOP_TYPE_IPV6;
|
||||
nh.gate.ipv6 = gate.sin6;
|
||||
nh.ifindex = ifindex;
|
||||
if (!nh.type) {
|
||||
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
|
||||
: NEXTHOP_TYPE_IPV6;
|
||||
nh.gate.ipv6 = gate.sin6.sin6_addr;
|
||||
nh.ifindex = ifindex;
|
||||
}
|
||||
|
||||
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|
||||
|| 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,
|
||||
union sockunion *gate, union sockunion *mpls, unsigned int index,
|
||||
int zebra_flags, int metric)
|
||||
enum blackhole_type bh_type, int metric)
|
||||
{
|
||||
int ret;
|
||||
caddr_t pnt;
|
||||
|
@ -1178,11 +1184,16 @@ int rtm_write(int message, union sockunion *dest, union sockunion *mask,
|
|||
/* Tagging route with flags */
|
||||
msg.rtm.rtm_flags |= (RTF_PROTO1);
|
||||
|
||||
/* Additional flags. */
|
||||
if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
|
||||
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
||||
if (zebra_flags & ZEBRA_FLAG_REJECT)
|
||||
switch (bh_type) {
|
||||
case BLACKHOLE_UNSPEC:
|
||||
break;
|
||||
case BLACKHOLE_REJECT:
|
||||
msg.rtm.rtm_flags |= RTF_REJECT;
|
||||
break;
|
||||
default:
|
||||
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#define SOCKADDRSET(X, R) \
|
||||
|
|
|
@ -34,8 +34,8 @@ extern void rtm_read(struct rt_msghdr *);
|
|||
extern int ifam_read(struct ifa_msghdr *);
|
||||
extern int ifm_read(struct if_msghdr *);
|
||||
extern int rtm_write(int, union sockunion *, union sockunion *,
|
||||
union sockunion *, union sockunion *, unsigned int, int,
|
||||
int);
|
||||
union sockunion *, union sockunion *, unsigned int,
|
||||
enum blackhole_type, int);
|
||||
extern const struct message rtm_type_str[];
|
||||
|
||||
#endif /* __ZEBRA_KERNEL_SOCKET_H */
|
||||
|
|
|
@ -231,7 +231,8 @@ typedef enum {
|
|||
|
||||
extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *,
|
||||
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 *,
|
||||
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 nexthop *nexthop = NULL;
|
||||
unsigned int nexthop_num;
|
||||
int discard;
|
||||
int discard = 0;
|
||||
int family = PREFIX_FAMILY(p);
|
||||
const char *routedesc;
|
||||
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_protocol = get_rt_proto(re->type);
|
||||
req.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
req.r.rtm_type = RTN_UNICAST;
|
||||
|
||||
if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
|
||||
|| (re->flags & ZEBRA_FLAG_REJECT))
|
||||
if (re->nexthop_num == 1
|
||||
&& re->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
|
||||
discard = 1;
|
||||
else
|
||||
discard = 0;
|
||||
|
||||
if (cmd == RTM_NEWROUTE) {
|
||||
if (discard) {
|
||||
if (re->flags & ZEBRA_FLAG_BLACKHOLE)
|
||||
req.r.rtm_type = RTN_BLACKHOLE;
|
||||
else if (re->flags & ZEBRA_FLAG_REJECT)
|
||||
req.r.rtm_type = RTN_UNREACHABLE;
|
||||
else
|
||||
assert(RTN_BLACKHOLE
|
||||
!= RTN_UNREACHABLE); /* false */
|
||||
} else
|
||||
req.r.rtm_type = RTN_UNICAST;
|
||||
switch (re->nexthop->bh_type) {
|
||||
case BLACKHOLE_ADMINPROHIB:
|
||||
req.r.rtm_type = RTN_PROHIBIT;
|
||||
break;
|
||||
case BLACKHOLE_REJECT:
|
||||
req.r.rtm_type = RTN_UNREACHABLE;
|
||||
break;
|
||||
default:
|
||||
req.r.rtm_type = RTN_BLACKHOLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (discard)
|
||||
goto skip;
|
||||
|
||||
if (re->mtu || re->nexthop_mtu) {
|
||||
char buf[NL_PKT_BUF_SIZE];
|
||||
struct rtattr *rta = (void *)buf;
|
||||
|
@ -1307,21 +1309,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
|
|||
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
|
||||
* or multipath case. */
|
||||
nexthop_num = 0;
|
||||
|
|
|
@ -42,11 +42,6 @@
|
|||
|
||||
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
|
||||
/* Adjust netmask socket length. Return value is a adjusted sin_len
|
||||
value. */
|
||||
|
@ -108,6 +103,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
|
|||
int gate = 0;
|
||||
int error;
|
||||
char prefix_buf[PREFIX_STRLEN];
|
||||
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
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;
|
||||
loopback.s_addr = htonl(INADDR_LOOPBACK);
|
||||
sin_gate.sin_addr = loopback;
|
||||
bh_type = nexthop->bh_type;
|
||||
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,
|
||||
(union sockunion *)mask,
|
||||
gate ? (union sockunion *)&sin_gate : NULL,
|
||||
smplsp, ifindex, re->flags, re->metric);
|
||||
smplsp, ifindex, bh_type, re->metric);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB) {
|
||||
if (!gate) {
|
||||
|
@ -292,6 +289,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
|
|||
ifindex_t ifindex = 0;
|
||||
int gate = 0;
|
||||
int error;
|
||||
enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
|
||||
|
||||
memset(&sin_dest, 0, sizeof(struct sockaddr_in6));
|
||||
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)
|
||||
ifindex = nexthop->ifindex;
|
||||
|
||||
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
|
||||
bh_type = nexthop->bh_type;
|
||||
|
||||
if (cmd == RTM_ADD)
|
||||
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,
|
||||
(union sockunion *)mask,
|
||||
gate ? (union sockunion *)&sin_gate : NULL,
|
||||
smplsp, ifindex, re->flags, re->metric);
|
||||
smplsp, ifindex, bh_type, re->metric);
|
||||
|
||||
#if 0
|
||||
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)
|
||||
{
|
||||
struct nexthop *nexthop;
|
||||
int discard;
|
||||
|
||||
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);
|
||||
|
||||
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->rtm_type = RTN_UNICAST;
|
||||
ri->metric = &re->metric;
|
||||
|
||||
if (discard)
|
||||
return 1;
|
||||
|
||||
for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
|
||||
if (ri->num_nhs >= multipath_num)
|
||||
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))
|
||||
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
|
||||
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
||||
|| (cmd == RTM_DELROUTE
|
||||
|
|
|
@ -141,7 +141,6 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
|
|||
struct route_entry *re)
|
||||
{
|
||||
Fpm__AddRoute *msg;
|
||||
int discard;
|
||||
struct nexthop *nexthop;
|
||||
uint num_nhs, u;
|
||||
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->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
|
||||
qpb_protocol_set(&msg->protocol, re->type);
|
||||
|
||||
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->route_type = FPM__ROUTE_TYPE__NORMAL;
|
||||
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))
|
||||
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))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -291,13 +291,14 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
|
|||
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;
|
||||
|
||||
nexthop = nexthop_new();
|
||||
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
|
||||
SET_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE);
|
||||
nexthop->bh_type = bh_type;
|
||||
|
||||
route_entry_nexthop_add(re, nexthop);
|
||||
|
||||
|
@ -471,12 +472,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
|||
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) {
|
||||
/* Directly point connected route. */
|
||||
newhop = match->nexthop;
|
||||
|
@ -488,41 +483,46 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
|||
return 1;
|
||||
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) {
|
||||
resolved = 0;
|
||||
for (ALL_NEXTHOPS(match->nexthop, newhop))
|
||||
if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB)
|
||||
&& !CHECK_FLAG(newhop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE)) {
|
||||
if (set) {
|
||||
SET_FLAG(
|
||||
nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE);
|
||||
SET_FLAG(
|
||||
re->status,
|
||||
ROUTE_ENTRY_NEXTHOPS_CHANGED);
|
||||
for (ALL_NEXTHOPS(match->nexthop, newhop)) {
|
||||
if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
|
||||
continue;
|
||||
if (!CHECK_FLAG(newhop->flags,
|
||||
NEXTHOP_FLAG_FIB))
|
||||
continue;
|
||||
if (CHECK_FLAG(newhop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE))
|
||||
continue;
|
||||
|
||||
nexthop_set_resolved(
|
||||
afi, newhop, nexthop);
|
||||
}
|
||||
resolved = 1;
|
||||
if (set) {
|
||||
SET_FLAG(nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE);
|
||||
SET_FLAG(re->status,
|
||||
ROUTE_ENTRY_NEXTHOPS_CHANGED);
|
||||
nexthop_set_resolved(afi, newhop,
|
||||
nexthop);
|
||||
}
|
||||
resolved = 1;
|
||||
}
|
||||
if (resolved && set)
|
||||
re->nexthop_mtu = match->mtu;
|
||||
return resolved;
|
||||
} else if (re->type == ZEBRA_ROUTE_STATIC) {
|
||||
resolved = 0;
|
||||
for (ALL_NEXTHOPS(match->nexthop, newhop))
|
||||
if (CHECK_FLAG(newhop->flags,
|
||||
NEXTHOP_FLAG_FIB)) {
|
||||
if (set) {
|
||||
SET_FLAG(
|
||||
nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE);
|
||||
for (ALL_NEXTHOPS(match->nexthop, newhop)) {
|
||||
if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
|
||||
continue;
|
||||
if (!CHECK_FLAG(newhop->flags,
|
||||
NEXTHOP_FLAG_FIB))
|
||||
continue;
|
||||
|
||||
nexthop_set_resolved(
|
||||
afi, newhop, nexthop);
|
||||
}
|
||||
resolved = 1;
|
||||
if (set) {
|
||||
SET_FLAG(nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE);
|
||||
nexthop_set_resolved(afi, newhop,
|
||||
nexthop);
|
||||
}
|
||||
resolved = 1;
|
||||
}
|
||||
if (resolved && set)
|
||||
re->nexthop_mtu = match->mtu;
|
||||
return resolved;
|
||||
|
|
|
@ -91,7 +91,8 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
|
|||
si->ifindex);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
nexthop = route_entry_nexthop_blackhole_add(re);
|
||||
nexthop = route_entry_nexthop_blackhole_add(re,
|
||||
si->bh_type);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
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);
|
||||
break;
|
||||
case STATIC_BLACKHOLE:
|
||||
nexthop = route_entry_nexthop_blackhole_add(re);
|
||||
nexthop = route_entry_nexthop_blackhole_add(re,
|
||||
si->bh_type);
|
||||
break;
|
||||
case STATIC_IPV6_GATEWAY:
|
||||
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.label[0]);
|
||||
|
||||
/* Save the flags of this static routes (reject, blackhole) */
|
||||
re->flags = si->flags;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
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,
|
||||
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,
|
||||
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)
|
||||
&& !memcmp(&si->snh_label, snh_label,
|
||||
sizeof(struct static_nh_label))
|
||||
&& si->flags == flags) {
|
||||
&& si->bh_type == bh_type) {
|
||||
route_unlock_node(rn);
|
||||
return 0;
|
||||
} 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->distance = distance;
|
||||
si->flags = flags;
|
||||
si->bh_type = bh_type;
|
||||
si->tag = tag;
|
||||
si->vrf_id = zvrf_id(zvrf);
|
||||
if (ifname)
|
||||
|
|
|
@ -61,18 +61,12 @@ struct static_route {
|
|||
/*
|
||||
* Nexthop value.
|
||||
*/
|
||||
enum blackhole_type bh_type;
|
||||
union g_addr addr;
|
||||
ifindex_t ifindex;
|
||||
|
||||
char ifname[INTERFACE_NAMSIZ + 1];
|
||||
|
||||
/* bit flags */
|
||||
u_char flags;
|
||||
/*
|
||||
see ZEBRA_FLAG_REJECT
|
||||
ZEBRA_FLAG_BLACKHOLE
|
||||
*/
|
||||
|
||||
/* Label information */
|
||||
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,
|
||||
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,
|
||||
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 *gatep = NULL;
|
||||
struct in_addr mask;
|
||||
u_char flag = 0;
|
||||
enum blackhole_type bh_type = 0;
|
||||
route_tag_t tag = 0;
|
||||
struct zebra_vrf *zvrf;
|
||||
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 */
|
||||
if (flag_str) {
|
||||
switch (flag_str[0]) {
|
||||
case 'r':
|
||||
case 'R': /* XXX */
|
||||
SET_FLAG(flag, ZEBRA_FLAG_REJECT);
|
||||
bh_type = BLACKHOLE_REJECT;
|
||||
break;
|
||||
case 'n':
|
||||
case 'N' /* XXX */:
|
||||
case 'b':
|
||||
case 'B': /* XXX */
|
||||
SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
|
||||
bh_type = BLACKHOLE_NULL;
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
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
|
||||
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
|
||||
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$gate|INTERFACE$ifname}\
|
||||
|null0$ifname\
|
||||
|<reject|blackhole>$flag\
|
||||
|<null0|reject|blackhole>$flag\
|
||||
>\
|
||||
[{\
|
||||
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");
|
||||
if (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");
|
||||
|
||||
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));
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|| re->type == ZEBRA_ROUTE_ISIS
|
||||
|| re->type == ZEBRA_ROUTE_NHRP
|
||||
|
@ -671,7 +663,26 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
|||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
|
@ -796,7 +807,20 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
|||
ifindex2ifname(nexthop->ifindex, re->vrf_id));
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
|
@ -839,11 +863,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
|
|||
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
|
||||
|| re->type == ZEBRA_ROUTE_ISIS
|
||||
|| 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:
|
||||
vty_out(vty, " %s", si->ifname);
|
||||
break;
|
||||
/* blackhole and Null0 mean the same thing */
|
||||
case STATIC_BLACKHOLE:
|
||||
if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
|
||||
switch (si->bh_type) {
|
||||
case BLACKHOLE_REJECT:
|
||||
vty_out(vty, " reject");
|
||||
else
|
||||
vty_out(vty, " Null0");
|
||||
break;
|
||||
default:
|
||||
vty_out(vty, " blackhole");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case STATIC_IPV4_GATEWAY_IFNAME:
|
||||
vty_out(vty, " %s %s",
|
||||
|
@ -1716,19 +1738,6 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
|
|||
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)
|
||||
vty_out(vty, " tag %" ROUTE_TAG_PRI,
|
||||
si->tag);
|
||||
|
@ -1763,8 +1772,7 @@ DEFPY (ipv6_route,
|
|||
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
|
||||
<\
|
||||
{X:X::X:X$gate|INTERFACE$ifname}\
|
||||
|null0$ifname\
|
||||
|<reject|blackhole>$flag\
|
||||
|<null0|reject|blackhole>$flag\
|
||||
>\
|
||||
[{\
|
||||
tag (1-4294967295)\
|
||||
|
|
|
@ -1051,6 +1051,7 @@ static int zread_route_add(struct zserv *client, u_short length,
|
|||
struct route_entry *re;
|
||||
struct nexthop *nexthop = NULL;
|
||||
int i, ret;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
s = client->ibuf;
|
||||
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);
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re);
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1163,7 +1164,7 @@ static int zread_route_del(struct zserv *client, u_short length,
|
|||
src_p = &api.src_prefix;
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
/* Get input stream. */
|
||||
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);
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re);
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1329,7 +1331,7 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
|
|||
table_id = zvrf->table_id;
|
||||
|
||||
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++;
|
||||
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;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
/* Get input stream. */
|
||||
s = client->ibuf;
|
||||
|
@ -1434,7 +1437,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
|
|||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re);
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
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;
|
||||
mpls_label_t label;
|
||||
struct nexthop *nexthop;
|
||||
enum blackhole_type bh_type = BLACKHOLE_NULL;
|
||||
|
||||
/* Get input stream. */
|
||||
s = client->ibuf;
|
||||
|
@ -1594,7 +1598,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
|
|||
}
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
route_entry_nexthop_blackhole_add(re);
|
||||
route_entry_nexthop_blackhole_add(re, bh_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1689,7 +1693,7 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
|
|||
src_pp = NULL;
|
||||
|
||||
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++;
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue