diff options
34 files changed, 989 insertions, 346 deletions
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index d4ccca84bb..3d2dda4ee4 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -441,7 +441,7 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, } if (total_count && !use_json) vty_out(vty, - "\nDisplayed %ld flowspec entries\n", + "\nDisplayed %ld flowspec entries\n", total_count); return CMD_SUCCESS; } diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 490451f193..cadef39974 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -265,7 +265,7 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) from_peer->addpath_paths_limit[afi][safi]; } - if (bgp_getsockname(peer) < 0) { + if (bgp_getsockname(keeper) < 0) { flog_err(EC_LIB_SOCKET, "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)", (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER) @@ -277,7 +277,7 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) return NULL; } if (going_away->status > Active) { - if (bgp_getsockname(from_peer) < 0) { + if (bgp_getsockname(going_away) < 0) { flog_err(EC_LIB_SOCKET, "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)", @@ -325,8 +325,8 @@ void bgp_timer_set(struct peer_connection *connection) /* First entry point of peer's finite state machine. In Idle status start timer is on unless peer is shutdown or peer is inactive. All other timer must be turned off */ - if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer) - || peer->bgp->vrf_id == VRF_UNKNOWN) { + if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(connection) || + peer->bgp->vrf_id == VRF_UNKNOWN) { EVENT_OFF(connection->t_start); } else { BGP_TIMER_ON(connection->t_start, bgp_start_timer, @@ -1694,11 +1694,11 @@ bgp_connect_success(struct peer_connection *connection) return bgp_stop(connection); } - if (bgp_getsockname(peer) < 0) { + if (bgp_getsockname(connection) < 0) { flog_err_sys(EC_LIB_SOCKET, "%s: bgp_getsockname(): failed for peer %s, fd %d", __func__, peer->host, connection->fd); - bgp_notify_send(peer->connection, BGP_NOTIFY_FSM_ERR, + bgp_notify_send(connection, BGP_NOTIFY_FSM_ERR, bgp_fsm_error_subcode(connection->status)); bgp_writes_on(connection); return BGP_FSM_FAILURE; @@ -1740,11 +1740,11 @@ bgp_connect_success_w_delayopen(struct peer_connection *connection) return bgp_stop(connection); } - if (bgp_getsockname(peer) < 0) { + if (bgp_getsockname(connection) < 0) { flog_err_sys(EC_LIB_SOCKET, "%s: bgp_getsockname(): failed for peer %s, fd %d", __func__, peer->host, connection->fd); - bgp_notify_send(peer->connection, BGP_NOTIFY_FSM_ERR, + bgp_notify_send(connection, BGP_NOTIFY_FSM_ERR, bgp_fsm_error_subcode(connection->status)); bgp_writes_on(connection); return BGP_FSM_FAILURE; @@ -1807,12 +1807,14 @@ bgp_connect_fail(struct peer_connection *connection) /* after connect is called(), getpeername is able to return * port and address on non established streams */ -static void bgp_connect_in_progress_update_connection(struct peer *peer) +static void bgp_connect_in_progress_update_connection(struct peer_connection *connection) { - bgp_updatesockname(peer); + struct peer *peer = connection->peer; + + bgp_updatesockname(peer, connection); if (!peer->su_remote && !BGP_CONNECTION_SU_UNSPEC(peer->connection)) { /* if connect initiated, then dest port and dest addresses are well known */ - peer->su_remote = sockunion_dup(&peer->connection->su); + peer->su_remote = sockunion_dup(&connection->su); if (sockunion_family(peer->su_remote) == AF_INET) peer->su_remote->sin.sin_port = htons(peer->port); else if (sockunion_family(peer->su_remote) == AF_INET6) @@ -1916,7 +1918,7 @@ static enum bgp_fsm_state_progress bgp_start(struct peer_connection *connection) __func__, peer->connection->fd); return BGP_FSM_FAILURE; } - bgp_connect_in_progress_update_connection(peer); + bgp_connect_in_progress_update_connection(connection); /* * - when the socket becomes ready, poll() will signify POLLOUT @@ -2745,10 +2747,7 @@ static void bgp_gr_update_mode_of_all_peers(struct bgp *bgp, peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset_safe(peer, &nnode); } else { group = peer->group; @@ -2768,10 +2767,7 @@ static void bgp_gr_update_mode_of_all_peers(struct bgp *bgp, member->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); } } @@ -2973,10 +2969,7 @@ unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_state, if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); } else { group = peer->group; @@ -2984,10 +2977,7 @@ unsigned int bgp_peer_gr_action(struct peer *peer, enum peer_mode old_state, member->last_reset = PEER_DOWN_CAPABILITY_CHANGE; bgp_peer_move_to_gr_mode(member, new_state); - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); } } diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 844f6b9af2..f1bea1c189 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -504,7 +504,7 @@ static void bgp_accept(struct event *thread) bgp_fsm_change_status(connection1, Active); EVENT_OFF(connection1->t_start); - if (peer_active(peer1)) { + if (peer_active(peer1->connection)) { if (CHECK_FLAG(peer1->flags, PEER_FLAG_TIMER_DELAYOPEN)) BGP_EVENT_ADD(connection1, @@ -557,7 +557,7 @@ static void bgp_accept(struct event *thread) } /* Check that at least one AF is activated for the peer. */ - if (!peer_active(peer1)) { + if (!peer_active(connection1)) { if (bgp_debug_neighbor_events(peer1)) zlog_debug( "%s - incoming conn rejected - no AF activated for peer", @@ -658,7 +658,7 @@ static void bgp_accept(struct event *thread) bgp_event_update(connection1, TCP_connection_closed); } - if (peer_active(peer)) { + if (peer_active(peer->connection)) { if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER_DELAYOPEN)) BGP_EVENT_ADD(connection, TCP_connection_open_w_delay); else @@ -861,7 +861,7 @@ enum connect_result bgp_connect(struct peer_connection *connection) htons(peer->port), ifindex); } -void bgp_updatesockname(struct peer *peer) +void bgp_updatesockname(struct peer *peer, struct peer_connection *connection) { if (peer->su_local) { sockunion_free(peer->su_local); @@ -873,14 +873,16 @@ void bgp_updatesockname(struct peer *peer) peer->su_remote = NULL; } - peer->su_local = sockunion_getsockname(peer->connection->fd); - peer->su_remote = sockunion_getpeername(peer->connection->fd); + peer->su_local = sockunion_getsockname(connection->fd); + peer->su_remote = sockunion_getpeername(connection->fd); } /* After TCP connection is established. Get local address and port. */ -int bgp_getsockname(struct peer *peer) +int bgp_getsockname(struct peer_connection *connection) { - bgp_updatesockname(peer); + struct peer *peer = connection->peer; + + bgp_updatesockname(peer, peer->connection); if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote, &peer->nexthop, peer)) { diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h index 61ca19a34d..ed1a72ec89 100644 --- a/bgpd/bgp_network.h +++ b/bgpd/bgp_network.h @@ -22,8 +22,8 @@ extern int bgp_socket(struct bgp *bgp, unsigned short port, extern void bgp_close_vrf_socket(struct bgp *bgp); extern void bgp_close(void); extern enum connect_result bgp_connect(struct peer_connection *connection); -extern int bgp_getsockname(struct peer *peer); -extern void bgp_updatesockname(struct peer *peer); +extern int bgp_getsockname(struct peer_connection *connection); +extern void bgp_updatesockname(struct peer *peer, struct peer_connection *connection); extern int bgp_md5_set_prefix(struct bgp *bgp, struct prefix *p, const char *password); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index bf0f3b15cf..1ef90a8e38 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -444,7 +444,7 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) !peer_established(peer->connection) && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) { connection = peer->connection; - if (peer_active(peer)) + if (peer_active(connection)) BGP_EVENT_ADD(connection, BGP_Stop); BGP_EVENT_ADD(connection, BGP_Start); } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 9b633b7139..ed83757ea3 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -1066,9 +1066,16 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) case AFI_IP6: p->family = AF_INET6; if (pi->attr->srv6_l3vpn) { - IPV6_ADDR_COPY(&(p->u.prefix6), - &(pi->attr->srv6_l3vpn->sid)); p->prefixlen = IPV6_MAX_BITLEN; + if (pi->attr->srv6_l3vpn->transposition_len != 0 && + BGP_PATH_INFO_NUM_LABELS(pi)) { + IPV6_ADDR_COPY(&p->u.prefix6, &pi->attr->srv6_l3vpn->sid); + transpose_sid(&p->u.prefix6, + decode_label(&pi->extra->labels->label[0]), + pi->attr->srv6_l3vpn->transposition_offset, + pi->attr->srv6_l3vpn->transposition_len); + } else + IPV6_ADDR_COPY(&(p->u.prefix6), &(pi->attr->srv6_l3vpn->sid)); } else if (is_bgp_static) { p->u.prefix6 = p_orig->u.prefix6; p->prefixlen = p_orig->prefixlen; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index a76a300c11..e9cc52449b 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -2054,7 +2054,7 @@ static int bgp_open_receive(struct peer_connection *connection, return BGP_Stop; /* Get sockname. */ - if (bgp_getsockname(peer) < 0) { + if (bgp_getsockname(connection) < 0) { flog_err_sys(EC_LIB_SOCKET, "%s: bgp_getsockname() failed for peer: %s", __func__, peer->host); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index d1238bc8de..6ff94129dc 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2940,9 +2940,7 @@ DEFUN(bgp_reject_as_sets, bgp_reject_as_sets_cmd, */ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { peer->last_reset = PEER_DOWN_AS_SETS_REJECT; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } return CMD_SUCCESS; @@ -2965,9 +2963,7 @@ DEFUN(no_bgp_reject_as_sets, no_bgp_reject_as_sets_cmd, */ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { peer->last_reset = PEER_DOWN_AS_SETS_REJECT; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } return CMD_SUCCESS; @@ -5100,10 +5096,7 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if, peer->last_reset = PEER_DOWN_V6ONLY_CHANGE; /* v6only flag changed. Reset bgp seesion */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); } @@ -5264,7 +5257,7 @@ DEFUN (no_neighbor, * interface. */ if (peer->ifp) bgp_zebra_terminate_radv(peer->bgp, peer); - peer_notify_unconfig(peer); + peer_notify_unconfig(peer->connection); peer_delete(peer); return CMD_SUCCESS; } @@ -5300,10 +5293,10 @@ DEFUN (no_neighbor, if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) bgp_zebra_terminate_radv(peer->bgp, peer); - peer_notify_unconfig(peer); + peer_notify_unconfig(peer->connection); peer_delete(peer); if (other && other->connection->status != Deleted) { - peer_notify_unconfig(other); + peer_notify_unconfig(other->connection); peer_delete(other); } } @@ -5338,7 +5331,7 @@ DEFUN (no_neighbor_interface_config, /* Request zebra to terminate IPv6 RAs on this interface. */ if (peer->ifp) bgp_zebra_terminate_radv(peer->bgp, peer); - peer_notify_unconfig(peer); + peer_notify_unconfig(peer->connection); peer_delete(peer); } else { vty_out(vty, "%% Create the bgp interface first\n"); @@ -5746,7 +5739,7 @@ DEFUN (no_neighbor_set_peer_group, if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) bgp_zebra_terminate_radv(peer->bgp, peer); - peer_notify_unconfig(peer); + peer_notify_unconfig(peer->connection); ret = peer_delete(peer); return bgp_vty_return(vty, ret); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 16f4a0d2df..688dfacaa0 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -137,7 +137,7 @@ static void bgp_start_interface_nbrs(struct bgp *bgp, struct interface *ifp) for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0) && !peer_established(peer->connection)) { - if (peer_active(peer)) + if (peer_active(peer->connection)) BGP_EVENT_ADD(peer->connection, BGP_Stop); BGP_EVENT_ADD(peer->connection, BGP_Start); } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 258fc87f96..f92ae969f8 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -309,9 +309,7 @@ static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id, peer->last_reset = PEER_DOWN_RID_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } /* EVPN uses router id in RD, update them */ @@ -447,8 +445,7 @@ void bm_wait_for_fib_set(bool set) peer->connection->status)) continue; - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } } } @@ -507,8 +504,7 @@ void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set) if (!BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) continue; - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } } @@ -532,9 +528,7 @@ void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id) peer->last_reset = PEER_DOWN_CLID_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } } @@ -556,9 +550,7 @@ void bgp_cluster_id_unset(struct bgp *bgp) peer->last_reset = PEER_DOWN_CLID_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } } @@ -637,14 +629,10 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str) if (already_confed) { if (ptype == BGP_PEER_EBGP) { peer->local_as = as; - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) { + if (peer_notify_config_change(peer->connection)) peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } else + else bgp_session_reset_safe(peer, &nnode); } } else { @@ -655,14 +643,10 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str) /* Reset the local_as to be our EBGP one */ if (ptype == BGP_PEER_EBGP) peer->local_as = as; - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) { + if (peer_notify_config_change(peer->connection)) peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } else + else bgp_session_reset_safe(peer, &nnode); } } @@ -684,12 +668,7 @@ void bgp_confederation_id_unset(struct bgp *bgp) if (peer_sort(peer) != BGP_PEER_IBGP) { peer->local_as = bgp->as; peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset_safe(peer, &nnode); } } @@ -736,14 +715,10 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as, const char *as_str) if (peer->as == as) { peer->local_as = bgp->as; (void)peer_sort(peer); - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) { + if (peer_notify_config_change(peer->connection)) peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE; - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } else + else bgp_session_reset_safe(peer, &nnode); } } @@ -793,14 +768,10 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as) if (peer->as == as) { peer->local_as = bgp->confed_id; (void)peer_sort(peer); - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) { + if (peer_notify_config_change(peer->connection)) peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE; - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } else + else bgp_session_reset_safe(peer, &nnode); } } @@ -2015,7 +1986,7 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct); } - active = peer_active(peer); + active = peer_active(peer->connection); if (!active) { if (peer->connection->su.sa.sa_family == AF_UNSPEC) peer->last_reset = PEER_DOWN_NBR_ADDR; @@ -2048,7 +2019,7 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, if (bgp->autoshutdown) peer_flag_set(peer, PEER_FLAG_SHUTDOWN); /* Set up peer's events and timers. */ - else if (!active && peer_active(peer)) + else if (!active && peer_active(peer->connection)) bgp_timer_set(peer->connection); bgp_peer_gr_flags_update(peer); @@ -2099,10 +2070,7 @@ void peer_as_change(struct peer *peer, as_t as, enum peer_asn_type as_type, /* Stop peer. */ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); } origtype = peer_sort_lookup(peer); @@ -2444,13 +2412,13 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi) if (peer_af_create(peer, afi, safi) == NULL) return 1; - active = peer_active(peer); + active = peer_active(peer->connection); peer->afc[afi][safi] = 1; if (peer->group) peer_group2peer_config_copy_af(peer->group, peer, afi, safi); - if (!active && peer_active(peer)) { + if (!active && peer_active(peer->connection)) { bgp_timer_set(peer->connection); } else { peer->last_reset = PEER_DOWN_AF_ACTIVATE; @@ -2467,15 +2435,11 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi) false); } } else { - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } } - if (peer->connection->status == OpenSent || - peer->connection->status == OpenConfirm) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); + /* * If we are turning on a AFI/SAFI locally and we've * started bringing a peer up, we need to tell @@ -2486,10 +2450,8 @@ static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi) * activation. */ other = peer->doppelganger; - if (other && (other->connection->status == OpenSent || - other->connection->status == OpenConfirm)) - bgp_notify_send(other->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + if (other) + peer_notify_config_change(other->connection); } return 0; @@ -2596,14 +2558,10 @@ static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi, bgp_clear_route(peer, afi, safi); peer->pcount[afi][safi] = 0; } else { - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } - } else { - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } + } else + peer_notify_config_change(peer->connection); } return false; @@ -3076,11 +3034,20 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, return 0; } -void peer_notify_unconfig(struct peer *peer) +bool peer_notify_config_change(struct peer_connection *connection) { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_PEER_UNCONFIG); + if (BGP_IS_VALID_STATE_FOR_NOTIF(connection->status)) { + bgp_notify_send(connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + return true; + } + + return false; +} + +void peer_notify_unconfig(struct peer_connection *connection) +{ + if (BGP_IS_VALID_STATE_FOR_NOTIF(connection->status)) + bgp_notify_send(connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_PEER_UNCONFIG); } static void peer_notify_shutdown(struct peer *peer) @@ -3107,9 +3074,9 @@ void peer_group_notify_unconfig(struct peer_group *group) other = peer->doppelganger; if (other && other->connection->status != Deleted) { other->group = NULL; - peer_notify_unconfig(other); + peer_notify_unconfig(other->connection); } else - peer_notify_unconfig(peer); + peer_notify_unconfig(peer->connection); } } @@ -3356,10 +3323,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, peer->last_reset = PEER_DOWN_RMAP_BIND; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); } @@ -3394,7 +3358,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, } /* Set up peer's events and timers. */ - if (peer_active(peer)) + if (peer_active(peer->connection)) bgp_timer_set(peer->connection); } @@ -4635,9 +4599,11 @@ bool bgp_path_attribute_treat_as_withdraw(struct peer *peer, char *buf, } /* If peer is configured at least one address family return 1. */ -bool peer_active(struct peer *peer) +bool peer_active(struct peer_connection *connection) { - if (BGP_CONNECTION_SU_UNSPEC(peer->connection)) + struct peer *peer = connection->peer; + + if (BGP_CONNECTION_SU_UNSPEC(connection)) return false; if (peer->bfd_config) { @@ -4726,8 +4692,7 @@ void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, PEER_FLAG_CONFIG_NODE))) peer_delete(peer->doppelganger); - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } else if (type == peer_change_reset_in) { if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_RCV)) bgp_route_refresh_send(peer, afi, safi, 0, 0, 0, @@ -4739,8 +4704,7 @@ void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, PEER_FLAG_CONFIG_NODE))) peer_delete(peer->doppelganger); - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + peer_notify_config_change(peer->connection); } } else if (type == peer_change_reset_out) { paf = peer_af_find(peer, afi, safi); @@ -4939,10 +4903,7 @@ static void peer_flag_modify_action(struct peer *peer, uint64_t flag) peer->v_start = BGP_INIT_START_TIMER; BGP_EVENT_ADD(peer->connection, BGP_Stop); } - } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) { - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } else + } else if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); } @@ -5426,12 +5387,7 @@ int peer_ebgp_multihop_set(struct peer *peer, int ttl) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (peer->sort != BGP_PEER_IBGP) { - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* Reconfigure BFD peer with new TTL. */ @@ -5446,10 +5402,7 @@ int peer_ebgp_multihop_set(struct peer *peer, int ttl) member->ttl = group->conf->ttl; - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); /* Reconfigure BFD peer with new TTL. */ @@ -5484,10 +5437,7 @@ int peer_ebgp_multihop_unset(struct peer *peer) peer->ttl = ttl; if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* Reconfigure BFD peer with new TTL. */ @@ -5502,10 +5452,7 @@ int peer_ebgp_multihop_unset(struct peer *peer) member->ttl = BGP_DEFAULT_TTL; if (member->connection->fd >= 0) { - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); } @@ -5657,10 +5604,7 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* Apply new source configuration to BFD session. */ @@ -5695,10 +5639,7 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname) member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); /* Apply new source configuration to BFD session. */ @@ -5728,10 +5669,7 @@ void peer_update_source_addr_set(struct peer *peer, const union sockunion *su) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* Apply new source configuration to BFD session. */ @@ -5765,10 +5703,7 @@ void peer_update_source_addr_set(struct peer *peer, const union sockunion *su) member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(member); /* Apply new source configuration to BFD session. */ @@ -5816,10 +5751,7 @@ void peer_update_source_unset(struct peer *peer) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* Apply new source configuration to BFD session. */ @@ -5852,10 +5784,7 @@ void peer_update_source_unset(struct peer *peer) member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); /* Apply new source configuration to BFD session. */ @@ -6369,7 +6298,7 @@ int peer_timers_connect_set(struct peer *peer, uint32_t connect) /* Skip peer-group mechanics for regular peers. */ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!peer_established(peer->connection)) { - if (peer_active(peer)) + if (peer_active(peer->connection)) BGP_EVENT_ADD(peer->connection, BGP_Stop); BGP_EVENT_ADD(peer->connection, BGP_Start); } @@ -6390,7 +6319,7 @@ int peer_timers_connect_set(struct peer *peer, uint32_t connect) member->v_connect = connect; if (!peer_established(member->connection)) { - if (peer_active(member)) + if (peer_active(member->connection)) BGP_EVENT_ADD(member->connection, BGP_Stop); BGP_EVENT_ADD(member->connection, BGP_Start); } @@ -6423,7 +6352,7 @@ int peer_timers_connect_unset(struct peer *peer) /* Skip peer-group mechanics for regular peers. */ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { if (!peer_established(peer->connection)) { - if (peer_active(peer)) + if (peer_active(peer->connection)) BGP_EVENT_ADD(peer->connection, BGP_Stop); BGP_EVENT_ADD(peer->connection, BGP_Start); } @@ -6444,7 +6373,7 @@ int peer_timers_connect_unset(struct peer *peer) member->v_connect = peer->bgp->default_connect_retry; if (!peer_established(member->connection)) { - if (peer_active(member)) + if (peer_active(member->connection)) BGP_EVENT_ADD(member->connection, BGP_Stop); BGP_EVENT_ADD(member->connection, BGP_Start); } @@ -6885,10 +6814,7 @@ int peer_local_as_unset(struct peer *peer) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; /* Send notification or stop peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) BGP_EVENT_ADD(peer->connection, BGP_Stop); /* Skip peer-group mechanics for regular peers. */ @@ -6914,10 +6840,7 @@ int peer_local_as_unset(struct peer *peer) member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; /* Send notification or stop peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); } @@ -6946,10 +6869,7 @@ int peer_password_set(struct peer *peer, const char *password) if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { peer->last_reset = PEER_DOWN_PASSWORD_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* @@ -6984,10 +6904,7 @@ int peer_password_set(struct peer *peer, const char *password) member->last_reset = PEER_DOWN_PASSWORD_CHANGE; /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); /* Attempt to install password on socket. */ @@ -7030,10 +6947,7 @@ int peer_password_unset(struct peer *peer) /* Check if handling a regular peer. */ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(peer->connection)) bgp_session_reset(peer); /* Attempt to uninstall password on socket. */ @@ -7057,10 +6971,7 @@ int peer_password_unset(struct peer *peer) XFREE(MTYPE_PEER_PASSWORD, member->password); /* Send notification or reset peer depending on state. */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(member->connection->status)) - bgp_notify_send(member->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else + if (!peer_notify_config_change(member->connection)) bgp_session_reset(member); /* Attempt to uninstall password on socket. */ @@ -8737,8 +8648,7 @@ static int peer_unshut_after_cfg(struct bgp *bgp) peer->host); peer->shut_during_cfg = false; - if (peer_active(peer) && - peer->connection->status != Established) { + if (peer_active(peer->connection) && peer->connection->status != Established) { if (peer->connection->status != Idle) BGP_EVENT_ADD(peer->connection, BGP_Stop); BGP_EVENT_ADD(peer->connection, BGP_Start); @@ -8841,11 +8751,7 @@ void bgp_terminate(void) peer); continue; } - if (BGP_IS_VALID_STATE_FOR_NOTIF( - peer->connection->status)) - bgp_notify_send(peer->connection, - BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_PEER_UNCONFIG); + peer_notify_unconfig(peer->connection); } } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index f123188ae8..df55d879e7 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -2295,7 +2295,7 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *); extern enum bgp_peer_sort peer_sort(struct peer *peer); extern enum bgp_peer_sort peer_sort_lookup(struct peer *peer); -extern bool peer_active(struct peer *); +extern bool peer_active(struct peer_connection *connection); extern bool peer_active_nego(struct peer *); extern bool peer_afc_received(struct peer *peer); extern bool peer_afc_advertised(struct peer *peer); @@ -2385,7 +2385,8 @@ extern int peer_remote_as(struct bgp *bgp, union sockunion *su, extern int peer_group_remote_as(struct bgp *bgp, const char *peer_str, as_t *as, enum peer_asn_type as_type, const char *as_str); extern int peer_delete(struct peer *peer); -extern void peer_notify_unconfig(struct peer *peer); +extern void peer_notify_unconfig(struct peer_connection *connection); +extern bool peer_notify_config_change(struct peer_connection *connection); extern int peer_group_delete(struct peer_group *); extern int peer_group_remote_as_delete(struct peer_group *); extern int peer_group_listen_range_add(struct peer_group *, struct prefix *); diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index c0db7f2b87..dafcac7c84 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2938,6 +2938,7 @@ BGP Extended Communities in Route Map match on to for the purpose of determining what type of SR-TE Policy Tunnel a BGP route can resolve over, and it also shows the order for resolving the BGP route if there are different tunnels. + - ``00`` Can match on a specific endpoint only which should be the nexthop of the route(Default Setting). - ``01`` Can match on a specific endpoint or a null endpoint. diff --git a/docker/ubuntu-ci/Dockerfile b/docker/ubuntu-ci/Dockerfile index 5c4649dc32..aaad3bc172 100644 --- a/docker/ubuntu-ci/Dockerfile +++ b/docker/ubuntu-ci/Dockerfile @@ -84,10 +84,11 @@ RUN apt update && apt upgrade -y && \ python3 -m pip install xmltodict && \ python3 -m pip install git+https://github.com/Exa-Networks/exabgp@0659057837cd6c6351579e9f0fa47e9fb7de7311 +ARG UID=1000 RUN groupadd -r -g 92 frr && \ groupadd -r -g 85 frrvty && \ adduser --system --ingroup frr --home /home/frr \ - --gecos "FRR suite" --shell /bin/bash frr && \ + --gecos "FRR suite" -u $UID --shell /bin/bash frr && \ usermod -a -G frrvty frr && \ useradd -d /var/run/exabgp/ -s /bin/false exabgp && \ echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \ diff --git a/lib/table.c b/lib/table.c index 3bf93894ec..cf185de226 100644 --- a/lib/table.c +++ b/lib/table.c @@ -208,32 +208,6 @@ struct route_node *route_node_match(struct route_table *table, return NULL; } -struct route_node *route_node_match_ipv4(struct route_table *table, - const struct in_addr *addr) -{ - struct prefix_ipv4 p; - - memset(&p, 0, sizeof(p)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.prefix = *addr; - - return route_node_match(table, (struct prefix *)&p); -} - -struct route_node *route_node_match_ipv6(struct route_table *table, - const struct in6_addr *addr) -{ - struct prefix_ipv6 p; - - memset(&p, 0, sizeof(p)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_BITLEN; - p.prefix = *addr; - - return route_node_match(table, &p); -} - /* Lookup same prefix node. Return NULL when we can't find route. */ struct route_node *route_node_lookup(struct route_table *table, union prefixconstptr pu) diff --git a/lib/table.h b/lib/table.h index acfc876154..c31be2b688 100644 --- a/lib/table.h +++ b/lib/table.h @@ -195,10 +195,6 @@ extern struct route_node *route_node_lookup_maynull(struct route_table *table, union prefixconstptr pu); extern struct route_node *route_node_match(struct route_table *table, union prefixconstptr pu); -extern struct route_node *route_node_match_ipv4(struct route_table *table, - const struct in_addr *addr); -extern struct route_node *route_node_match_ipv6(struct route_table *table, - const struct in6_addr *addr); extern unsigned long route_table_count(struct route_table *table); diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 199f4d75d4..cae93c6e53 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -933,6 +933,10 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) return; + if (ctx->count && !ctx->json) + vty_out(ctx->vty, "\n"); + ctx->count++; + sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])); if (c->cur.peer) sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], @@ -985,8 +989,6 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", buf[2]); - - vty_out(ctx->vty, "\n\n"); } DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, @@ -1030,7 +1032,6 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, else json_object_string_add(json_vrf, "status", "ok"); - ctx.count++; FOR_ALL_INTERFACES (vrf, ifp) nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx); } diff --git a/ripd/ripd.c b/ripd/ripd.c index 8768819fe2..2d038507ab 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1263,9 +1263,13 @@ static void rip_response_process(struct rip_packet *packet, int size, rip->vrf->vrf_id)) { struct route_node *rn; struct rip_info *rinfo; + struct prefix p = { 0 }; - rn = route_node_match_ipv4(rip->table, - &rte->nexthop); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = rte->nexthop; + + rn = route_node_match(rip->table, &p); if (rn) { rinfo = rn->info; diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index 0ffd762734..06a350c8e9 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -20,6 +20,7 @@ import sys import pytest import glob from time import sleep +from lib.topolog import logger pytestmark = [ pytest.mark.babeld, @@ -1715,6 +1716,77 @@ def test_resilient_nexthop_group(): net["r1"].cmd('vtysh -c "conf" -c "no nexthop-group resilience"') +def test_interface_stuff(): + global fatal_error + net = get_topogen().net + + # Skip if previous fatal error condition is raised + if fatal_error != "": + pytest.skip(fatal_error) + + print("\n\n** Verifying some interface code") + print("************************************\n") + + net["r1"].cmd('vtysh -c "conf" -c "interface r1-eth0" -c "multicast enable"') + + def _test_interface_multicast_on(): + output = json.loads(net["r1"].cmd('vtysh -c "show int r1-eth0 json"')) + expected = { + "r1-eth0": { + "flags": "<UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>", + "multicastConfig": "Enabled by CLI", + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_test_interface_multicast_on) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Multicast bit was not set on r1-eth0" + + net["r1"].cmd('vtysh -c "conf" -c "interface r1-eth0" -c "multicast disable"') + + def _test_interface_multicast_off(): + output = json.loads( + net["r1"].cmd('vtysh -c "show int r1-eth0 vrf default json"') + ) + expected = { + "r1-eth0": { + "flags": "<UP,LOWER_UP,BROADCAST,RUNNING>", + "multicastConfig": "Disabled by CLI", + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_test_interface_multicast_off) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Multicast bit was not turned off on r1-eth0" + + net["r1"].cmd('vtysh -c "conf" -c "interface r1-eth0" -c "no multicast disable"') + + def _test_interface_multicast_disable(): + output = json.loads(net["r1"].cmd('vtysh -c "show int r1-eth0 json"')) + expected = { + "r1-eth0": { + "flags": "<UP,LOWER_UP,BROADCAST,RUNNING>", + "multicastConfig": "Not specified by CLI", + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_test_interface_multicast_disable) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Multicast bit was set on r1-eth0" + + logger.info("Ensure that these commands are still nominally working") + rc, o, e = net["r1"].cmd_status('vtysh -c "show interface description vrf all"') + logger.info(o) + assert rc == 0 + + rc, o, e = net["r1"].cmd_status('vtysh -c "show interface description vrf default"') + logger.info(o) + assert rc == 0 + + def test_shutdown_check_stderr(): global fatal_error net = get_topogen().net diff --git a/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json new file mode 100644 index 0000000000..7532ce9331 --- /dev/null +++ b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes.json @@ -0,0 +1,131 @@ +{ + "bgpLocalRouterId":"192.168.100.21", + "defaultLocPrf":100, + "localAS":65000, + "192.168.101.41:2":{ + "rd":"192.168.101.41:2", + "[5]:[0]:[32]:[192.168.101.41]":{ + "prefix":"[5]:[0]:[32]:[192.168.101.41]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.101.41", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.41", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::2]":{ + "prefix":"[5]:[0]:[128]:[fd00::2]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::2", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.41", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + } + }, + "192.168.102.21:2":{ + "rd":"192.168.102.21:2", + "[5]:[0]:[32]:[192.168.102.21]":{ + "prefix":"[5]:[0]:[32]:[192.168.102.21]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.102.21", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.21", + "hostname":"r1", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::1]":{ + "prefix":"[5]:[0]:[128]:[fd00::1]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::1", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.21", + "hostname":"r1", + "afi":"ipv4", + "used":true + } + ] + } + ] + } + }, + "numPrefix":4, + "totalPrefix":4 +} diff --git a/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json new file mode 100644 index 0000000000..a14ba1291e --- /dev/null +++ b/tests/topotests/bgp_evpn_rt5/r1/bgp_l2vpn_evpn_routes_all.json @@ -0,0 +1,191 @@ +{ + "bgpLocalRouterId":"192.168.100.21", + "defaultLocPrf":100, + "localAS":65000, + "192.168.101.41:2":{ + "rd":"192.168.101.41:2", + "[5]:[0]:[32]:[192.168.101.41]":{ + "prefix":"[5]:[0]:[32]:[192.168.101.41]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.101.41", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.41", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[32]:[192.168.102.41]":{ + "prefix":"[5]:[0]:[32]:[192.168.102.41]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.102.41", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.41", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::2]":{ + "prefix":"[5]:[0]:[128]:[fd00::2]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::2", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.41", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::3]":{ + "prefix":"[5]:[0]:[128]:[fd00::3]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::3", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.41", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + } + }, + "192.168.102.21:2":{ + "rd":"192.168.102.21:2", + "[5]:[0]:[32]:[192.168.102.21]":{ + "prefix":"[5]:[0]:[32]:[192.168.102.21]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.102.21", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.21", + "hostname":"r1", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::1]":{ + "prefix":"[5]:[0]:[128]:[fd00::1]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::1", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.21", + "hostname":"r1", + "afi":"ipv4", + "used":true + } + ] + } + ] + } + }, + "numPrefix":6, + "totalPrefix":6 +} diff --git a/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json b/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json new file mode 100644 index 0000000000..597bca5fd3 --- /dev/null +++ b/tests/topotests/bgp_evpn_rt5/r2/bgp_l2vpn_evpn_routes.json @@ -0,0 +1,131 @@ +{ + "bgpLocalRouterId":"192.168.100.41", + "defaultLocPrf":100, + "localAS":65000, + "192.168.101.41:2":{ + "rd":"192.168.101.41:2", + "[5]:[0]:[32]:[192.168.101.41]":{ + "prefix":"[5]:[0]:[32]:[192.168.101.41]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.101.41", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::2]":{ + "prefix":"[5]:[0]:[128]:[fd00::2]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"external", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::2", + "metric":0, + "weight":32768, + "peerId":"(unspec)", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.41", + "hostname":"r2", + "afi":"ipv4", + "used":true + } + ] + } + ] + } + }, + "192.168.102.21:2":{ + "rd":"192.168.102.21:2", + "[5]:[0]:[32]:[192.168.102.21]":{ + "prefix":"[5]:[0]:[32]:[192.168.102.21]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":32, + "ip":"192.168.102.21", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.21", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.21", + "hostname":"r1", + "afi":"ipv4", + "used":true + } + ] + } + ] + }, + "[5]:[0]:[128]:[fd00::1]":{ + "prefix":"[5]:[0]:[128]:[fd00::1]", + "prefixLen":352, + "paths":[ + { + "valid":true, + "bestpath":true, + "selectionReason":"First path received", + "pathFrom":"internal", + "routeType":5, + "ethTag":0, + "ipLen":128, + "ip":"fd00::1", + "metric":0, + "locPrf":100, + "weight":0, + "peerId":"192.168.100.21", + "path":"", + "origin":"IGP", + "nexthops":[ + { + "ip":"192.168.100.21", + "hostname":"r1", + "afi":"ipv4", + "used":true + } + ] + } + ] + } + }, + "numPrefix":4, + "totalPrefix":4 +} diff --git a/tests/topotests/bgp_evpn_rt5/r2/bgpd.conf b/tests/topotests/bgp_evpn_rt5/r2/bgpd.conf index de5a0efc44..4f1d8e4a37 100644 --- a/tests/topotests/bgp_evpn_rt5/r2/bgpd.conf +++ b/tests/topotests/bgp_evpn_rt5/r2/bgpd.conf @@ -20,12 +20,30 @@ router bgp 65000 vrf r2-vrf-101 no bgp network import-check address-family ipv4 unicast network 192.168.101.41/32 + network 192.168.102.41/32 exit-address-family address-family ipv6 unicast network fd00::2/128 + network fd00::3/128 exit-address-family address-family l2vpn evpn - advertise ipv4 unicast - advertise ipv6 unicast + advertise ipv4 unicast route-map rmap4 + advertise ipv6 unicast route-map rmap6 exit-address-family ! +access-list acl4_1 seq 10 permit 192.168.101.41/32 +access-list acl4_2 seq 10 permit 192.168.102.41/32 +ipv6 access-list acl6_1 seq 10 permit fd00::2/128 +ipv6 access-list acl6_2 seq 10 permit fd00::3/128 +route-map rmap4 permit 1 + match ip address acl4_1 +exit +route-map rmap4 deny 2 + match ip address acl4_2 +exit +route-map rmap6 permit 1 + match ipv6 address acl6_1 +exit +route-map rmap6 deny 2 + match ipv6 address acl6_2 +exit diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py index 9dfb7fc4d9..a9636a92f4 100644 --- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py +++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py @@ -13,6 +13,8 @@ with route advertisements on a separate netns. """ +import json +from functools import partial import os import sys import pytest @@ -160,6 +162,36 @@ def teardown_module(_mod): tgen.stop_topology() +def _test_evpn_ping_router(pingrouter, ipv4_only=False): + """ + internal function to check ping between r1 and r2 + """ + # Check IPv4 and IPv6 connectivity between r1 and r2 ( routing vxlan evpn) + logger.info( + "Check Ping IPv4 from R1(r1-vrf-101) to R2(r2-vrf-101 = 192.168.101.41)" + ) + output = pingrouter.run("ip netns exec r1-vrf-101 ping 192.168.101.41 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assertmsg = ( + "expected ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) should be ok" + ) + assert 0, assertmsg + else: + logger.info("Check Ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) OK") + + if ipv4_only: + return + + logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(r2-vrf-101 = fd00::2)") + output = pingrouter.run("ip netns exec r1-vrf-101 ping fd00::2 -f -c 1000") + logger.info(output) + if "1000 packets transmitted, 1000 received" not in output: + assert 0, "expected ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) should be ok" + else: + logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) OK") + + def test_protocols_convergence(): """ Assert that all protocols have converged @@ -168,7 +200,34 @@ def test_protocols_convergence(): tgen = get_topogen() if tgen.routers_have_failure(): pytest.skip(tgen.errors) - topotest.sleep(4, "waiting 4 seconds for bgp convergence") + # Check BGP IPv4 routing tables on r1 + logger.info("Checking BGP L2VPN EVPN routes for convergence on r1") + + for rname in ("r1", "r2"): + router = tgen.gears[rname] + json_file = "{}/{}/bgp_l2vpn_evpn_routes.json".format(CWD, router.name) + if not os.path.isfile(json_file): + assert 0, "bgp_l2vpn_evpn_routes.json file not found" + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp l2vpn evpn json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + +def test_protocols_dump_info(): + """ + Dump EVPN information + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) # Check IPv4/IPv6 routing tables. output = tgen.gears["r1"].vtysh_cmd("show bgp l2vpn evpn", isjson=False) logger.info("==== result from show bgp l2vpn evpn") @@ -203,6 +262,15 @@ def test_protocols_convergence(): logger.info("==== result from show evpn rmac vni all") logger.info(output) + +def test_router_check_ip(): + """ + Check routes are correctly installed + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + expected = { "fd00::2/128": [ { @@ -221,56 +289,112 @@ def test_protocols_convergence(): ) assert result is None, "ipv6 route check failed" - expected = { - "101": { - "numNextHops": 2, - "192.168.100.41": { - "nexthopIp": "192.168.100.41", - }, - "::ffff:192.168.100.41": { - "nexthopIp": "::ffff:192.168.100.41", - }, + +def _test_router_check_evpn_contexts(router, ipv4_only=False): + """ + Check EVPN nexthops and RMAC number are correctly configured + """ + if ipv4_only: + expected = { + "101": { + "numNextHops": 1, + "192.168.100.41": { + "nexthopIp": "192.168.100.41", + }, + } + } + else: + expected = { + "101": { + "numNextHops": 2, + "192.168.100.41": { + "nexthopIp": "192.168.100.41", + }, + "::ffff:192.168.100.41": { + "nexthopIp": "::ffff:192.168.100.41", + }, + } } - } result = topotest.router_json_cmp( - tgen.gears["r1"], "show evpn next-hops vni all json", expected + router, "show evpn next-hops vni all json", expected ) assert result is None, "evpn next-hops check failed" expected = {"101": {"numRmacs": 1}} - result = topotest.router_json_cmp( - tgen.gears["r1"], "show evpn rmac vni all json", expected - ) + result = topotest.router_json_cmp(router, "show evpn rmac vni all json", expected) assert result is None, "evpn rmac number check failed" - # Check IPv4 and IPv6 connectivity between r1 and r2 ( routing vxlan evpn) - pingrouter = tgen.gears["r1"] - logger.info( - "Check Ping IPv4 from R1(r1-vrf-101) to R2(r2-vrf-101 = 192.168.101.41)" + +def test_router_check_evpn_contexts(): + """ + Check EVPN nexthops and RMAC number are correctly configured + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + _test_router_check_evpn_contexts(tgen.gears["r1"]) + + +def test_evpn_ping(): + """ + Check ping between R1 and R2 is ok + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + _test_evpn_ping_router(tgen.gears["r1"]) + + +def test_evpn_disable_routemap(): + """ + Check the removal of a route-map on R2. More EVPN Prefixes are expected + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + tgen.gears["r2"].vtysh_cmd( + """ + configure terminal\n + router bgp 65000 vrf r2-vrf-101\n + address-family l2vpn evpn\n + advertise ipv4 unicast\n + advertise ipv6 unicast\n + """ ) - output = pingrouter.run("ip netns exec r1-vrf-101 ping 192.168.101.41 -f -c 1000") - logger.info(output) - if "1000 packets transmitted, 1000 received" not in output: - assertmsg = ( - "expected ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) should be ok" - ) - assert 0, assertmsg - else: - logger.info("Check Ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) OK") + router = tgen.gears["r1"] + json_file = "{}/{}/bgp_l2vpn_evpn_routes_all.json".format(CWD, router.name) + if not os.path.isfile(json_file): + assert 0, "bgp_l2vpn_evpn_routes.json file not found" + + expected = json.loads(open(json_file).read()) + test_func = partial( + topotest.router_json_cmp, + router, + "show bgp l2vpn evpn json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=1) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg - logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(r2-vrf-101 = fd00::2)") - output = pingrouter.run("ip netns exec r1-vrf-101 ping fd00::2 -f -c 1000") - logger.info(output) - if "1000 packets transmitted, 1000 received" not in output: - assert 0, "expected ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) should be ok" - else: - logger.info("Check Ping IPv6 from R1(r1-vrf-101) to R2(fd00::2) OK") + +def test_evpn_remove_ip(): + """ + Check the removal of an EVPN route is correctly handled + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) config_no_ipv6 = { "r2": { "raw_config": [ "router bgp 65000 vrf r2-vrf-101", "address-family ipv6 unicast", + "no network fd00::3/128", "no network fd00::2/128", ] } @@ -293,6 +417,7 @@ def test_protocols_convergence(): } result = verify_bgp_rib(tgen, "ipv6", "r1", ipv6_routes, expected=False) assert result is not True, "expect IPv6 route fd00::2/128 withdrawn" + output = tgen.gears["r1"].vtysh_cmd("show evpn next-hops vni all", isjson=False) logger.info("==== result from show evpn next-hops vni all") logger.info(output) @@ -300,37 +425,27 @@ def test_protocols_convergence(): logger.info("==== result from show evpn next-hops vni all") logger.info(output) - expected = { - "101": { - "numNextHops": 1, - "192.168.100.41": { - "nexthopIp": "192.168.100.41", - }, - } - } - result = topotest.router_json_cmp( - tgen.gears["r1"], "show evpn next-hops vni all json", expected - ) - assert result is None, "evpn next-hops check failed" - expected = {"101": {"numRmacs": 1}} - result = topotest.router_json_cmp( - tgen.gears["r1"], "show evpn rmac vni all json", expected - ) - assert result is None, "evpn rmac number check failed" +def test_router_check_evpn_contexts_again(): + """ + Check EVPN nexthops and RMAC number are correctly configured + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) - logger.info( - "Check Ping IPv4 from R1(r1-vrf-101) to R2(r2-vrf-101 = 192.168.101.41)" - ) - output = pingrouter.run("ip netns exec r1-vrf-101 ping 192.168.101.41 -f -c 1000") - logger.info(output) - if "1000 packets transmitted, 1000 received" not in output: - assertmsg = ( - "expected ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) should be ok" - ) - assert 0, assertmsg - else: - logger.info("Check Ping IPv4 from R1(r1-vrf-101) to R2(192.168.101.41) OK") + _test_router_check_evpn_contexts(tgen.gears["r1"], ipv4_only=True) + + +def test_evpn_ping_again(): + """ + Check ping between R1 and R2 is ok + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + _test_evpn_ping_router(tgen.gears["r1"], ipv4_only=True) def test_memory_leak(): diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py index 8e2e76d154..6d586cee50 100644 --- a/tests/topotests/lib/snmptest.py +++ b/tests/topotests/lib/snmptest.py @@ -104,12 +104,16 @@ class SnmpTester(object): return None return self._get_snmp_value(result) - def walk(self, oid): + def walk(self, oid, raw=False): cmd = "snmpwalk {0} {1} 2>&1 | grep -v SNMPv2-PDU".format( self._snmp_config(), oid ) result = self.router.cmd(cmd) + + if raw: + return result + return self._parse_multiline(result) def parse_notif_ipv4(self, notif): diff --git a/tests/topotests/simple_snmp_test/r1/isisd.conf b/tests/topotests/simple_snmp_test/r1/isisd.conf index 435abde330..c53d2509e2 100644 --- a/tests/topotests/simple_snmp_test/r1/isisd.conf +++ b/tests/topotests/simple_snmp_test/r1/isisd.conf @@ -3,6 +3,8 @@ log stdout debugging ! debug isis route-events ! debug isis events ! +agentx +! interface r1-eth0 ip router isis ISIS1 ipv6 router isis ISIS1 diff --git a/tests/topotests/simple_snmp_test/r1/ospf6d.conf b/tests/topotests/simple_snmp_test/r1/ospf6d.conf new file mode 100644 index 0000000000..e81151710b --- /dev/null +++ b/tests/topotests/simple_snmp_test/r1/ospf6d.conf @@ -0,0 +1,12 @@ +agentx + +int r1-eth0 + ipv6 ospf6 area 0.0.0.0 + +int r1-eth1 + ipv6 ospf6 area 0.0.0.0 +int r1-eth2 + ipv6 ospf6 area 0.0.0.0 + +router ospf6 + redistribute local
\ No newline at end of file diff --git a/tests/topotests/simple_snmp_test/r1/ospfd.conf b/tests/topotests/simple_snmp_test/r1/ospfd.conf new file mode 100644 index 0000000000..cc0d9e52c2 --- /dev/null +++ b/tests/topotests/simple_snmp_test/r1/ospfd.conf @@ -0,0 +1,11 @@ +agentx + +int r1-eth0 + ip ospf area 0.0.0.0 +int r1-eth1 + ip ospf area 0.0.0.0 +int r1-eth2 + ip ospf area 0.0.0.0 + +router ospf + redistribute local
\ No newline at end of file diff --git a/tests/topotests/simple_snmp_test/r1/ripd.conf b/tests/topotests/simple_snmp_test/r1/ripd.conf new file mode 100644 index 0000000000..71cdb058cf --- /dev/null +++ b/tests/topotests/simple_snmp_test/r1/ripd.conf @@ -0,0 +1,8 @@ +! +! +router rip + network 0.0.0.0/0 + redistribute local +! +agentx +!
\ No newline at end of file diff --git a/tests/topotests/simple_snmp_test/r1/zebra.conf b/tests/topotests/simple_snmp_test/r1/zebra.conf index 5281d0055d..6483a661ce 100644 --- a/tests/topotests/simple_snmp_test/r1/zebra.conf +++ b/tests/topotests/simple_snmp_test/r1/zebra.conf @@ -1,5 +1,7 @@ log file zebra.log ! +agentx +! interface r1-eth0 ip address 192.168.12.12/24 ipv6 address 2000:1:1:12::12/64 @@ -18,5 +20,4 @@ interface lo ipv6 address 2000:1:1:1::1/128 ! ! -! line vty diff --git a/tests/topotests/simple_snmp_test/test_simple_snmp.py b/tests/topotests/simple_snmp_test/test_simple_snmp.py index 0387e29274..c74ffcc2db 100755 --- a/tests/topotests/simple_snmp_test/test_simple_snmp.py +++ b/tests/topotests/simple_snmp_test/test_simple_snmp.py @@ -24,7 +24,8 @@ sys.path.append(os.path.join(CWD, "../")) # Import topogen and topotest helpers from lib.topogen import Topogen, TopoRouter, get_topogen from lib.snmptest import SnmpTester - +from time import sleep +from lib.topolog import logger pytestmark = [pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.snmp] @@ -59,10 +60,14 @@ def setup_module(mod): # For all registered routers, load the zebra configuration file for rname, router in router_list.items(): router.load_config( - TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + TopoRouter.RD_ZEBRA, + os.path.join(CWD, "{}/zebra.conf".format(rname)), + "-M snmp", ) router.load_config( - TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) + TopoRouter.RD_ISIS, + os.path.join(CWD, "{}/isisd.conf".format(rname)), + "-M snmp", ) router.load_config( TopoRouter.RD_BGP, @@ -70,6 +75,21 @@ def setup_module(mod): "-M snmp", ) router.load_config( + TopoRouter.RD_RIP, + os.path.join(CWD, "{}/ripd.conf".format(rname)), + "-M snmp", + ) + router.load_config( + TopoRouter.RD_OSPF, + os.path.join(CWD, "{}/ospfd.conf".format(rname)), + "-M snmp", + ) + router.load_config( + TopoRouter.RD_OSPF6, + os.path.join(CWD, "{}/ospf6d.conf".format(rname)), + "-M snmp", + ) + router.load_config( TopoRouter.RD_SNMP, os.path.join(CWD, "{}/snmpd.conf".format(rname)), "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap", @@ -77,6 +97,16 @@ def setup_module(mod): # After loading the configurations, this function loads configured daemons. tgen.start_router() + # Why this sleep? If you are using zebra w/ snmp we have a chicken + # and egg problem with the snmpd. snmpd is being started up with + # ip addresses, and as such snmpd may not be ready to listen yet + # (see startup stuff in topotest.py ) with the 2 second delay + # on starting snmpd after zebra. As such if we want to test + # anything in zebra we need to sleep a bit to allow the connection + # to happen. I have no good way to test to see if zebra is up + # and running with snmp at this point in time. So this will have + # to do. + sleep(17) def teardown_module(): @@ -103,6 +133,22 @@ def test_r1_bgp_version(): assert r1_snmp.test_oid_walk("bgpVersion", ["10"]) assert r1_snmp.test_oid_walk("bgpVersion", ["10"], ["0"]) + assert r1_snmp.test_oid( + "IP-FORWARD-MIB::ipForwardDest.192.168.12.0", "192.168.12.0" + ) + + assert r1_snmp.test_oid("ISIS-MIB::isisSysVersion", "one(1)") + # rip is not auto-loading agentx from mgmtd + # assert r1_snmp.test_oid("RIPv2-MIB::rip2GlobalQueries", "0") + + assert r1_snmp.test_oid("OSPF-MIB::ospfVersionNumber", "version2(2)") + assert r1_snmp.test_oid("OSPFV3-MIB::ospfv3VersionNumber", "version3(3)") + + # Let's just dump everything and make sure we get some additional test + # coverage + logger.info("Let's walk everything") + logger.info(r1_snmp.walk(".1", raw=True)) + def test_memory_leak(): "Run the memory leak test and report results." diff --git a/zebra/interface.c b/zebra/interface.c index 86de5dbae6..f7fd112cd4 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -47,6 +47,20 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZIF_DESC, "Intf desc"); static void if_down_del_nbr_connected(struct interface *ifp); +static const char *if_zebra_data_state(uint8_t state) +{ + switch (state) { + case IF_ZEBRA_DATA_UNSPEC: + return "Not specified by CLI"; + case IF_ZEBRA_DATA_ON: + return "Enabled by CLI"; + case IF_ZEBRA_DATA_OFF: + return "Disabled by CLI"; + } + + return "STATE IS WRONG DEV ESCAPE"; +} + static void if_zebra_speed_update(struct event *thread) { struct interface *ifp = EVENT_ARG(thread); @@ -366,6 +380,7 @@ int if_subnet_delete(struct interface *ifp, struct connected *ifc) return 0; } +#ifndef HAVE_NETLINK /* if_flags_mangle: A place for hacks that require mangling * or tweaking the interface flags. * @@ -417,6 +432,7 @@ void if_flags_update(struct interface *ifp, uint64_t newflags) if_up(ifp, true); } } +#endif /* Wake up configured address if it is not in current kernel address. */ @@ -2627,8 +2643,8 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) vty_out(vty, "mtu6 %d ", ifp->mtu6); vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags)); - if (zebra_if->mpls) - vty_out(vty, " MPLS enabled\n"); + vty_out(vty, " MPLS %s %s\n", zebra_if->mpls ? "enabled" : "", + if_zebra_data_state(zebra_if->multicast)); if (zebra_if->linkdown) vty_out(vty, " Ignore all v4 routes with linkdown\n"); @@ -2640,6 +2656,10 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) if (zebra_if->v6mcast_on) vty_out(vty, " v6 Multicast forwarding is on\n"); + vty_out(vty, " Multicast config is %s\n", if_zebra_data_state(zebra_if->multicast)); + + vty_out(vty, " Shutdown config is %s\n", if_zebra_data_state(zebra_if->shutdown)); + /* Hardware address. */ vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type)); if (ifp->hw_addr_len != 0) { @@ -2988,10 +3008,14 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, json_object_boolean_add(json_if, "mplsEnabled", zebra_if->mpls); json_object_boolean_add(json_if, "linkDown", zebra_if->linkdown); json_object_boolean_add(json_if, "linkDownV6", zebra_if->linkdownv6); - json_object_boolean_add(json_if, "mcForwardingV4", - zebra_if->v4mcast_on); - json_object_boolean_add(json_if, "mcForwardingV6", - zebra_if->v6mcast_on); + json_object_boolean_add(json_if, "mcForwardingV4", zebra_if->v4mcast_on); + json_object_boolean_add(json_if, "mcForwardingV6", zebra_if->v6mcast_on); + + json_object_string_add(json_if, "multicastConfig", if_zebra_data_state(zebra_if->multicast)); + + json_object_string_add(json_if, "shutdownConfig", if_zebra_data_state(zebra_if->shutdown)); + + json_object_string_add(json_if, "mplsConfig", if_zebra_data_state(zebra_if->mpls_config)); if (ifp->ifindex == IFINDEX_INTERNAL) { json_object_boolean_add(json_if, "pseudoInterface", true); diff --git a/zebra/ioctl.c b/zebra/ioctl.c index a35784cd36..47ce7c943d 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -390,6 +390,7 @@ int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx) #endif /* HAVE_STRUCT_IFALIASREQ */ #endif /* HAVE_NETLINK */ +#ifndef HAVE_NETLINK /* get interface flags */ void if_get_flags(struct interface *ifp) { @@ -485,6 +486,7 @@ void if_get_flags(struct interface *ifp) out: if_flags_update(ifp, (ifreqflags.ifr_flags & 0x0000ffff)); } +#endif /* Set interface flags */ int if_set_flags(struct interface *ifp, uint64_t flags) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0658f996e6..ad112a4ab1 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -4757,10 +4757,9 @@ void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni, /* If down or not mapped to a bridge, we're done. */ if (!if_is_operative(ifp) || !zif->brslave_info.br_if) { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug( - "%s VNI %u VTEP %pI4 ifp %s oper %u br_if %u skipping update", - __func__, zevpn->vni, &vtep_ip, ifp->name, - if_is_operative(ifp), !zif->brslave_info.br_if); + zlog_debug("%s VNI %u VTEP %pI4 ifp %s oper %u br_if %u skipping update", + __func__, zevpn->vni, &vtep_ip, ifp->name, if_is_operative(ifp), + !zif->brslave_info.br_if); return; } diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c index 2658c9f01c..ea0be2f644 100644 --- a/zebra/zebra_vxlan_if.c +++ b/zebra/zebra_vxlan_if.c @@ -1037,7 +1037,7 @@ int zebra_vxlan_if_vni_up(struct interface *ifp, struct zebra_vxlan_vni *vnip) } else { if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN) zlog_debug("%s VNI %u vxlan_if %s oper down skipping vni up to client", - __func__, zevpn->vni, zevpn->vxlan_if->name); + __func__, zevpn->vni, zevpn->vxlan_if->name); } zebra_evpn_read_mac_neigh(zevpn, ifp); } |
