diff options
Diffstat (limited to 'bgpd/bgp_route.c')
| -rw-r--r-- | bgpd/bgp_route.c | 166 |
1 files changed, 112 insertions, 54 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index af73a3afc4..4fb4faebc2 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -196,7 +196,8 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) e = *extra; if (e->damp_info) - bgp_damp_info_free(e->damp_info, 0); + bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi, + e->damp_info->safi); e->damp_info = NULL; if (e->parent) { @@ -1243,7 +1244,7 @@ static int bgp_cluster_filter(struct peer *peer, struct attr *attr) static int bgp_input_modifier(struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi, const char *rmap_name, mpls_label_t *label, - uint32_t num_labels) + uint32_t num_labels, struct bgp_node *rn) { struct bgp_filter *filter; struct bgp_path_info rmap_path = { 0 }; @@ -1278,6 +1279,8 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p, rmap_path.peer = peer; rmap_path.attr = attr; rmap_path.extra = &extra; + rmap_path.net = rn; + extra.num_labels = num_labels; if (label && num_labels && num_labels <= BGP_MAX_LABELS) memcpy(extra.label, label, @@ -1639,9 +1642,9 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, return 0; } -#ifdef BGP_SEND_ASPATH_CHECK /* AS path loop check. */ - if (onlypeer && aspath_loop_check(piattr->aspath, onlypeer->as)) { + if (onlypeer && onlypeer->as_path_loop_detection + && aspath_loop_check(piattr->aspath, onlypeer->as)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( "%s [Update:SEND] suppress announcement to peer AS %u " @@ -1649,7 +1652,6 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, onlypeer->host, onlypeer->as); return 0; } -#endif /* BGP_SEND_ASPATH_CHECK */ /* If we're a CONFED we need to loop check the CONFED ID too */ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { @@ -1751,18 +1753,22 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, * if * the peer (group) is configured to receive link-local nexthop * unchanged - * and it is available in the prefix OR we're not reflecting the route - * and + * and it is available in the prefix OR we're not reflecting the route, + * link-local nexthop address is valid and * the peer (group) to whom we're going to announce is on a shared * network * and this is either a self-originated route or the peer is EBGP. + * By checking if nexthop LL address is valid we are sure that + * we do not announce LL address as `::`. */ if (NEXTHOP_IS_V6) { attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; if ((CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) - || (!reflect && peer->shared_network + || (!reflect + && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) + && peer->shared_network && (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP))) { attr->mp_nexthop_len = @@ -1791,6 +1797,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, memset(&rmap_path, 0, sizeof(struct bgp_path_info)); rmap_path.peer = peer; rmap_path.attr = attr; + rmap_path.net = rn; if (pi->extra) { memcpy(&dummy_rmap_path_extra, pi->extra, @@ -1938,19 +1945,19 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, __func__, family2str(family)); subgroup_announce_reset_nhop(family, attr); } + } - /* If IPv6/MP and nexthop does not have any override and happens - * to - * be a link-local address, reset it so that we don't pass along - * the - * source's link-local IPv6 address to recipients who may not be - * on - * the same interface. - */ - if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) { - if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) - subgroup_announce_reset_nhop(AF_INET6, attr); - } + /* If IPv6/MP and nexthop does not have any override and happens + * to + * be a link-local address, reset it so that we don't pass along + * the + * source's link-local IPv6 address to recipients who may not be + * on + * the same interface. + */ + if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) { + if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) + subgroup_announce_reset_nhop(AF_INET6, attr); } return 1; @@ -3034,6 +3041,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, int connected = 0; int do_loop_check = 1; int has_valid_label = 0; + afi_t nh_afi; #if ENABLE_BGP_VNC int vnc_implicit_withdraw = 0; #endif @@ -3149,7 +3157,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * intern * the attr (which takes over the memory references) */ if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, - label, num_labels) == RMAP_DENY) { + label, num_labels, rn) == RMAP_DENY) { peer->stat_pfx_filter++; reason = "route-map;"; bgp_attr_flush(&new_attr); @@ -3429,8 +3437,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, /* Nexthop reachability check - for unicast and * labeled-unicast.. */ - if ((afi == AFI_IP || afi == AFI_IP6) - && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) + || (safi == SAFI_EVPN && + bgp_evpn_is_prefix_nht_supported(p))) { if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) @@ -3445,8 +3455,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, if (pi->extra && pi->extra->bgp_orig) bgp_nexthop = pi->extra->bgp_orig; - if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi, - NULL, connected) + nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr); + + if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi, + pi, NULL, connected) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID); else { @@ -3494,7 +3506,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * updating * the attributes for the route in the VNI(s). */ - if (safi == SAFI_EVPN && !same_attr) + if (safi == SAFI_EVPN && !same_attr && + CHECK_FLAG(pi->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, pi); /* Process change. */ @@ -3567,8 +3580,9 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, evpn == NULL ? NULL : &evpn->gw_ip); } /* Nexthop reachability check. */ - if ((afi == AFI_IP || afi == AFI_IP6) - && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) + || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) { if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) @@ -3577,7 +3591,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, else connected = 0; - if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected) + nh_afi = BGP_ATTR_NH_AFI(afi, new->attr); + + if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL, + connected) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) bgp_path_info_set_flag(rn, new, BGP_PATH_VALID); else { @@ -3628,7 +3645,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, return -1; /* If this is an EVPN route, process for import. */ - if (safi == SAFI_EVPN) + if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, new); hook_call(bgp_process, bgp, afi, safi, rn, peer, false); @@ -7880,7 +7897,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, /* dampening route */ static void damp_route_vty_out(struct vty *vty, struct prefix *p, - struct bgp_path_info *path, int display, + struct bgp_path_info *path, int display, afi_t afi, safi_t safi, bool use_json, json_object *json) { struct attr *attr; @@ -7911,13 +7928,13 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, } if (use_json) - bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, - use_json, json); + bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi, + safi, use_json, json); else vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, use_json, - json)); + BGP_UPTIME_LEN, afi, safi, + use_json, json)); /* Print attribute */ attr = path->attr; @@ -7944,7 +7961,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, /* flap route */ static void flap_route_vty_out(struct vty *vty, struct prefix *p, - struct bgp_path_info *path, int display, + struct bgp_path_info *path, int display, afi_t afi, safi_t safi, bool use_json, json_object *json) { struct attr *attr; @@ -8003,12 +8020,13 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p, && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) { if (use_json) bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, use_json, json); + BGP_UPTIME_LEN, afi, safi, + use_json, json); else vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, - use_json, json)); + BGP_UPTIME_LEN, afi, + safi, use_json, json)); } else { if (!use_json) vty_out(vty, "%*s ", 8, " "); @@ -8876,7 +8894,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, } if (path->extra && path->extra->damp_info) - bgp_damp_info_vty(vty, path, json_path); + bgp_damp_info_vty(vty, path, afi, safi, json_path); /* Remote Label */ if (path->extra && bgp_is_valid_label(&path->extra->label[0]) @@ -9289,11 +9307,11 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, } if (type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) - damp_route_vty_out(vty, &rn->p, pi, display, + damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP, safi, use_json, json_paths); else if (type == bgp_show_type_flap_statistics || type == bgp_show_type_flap_neighbor) - flap_route_vty_out(vty, &rn->p, pi, display, + flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP, safi, use_json, json_paths); else route_vty_out(vty, &rn->p, pi, display, safi, @@ -10545,7 +10563,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, } ret = bgp_show(vty, bgp, afi, safi, type, p, 0); - prefix_free(p); + prefix_free(&p); return ret; } @@ -11106,7 +11124,7 @@ DEFUN (show_bgp_l2vpn_evpn_route_prefix, argv_find(argv, argc, "X:X::X:X", &idx)) network = argv[idx]->arg; else if (argv_find(argv, argc, "A.B.C.D/M", &idx) || - argv_find(argv, argc, "A.B.C.D/M", &idx)) { + argv_find(argv, argc, "X:X::X:X/M", &idx)) { network = argv[idx]->arg; prefix_check = 1; } else { @@ -11294,7 +11312,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, /* Filter prefix using route-map */ ret = bgp_input_modifier(peer, &rn->p, &attr, - afi, safi, rmap_name, NULL, 0); + afi, safi, rmap_name, NULL, 0, + NULL); if (type == bgp_show_adj_route_filtered && !route_filtered && ret != RMAP_DENY) { @@ -11923,6 +11942,32 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo, } } +/* If we enter `distance bgp (1-255) (1-255) (1-255)`, + * we should tell ZEBRA update the routes for a specific + * AFI/SAFI to reflect changes in RIB. + */ +static void bgp_announce_routes_distance_update(struct bgp *bgp, + afi_t update_afi, + safi_t update_safi) +{ + afi_t afi; + safi_t safi; + + FOREACH_AFI_SAFI (afi, safi) { + if (!bgp_fibupd_safi(safi)) + continue; + + if (afi != update_afi && safi != update_safi) + continue; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug( + "%s: Announcing routes due to distance change afi/safi (%d/%d)", + __func__, afi, safi); + bgp_zebra_announce_table(bgp, afi, safi); + } +} + DEFUN (bgp_distance, bgp_distance_cmd, "distance bgp (1-255) (1-255) (1-255)", @@ -11936,15 +11981,23 @@ DEFUN (bgp_distance, int idx_number = 2; int idx_number_2 = 3; int idx_number_3 = 4; + int distance_ebgp = atoi(argv[idx_number]->arg); + int distance_ibgp = atoi(argv[idx_number_2]->arg); + int distance_local = atoi(argv[idx_number_3]->arg); afi_t afi; safi_t safi; afi = bgp_node_afi(vty); safi = bgp_node_safi(vty); - bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg); - bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg); - bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg); + if (bgp->distance_ebgp[afi][safi] != distance_ebgp + || bgp->distance_ibgp[afi][safi] != distance_ibgp + || bgp->distance_local[afi][safi] != distance_local) { + bgp->distance_ebgp[afi][safi] = distance_ebgp; + bgp->distance_ibgp[afi][safi] = distance_ibgp; + bgp->distance_local[afi][safi] = distance_local; + bgp_announce_routes_distance_update(bgp, afi, safi); + } return CMD_SUCCESS; } @@ -11965,9 +12018,14 @@ DEFUN (no_bgp_distance, afi = bgp_node_afi(vty); safi = bgp_node_safi(vty); - bgp->distance_ebgp[afi][safi] = 0; - bgp->distance_ibgp[afi][safi] = 0; - bgp->distance_local[afi][safi] = 0; + if (bgp->distance_ebgp[afi][safi] != 0 + || bgp->distance_ibgp[afi][safi] != 0 + || bgp->distance_local[afi][safi] != 0) { + bgp->distance_ebgp[afi][safi] = 0; + bgp->distance_ibgp[afi][safi] = 0; + bgp->distance_local[afi][safi] = 0; + bgp_announce_routes_distance_update(bgp, afi, safi); + } return CMD_SUCCESS; } @@ -12196,7 +12254,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, pi_temp = pi->next; bgp_damp_info_free( pi->extra->damp_info, - 1); + 1, afi, safi); pi = pi_temp; } else pi = pi->next; @@ -12216,7 +12274,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, pi_temp = pi->next; bgp_damp_info_free( pi->extra->damp_info, - 1); + 1, afi, safi); pi = pi_temp; } else pi = pi->next; @@ -12238,7 +12296,7 @@ DEFUN (clear_ip_bgp_dampening, BGP_STR "Clear route flap dampening information\n") { - bgp_damp_info_clean(); + bgp_damp_info_clean(AFI_IP, SAFI_UNICAST); return CMD_SUCCESS; } |
