diff options
30 files changed, 385 insertions, 153 deletions
diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 66bf706808..9963901e13 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -105,6 +105,8 @@ struct bfd_echo_pkt { #define BFD_CBIT 0x08 #define BFD_ABIT 0x04 #define BFD_DEMANDBIT 0x02 +#define BFD_MBIT 0x01 +#define BFD_GETMBIT(flags) (flags & BFD_MBIT) #define BFD_SETDEMANDBIT(flags, val) \ { \ if ((val)) \ diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index fec195c77e..8110f434c2 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -898,6 +898,12 @@ void bfd_recv_cb(struct event *t) return; } + if (BFD_GETMBIT(cp->flags)) { + cp_debug(is_mhop, &peer, &local, ifindex, vrfid, + "detect non-zero Multipoint (M) flag"); + return; + } + if (cp->discrs.my_discr == 0) { cp_debug(is_mhop, &peer, &local, ifindex, vrfid, "'my discriminator' is zero"); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 5386f24a0b..164aa5ae79 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -517,9 +517,11 @@ static inline void bgp_attr_set_ecommunity(struct attr *attr, { attr->ecommunity = ecomm; - if (ecomm) + if (ecomm) { SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); - else + if (ecommunity_select_color(ecomm)) + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)); + } else UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index d20ad01c35..794c5a3975 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -52,10 +52,8 @@ * 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect */ #define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c -/* from draft-ietf-idr-flow-spec-v6-09 - * 0x0b Flow-spec Redirect to IPv6 - */ -#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b +/* RFC 8956 */ +#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d /* Low-order octet of the Extended Communities type field for EVPN types */ #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00 diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index e142ff6a34..5a28f53d76 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -3862,7 +3862,7 @@ int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf, * Install or uninstall mac-ip routes are appropriate for this * particular VRF. */ -static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) +static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, bool install) { afi_t afi; safi_t safi; @@ -3926,9 +3926,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) * particular VNI. */ static int install_uninstall_routes_for_vni(struct bgp *bgp, - struct bgpevpn *vpn, - bgp_evpn_route_type rtype, - int install) + struct bgpevpn *vpn, bool install) { afi_t afi; safi_t safi; @@ -3959,7 +3957,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, (const struct prefix_evpn *)bgp_dest_get_prefix( dest); - if (evp->prefix.route_type != rtype) + if (evp->prefix.route_type != BGP_EVPN_IMET_ROUTE && + evp->prefix.route_type != BGP_EVPN_AD_ROUTE && + evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; for (pi = bgp_dest_get_bgp_path_info(dest); pi; @@ -3986,16 +3986,16 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, bgp, vpn, evp, pi); if (ret) { - flog_err( - EC_BGP_EVPN_FAIL, - "%u: Failed to %s EVPN %s route in VNI %u", - bgp->vrf_id, - install ? "install" - : "uninstall", - rtype == BGP_EVPN_MAC_IP_ROUTE - ? "MACIP" - : "IMET", - vpn->vni); + flog_err(EC_BGP_EVPN_FAIL, + "%u: Failed to %s EVPN %s route in VNI %u", + bgp->vrf_id, + install ? "install" + : "uninstall", + evp->prefix.route_type == + BGP_EVPN_MAC_IP_ROUTE + ? "MACIP" + : "IMET", + vpn->vni); bgp_dest_unlock_node(rd_dest); bgp_dest_unlock_node(dest); @@ -4013,7 +4013,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, */ static int install_routes_for_vrf(struct bgp *bgp_vrf) { - install_uninstall_routes_for_vrf(bgp_vrf, 1); + install_uninstall_routes_for_vrf(bgp_vrf, true); return 0; } @@ -4024,29 +4024,17 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf) */ static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - - /* Install type-3 routes followed by type-2 routes - the ones applicable + /* + * Install type-3 routes followed by type-2 routes - the ones applicable * for this VNI. */ - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE, - 1); - if (ret) - return ret; - - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE, - 1); - if (ret) - return ret; - - return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, - 1); + return install_uninstall_routes_for_vni(bgp, vpn, true); } /* uninstall routes from l3vni vrf. */ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) { - install_uninstall_routes_for_vrf(bgp_vrf, 0); + install_uninstall_routes_for_vrf(bgp_vrf, false); return 0; } @@ -4056,25 +4044,11 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) */ static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - - /* Uninstall type-2 routes followed by type-3 routes - the ones - * applicable - * for this VNI. + /* + * Uninstall type-2 routes followed by type-3 routes - the ones + * applicable for this VNI. */ - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, - 0); - if (ret) - return ret; - - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE, - 0); - if (ret) - return ret; - - - return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE, - 0); + return install_uninstall_routes_for_vni(bgp, vpn, false); } /* diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index a2d3172882..7866adbdcd 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1796,6 +1796,22 @@ bgp_connect_fail(struct peer_connection *connection) return bgp_stop(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) +{ + bgp_getsockname(peer); + 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); + 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) + peer->su_remote->sin6.sin6_port = htons(peer->port); + } +} + /* This function is the first starting point of all BGP connection. It * try to connect to remote peer with non-blocking IO. */ @@ -1892,6 +1908,8 @@ 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); + /* * - when the socket becomes ready, poll() will signify POLLOUT * - if it fails to connect, poll() will signify POLLHUP diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index dbb34b048f..b409cbe706 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -875,11 +875,7 @@ int bgp_getsockname(struct peer *peer) } peer->su_local = sockunion_getsockname(peer->connection->fd); - if (!peer->su_local) - return -1; peer->su_remote = sockunion_getpeername(peer->connection->fd); - if (!peer->su_remote) - return -1; if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote, &peer->nexthop, peer)) { diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 97883418ef..0a865d7098 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3339,7 +3339,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, return; } +#ifdef ENABLE_BGP_VNC const struct prefix *p = bgp_dest_get_prefix(dest); +#endif debug = bgp_debug_bestpath(dest); if (debug) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 0a1cf3362b..62549a0678 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -3035,14 +3035,17 @@ DEFUN (bgp_graceful_restart, VTY_DECLVAR_CONTEXT(bgp, bgp); ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer, - ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); + return bgp_vty_return(vty, ret); } @@ -3062,14 +3065,16 @@ DEFUN (no_bgp_graceful_restart, int ret = BGP_GR_FAILURE; ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer, - ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3277,24 +3282,25 @@ DEFUN (bgp_graceful_restart_disable, VTY_DECLVAR_CONTEXT(bgp, bgp); ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, - bgp->peer, ret); + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_RESTART, + CAPABILITY_ACTION_UNSET); + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_LLGR, + CAPABILITY_ACTION_UNSET); + } + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) - zlog_debug( - "[BGP_GR] bgp_graceful_restart_disable_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); - - for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { - bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, - CAPABILITY_CODE_RESTART, - CAPABILITY_ACTION_UNSET); - bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, - CAPABILITY_CODE_LLGR, - CAPABILITY_ACTION_UNSET); - } + zlog_debug("[BGP_GR] bgp_graceful_restart_disable_cmd : END "); return bgp_vty_return(vty, ret); } @@ -3316,15 +3322,17 @@ DEFUN (no_bgp_graceful_restart_disable, int ret = BGP_GR_FAILURE; ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD); - - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer, - ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_graceful_restart_disable_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3352,15 +3360,16 @@ DEFUN (bgp_neighbor_graceful_restart_set, return CMD_WARNING_CONFIG_FAILED; ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3389,15 +3398,16 @@ DEFUN (no_bgp_neighbor_graceful_restart, "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START "); ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3427,15 +3437,16 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set, ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3464,15 +3475,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper, "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START "); ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3500,18 +3512,19 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set, return CMD_WARNING_CONFIG_FAILED; ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD); + if (ret == BGP_GR_SUCCESS) { + if (peer->bgp->t_startup) + bgp_peer_gr_flags_update(peer); - if (peer->bgp->t_startup) - bgp_peer_gr_flags_update(peer); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3540,15 +3553,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable, "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START "); ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -12750,7 +12764,7 @@ static void bgp_show_neighbor_graceful_restart_remote_mode(struct vty *vty, if (json) json_object_string_add(json, "remoteGrMode", mode); else - vty_out(vty, "%s\n", mode); + vty_out(vty, "%s", mode); } static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty, @@ -12782,7 +12796,7 @@ static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty, if (json) json_object_string_add(json, "localGrMode", mode); else - vty_out(vty, "%s\n", mode); + vty_out(vty, "%s", mode); } static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi( @@ -21187,6 +21201,15 @@ void bgp_vty_init(void) install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_EVPN_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_EVPN_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_maximum_prefix_cmd); /* "neighbor allowas-in" */ install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index dbba1dc71a..5247408f70 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1782,7 +1782,7 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e) table = bgp_dest_table(dest); install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL); - if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN) + if (table->afi == AFI_L2VPN && table->safi == SAFI_EVPN) is_evpn = true; if (BGP_DEBUG(zebra, ZEBRA)) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d98df754ef..33da70fb9b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1377,7 +1377,7 @@ int bgp_global_gr_init(struct bgp *bgp) /*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/ GLOBAL_GR, GLOBAL_INVALID, /*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/ - GLOBAL_INVALID, GLOBAL_HELPER + GLOBAL_DISABLE, GLOBAL_HELPER }, /* GLOBAL_INVALID Mode */ { @@ -1411,13 +1411,13 @@ int bgp_peer_gr_init(struct peer *peer) /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ {PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL }, /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ - { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT, + { PEER_HELPER, NULL }, {PEER_GLOBAL_INHERIT, bgp_peer_gr_action } }, { /* PEER_GR Mode */ /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ - { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT, + { PEER_GR, NULL }, { PEER_GLOBAL_INHERIT, bgp_peer_gr_action }, /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ {PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL }, @@ -1429,7 +1429,7 @@ int bgp_peer_gr_init(struct peer *peer) /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL }, /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ - { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT, + { PEER_DISABLE, NULL }, { PEER_GLOBAL_INHERIT, bgp_peer_gr_action }, /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst index be2952e71a..482df96267 100644 --- a/doc/developer/zebra.rst +++ b/doc/developer/zebra.rst @@ -161,6 +161,21 @@ Zebra Protocol Commands The definitions of zebra protocol commands can be found at ``lib/zclient.h``. + +Zebra Dataplane +=============== + +The zebra dataplane subsystem provides a framework for FIB +programming. Zebra uses the dataplane to program the local kernel as +it makes changes to objects such as IP routes, MPLS LSPs, and +interface IP addresses. The dataplane runs in its own pthread, in +order to off-load work from the main zebra pthread. + +The zebra dataplane API is versioned; the version number must be +updated along with API changes. Plugins can test the current version +number and confirm that they are compatible with the current version. + + Dataplane batching ================== diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 36986a19c5..294c03def1 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -2908,7 +2908,7 @@ static void show_isis_route_common(struct vty *vty, int levels, struct isis_spftree *spftree; struct listnode *node; struct isis_area *area; - char key[8]; + char key[18]; if (!isis->area_list || isis->area_list->count == 0) return; diff --git a/lib/libfrr.c b/lib/libfrr.c index c5c7e7837a..03025328b7 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -1450,3 +1450,12 @@ void _libfrr_version(void) write(1, banner, sizeof(banner) - 1); _exit(0); } + +/* Render simple version tuple to string */ +const char *frr_vers2str(uint32_t version, char *buf, int buflen) +{ + snprintf(buf, buflen, "%d.%d.%d", MAJOR_FRRVERSION(version), + MINOR_FRRVERSION(version), SUB_FRRVERSION(version)); + + return buf; +} diff --git a/lib/libfrr.h b/lib/libfrr.h index ee436d9f8f..77d70448a9 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -233,6 +233,17 @@ extern bool frr_is_after_fork; extern bool debug_memstats_at_exit; +/* + * Version numbering: MAJOR (8) | MINOR (16) | SUB (8) + */ +#define MAKE_FRRVERSION(maj, min, sub) \ + ((((maj) & 0xff) << 24) | (((min) & 0xffff) << 8) | ((sub) & 0xff)) +#define MAJOR_FRRVERSION(v) (((v) >> 24) & 0xff) +#define MINOR_FRRVERSION(v) (((v) >> 8) & 0xffff) +#define SUB_FRRVERSION(v) ((v) & 0xff) + +const char *frr_vers2str(uint32_t version, char *buf, int buflen); + #ifdef __cplusplus } #endif diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index e26fe6f53a..198309c1ef 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -2740,9 +2740,9 @@ static void show_sr_node(struct vty *vty, struct json_object *json, if (srn->algo[i] == SR_ALGORITHM_UNSET) continue; json_obj = json_object_new_object(); - char tmp[2]; + char tmp[12]; - snprintf(tmp, sizeof(tmp), "%u", i); + snprintf(tmp, sizeof(tmp), "%d", i); json_object_string_add(json_obj, tmp, srn->algo[i] == SR_ALGORITHM_SPF ? "SPF" diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index be36a07687..15d3904c37 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1941,12 +1941,15 @@ DEFUN (show_ip_pim_mlag_summary, json_object *json_stat = NULL; json = json_object_new_object(); - if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP) - json_object_boolean_true_add(json, "mlagConnUp"); - if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP) - json_object_boolean_true_add(json, "mlagPeerConnUp"); - if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP) - json_object_boolean_true_add(json, "mlagPeerZebraUp"); + json_object_boolean_add(json, "mlagConnUp", + CHECK_FLAG(router->mlag_flags, + PIM_MLAGF_LOCAL_CONN_UP)); + json_object_boolean_add(json, "mlagPeerConnUp", + CHECK_FLAG(router->mlag_flags, + PIM_MLAGF_PEER_CONN_UP)); + json_object_boolean_add(json, "mlagPeerZebraUp", + CHECK_FLAG(router->mlag_flags, + PIM_MLAGF_PEER_ZEBRA_UP)); json_object_string_add(json, "mlagRole", mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf))); diff --git a/tests/topotests/bgp_evpn_maximum_prefix/__init__.py b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf new file mode 100644 index 0000000000..7476a3723d --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf @@ -0,0 +1,4 @@ +! +int c1-eth0 + ip address 192.168.0.1/24 +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf new file mode 100644 index 0000000000..a203daae05 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf @@ -0,0 +1,4 @@ +! +int c2-eth0 + ip address 192.168.0.2/24 +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf new file mode 100644 index 0000000000..0534518cfb --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf @@ -0,0 +1,30 @@ +! +!debug bgp neighbor +!debug route-map detail +! +vni 10 +! +int lo + ip address 10.10.10.1/32 +! +int r1-eth1 + ip address 192.168.1.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + ! + address-family ipv4 unicast + redistribute connected + network 10.10.10.10/32 + exit-address-family + ! + address-family l2vpn evpn + neighbor 192.168.1.2 activate + advertise-all-vni + advertise ipv4 unicast + exit-address-family +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf new file mode 100644 index 0000000000..353302b9e7 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf @@ -0,0 +1,25 @@ +! +!debug bgp neighbor +! +int lo + ip address 10.10.10.2/32 +! +int r2-eth0 + ip address 192.168.1.2/24 +! +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + ! + address-family ipv4 unicast + redistribute connected + exit-address-family + ! + address-family l2vpn evpn + neighbor 192.168.1.1 activate + neighbor 192.168.1.1 maximum-prefix 2 + advertise-all-vni + exit-address-family +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py new file mode 100644 index 0000000000..5469eff144 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2024 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +import os +import re +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")} + tgen = Topogen(topodef, mod.__name__) + tgen.start_topology() + + tgen.net["r1"].cmd( + """ +ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.1 nolearning +ip link add name br10 type bridge +ip link set dev vxlan10 master br10 +ip link set dev r1-eth0 master br10 +ip link set up dev br10 +ip link set up dev vxlan10""" + ) + + tgen.net["r2"].cmd( + """ +ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.2 nolearning +ip link add name br10 type bridge +ip link set dev vxlan10 master br10 +ip link set dev r2-eth1 master br10 +ip link set up dev br10 +ip link set up dev vxlan10""" + ) + + router_list = tgen.routers() + + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_evpn_maximum_prefix(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp l2vpn evpn summary failed json")) + expected = { + "peers": { + "192.168.1.1": { + "lastNotificationReason": "Cease/Maximum Number of Prefixes Reached", + "lastResetDueTo": "BGP Notification send", + } + }, + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_converge, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assert result is None, "Can't limit maximum-prefixes for EVPN routes" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tools/indent.py b/tools/indent.py index fe9eb7c252..dac7d3f04b 100755 --- a/tools/indent.py +++ b/tools/indent.py @@ -34,13 +34,13 @@ def wrap_file(fn): ci = subprocess.Popen( ["clang-format"], stdin=subprocess.PIPE, stdout=subprocess.PIPE ) - stdout, ign = ci.communicate(text) + stdout, ign = ci.communicate(text.encode("utf-8")) ci.wait() if ci.returncode != 0: raise IOError("clang-format returned %d" % (ci.returncode)) # remove the bits we inserted above - final = clean_re.sub("", stdout) + final = clean_re.sub("", stdout.decode("utf-8")) tmpname = fn + ".indent" with open(tmpname, "w") as ofd: diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 006ab504ef..06b34da209 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -39,6 +39,13 @@ DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes"); # define AOK 0 #endif +/* + * Dataplane API version. This must be updated when any incompatible changes + * are made. The minor version (at least) should be updated when new APIs + * are introduced. + */ +static uint32_t zdplane_version = MAKE_FRRVERSION(2, 0, 0); + /* Control for collection of extra interface info with route updates; a plugin * can enable the extra info via a dplane api. */ @@ -664,6 +671,12 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp, * Public APIs */ +/* Access the dplane API version */ +uint32_t zebra_dplane_get_version(void) +{ + return zdplane_version; +} + /* Obtain thread_master for dataplane thread */ struct event_loop *dplane_get_thread_master(void) { diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 2f7d218508..060b1c8b9e 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -24,6 +24,13 @@ extern "C" { #endif +/* Retrieve the dataplane API version number; see libfrr.h to decode major, + * minor, sub version values. + * Plugins should pay attention to the major version number, at least, to + * be able to detect API changes that may not be backward-compatible. + */ +uint32_t zebra_dplane_get_version(void); + /* Key netlink info from zebra ns */ struct zebra_dplane_info { ns_id_t ns_id; diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c index 941088afd6..a222e7f6e8 100644 --- a/zebra/zebra_neigh.c +++ b/zebra/zebra_neigh.c @@ -83,7 +83,7 @@ zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac) n->ifindex = ifindex; if (mac) { memcpy(&n->mac, mac, sizeof(*mac)); - n->flags |= ZEBRA_NEIGH_ENT_ACTIVE; + SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); } /* Add to rb_tree */ @@ -118,10 +118,8 @@ static void zebra_neigh_free(struct zebra_neigh_ent *n) /* if rules are still using the neigh mark it as inactive and * update the dataplane */ - if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) { - n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE; - memset(&n->mac, 0, sizeof(n->mac)); - } + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); + memset(&n->mac, 0, sizeof(n->mac)); zebra_neigh_pbr_rules_update(n); return; } @@ -181,7 +179,7 @@ void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip, return; memcpy(&n->mac, mac, sizeof(*mac)); - n->flags |= ZEBRA_NEIGH_ENT_ACTIVE; + SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); /* update rules linked to the neigh */ zebra_neigh_pbr_rules_update(n); @@ -201,7 +199,7 @@ void zebra_neigh_deref(struct zebra_pbr_rule *rule) rule->action.neigh = NULL; /* remove rule from the list and free if it is inactive */ list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode); - if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE)) + if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE)) zebra_neigh_free(n); } diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c index 1af3a3e857..4cee3b89f1 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -42,7 +42,7 @@ #define NETLINK_SOCKET_BUFFER_SIZE 512 #define NETLINK_ALIGNTO 4 #define NETLINK_ALIGN(len) \ - (((len) + NETLINK_ALIGNTO - 1) & ~(NETLINK_ALIGNTO - 1)) + CHECK_FLAG(((len) + NETLINK_ALIGNTO - 1), ~(NETLINK_ALIGNTO - 1)) #define NETLINK_NLATTR_LEN(_a, _b) (unsigned int)((char *)_a - (char *)_b) #endif /* defined(HAVE_NETLINK) */ @@ -66,7 +66,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type) nlh->nlmsg_type = type; nlh->nlmsg_flags = NLM_F_REQUEST; if (type == RTM_NEWNSID) - nlh->nlmsg_flags |= NLM_F_ACK; + SET_FLAG(nlh->nlmsg_flags, NLM_F_ACK); nlh->nlmsg_seq = *seq = frr_sequence32_next(); return nlh; } diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 1bb1292e34..617a2225f8 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -304,7 +304,7 @@ static void zebra_ns_notify_read(struct event *t) char *netnspath; struct zebra_netns_info *netnsinfo; - if (!(event->mask & (IN_CREATE | IN_DELETE))) + if (!CHECK_FLAG(event->mask, (IN_CREATE | IN_DELETE))) continue; if (offsetof(struct inotify_event, name) + event->len @@ -350,7 +350,7 @@ static void zebra_ns_notify_read(struct event *t) memcpy(event_name, event->name, event->len); event_name[event->len - 1] = 0; - if (event->mask & IN_DELETE) { + if (CHECK_FLAG(event->mask, IN_DELETE)) { zebra_ns_delete(event_name); continue; } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 934b8ba0db..ff97a11c17 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1795,8 +1795,8 @@ static struct nexthop *nexthop_set_resolved(afi_t afi, break; } - if (newhop->flags & NEXTHOP_FLAG_ONLINK) - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_ONLINK)) + SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ONLINK); /* Copy labels of the resolved route and the parent resolving to it */ if (policy) { |
