diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 8c08fe4c8f..2d05a9e194 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -430,12 +430,59 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) return (ret); } +static void bgp_show_nexthops_detail(struct vty *vty, + struct bgp *bgp, + struct bgp_nexthop_cache *bnc) +{ + char buf[PREFIX2STR_BUFFER]; + struct nexthop *nexthop; + + for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV6: + vty_out(vty, " gate %s\n", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, + buf, sizeof(buf))); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " gate %s, if %s\n", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, + buf, sizeof(buf)), + ifindex2ifname(nexthop->ifindex, + bgp->vrf_id)); + break; + case NEXTHOP_TYPE_IPV4: + vty_out(vty, " gate %s\n", + inet_ntop(AF_INET, &nexthop->gate.ipv4, + buf, sizeof(buf))); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " if %s\n", + ifindex2ifname(nexthop->ifindex, + bgp->vrf_id)); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " gate %s, if %s\n", + inet_ntop(AF_INET, &nexthop->gate.ipv4, + buf, sizeof(buf)), + ifindex2ifname(nexthop->ifindex, + bgp->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " blackhole\n"); + break; + default: + vty_out(vty, + " invalid nexthop type %u\n", + nexthop->type); + } +} + static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail) { struct bgp_node *rn; struct bgp_nexthop_cache *bnc; char buf[PREFIX2STR_BUFFER]; - struct nexthop *nexthop; time_t tbuf; afi_t afi; @@ -454,70 +501,13 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail) &rn->p.u.prefix, buf, sizeof(buf)), bnc->metric, bnc->path_count); - if (detail) - for (nexthop = bnc->nexthop; - nexthop; - nexthop = nexthop->next) - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV6: - vty_out(vty, - " gate %s\n", - inet_ntop( - AF_INET6, - &nexthop->gate - .ipv6, - buf, - sizeof(buf))); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out(vty, - " gate %s, if %s\n", - inet_ntop( - AF_INET6, - &nexthop->gate - .ipv6, - buf, - sizeof(buf)), - ifindex2ifname( - nexthop->ifindex, - bgp->vrf_id)); - break; - case NEXTHOP_TYPE_IPV4: - vty_out(vty, - " gate %s\n", - inet_ntop( - AF_INET, - &nexthop->gate - .ipv4, - buf, - sizeof(buf))); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out(vty, - " if %s\n", - ifindex2ifname( - nexthop->ifindex, - bgp->vrf_id)); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out(vty, - " gate %s, if %s\n", - inet_ntop( - AF_INET, - &nexthop->gate - .ipv4, - buf, - sizeof(buf)), - ifindex2ifname( - nexthop->ifindex, - bgp->vrf_id)); - break; - default: - vty_out(vty, - " invalid nexthop type %u\n", - nexthop->type); - } - } else { + + if (!detail) + continue; + + bgp_show_nexthops_detail(vty, bgp, bnc); + + } else{ vty_out(vty, " %s invalid\n", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index bf1042a724..039fac4e67 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1320,23 +1320,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p, req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; - if (re->nexthop_num == 1 - && re->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { - discard = 1; - - 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); if (src_p) addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, @@ -1395,6 +1378,27 @@ static int netlink_route_multipath(int cmd, struct prefix *p, if (nexthop_num == 1 || multipath_num == 1) { nexthop_num = 0; for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + /* + * So we want to cover 2 types of blackhole + * routes here: + * 1) A normal blackhole route( ala from a static + * install. + * 2) A recursively resolved blackhole route + */ + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { + switch (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; + } + goto skip; + } if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) { if (!setsrc) { diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 4c63d1d8bf..bb49663319 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -370,6 +370,10 @@ static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop, resolved_hop->ifindex = newhop->ifindex; } + if (newhop->type == NEXTHOP_TYPE_BLACKHOLE) { + resolved_hop->type = NEXTHOP_TYPE_BLACKHOLE; + resolved_hop->bh_type = nexthop->bh_type; + } resolved_hop->rparent = nexthop; nexthop_add(&nexthop->resolved, resolved_hop); } @@ -496,8 +500,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re, } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) { resolved = 0; for (ALL_NEXTHOPS(match->nexthop, newhop)) { - if (newhop->type == NEXTHOP_TYPE_BLACKHOLE) - continue; if (!CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB)) continue; @@ -521,8 +523,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re, } else if (re->type == ZEBRA_ROUTE_STATIC) { resolved = 0; for (ALL_NEXTHOPS(match->nexthop, newhop)) { - if (newhop->type == NEXTHOP_TYPE_BLACKHOLE) - continue; if (!CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB)) continue;