summaryrefslogtreecommitdiff
path: root/bgpd/bgp_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r--bgpd/bgp_route.c166
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;
}