diff options
60 files changed, 1061 insertions, 615 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 1385345d64..f5652b07c5 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1466,7 +1466,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2) /* Not reached */ } -/* Iterate over AS_PATH segments and wipe all occurences of the +/* Iterate over AS_PATH segments and wipe all occurrences of the * listed AS numbers. Hence some segments may lose some or even * all data on the way, the operation is implemented as a smarter * version of aspath_dup(), which allocates memory to hold the new diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index d031d34f1f..e6d81e54c4 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -3757,9 +3757,9 @@ DEFUN(show_bgp_l2vpn_evpn_route, type = BGP_EVPN_MAC_IP_ROUTE; else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0) type = BGP_EVPN_IMET_ROUTE; - else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0) + else if (strncmp(argv[type_idx + 1]->arg, "e", 1) == 0) type = BGP_EVPN_ES_ROUTE; - else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0) + else if (strncmp(argv[type_idx + 1]->arg, "p", 1) == 0) type = BGP_EVPN_IP_PREFIX_ROUTE; else return CMD_WARNING; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 4348e6b240..c9c6fc157e 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -96,6 +96,21 @@ static int bgp_holdtime_timer(struct thread *); /* BGP FSM functions. */ static int bgp_start(struct peer *); +/* Register peer with NHT */ +static int bgp_peer_reg_with_nht(struct peer *peer) +{ + int connected = 0; + + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 + && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + connected = 1; + + return bgp_find_or_add_nexthop( + peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family), + NULL, peer, connected); +} + static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src) { /* Copy stats over. These are only the pre-established state stats */ @@ -293,6 +308,11 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) if (from_peer) peer_xfer_stats(peer, from_peer); + /* Register peer for NHT. This is to allow RAs to be enabled when + * needed, even on a passive connection. + */ + bgp_peer_reg_with_nht(peer); + bgp_reads_on(peer); bgp_writes_on(peer); thread_add_timer_msec(bm->master, bgp_process_packet, peer, 0, @@ -1382,7 +1402,6 @@ static int bgp_connect_fail(struct peer *peer) int bgp_start(struct peer *peer) { int status; - int connected = 0; bgp_peer_conf_if_to_su_update(peer); @@ -1439,17 +1458,10 @@ int bgp_start(struct peer *peer) return -1; } - /* Register to be notified on peer up */ - if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 - && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - connected = 1; - else - connected = 0; - - if (!bgp_find_or_add_nexthop(peer->bgp, peer->bgp, - family2afi(peer->su.sa.sa_family), NULL, - peer, connected)) { + /* Register peer for NHT. If next hop is already resolved, proceed + * with connection setup, else wait. + */ + if (!bgp_peer_reg_with_nht(peer)) { if (bgp_zebra_num_connects()) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s [FSM] Waiting for NHT", diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index a8c507832c..812f0ce16e 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -680,17 +680,23 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail, continue; for (rn = bgp_table_top(table[afi]); rn; rn = bgp_route_next(rn)) { + struct peer *peer; + bnc = bgp_node_get_bgp_nexthop_info(rn); if (!bnc) continue; + peer = (struct peer *)bnc->nht_info; if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) { vty_out(vty, - " %s valid [IGP metric %d], #paths %d\n", + " %s valid [IGP metric %d], #paths %d", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf)), bnc->metric, bnc->path_count); + if (peer) + vty_out(vty, ", peer %s", peer->host); + vty_out(vty, "\n"); if (!detail) continue; @@ -698,10 +704,13 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail, bgp_show_nexthops_detail(vty, bgp, bnc); } else { - vty_out(vty, " %s invalid\n", + vty_out(vty, " %s invalid", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf))); + if (peer) + vty_out(vty, ", peer %s", peer->host); + vty_out(vty, "\n"); if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) vty_out(vty, " Must be Connected\n"); diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 64529f6ef3..7e5e07099d 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -503,7 +503,7 @@ static int bgp_capability_restart(struct peer *peer, if (bgp_debug_neighbor_events(peer)) zlog_debug( "%s Address family %s is%spreserved", - peer->host, afi_safi_print(afi, safi), + peer->host, get_afi_safi_str(afi, safi, false), CHECK_FLAG( peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 99522a6522..d3a08d23d9 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -140,7 +140,7 @@ static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi, if (bgp_debug_neighbor_events(peer)) zlog_debug("send End-of-RIB for %s to %s", - afi_safi_print(afi, safi), peer->host); + get_afi_safi_str(afi, safi, false), peer->host); s = stream_new(BGP_MAX_PACKET_SIZE); @@ -1660,7 +1660,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) bgp_clear_stale_route(peer, afi, safi); zlog_info("%%NOTIFICATION: rcvd End-of-RIB for %s from %s in vrf %s", - afi_safi_print(afi, safi), peer->host, + get_afi_safi_str(afi, safi, false), peer->host, vrf ? vrf->name : VRF_DEFAULT_NAME); } } diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h index e8eacee589..fc6fc66a4c 100644 --- a/bgpd/bgp_packet.h +++ b/bgpd/bgp_packet.h @@ -57,9 +57,6 @@ extern void bgp_notify_send_with_data(struct peer *, uint8_t, uint8_t, extern void bgp_route_refresh_send(struct peer *, afi_t, safi_t, uint8_t, uint8_t, int); extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int); -extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t, - struct peer *); -extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t); extern int bgp_capability_receive(struct peer *, bgp_size_t); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 183debddba..32c9fb16f3 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2750,7 +2750,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, zlog_info( "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, " "limit %ld", - afi_safi_print(afi, safi), peer->host, + get_afi_safi_str(afi, safi, false), peer->host, peer->pcount[afi][safi], peer->pmax[afi][safi]); SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); @@ -2811,7 +2811,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, zlog_info( "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld", - afi_safi_print(afi, safi), peer->host, + get_afi_safi_str(afi, safi, false), peer->host, peer->pcount[afi][safi], peer->pmax[afi][safi]); SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); @@ -10696,7 +10696,7 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, return CMD_WARNING; } - vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi)); + vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false)); /* labeled-unicast routes live in the unicast table */ if (safi == SAFI_LABELED_UNICAST) @@ -10895,7 +10895,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, if (use_json) { json_object_string_add(json, "prefixCountsFor", peer->host); json_object_string_add(json, "multiProtocol", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, true)); json_object_int_add(json, "pfxCounter", peer->pcount[afi][safi]); @@ -10921,10 +10921,10 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) { vty_out(vty, "Prefix counts for %s/%s, %s\n", peer->hostname, peer->host, - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); } else { vty_out(vty, "Prefix counts for %s, %s\n", peer->host, - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); } vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]); @@ -11552,7 +11552,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, if (count) { if (!uj) vty_out(vty, "Address Family: %s\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); prefix_bgp_show_prefix_list(vty, afi, name, uj); } else { if (uj) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 7f1a9b71c1..aaae9e380e 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -4158,6 +4158,18 @@ DEFUN (no_set_aspath_prepend, return ret; } +DEFUN (no_set_aspath_prepend_lastas, + no_set_aspath_prepend_lastas_cmd, + "no set as-path prepend last-as [(1-10)]", + NO_STR + SET_STR + "Transform BGP AS_PATH attribute\n" + "Prepend to the as-path\n" + "Use the peers AS-number\n" + "Number of times to insert\n") +{ + return no_set_aspath_prepend(self, vty, argc, argv); +} DEFUN (set_aspath_exclude, set_aspath_exclude_cmd, @@ -5123,6 +5135,7 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd); install_element(RMAP_NODE, &set_aspath_exclude_cmd); install_element(RMAP_NODE, &no_set_aspath_prepend_cmd); + install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_cmd); install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd); install_element(RMAP_NODE, &set_origin_cmd); diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 5414e2ef15..22840d54c6 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -1180,7 +1180,7 @@ DEFPY (show_rpki_prefix, { if (!is_synchronized()) { - vty_out(vty, "No Conection to RPKI cache server.\n"); + vty_out(vty, "No Connection to RPKI cache server.\n"); return CMD_WARNING; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 58a202d510..f6aca6fbf5 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -22,6 +22,7 @@ #include "command.h" #include "lib/json.h" +#include "lib_errors.h" #include "lib/zclient.h" #include "prefix.h" #include "plist.h" @@ -130,6 +131,80 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi) return BGP_IPV4_NODE; } +static const char *get_afi_safi_vty_str(afi_t afi, safi_t safi) +{ + if (afi == AFI_IP && safi == SAFI_UNICAST) + return "IPv4 Unicast"; + else if (afi == AFI_IP && safi == SAFI_MULTICAST) + return "IPv4 Multicast"; + else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) + return "IPv4 Labeled Unicast"; + else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) + return "IPv4 VPN"; + else if (afi == AFI_IP && safi == SAFI_ENCAP) + return "IPv4 Encap"; + else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) + return "IPv4 Flowspec"; + else if (afi == AFI_IP6 && safi == SAFI_UNICAST) + return "IPv6 Unicast"; + else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) + return "IPv6 Multicast"; + else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) + return "IPv6 Labeled Unicast"; + else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) + return "IPv6 VPN"; + else if (afi == AFI_IP6 && safi == SAFI_ENCAP) + return "IPv6 Encap"; + else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) + return "IPv6 Flowspec"; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return "L2VPN EVPN"; + else { + flog_err(EC_LIB_DEVELOPMENT, "New afi/safi that needs to be taken care of?"); + return "Unknown"; + } +} + +/* + * Please note that we have intentionally camelCased + * the return strings here. So if you want + * to use this function, please ensure you + * are doing this within json output + */ +static const char *get_afi_safi_json_str(afi_t afi, safi_t safi) +{ + if (afi == AFI_IP && safi == SAFI_UNICAST) + return "ipv4Unicast"; + else if (afi == AFI_IP && safi == SAFI_MULTICAST) + return "ipv4Multicast"; + else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) + return "ipv4LabeledUnicast"; + else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) + return "ipv4Vpn"; + else if (afi == AFI_IP && safi == SAFI_ENCAP) + return "ipv4Encap"; + else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) + return "ipv4Flowspec"; + else if (afi == AFI_IP6 && safi == SAFI_UNICAST) + return "ipv6Unicast"; + else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) + return "ipv6Multicast"; + else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) + return "ipv6LabeledUnicast"; + else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) + return "ipv6Vpn"; + else if (afi == AFI_IP6 && safi == SAFI_ENCAP) + return "ipv6Encap"; + else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) + return "ipv6Flowspec"; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return "l2VpnEvpn"; + else { + flog_err(EC_LIB_DEVELOPMENT, "New afi/safi that needs to be taken care of?"); + return "Unknown"; + } +} + /* Utility function to get address family from current node. */ afi_t bgp_node_afi(struct vty *vty) { @@ -584,7 +659,7 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi, case BGP_ERR_AF_UNCONFIGURED: vty_out(vty, "%%BGP: Enable %s address family for the neighbor %s\n", - afi_safi_print(afi, safi), peer->host); + get_afi_safi_str(afi, safi, false), peer->host); break; case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED: vty_out(vty, @@ -596,12 +671,61 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi, } } +static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi, + struct listnode *nnode, enum bgp_clear_type stype) +{ + int ret = 0; + + /* if afi/.safi not specified, spin thru all of them */ + if ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC)) { + afi_t tmp_afi; + safi_t tmp_safi; + + FOREACH_AFI_SAFI (tmp_afi, tmp_safi) { + if (!peer->afc[tmp_afi][tmp_safi]) + continue; + + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, &nnode); + else + ret = peer_clear_soft(peer, tmp_afi, tmp_safi, + stype); + } + /* if afi specified and safi not, spin thru safis on this afi */ + } else if (safi == SAFI_UNSPEC) { + safi_t tmp_safi; + + for (tmp_safi = SAFI_UNICAST; + tmp_safi < SAFI_MAX; tmp_safi++) { + if (!peer->afc[afi][tmp_safi]) + continue; + + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, &nnode); + else + ret = peer_clear_soft(peer, afi, + tmp_safi, stype); + } + /* both afi/safi specified, let the caller know if not defined */ + } else { + if (!peer->afc[afi][safi]) + return 1; + + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, &nnode); + else + ret = peer_clear_soft(peer, afi, safi, stype); + } + + return ret; +} + /* `clear ip bgp' functions. */ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, enum clear_sort sort, enum bgp_clear_type stype, const char *arg) { - int ret; + int ret = 0; bool found = false; struct peer *peer; struct listnode *node, *nnode; @@ -614,13 +738,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, */ if (sort == clear_all) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { - if (!peer->afc[afi][safi]) - continue; - - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear(peer, &nnode); - else - ret = peer_clear_soft(peer, afi, safi, stype); + ret = bgp_peer_clear(peer, afi, safi, nnode, + stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); @@ -660,12 +779,11 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, } } - if (!peer->afc[afi][safi]) + ret = bgp_peer_clear(peer, afi, safi, NULL, stype); + + /* if afi/safi not defined for this peer, let caller know */ + if (ret == 1) ret = BGP_ERR_AF_UNCONFIGURED; - else if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear(peer, NULL); - else - ret = peer_clear_soft(peer, afi, safi, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); @@ -684,13 +802,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, } for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { - if (!peer->afc[afi][safi]) - continue; - - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear(peer, NULL); - else - ret = peer_clear_soft(peer, afi, safi, stype); + ret = bgp_peer_clear(peer, afi, safi, nnode, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); @@ -701,7 +813,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (!found) vty_out(vty, "%%BGP: No %s peer belonging to peer-group %s is configured\n", - afi_safi_print(afi, safi), arg); + get_afi_safi_str(afi, safi, false), arg); return CMD_SUCCESS; } @@ -712,13 +824,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (peer->sort == BGP_PEER_IBGP) continue; - if (!peer->afc[afi][safi]) - continue; - - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear(peer, &nnode); - else - ret = peer_clear_soft(peer, afi, safi, stype); + ret = bgp_peer_clear(peer, afi, safi, nnode, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); @@ -729,7 +835,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (!found) vty_out(vty, "%%BGP: No external %s peer is configured\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); return CMD_SUCCESS; } @@ -742,12 +848,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (peer->as != as) continue; - if (!peer->afc[afi][safi]) - ret = BGP_ERR_AF_UNCONFIGURED; - else if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear(peer, &nnode); - else - ret = peer_clear_soft(peer, afi, safi, stype); + ret = bgp_peer_clear(peer, afi, safi, nnode, stype); if (ret < 0) bgp_clear_vty_error(vty, peer, afi, safi, ret); @@ -758,7 +859,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, if (!found) vty_out(vty, "%%BGP: No %s peer is configured with AS %s\n", - afi_safi_print(afi, safi), arg); + get_afi_safi_str(afi, safi, false), arg); return CMD_SUCCESS; } @@ -6069,7 +6170,7 @@ DEFUN (neighbor_allowas_in, NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Accept as-path with my AS present in it\n" - "Number of occurences of AS number\n" + "Number of occurrences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") { int idx_peer = 1; @@ -6103,7 +6204,7 @@ ALIAS_HIDDEN( "neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Accept as-path with my AS present in it\n" - "Number of occurences of AS number\n" + "Number of occurrences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (no_neighbor_allowas_in, @@ -6113,7 +6214,7 @@ DEFUN (no_neighbor_allowas_in, NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "allow local ASN appears in aspath attribute\n" - "Number of occurences of AS number\n" + "Number of occurrences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") { int idx_peer = 2; @@ -6135,7 +6236,7 @@ ALIAS_HIDDEN( "no neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "allow local ASN appears in aspath attribute\n" - "Number of occurences of AS number\n" + "Number of occurrences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (neighbor_ttl_security, @@ -7238,8 +7339,8 @@ DEFUN (clear_ip_bgp_all, { char *vrf = NULL; - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; + afi_t afi = AFI_UNSPEC; + safi_t safi = SAFI_UNSPEC; enum clear_sort clr_sort = clear_peer; enum bgp_clear_type clr_type; char *clr_arg = NULL; @@ -8187,7 +8288,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, vty_out(vty, "\nTotal number of neighbors %d\n", count); else { vty_out(vty, "No %s neighbor is configured\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); } if (dn_count) { @@ -8234,12 +8335,14 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, is_first = 0; vty_out(vty, "\"%s\":", - afi_safi_json(afi, - safi)); + get_afi_safi_str(afi, + safi, + true)); } else { vty_out(vty, "\n%s Summary:\n", - afi_safi_print(afi, - safi)); + get_afi_safi_str(afi, + safi, + false)); } } bgp_show_summary(vty, bgp, afi, safi, use_json); @@ -8384,74 +8487,12 @@ DEFUN (show_ip_bgp_summary, return bgp_show_summary_vty(vty, vrf, afi, safi, uj); } -const char *afi_safi_print(afi_t afi, safi_t safi) +const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json) { - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "IPv4 Unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "IPv4 Multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "IPv4 Labeled Unicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "IPv4 VPN"; - else if (afi == AFI_IP && safi == SAFI_ENCAP) - return "IPv4 Encap"; - else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) - return "IPv4 Flowspec"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "IPv6 Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "IPv6 Multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "IPv6 Labeled Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "IPv6 VPN"; - else if (afi == AFI_IP6 && safi == SAFI_ENCAP) - return "IPv6 Encap"; - else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) - return "IPv6 Flowspec"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "L2VPN EVPN"; + if (for_json) + return get_afi_safi_json_str(afi, safi); else - return "Unknown"; -} - -/* - * Please note that we have intentionally camelCased - * the return strings here. So if you want - * to use this function, please ensure you - * are doing this within json output - */ -const char *afi_safi_json(afi_t afi, safi_t safi) -{ - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "ipv4Unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "ipv4Multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "ipv4LabeledUnicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "ipv4Vpn"; - else if (afi == AFI_IP && safi == SAFI_ENCAP) - return "ipv4Encap"; - else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) - return "ipv4Flowspec"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "ipv6Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "ipv6Multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "ipv6LabeledUnicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "ipv6Vpn"; - else if (afi == AFI_IP6 && safi == SAFI_ENCAP) - return "ipv6Encap"; - else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) - return "ipv6Flowspec"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "l2VpnEvpn"; - else - return "Unknown"; + return get_afi_safi_vty_str(afi, safi); } /* Show BGP peer's information. */ @@ -8829,14 +8870,14 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi, "prefixAllowedRestartIntervalMsecs", p->pmax_restart[afi][safi] * 60000); } - json_object_object_add(json_neigh, afi_safi_print(afi, safi), + json_object_object_add(json_neigh, get_afi_safi_str(afi, safi, true), json_addr); } else { filter = &p->filter[afi][safi]; vty_out(vty, " For address family: %s\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); if (peer_group_active(p)) vty_out(vty, " %s peer-group member\n", @@ -9543,8 +9584,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object *json_sub = NULL; json_sub = json_object_new_object(); - print_store = afi_safi_print( - afi, safi); + print_store = get_afi_safi_str( + afi, safi, true); if (CHECK_FLAG( p->af_cap[afi] @@ -9722,9 +9763,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, [AFI_IP] [safi], PEER_CAP_ENHE_AF_RCV)) { - print_store = afi_safi_print( + print_store = get_afi_safi_str( AFI_IP, - safi); + safi, true); json_object_string_add( json_nxt, print_store, @@ -9824,8 +9865,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object_object_add( json_multi, - afi_safi_print(afi, - safi), + get_afi_safi_str(afi, + safi, + true), json_exten); } } @@ -9931,9 +9973,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, restart_af_count++; json_object_object_add( json_restart, - afi_safi_print( + get_afi_safi_str( afi, - safi), + safi, + true), json_sub); } } @@ -9992,9 +10035,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_CAP_ADDPATH_AF_TX_RCV)) { vty_out(vty, " %s: TX ", - afi_safi_print( + get_afi_safi_str( afi, - safi)); + safi, + false)); if (CHECK_FLAG( p->af_cap @@ -10003,9 +10047,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_CAP_ADDPATH_AF_TX_ADV)) vty_out(vty, "advertised %s", - afi_safi_print( + get_afi_safi_str( afi, - safi)); + safi, + false)); if (CHECK_FLAG( p->af_cap @@ -10035,9 +10080,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_CAP_ADDPATH_AF_RX_RCV)) { vty_out(vty, " %s: RX ", - afi_safi_print( + get_afi_safi_str( afi, - safi)); + safi, + false)); if (CHECK_FLAG( p->af_cap @@ -10046,9 +10092,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_CAP_ADDPATH_AF_RX_ADV)) vty_out(vty, "advertised %s", - afi_safi_print( + get_afi_safi_str( afi, - safi)); + safi, + false)); if (CHECK_FLAG( p->af_cap @@ -10119,9 +10166,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_CAP_ENHE_AF_RCV)) vty_out(vty, " %s\n", - afi_safi_print( + get_afi_safi_str( AFI_IP, - safi)); + safi, + false)); } } @@ -10168,8 +10216,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, || p->afc_recv[afi][safi]) { vty_out(vty, " Address Family %s:", - afi_safi_print(afi, - safi)); + get_afi_safi_str( + afi, + safi, + false)); if (p->afc_adv[afi][safi]) vty_out(vty, " advertised"); @@ -10254,9 +10304,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, restart_af_count ? ", " : "", - afi_safi_print( + get_afi_safi_str( afi, - safi), + safi, + false), CHECK_FLAG( p->af_cap [afi] @@ -10295,8 +10346,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_STATUS_EOR_SEND)) { json_object_boolean_true_add( json_grace_send, - afi_safi_print(afi, - safi)); + get_afi_safi_str(afi, + safi, + true)); eor_send_af_count++; } } @@ -10306,8 +10358,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, PEER_STATUS_EOR_RECEIVED)) { json_object_boolean_true_add( json_grace_recv, - afi_safi_print(afi, - safi)); + get_afi_safi_str(afi, + safi, + true)); eor_receive_af_count++; } } @@ -10345,8 +10398,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, vty_out(vty, "%s%s", eor_send_af_count ? ", " : "", - afi_safi_print(afi, - safi)); + get_afi_safi_str(afi, + safi, + false)); eor_send_af_count++; } } @@ -10360,8 +10414,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, eor_receive_af_count ? ", " : "", - afi_safi_print(afi, - safi)); + get_afi_safi_str(afi, + safi, + false)); eor_receive_af_count++; } } @@ -11293,7 +11348,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, /* Provide context for the block */ json_object_string_add(json, "vrf", name ? name : "default"); json_object_string_add(json, "afiSafi", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, true)); if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { @@ -11374,11 +11429,11 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, BGP_CONFIG_VRF_TO_VRF_IMPORT)) vty_out(vty, "This VRF is not importing %s routes from any other VRF\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); else { vty_out(vty, "This VRF is importing %s routes from the following VRFs:\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); for (ALL_LIST_ELEMENTS_RO( bgp->vpn_policy[afi].import_vrf, @@ -11402,11 +11457,11 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, BGP_CONFIG_VRF_TO_VRF_EXPORT)) vty_out(vty, "This VRF is not exporting %s routes to any other VRF\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); else { vty_out(vty, "This VRF is exporting %s routes to the following VRFs:\n", - afi_safi_print(afi, safi)); + get_afi_safi_str(afi, safi, false)); for (ALL_LIST_ELEMENTS_RO( bgp->vpn_policy[afi].export_vrf, @@ -11783,7 +11838,7 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group) FOREACH_AFI_SAFI (afi, safi) { if (conf->afc[afi][safi]) { af_cfgd = 1; - vty_out(vty, " %s;", afi_safi_print(afi, safi)); + vty_out(vty, " %s;", get_afi_safi_str(afi, safi, false)); } } if (!af_cfgd) @@ -14452,12 +14507,13 @@ ALIAS (show_community_list, DEFUN (show_community_list_arg, show_bgp_community_list_arg_cmd, - "show bgp community-list <(1-500)|WORD>", + "show bgp community-list <(1-500)|WORD> detail", SHOW_STR BGP_STR "List community-list\n" "Community-list number\n" - "Community-list name\n") + "Community-list name\n" + "Detailed information on community-list\n") { int idx_comm_list = 3; struct community_list *list; @@ -14466,8 +14522,8 @@ DEFUN (show_community_list_arg, if (argv_find(argv, argc, "ip", &idx)) { vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); vty_out(vty, "if you are using this please migrate to the below command.\n"); - vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n"); - zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used"); + vty_out(vty, "'show bgp community-list <(1-500)|WORD> detail'\n"); + zlog_warn("Deprecated option: 'show ip community-list <(1-500)|WORD>' being used"); } list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0, COMMUNITY_LIST_MASTER); @@ -14606,28 +14662,6 @@ CPP_NOTICE("bgpd: remove deprecated 'ip large-community-list <(1-99)|(100-500)|s #endif DEFUN (lcommunity_list_standard, bgp_lcommunity_list_standard_cmd, - "bgp large-community-list (1-99) <deny|permit>", - BGP_STR - LCOMMUNITY_LIST_STR - "Large Community list number (standard)\n" - "Specify large community to reject\n" - "Specify large community to accept\n") -{ - return lcommunity_list_set_vty(vty, argc, argv, - LARGE_COMMUNITY_LIST_STANDARD, 0); -} - -ALIAS (lcommunity_list_standard, - ip_lcommunity_list_standard_cmd, - "ip large-community-list (1-99) <deny|permit>", - IP_STR - LCOMMUNITY_LIST_STR - "Large Community list number (standard)\n" - "Specify large community to reject\n" - "Specify large community to accept\n") - -DEFUN (lcommunity_list_standard1, - bgp_lcommunity_list_standard1_cmd, "bgp large-community-list (1-99) <deny|permit> AA:BB:CC...", BGP_STR LCOMMUNITY_LIST_STR @@ -14640,8 +14674,8 @@ DEFUN (lcommunity_list_standard1, LARGE_COMMUNITY_LIST_STANDARD, 0); } -ALIAS (lcommunity_list_standard1, - ip_lcommunity_list_standard1_cmd, +ALIAS (lcommunity_list_standard, + ip_lcommunity_list_standard_cmd, "ip large-community-list (1-99) <deny|permit> AA:BB:CC...", IP_STR LCOMMUNITY_LIST_STR @@ -14676,30 +14710,6 @@ ALIAS (lcommunity_list_expanded, DEFUN (lcommunity_list_name_standard, bgp_lcommunity_list_name_standard_cmd, - "bgp large-community-list standard WORD <deny|permit>", - BGP_STR - LCOMMUNITY_LIST_STR - "Specify standard large-community-list\n" - "Large Community list name\n" - "Specify large community to reject\n" - "Specify large community to accept\n") -{ - return lcommunity_list_set_vty(vty, argc, argv, - LARGE_COMMUNITY_LIST_STANDARD, 1); -} - -ALIAS (lcommunity_list_name_standard, - ip_lcommunity_list_name_standard_cmd, - "ip large-community-list standard WORD <deny|permit>", - IP_STR - LCOMMUNITY_LIST_STR - "Specify standard large-community-list\n" - "Large Community list name\n" - "Specify large community to reject\n" - "Specify large community to accept\n") - -DEFUN (lcommunity_list_name_standard1, - bgp_lcommunity_list_name_standard1_cmd, "bgp large-community-list standard WORD <deny|permit> AA:BB:CC...", BGP_STR LCOMMUNITY_LIST_STR @@ -14713,8 +14723,8 @@ DEFUN (lcommunity_list_name_standard1, LARGE_COMMUNITY_LIST_STANDARD, 1); } -ALIAS (lcommunity_list_name_standard1, - ip_lcommunity_list_name_standard1_cmd, +ALIAS (lcommunity_list_name_standard, + ip_lcommunity_list_name_standard_cmd, "ip large-community-list standard WORD <deny|permit> AA:BB:CC...", IP_STR LCOMMUNITY_LIST_STR @@ -14977,12 +14987,13 @@ ALIAS (show_lcommunity_list, DEFUN (show_lcommunity_list_arg, show_bgp_lcommunity_list_arg_cmd, - "show bgp large-community-list <(1-500)|WORD>", + "show bgp large-community-list <(1-500)|WORD> detail", SHOW_STR BGP_STR "List large-community list\n" - "large-community-list number\n" - "large-community-list name\n") + "Large-community-list number\n" + "Large-community-list name\n" + "Detailed information on large-community-list\n") { struct community_list *list; int idx = 0; @@ -14990,14 +15001,14 @@ DEFUN (show_lcommunity_list_arg, if (argv_find(argv, argc, "ip", &idx)) { vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); vty_out(vty, "if you are using this please migrate to the below command.\n"); - vty_out(vty, "'show bgp large-community-list <(1-500)|WORD>'\n"); - zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used"); + vty_out(vty, "'show bgp large-community-list <(1-500)|WORD> detail'\n"); + zlog_warn("Deprecated option: 'show ip large-community-list <(1-500)|WORD>' being used"); } list = community_list_lookup(bgp_clist, argv[3]->arg, 0, LARGE_COMMUNITY_LIST_MASTER); if (!list) { - vty_out(vty, "%% Can't find extcommunity-list\n"); + vty_out(vty, "%% Can't find large-community-list\n"); return CMD_WARNING; } @@ -15378,12 +15389,13 @@ ALIAS (show_extcommunity_list, DEFUN (show_extcommunity_list_arg, show_bgp_extcommunity_list_arg_cmd, - "show bgp extcommunity-list <(1-500)|WORD>", + "show bgp extcommunity-list <(1-500)|WORD> detail", SHOW_STR BGP_STR "List extended-community list\n" "Extcommunity-list number\n" - "Extcommunity-list name\n") + "Extcommunity-list name\n" + "Detailed information on extcommunity-list\n") { int idx_comm_list = 3; struct community_list *list; @@ -15392,8 +15404,8 @@ DEFUN (show_extcommunity_list_arg, if (argv_find(argv, argc, "ip", &idx)) { vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); vty_out(vty, "if you are using this please migrate to the below command.\n"); - vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n"); - zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used"); + vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD> detail'\n"); + zlog_warn("Deprecated option: 'show ip extcommunity-list <(1-500)|WORD>' being used"); } list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0, EXTCOMMUNITY_LIST_MASTER); @@ -15540,10 +15552,8 @@ static void community_list_vty(void) /* Large Community List */ install_element(CONFIG_NODE, &bgp_lcommunity_list_standard_cmd); - install_element(CONFIG_NODE, &bgp_lcommunity_list_standard1_cmd); install_element(CONFIG_NODE, &bgp_lcommunity_list_expanded_cmd); install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard_cmd); - install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard1_cmd); install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd); install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_all_cmd); install_element(CONFIG_NODE, @@ -15555,10 +15565,8 @@ static void community_list_vty(void) install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd); install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_standard_cmd); - install_element(CONFIG_NODE, &ip_lcommunity_list_standard1_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd); - install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd); install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd); install_element(CONFIG_NODE, diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index d9df2b4cfe..961467e229 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -45,8 +45,7 @@ struct bgp; "Address Family modifier\n" extern void bgp_vty_init(void); -extern const char *afi_safi_print(afi_t afi, safi_t safi); -extern const char *afi_safi_json(afi_t afi, safi_t safi); +extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json); extern void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp); extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); extern void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp); diff --git a/configure.ac b/configure.ac index 134c8692d4..676c984385 100755 --- a/configure.ac +++ b/configure.ac @@ -1061,6 +1061,7 @@ case "$host_os" in AC_CHECK_LIB([nsl], [main]) AC_CHECK_LIB([umem], [main]) SOLARIS="solaris" + AC_MSG_WARN([--Solaris support is being considered for deprecation, please let us know if you are still using this--]) ;; linux*) AC_MSG_RESULT([Linux]) diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index f2b1328075..92d4126cec 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1169,19 +1169,24 @@ AS path access list is user defined AS path. Using AS Path in Route Map -------------------------- -.. index:: match as-path WORD -.. clicmd:: match as-path WORD +.. index:: [no] match as-path WORD +.. clicmd:: [no] match as-path WORD + For a given as-path, WORD, match it on the BGP as-path given for the prefix + and if it matches do normal route-map actions. The no form of the command + removes this match from the route-map. -.. index:: set as-path prepend AS-PATH -.. clicmd:: set as-path prepend AS-PATH +.. index:: [no] set as-path prepend AS-PATH +.. clicmd:: [no] set as-path prepend AS-PATH - Prepend the given string of AS numbers to the AS_PATH. + Prepend the given string of AS numbers to the AS_PATH of the BGP path's NLRI. + The no form of this command removes this set operation from the route-map. -.. index:: set as-path prepend last-as NUM -.. clicmd:: set as-path prepend last-as NUM +.. index:: [no] set as-path prepend last-as NUM +.. clicmd:: [no] set as-path prepend last-as NUM Prepend the existing last AS number (the leftmost ASN) to the AS_PATH. + The no form of this command removes this set operation from the route-map. .. _bgp-communities-attribute: @@ -2138,20 +2143,40 @@ Dumping Messages and Routing Tables Other BGP Commands ------------------ +.. index:: clear bgp \* +.. clicmd:: clear bgp \* + + Clear all peers. + .. index:: clear bgp ipv4|ipv6 \* .. clicmd:: clear bgp ipv4|ipv6 \* - Clear all address family peers. + Clear all peers with this address-family activated. + +.. index:: clear bgp ipv4|ipv6 unicast \* +.. clicmd:: clear bgp ipv4|ipv6 unicast \* + + Clear all peers with this address-family and sub-address-family activated. .. index:: clear bgp ipv4|ipv6 PEER .. clicmd:: clear bgp ipv4|ipv6 PEER - Clear peers which have addresses of X.X.X.X + Clear peers with address of X.X.X.X and this address-family activated. + +.. index:: clear bgp ipv4|ipv6 unicast PEER +.. clicmd:: clear bgp ipv4|ipv6 unicast PEER + + Clear peer with address of X.X.X.X and this address-family and sub-address-family activated. + +.. index:: clear bgp ipv4|ipv6 PEER soft|in|out +.. clicmd:: clear bgp ipv4|ipv6 PEER soft|in|out + + Clear peer using soft reconfiguration in this address-family. -.. index:: clear bgp ipv4|ipv6 PEER soft in -.. clicmd:: clear bgp ipv4|ipv6 PEER soft in +.. index:: clear bgp ipv4|ipv6 unicast PEER soft|in|out +.. clicmd:: clear bgp ipv4|ipv6 unicast PEER soft|in|out - Clear peer using soft reconfiguration. + Clear peer using soft reconfiguration in this address-family and sub-address-family. .. _bgp-displaying-bgp-information: diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c index fa89c80049..8fc7997d79 100644 --- a/isisd/isis_bfd.c +++ b/isisd/isis_bfd.c @@ -19,7 +19,9 @@ #include <zebra.h> #include "zclient.h" +#include "nexthop.h" #include "bfd.h" +#include "lib_errors.h" #include "isisd/isis_bfd.h" #include "isisd/isis_zebra.h" @@ -33,17 +35,19 @@ DEFINE_MTYPE_STATIC(ISISD, BFD_SESSION, "ISIS BFD Session") struct bfd_session { - struct in_addr dst_ip; - struct in_addr src_ip; + int family; + union g_addr dst_ip; + union g_addr src_ip; int status; }; -static struct bfd_session *bfd_session_new(struct in_addr *dst_ip, - struct in_addr *src_ip) +static struct bfd_session *bfd_session_new(int family, union g_addr *dst_ip, + union g_addr *src_ip) { struct bfd_session *rv; rv = XCALLOC(MTYPE_BFD_SESSION, sizeof(*rv)); + rv->family = family; rv->dst_ip = *dst_ip; rv->src_ip = *src_ip; return rv; @@ -58,15 +62,60 @@ static void bfd_session_free(struct bfd_session **session) *session = NULL; } +static bool bfd_session_same(const struct bfd_session *session, int family, + const union g_addr *src, const union g_addr *dst) +{ + if (session->family != family) + return false; + + switch (session->family) { + case AF_INET: + if (!IPV4_ADDR_SAME(&session->dst_ip.ipv4, &dst->ipv4)) + return false; + if (!IPV4_ADDR_SAME(&session->src_ip.ipv4, &src->ipv4)) + return false; + break; + case AF_INET6: + if (!IPV6_ADDR_SAME(&session->dst_ip.ipv6, &dst->ipv6)) + return false; + if (!IPV6_ADDR_SAME(&session->src_ip.ipv6, &src->ipv6)) + return false; + break; + default: + flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address-family: %u", + __func__, session->family); + exit(1); + } + + return true; +} + static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst, int new_status) { if (!adj->bfd_session) return; - if (adj->bfd_session->dst_ip.s_addr != dst->u.prefix4.s_addr) + if (adj->bfd_session->family != dst->family) return; + switch (adj->bfd_session->family) { + case AF_INET: + if (!IPV4_ADDR_SAME(&adj->bfd_session->dst_ip.ipv4, + &dst->u.prefix4)) + return; + break; + case AF_INET6: + if (!IPV6_ADDR_SAME(&adj->bfd_session->dst_ip.ipv6, + &dst->u.prefix6)) + return; + break; + default: + flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address-family: %u", + __func__, adj->bfd_session->family); + exit(1); + } + int old_status = adj->bfd_session->status; adj->bfd_session->status = new_status; @@ -76,7 +125,7 @@ static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst, if (isis->debugs & DEBUG_BFD) { char dst_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET, &adj->bfd_session->dst_ip, + inet_ntop(adj->bfd_session->family, &adj->bfd_session->dst_ip, dst_str, sizeof(dst_str)); zlog_debug("ISIS-BFD: Peer %s on %s changed from %s to %s", dst_str, adj->circuit->interface->name, @@ -100,14 +149,14 @@ static int isis_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS) ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status, NULL, vrf_id); - if (!ifp || dst_ip.family != AF_INET) + if (!ifp || (dst_ip.family != AF_INET && dst_ip.family != AF_INET6)) return 0; if (isis->debugs & DEBUG_BFD) { char dst_buf[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET, &dst_ip.u.prefix4, - dst_buf, sizeof(dst_buf)); + inet_ntop(dst_ip.family, &dst_ip.u.prefix, dst_buf, + sizeof(dst_buf)); zlog_debug("ISIS-BFD: Received update for %s on %s: Changed state to %s", dst_buf, ifp->name, bfd_get_status_str(status)); @@ -171,7 +220,7 @@ static void isis_bfd_zebra_connected(struct zclient *zclient) bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT); } -static void bfd_debug(struct in_addr *dst, struct in_addr *src, +static void bfd_debug(int family, union g_addr *dst, union g_addr *src, const char *interface, int command) { if (!(isis->debugs & DEBUG_BFD)) @@ -180,8 +229,8 @@ static void bfd_debug(struct in_addr *dst, struct in_addr *src, char dst_str[INET6_ADDRSTRLEN]; char src_str[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET, dst, dst_str, sizeof(dst_str)); - inet_ntop(AF_INET, src, src_str, sizeof(src_str)); + inet_ntop(family, dst, dst_str, sizeof(dst_str)); + inet_ntop(family, src, src_str, sizeof(src_str)); const char *command_str; @@ -209,10 +258,11 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj) if (!adj->bfd_session) return; - bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, - adj->circuit->interface->name, ZEBRA_BFD_DEST_DEREGISTER); + bfd_debug(adj->bfd_session->family, &adj->bfd_session->dst_ip, + &adj->bfd_session->src_ip, adj->circuit->interface->name, + ZEBRA_BFD_DEST_DEREGISTER); - bfd_peer_sendmsg(zclient, NULL, AF_INET, + bfd_peer_sendmsg(zclient, NULL, adj->bfd_session->family, &adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, adj->circuit->interface->name, @@ -228,33 +278,50 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj) static void bfd_handle_adj_up(struct isis_adjacency *adj, int command) { struct isis_circuit *circuit = adj->circuit; + int family; + union g_addr dst_ip; + union g_addr src_ip; + struct list *local_ips; + struct prefix *local_ip; - if (!circuit->bfd_info - || !circuit->ip_router - || !adj->ipv4_address_count) + if (!circuit->bfd_info) goto out; - struct list *local_ips = fabricd_ip_addrs(adj->circuit); - - if (!local_ips) + /* + * If IS-IS is enabled for both IPv4 and IPv6 on the circuit, prefer + * creating a BFD session over IPv6. + */ + if (circuit->ipv6_router && adj->ipv6_address_count) { + family = AF_INET6; + dst_ip.ipv6 = adj->ipv6_addresses[0]; + local_ips = circuit->ipv6_link; + if (!local_ips || list_isempty(local_ips)) + goto out; + local_ip = listgetdata(listhead(local_ips)); + src_ip.ipv6 = local_ip->u.prefix6; + } else if (circuit->ip_router && adj->ipv4_address_count) { + family = AF_INET; + dst_ip.ipv4 = adj->ipv4_addresses[0]; + local_ips = fabricd_ip_addrs(adj->circuit); + if (!local_ips || list_isempty(local_ips)) + goto out; + local_ip = listgetdata(listhead(local_ips)); + src_ip.ipv4 = local_ip->u.prefix4; + } else goto out; - struct in_addr *dst_ip = &adj->ipv4_addresses[0]; - struct prefix_ipv4 *local_ip = listgetdata(listhead(local_ips)); - struct in_addr *src_ip = &local_ip->prefix; - if (adj->bfd_session) { - if (adj->bfd_session->dst_ip.s_addr != dst_ip->s_addr - || adj->bfd_session->src_ip.s_addr != src_ip->s_addr) + if (bfd_session_same(adj->bfd_session, family, &src_ip, + &dst_ip)) bfd_handle_adj_down(adj); } if (!adj->bfd_session) - adj->bfd_session = bfd_session_new(dst_ip, src_ip); + adj->bfd_session = bfd_session_new(family, &dst_ip, &src_ip); - bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, - circuit->interface->name, command); - bfd_peer_sendmsg(zclient, circuit->bfd_info, AF_INET, + bfd_debug(adj->bfd_session->family, &adj->bfd_session->dst_ip, + &adj->bfd_session->src_ip, circuit->interface->name, command); + bfd_peer_sendmsg(zclient, circuit->bfd_info, adj->bfd_session->family, &adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, circuit->interface->name, diff --git a/lib/ferr.c b/lib/ferr.c index 8afc926c41..fd5fb50172 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -170,7 +170,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) DEFUN_NOSH(show_error_code, show_error_code_cmd, - "show error <(1-4294967296)|all> [json]", + "show error <(1-4294967295)|all> [json]", SHOW_STR "Information on errors\n" "Error code to get info about\n" diff --git a/lib/frrcu.c b/lib/frrcu.c index 7e6475b648..54626f909d 100644 --- a/lib/frrcu.c +++ b/lib/frrcu.c @@ -55,7 +55,6 @@ #include "atomlist.h" DEFINE_MTYPE_STATIC(LIB, RCU_THREAD, "RCU thread") -DEFINE_MTYPE_STATIC(LIB, RCU_NEXT, "RCU sequence barrier") DECLARE_ATOMLIST(rcu_heads, struct rcu_head, head) @@ -226,7 +225,7 @@ static void rcu_bump(void) { struct rcu_next *rn; - rn = XMALLOC(MTYPE_RCU_NEXT, sizeof(*rn)); + rn = XMALLOC(MTYPE_RCU_THREAD, sizeof(*rn)); /* note: each RCUA_NEXT item corresponds to exactly one seqno bump. * This means we don't need to communicate which seqno is which @@ -269,7 +268,7 @@ static void rcu_bump(void) * "last item is being deleted - start over" case, and then we may end * up accessing old RCU queue items that are already free'd. */ - rcu_free_internal(MTYPE_RCU_NEXT, rn, head_free); + rcu_free_internal(MTYPE_RCU_THREAD, rn, head_free); /* Only allow the RCU sweeper to run after these 2 items are queued. * @@ -45,6 +45,8 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected") DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label") DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") +static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, + vrf_id_t vrf_id); static int if_cmp_func(const struct interface *, const struct interface *); static int if_cmp_index_func(const struct interface *ifp1, const struct interface *ifp2); @@ -257,8 +259,9 @@ void if_delete(struct interface *ifp) XFREE(MTYPE_IF, ifp); } -/* Interface existance check by index. */ -struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) +/* Used only internally to check within VRF only */ +static struct interface *if_lookup_by_ifindex(ifindex_t ifindex, + vrf_id_t vrf_id) { struct vrf *vrf; struct interface if_tmp; @@ -271,6 +274,19 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp); } +/* Interface existance check by index. */ +struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) +{ + switch (vrf_get_backend()) { + case VRF_BACKEND_UNKNOWN: + case VRF_BACKEND_NETNS: + return(if_lookup_by_ifindex(ifindex, vrf_id)); + case VRF_BACKEND_VRF_LITE: + return(if_lookup_by_index_all_vrf(ifindex)); + } + return NULL; +} + const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; @@ -329,7 +345,7 @@ struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex) return NULL; RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - ifp = if_lookup_by_index(ifindex, vrf->vrf_id); + ifp = if_lookup_by_ifindex(ifindex, vrf->vrf_id); if (ifp) return ifp; } @@ -337,7 +353,7 @@ struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex) return NULL; } -/* Lookup interface by IPv4 address. */ +/* Lookup interface by IP address. */ struct interface *if_lookup_exact_address(void *src, int family, vrf_id_t vrf_id) { @@ -369,7 +385,7 @@ struct interface *if_lookup_exact_address(void *src, int family, return NULL; } -/* Lookup interface by IPv4 address. */ +/* Lookup interface by IP address. */ struct connected *if_lookup_address(void *matchaddr, int family, vrf_id_t vrf_id) { @@ -489,7 +505,7 @@ struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) switch (vrf_get_backend()) { case VRF_BACKEND_UNKNOWN: case VRF_BACKEND_NETNS: - ifp = if_lookup_by_index(ifindex, vrf_id); + ifp = if_lookup_by_ifindex(ifindex, vrf_id); if (ifp) return ifp; return if_create_ifindex(ifindex, vrf_id); @@ -383,16 +383,12 @@ struct connected { /* N.B. the ZEBRA_IFA_PEER flag should be set if and only if a peer address has been configured. If this flag is set, the destination field must contain the peer address. - Otherwise, if this flag is not set, the destination address - will either contain a broadcast address or be NULL. */ /* Address of connected network. */ struct prefix *address; - /* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is - set. - Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */ + /* Peer address, if ZEBRA_IFA_PEER is set, otherwise NULL */ struct prefix *destination; /* Label for Linux 2.2.X and upper. */ diff --git a/lib/libfrr.c b/lib/libfrr.c index 35c6092140..4301dc20ad 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -410,7 +410,7 @@ static int frr_opt(int opt) } if (di->zpathspace) fprintf(stderr, - "-N option overriden by -z for zebra named socket path\n"); + "-N option overridden by -z for zebra named socket path\n"); if (strchr(optarg, '/') || strchr(optarg, '.')) { fprintf(stderr, diff --git a/lib/northbound.h b/lib/northbound.h index 69d7c8e0ee..ce79d907f9 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -347,15 +347,6 @@ struct nb_callbacks { * dnode * libyang data node that should be shown in the form of a CLI * command. - * - * show_defaults - * Specify whether to display default configuration values or not. - * This parameter can be ignored most of the time since the - * northbound doesn't call this callback for default leaves or - * non-presence containers that contain only default child nodes. - * The exception are commands associated to multiple configuration - * nodes, in which case it might be desirable to hide one or more - * parts of the command when this parameter is set to false. */ void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode); }; diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index c691bb27aa..884c01a457 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -757,7 +757,7 @@ DEFPY (config_load, "configuration load\ <\ file [<json$json|xml$xml> [translate WORD$translator_family]] FILENAME$filename\ - |transaction (1-4294967296)$tid\ + |transaction (1-4294967295)$tid\ >\ [replace$replace]", "Configuration related settings\n" @@ -923,12 +923,12 @@ DEFPY (show_config_compare, <\ candidate$c1_candidate\ |running$c1_running\ - |transaction (1-4294967296)$c1_tid\ + |transaction (1-4294967295)$c1_tid\ >\ <\ candidate$c2_candidate\ |running$c2_running\ - |transaction (1-4294967296)$c2_tid\ + |transaction (1-4294967295)$c2_tid\ >\ [<json$json|xml$xml> [translate WORD$translator_family]]", SHOW_STR @@ -1029,11 +1029,11 @@ ALIAS (show_config_compare, "show configuration compare\ <\ running$c1_running\ - |transaction (1-4294967296)$c1_tid\ + |transaction (1-4294967295)$c1_tid\ >\ <\ running$c2_running\ - |transaction (1-4294967296)$c2_tid\ + |transaction (1-4294967295)$c2_tid\ >\ [<json$json|xml$xml> [translate WORD$translator_family]]", SHOW_STR @@ -1192,7 +1192,7 @@ DEFPY (show_config_transaction, show_config_transaction_cmd, "show configuration transaction\ [\ - (1-4294967296)$transaction_id\ + (1-4294967295)$transaction_id\ [<json$json|xml$xml> [translate WORD$translator_family]]\ [<\ with-defaults$with_defaults\ @@ -1593,7 +1593,7 @@ static int nb_cli_rollback_configuration(struct vty *vty, DEFPY (rollback_config, rollback_config_cmd, - "rollback configuration (1-4294967296)$transaction_id", + "rollback configuration (1-4294967295)$transaction_id", "Rollback to a previous state\n" "Running configuration\n" "Transaction ID\n") diff --git a/lib/prefix.c b/lib/prefix.c index 1a4a914e05..ad8dea273e 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -853,7 +853,7 @@ void prefix_ipv4_free(struct prefix_ipv4 *p) prefix_free((struct prefix *)p); } -/* When string format is invalid return 0. */ +/* If given string is valid return 1 else return 0 */ int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p) { int ret; @@ -881,8 +881,10 @@ int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p) cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1); memcpy(cp, str, pnt - str); *(cp + (pnt - str)) = '\0'; - ret = inet_aton(cp, &p->prefix); + ret = inet_pton(AF_INET, cp, &p->prefix); XFREE(MTYPE_TMP, cp); + if (ret == 0) + return 0; /* Get prefix length. */ plen = (uint8_t)atoi(++pnt); @@ -1023,7 +1025,7 @@ void prefix_ipv6_free(struct prefix_ipv6 *p) prefix_free((struct prefix *)p); } -/* If given string is valid return pin6 else return NULL */ +/* If given string is valid return 1 else return 0 */ int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p) { char *pnt; diff --git a/lib/stream.c b/lib/stream.c index c67bc3c993..dfd13ca186 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -186,14 +186,6 @@ size_t stream_resize_inplace(struct stream **sptr, size_t newsize) return orig->size; } -size_t __attribute__((deprecated))stream_resize_orig(struct stream *s, - size_t newsize) -{ - assert("stream_resize: Switch code to use stream_resize_inplace" == NULL); - - return stream_resize_inplace(&s, newsize); -} - size_t stream_get_getp(struct stream *s) { STREAM_VERIFY_SANE(s); diff --git a/lib/stream.h b/lib/stream.h index a903ec0ea5..1144e43ef0 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -153,11 +153,6 @@ extern void stream_free(struct stream *); extern struct stream *stream_copy(struct stream *, struct stream *src); extern struct stream *stream_dup(struct stream *); -#if CONFDATE > 20190821 -CPP_NOTICE("lib: time to remove stream_resize_orig") -#endif -extern size_t stream_resize_orig(struct stream *s, size_t newsize); -#define stream_resize stream_resize_orig extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize); extern size_t stream_get_getp(struct stream *); diff --git a/lib/thread.c b/lib/thread.c index 5756ebc1f9..943b849ebf 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -714,7 +714,7 @@ static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, { /* If timer_wait is null here, that means poll() should block * indefinitely, - * unless the thread_master has overriden it by setting + * unless the thread_master has overridden it by setting * ->selectpoll_timeout. * If the value is positive, it specifies the maximum number of * milliseconds @@ -348,6 +348,15 @@ void vty_hello(struct vty *vty) vty_out(vty, "MOTD file not found\n"); } else if (host.motd) vty_out(vty, "%s", host.motd); + +#if CONFDATE > 20200901 + CPP_NOTICE("Please remove solaris code from system as it is deprecated"); +#endif +#ifdef SUNOS_5 + zlog_warn("If you are using FRR on Solaris, the FRR developers would love to hear from you\n"); + zlog_warn("Please send email to dev@lists.frrouting.org about this message\n"); + zlog_warn("We are considering deprecating Solaris and want to find users of Solaris systems\n"); +#endif } /* Put out prompt and wait input from user. */ diff --git a/lib/zclient.c b/lib/zclient.c index 6937700199..2d79d9b3c5 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -325,8 +325,9 @@ int zclient_read_header(struct stream *s, int sock, uint16_t *size, if (*size && stream_read(s, sock, *size) != *size) return -1; -stream_failure: return 0; +stream_failure: + return -1; } bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr) @@ -1056,8 +1057,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID)) STREAM_GETL(s, api->tableid); -stream_failure: return 0; +stream_failure: + return -1; } static void zapi_encode_prefix(struct stream *s, struct prefix *p, @@ -2254,7 +2256,7 @@ int tm_table_manager_connect(struct zclient *zclient) return (int)result; stream_failure: - return 0; + return -1; } /** @@ -2321,8 +2323,9 @@ int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size, if (zclient_debug) zlog_debug("Table Chunk assign: %u - %u ", *start, *end); -stream_failure: return 0; +stream_failure: + return -1; } /** diff --git a/lib/zebra.h b/lib/zebra.h index 352887eca8..789a93a3c4 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -360,6 +360,7 @@ typedef enum { /* Subsequent Address Family Identifier. */ typedef enum { + SAFI_UNSPEC = 0, SAFI_UNICAST = 1, SAFI_MULTICAST = 2, SAFI_MPLS_VPN = 3, diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index af16c5aa7c..8454016b2e 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -258,7 +258,7 @@ DEFUN (show_zebra, return CMD_SUCCESS; } - vty_out(vty, "Zebra Infomation\n"); + vty_out(vty, "Zebra Information\n"); vty_out(vty, " fail: %d\n", zclient->fail); vty_out(vty, " redistribute default: %d\n", vrf_bitmap_check(zclient->default_information[AFI_IP6], diff --git a/ospfd/ospf_errors.c b/ospfd/ospf_errors.c index dd02160195..a985efc668 100644 --- a/ospfd/ospf_errors.c +++ b/ospfd/ospf_errors.c @@ -39,7 +39,7 @@ static struct log_ref ferr_ospf_warn[] = { }, { .code = EC_OSPF_PACKET, - .title = "OSPF has detected packet information missmatch", + .title = "OSPF has detected packet information mismatch", .description = "OSPF has detected that packet information received is incorrect", .suggestion = "Ensure interface configuration is correct, gather log files from here and the peer and open an Issue", }, diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 2564c6f330..8fa91f500c 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3442,6 +3442,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, else vty_out(vty, " This interface is UNNUMBERED,"); } else { + struct in_addr dest; + const char *dstr; + /* Show OSPF interface information. */ if (use_json) { json_object_string_add( @@ -3455,46 +3458,40 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, inet_ntoa(oi->address->u.prefix4), oi->address->prefixlen); - if (oi->connected->destination - || oi->type == OSPF_IFTYPE_VIRTUALLINK) { - struct in_addr *dest; - const char *dstr; - - if (CONNECTED_PEER(oi->connected) - || oi->type == OSPF_IFTYPE_VIRTUALLINK) - dstr = "Peer"; - else - dstr = "Broadcast"; + /* For Vlinks, showing the peer address is + * probably more informative than the local + * interface that is being used */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { + dstr = "Peer"; + dest = oi->vl_data->peer_addr; + } else if (CONNECTED_PEER(oi->connected) + && oi->connected->destination) { + dstr = "Peer"; + dest = oi->connected->destination->u.prefix4; + } else { + dstr = "Broadcast"; + dest.s_addr = ipv4_broadcast_addr( + oi->connected->address->u.prefix4.s_addr, + oi->connected->address->prefixlen); + } - /* For Vlinks, showing the peer address is - * probably more - * * * * * informative than the local - * interface that is being used - * * * * */ + if (use_json) { + json_object_string_add( + json_interface_sub, + "ospfIfType", dstr); if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - dest = &oi->vl_data->peer_addr; + json_object_string_add( + json_interface_sub, + "vlinkPeer", + inet_ntoa(dest)); else - dest = &oi->connected->destination->u - .prefix4; - - if (use_json) { json_object_string_add( json_interface_sub, - "ospfIfType", dstr); - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - json_object_string_add( - json_interface_sub, - "vlinkPeer", - inet_ntoa(*dest)); - else - json_object_string_add( - json_interface_sub, - "localIfUsed", - inet_ntoa(*dest)); - } else - vty_out(vty, " %s %s,", dstr, - inet_ntoa(*dest)); - } + "localIfUsed", + inet_ntoa(dest)); + } else + vty_out(vty, " %s %s,", dstr, + inet_ntoa(dest)); } if (use_json) { json_object_string_add(json_interface_sub, "area", diff --git a/pbrd/pbrd.conf.sample b/pbrd/pbrd.conf.sample index bb1c2edca8..c9e7dce01f 100644 --- a/pbrd/pbrd.conf.sample +++ b/pbrd/pbrd.conf.sample @@ -1,3 +1,19 @@ +! Sample pbrd configuration file +! +! A quick example of what a pbr configuration might look like ! ! log stdout +! +! nexthop-group TEST +! nexthop 4.5.6.7 +! nexthop 5.6.7.8 +! ! +! pbr-map BLUE seq 100 +! match dst-ip 9.9.9.0/24 +! match src-ip 10.10.10.0/24 +! set nexthop-group TEST +! ! +! int swp1 +! pbr-policy BLUE +! diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index 62f13b5b53..675092dbec 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -711,11 +711,11 @@ static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp, /* MTU passed here is PIM MTU (IP MTU less IP Hdr) */ if (pim_mtu < (PIM_MIN_BSM_LEN)) { zlog_warn( - "%s: mtu(pim mtu: %d) size less than minimum bootsrap len", + "%s: mtu(pim mtu: %d) size less than minimum bootstrap len", __PRETTY_FUNCTION__, pim_mtu); if (PIM_DEBUG_BSM) zlog_debug( - "%s: mtu (pim mtu:%d) less than minimum bootsrap len", + "%s: mtu (pim mtu:%d) less than minimum bootstrap len", __PRETTY_FUNCTION__, pim_mtu); return false; } diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 39dc8ad2fa..7900e39231 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -479,7 +479,7 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg) zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s", __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name, old.source_nexthop.interface - ? old.source_nexthop.interface->name : "Unknwon", + ? old.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop.interface->name); } diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 27042e197c..014cae02ee 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -1,6 +1,6 @@ # configure options # -# Some can be overriden on rpmbuild commandline with: +# Some can be overridden on rpmbuild commandline with: # rpmbuild --define 'variable value' # (use any value, ie 1 for flag "with_XXXX" definitions) # diff --git a/sharpd/sharpd.conf.sample b/sharpd/sharpd.conf.sample index bb1c2edca8..d1cc19a51f 100644 --- a/sharpd/sharpd.conf.sample +++ b/sharpd/sharpd.conf.sample @@ -1,3 +1,6 @@ +! Default sharpd configuration sample ! +! There are no `default` configuration commands for sharpd +! all commands are at the view or enable level. ! log stdout diff --git a/staticd/staticd.conf.sample b/staticd/staticd.conf.sample index bb1c2edca8..3b64eb9c90 100644 --- a/staticd/staticd.conf.sample +++ b/staticd/staticd.conf.sample @@ -1,3 +1,5 @@ -! +! Default staticd configuration sample ! log stdout +! +! ip route 4.5.6.7/32 10.10.10.10 diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index 78016dc9ce..8e1b62ac15 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -1170,7 +1170,7 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa) /* Test Preparation: Switch and activate address-family. */ if (!is_attr_type_global(pa->type)) { test_log(test, "prepare: switch address-family to [%s]", - afi_safi_print(pa->afi, pa->safi)); + get_afi_safi_str(pa->afi, pa->safi, false)); test_execute(test, "address-family %s %s", str_from_afi(pa->afi), str_from_safi(pa->safi)); test_execute(test, "neighbor %s activate", g->name); @@ -1237,7 +1237,7 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa) /* Test Preparation: Switch and activate address-family. */ if (!is_attr_type_global(pa->type)) { test_log(test, "prepare: switch address-family to [%s]", - afi_safi_print(pa->afi, pa->safi)); + get_afi_safi_str(pa->afi, pa->safi, false)); test_execute(test, "address-family %s %s", str_from_afi(pa->afi), str_from_safi(pa->safi)); test_execute(test, "neighbor %s activate", g->name); @@ -1285,7 +1285,7 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa) /* Test Preparation: Switch and activate address-family. */ if (!is_attr_type_global(pa->type)) { test_log(test, "prepare: switch address-family to [%s]", - afi_safi_print(pa->afi, pa->safi)); + get_afi_safi_str(pa->afi, pa->safi, false)); test_execute(test, "address-family %s %s", str_from_afi(pa->afi), str_from_safi(pa->safi)); test_execute(test, "neighbor %s activate", g->name); diff --git a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref index 1fb70a0e2f..0a20231371 100644 --- a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref +++ b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref @@ -13,6 +13,8 @@ O 192.168.3.0/26 [110/10] is directly connected, r1-eth3, XX:XX:XX S>* 4.5.6.10/32 [1/0] via 192.168.0.2, r1-eth0, XX:XX:XX S>* 4.5.6.11/32 [1/0] via 192.168.0.2, r1-eth0, XX:XX:XX S>* 4.5.6.12/32 [1/0] is directly connected, r1-eth0, XX:XX:XX +S>* 4.5.6.13/32 [1/0] unreachable (blackhole), XX:XX:XX +S>* 4.5.6.14/32 [1/0] unreachable (blackhole), XX:XX:XX S>* 4.5.6.7/32 [1/0] unreachable (blackhole), XX:XX:XX S>* 4.5.6.8/32 [1/0] unreachable (blackhole), XX:XX:XX S>* 4.5.6.9/32 [1/0] unreachable (ICMP unreachable), XX:XX:XX diff --git a/tests/topotests/all-protocol-startup/r1/zebra.conf b/tests/topotests/all-protocol-startup/r1/zebra.conf index 30e05f01e3..c621593ef7 100644 --- a/tests/topotests/all-protocol-startup/r1/zebra.conf +++ b/tests/topotests/all-protocol-startup/r1/zebra.conf @@ -9,6 +9,9 @@ ip route 4.5.6.8/32 Null0 ipv6 route 4:5::6:8/128 Null0 ip route 4.5.6.9/32 reject ipv6 route 4:5::6:9/128 reject +# Test various spellings of NULL0 to make sure we accept them +ip route 4.5.6.13/32 null0 +ip route 4.5.6.14/32 NULL0 # Create normal gateway routes ip route 4.5.6.10/32 192.168.0.2 ipv6 route 4:5::6:10/128 fc00:0:0:0::2 diff --git a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py index de6c35ba8f..ed350ebfeb 100644 --- a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py +++ b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py @@ -88,7 +88,7 @@ def test_bgp_maximum_prefix_invalid(): while True: output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp neighbor 192.168.255.1 json")) if output['192.168.255.1']['bgpState'] == 'Established': - if output['192.168.255.1']['addressFamilyInfo']['IPv4 Unicast']['acceptedPrefixCounter'] == 2: + if output['192.168.255.1']['addressFamilyInfo']['ipv4Unicast']['acceptedPrefixCounter'] == 2: return True def _bgp_comm_list_delete(router): diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index fba754f626..b053392bff 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -164,9 +164,10 @@ static int vtysh_reconnect(struct vtysh_client *vclient); static void vclient_close(struct vtysh_client *vclient) { if (vclient->fd >= 0) { - vty_out(vty, - "Warning: closing connection to %s because of an I/O error!\n", - vclient->name); + if (vty->of) + vty_out(vty, + "Warning: closing connection to %s because of an I/O error!\n", + vclient->name); close(vclient->fd); /* indicate as candidate for reconnect */ vclient->fd = VTYSH_WAS_ACTIVE; @@ -237,8 +238,11 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line, continue; if (nread <= 0) { - vty_out(vty, "vtysh: error reading from %s: %s (%d)", - vclient->name, safe_strerror(errno), errno); + if (vty->of) + vty_out(vty, + "vtysh: error reading from %s: %s (%d)", + vclient->name, safe_strerror(errno), + errno); goto out_err; } @@ -383,7 +387,7 @@ static int vtysh_client_run_all(struct vtysh_client *head_client, rc_all = rc; } } - if (wrong_instance && !correct_instance) { + if (wrong_instance && !correct_instance && vty->of) { vty_out(vty, "%% [%s]: command ignored as it targets an instance that is not running\n", head_client->name); diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang index 24ca8f68a8..f9ac2e43b0 100644 --- a/yang/frr-bfdd.yang +++ b/yang/frr-bfdd.yang @@ -264,22 +264,22 @@ module frr-bfdd { leaf session-down-count { type uint32; - description "Amount of times the session went down"; + description "Number of times the session went down"; } leaf session-up-count { type uint32; - description "Amount of times the session went up"; + description "Number of times the session went up"; } leaf control-packet-input-count { type uint64; - description "Amount of control packets received"; + description "Number of control packets received"; } leaf control-packet-output-count { type uint64; - description "Amount of control packets sent"; + description "Number of control packets sent"; } /* @@ -296,12 +296,12 @@ module frr-bfdd { */ leaf echo-packet-input-count { type uint64; - description "Amount of echo packets received"; + description "Number of echo packets received"; } leaf echo-packet-output-count { type uint64; - description "Amount of echo packets sent"; + description "Number of echo packets sent"; } } diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 05a896a1db..9180b0c5f3 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -1024,7 +1024,7 @@ module frr-isisd { "This notification is sent when we attempt to propagate an LSP that is larger than the dataLinkBlockSize for the circuit. The notification generation must be throttled - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1090,7 +1090,7 @@ module frr-isisd { "This notification is sent when we receive a PDU with a different value for the System ID length. The notification generation must be throttled - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1114,7 +1114,7 @@ module frr-isisd { "This notification is sent when we receive a PDU with a different value for the Maximum Area Addresses. The notification generation must be throttled - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1170,7 +1170,7 @@ module frr-isisd { "This notification is sent when the system receives a PDU with the wrong authentication type field. The notification generation must be throttled - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1188,7 +1188,7 @@ module frr-isisd { "This notification is sent when the system receives a PDU with the wrong authentication information. The notification generation must be throttled with - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1206,7 +1206,7 @@ module frr-isisd { "This notification is sent when the system receives a PDU with a different protocol version number. The notification generation must be throttled - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1230,7 +1230,7 @@ module frr-isisd { "This notification is sent when the system receives a Hello PDU from an IS that does not share any area address. The notification generation must be throttled - with at least 5 seconds betweeen successive + with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1248,7 +1248,7 @@ module frr-isisd { "This notification is sent when the system receives a Hello PDU from an IS but does not establish an adjacency for some reason. The notification generation must be - throttled with at least 5 seconds betweeen successive + throttled with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1273,7 +1273,7 @@ module frr-isisd { description "This notification is sent when the system receives an LSP with a parse error. The notification generation must - be throttled with at least 5 seconds betweeen successive + be throttled with at least 5 seconds between successive notifications."; uses notification-instance-hdr; @@ -1350,7 +1350,7 @@ module frr-isisd { description "This notification is sent when an LSP is received. The notification generation must be throttled with at - least 5 seconds betweeen successive notifications."; + least 5 seconds between successive notifications."; uses notification-instance-hdr; uses notification-interface-hdr; @@ -1384,7 +1384,7 @@ module frr-isisd { description "This notification is sent when an LSP is regenerated. The notification generation must be throttled with at - least 5 seconds betweeen successive notifications."; + least 5 seconds between successive notifications."; uses notification-instance-hdr; leaf lsp-id { diff --git a/zebra/connected.c b/zebra/connected.c index 4101a4bf24..ffc991861c 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -120,10 +120,6 @@ struct connected *connected_check_ptp(struct interface *ifp, struct connected *ifc; struct listnode *node; - /* ignore broadcast addresses */ - if (p->prefixlen != IPV4_MAX_PREFIXLEN) - d = NULL; - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { if (!prefix_same(ifc->address, p)) continue; @@ -143,6 +139,12 @@ static int connected_same(struct connected *ifc1, struct connected *ifc2) if (ifc1->ifp != ifc2->ifp) return 0; + if (ifc1->flags != ifc2->flags) + return 0; + + if (ifc1->conf != ifc2->conf) + return 0; + if (ifc1->destination) if (!ifc2->destination) return 0; @@ -154,12 +156,6 @@ static int connected_same(struct connected *ifc1, struct connected *ifc2) if (!prefix_same(ifc1->destination, ifc2->destination)) return 0; - if (ifc1->flags != ifc2->flags) - return 0; - - if (ifc1->conf != ifc2->conf) - return 0; - return 1; } @@ -276,7 +272,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) /* Add connected IPv4 route to the interface. */ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, - uint16_t prefixlen, struct in_addr *broad, + uint16_t prefixlen, struct in_addr *dest, const char *label, uint32_t metric) { struct prefix_ipv4 *p; @@ -302,59 +298,39 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, : prefixlen; ifc->address = (struct prefix *)p; - /* If there is broadcast or peer address. */ - if (broad) { - p = prefix_ipv4_new(); - p->family = AF_INET; - p->prefix = *broad; - p->prefixlen = prefixlen; - ifc->destination = (struct prefix *)p; - + /* If there is a peer address. */ + if (CONNECTED_PEER(ifc)) { /* validate the destination address */ - if (CONNECTED_PEER(ifc)) { - if (IPV4_ADDR_SAME(addr, broad)) + if (dest) { + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = *dest; + p->prefixlen = prefixlen; + ifc->destination = (struct prefix *)p; + + if (IPV4_ADDR_SAME(addr, dest)) flog_warn( EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER, "warning: interface %s has same local and peer " "address %s, routing protocols may malfunction", ifp->name, inet_ntoa(*addr)); } else { - if (broad->s_addr - != ipv4_broadcast_addr(addr->s_addr, prefixlen)) { - char buf[2][INET_ADDRSTRLEN]; - struct in_addr bcalc; - bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr, - prefixlen); - flog_warn( - EC_ZEBRA_BCAST_ADDR_MISMATCH, - "warning: interface %s broadcast addr %s/%d != " - "calculated %s, routing protocols may malfunction", - ifp->name, - inet_ntop(AF_INET, broad, buf[0], - sizeof(buf[0])), - prefixlen, - inet_ntop(AF_INET, &bcalc, buf[1], - sizeof(buf[1]))); - } - } - - } else { - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { zlog_debug( "warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } - - /* no broadcast or destination address was supplied */ - if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) - zlog_debug( - "warning: PtP interface %s with addr %s/%d needs a " - "peer address", - ifp->name, inet_ntoa(*addr), prefixlen); } + /* no destination address was supplied */ + if (!dest && (prefixlen == IPV4_MAX_PREFIXLEN) + && if_is_pointopoint(ifp)) + zlog_debug( + "warning: PtP interface %s with addr %s/%d needs a " + "peer address", + ifp->name, inet_ntoa(*addr), prefixlen); + /* Label of this address. */ if (label) ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); @@ -464,7 +440,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p) /* Delete connected IPv4 route to the interface. */ void connected_delete_ipv4(struct interface *ifp, int flags, struct in_addr *addr, uint16_t prefixlen, - struct in_addr *broad) + struct in_addr *dest) { struct prefix p, d; struct connected *ifc; @@ -475,10 +451,10 @@ void connected_delete_ipv4(struct interface *ifp, int flags, p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN : prefixlen; - if (broad) { + if (dest) { memset(&d, 0, sizeof(struct prefix)); d.family = AF_INET; - d.u.prefix4 = *broad; + d.u.prefix4 = *dest; d.prefixlen = prefixlen; ifc = connected_check_ptp(ifp, &p, &d); } else @@ -489,7 +465,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags, /* Add connected IPv6 route to the interface. */ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, - struct in6_addr *broad, uint16_t prefixlen, + struct in6_addr *dest, uint16_t prefixlen, const char *label, uint32_t metric) { struct prefix_ipv6 *p; @@ -514,10 +490,10 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, p->prefixlen = prefixlen; ifc->address = (struct prefix *)p; - if (broad) { + if (dest) { p = prefix_ipv6_new(); p->family = AF_INET6; - IPV6_ADDR_COPY(&p->prefix, broad); + IPV6_ADDR_COPY(&p->prefix, dest); p->prefixlen = prefixlen; ifc->destination = (struct prefix *)p; } else { @@ -547,7 +523,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, } void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, - struct in6_addr *broad, uint16_t prefixlen) + struct in6_addr *dest, uint16_t prefixlen) { struct prefix p, d; struct connected *ifc; @@ -557,10 +533,10 @@ void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, memcpy(&p.u.prefix6, address, sizeof(struct in6_addr)); p.prefixlen = prefixlen; - if (broad) { + if (dest) { memset(&d, 0, sizeof(struct prefix)); d.family = AF_INET6; - IPV6_ADDR_COPY(&d.u.prefix6, broad); + IPV6_ADDR_COPY(&d.u.prefix6, dest); d.prefixlen = prefixlen; ifc = connected_check_ptp(ifp, &p, &d); } else diff --git a/zebra/connected.h b/zebra/connected.h index 7672bec006..14f6cb2db0 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -40,12 +40,12 @@ extern struct connected *connected_check_ptp(struct interface *ifp, extern void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, uint16_t prefixlen, - struct in_addr *broad, const char *label, + struct in_addr *dest, const char *label, uint32_t metric); extern void connected_delete_ipv4(struct interface *ifp, int flags, struct in_addr *addr, uint16_t prefixlen, - struct in_addr *broad); + struct in_addr *dest); extern void connected_delete_ipv4_unnumbered(struct connected *ifc); @@ -53,12 +53,12 @@ extern void connected_up(struct interface *ifp, struct connected *ifc); extern void connected_down(struct interface *ifp, struct connected *ifc); extern void connected_add_ipv6(struct interface *ifp, int flags, - struct in6_addr *address, struct in6_addr *broad, + struct in6_addr *address, struct in6_addr *dest, uint16_t prefixlen, const char *label, uint32_t metric); extern void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, - struct in6_addr *broad, uint16_t prefixlen); + struct in6_addr *dest, uint16_t prefixlen); extern int connected_is_unnumbered(struct interface *); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 2c536c5d1f..e157c2d70a 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -888,11 +888,13 @@ static int netlink_address_ctx(const struct zebra_dplane_ctx *ctx) p = dplane_ctx_get_intf_dest(ctx); addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &p->u.prefix, bytelen); - } else if (cmd == RTM_NEWADDR && - dplane_ctx_intf_has_dest(ctx)) { - p = dplane_ctx_get_intf_dest(ctx); + } else if (cmd == RTM_NEWADDR) { + struct in_addr broad = { + .s_addr = ipv4_broadcast_addr(p->u.prefix4.s_addr, + p->prefixlen) + }; addattr_l(&req.n, sizeof(req), IFA_BROADCAST, - &p->u.prefix, bytelen); + &broad, bytelen); } } @@ -1065,7 +1067,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) else connected_delete_ipv4( ifp, flags, (struct in_addr *)addr, - ifa->ifa_prefixlen, (struct in_addr *)broad); + ifa->ifa_prefixlen, NULL); } if (ifa->ifa_family == AF_INET6) { if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) { @@ -1091,8 +1093,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) metric); } else connected_delete_ipv6(ifp, (struct in6_addr *)addr, - (struct in6_addr *)broad, - ifa->ifa_prefixlen); + NULL, ifa->ifa_prefixlen); } return 0; diff --git a/zebra/interface.c b/zebra/interface.c index a2f80aff4e..6486c01430 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1081,12 +1081,10 @@ static void connected_dump_vty(struct vty *vty, struct connected *connected) vty_out(vty, "/%d", p->prefixlen); /* If there is destination address, print it. */ - if (connected->destination) { - vty_out(vty, - (CONNECTED_PEER(connected) ? " peer " : " broadcast ")); + if (CONNECTED_PEER(connected) && connected->destination) { + vty_out(vty, " peer "); prefix_vty_out(vty, connected->destination); - if (CONNECTED_PEER(connected)) - vty_out(vty, "/%d", connected->destination->prefixlen); + vty_out(vty, "/%d", connected->destination->prefixlen); } if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) @@ -2684,12 +2682,6 @@ static int ip_address_install(struct vty *vty, struct interface *ifp, p = prefix_ipv4_new(); *p = pp; ifc->destination = (struct prefix *)p; - } else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) { - p = prefix_ipv4_new(); - *p = lp; - p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr, - p->prefixlen); - ifc->destination = (struct prefix *)p; } /* Label. */ diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 0280cde238..1ae2ba92b0 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -172,6 +172,13 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p, __FUNCTION__); return; } + if (!zebra_check_addr(p)) { + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("Redist update filter prefix %s", + prefix2str(p, buf, sizeof(buf))); + return; + } + for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { send_redistribute = 0; @@ -246,6 +253,13 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p, return; } + if (!zebra_check_addr(p)) { + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("Redist delete filter prefix %s", + prefix2str(p, buf, sizeof(buf))); + return; + } + for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { if ((is_default_prefix(p) && vrf_bitmap_check(client->redist_default[afi], diff --git a/zebra/rt.h b/zebra/rt.h index 04576671fe..727d2d0c55 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -41,7 +41,7 @@ extern "C" { ((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT) /* - * Update or delete a route, LSP, or pseudowire from the kernel, + * Update or delete a route, LSP, pseudowire, or vxlan MAC from the kernel, * using info from a dataplane context. */ extern enum zebra_dplane_result kernel_route_update( @@ -55,6 +55,8 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx); enum zebra_dplane_result kernel_address_update_ctx( struct zebra_dplane_ctx *ctx); +enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx); + extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, int llalen, ns_id_t ns_id); extern int kernel_interface_set_master(struct interface *master, @@ -68,12 +70,6 @@ extern int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip); extern int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip); -extern int kernel_add_mac(struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - bool sticky); -extern int kernel_del_mac(struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip); - extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, struct ethaddr *mac, uint8_t flags); extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 549deb7045..cc73effaf9 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2282,33 +2282,70 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, return ret; } -static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - int cmd, bool sticky) + +/* + * Netlink-specific handler for MAC updates using dataplane context object. + */ +static enum zebra_dplane_result +netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx) { - struct zebra_ns *zns; struct { struct nlmsghdr n; struct ndmsg ndm; char buf[256]; } req; + int ret; int dst_alen; struct zebra_if *zif; struct interface *br_if; struct zebra_if *br_zif; - char buf[ETHER_ADDR_STRLEN]; int vid_present = 0; char vid_buf[20]; - char dst_buf[30]; - struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + struct zebra_ns *zns; + struct interface *ifp; + int cmd; + struct in_addr vtep_ip; + vlanid_t vid; + + if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL) + cmd = RTM_NEWNEIGH; + else + cmd = RTM_DELNEIGH; + + /* Locate zebra ns and interface objects from context data */ + zns = zebra_ns_lookup(dplane_ctx_get_ns(ctx)->ns_id); + if (zns == NULL) { + /* Nothing to be done */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("MAC %s on IF %s(%u) - zebra ns unknown", + (cmd == RTM_NEWNEIGH) ? "add" : "del", + dplane_ctx_get_ifname(ctx), + dplane_ctx_get_ifindex(ctx)); + + return ZEBRA_DPLANE_REQUEST_FAILURE; + } + + ifp = if_lookup_by_index_per_ns(zns, dplane_ctx_get_ifindex(ctx)); + if (ifp == NULL) { + /* Nothing to be done */ + /* Nothing to be done */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("MAC %s on IF %s(%u) - interface unknown", + (cmd == RTM_NEWNEIGH) ? "add" : "del", + dplane_ctx_get_ifname(ctx), + dplane_ctx_get_ifindex(ctx)); + return ZEBRA_DPLANE_REQUEST_FAILURE; + } + + vid = dplane_ctx_mac_get_vlan(ctx); - zns = zvrf->zns; zif = ifp->info; if ((br_if = zif->brslave_info.br_if) == NULL) { - zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge", - (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name, - ifp->ifindex); - return -1; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge", + (cmd == RTM_NEWNEIGH) ? "add" : "del", + ifp->name, ifp->ifindex); + return ZEBRA_DPLANE_REQUEST_FAILURE; } memset(&req, 0, sizeof(req)); @@ -2322,16 +2359,19 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER; req.ndm.ndm_state = NUD_REACHABLE; - if (sticky) + if (dplane_ctx_mac_is_sticky(ctx)) req.ndm.ndm_state |= NUD_NOARP; else req.ndm.ndm_flags |= NTF_EXT_LEARNED; - addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); + addattr_l(&req.n, sizeof(req), NDA_LLADDR, + dplane_ctx_mac_get_addr(ctx), 6); req.ndm.ndm_ifindex = ifp->ifindex; + dst_alen = 4; // TODO: hardcoded + vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx)); addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen); - sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip)); + br_zif = (struct zebra_if *)br_if->info; if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) { addattr16(&req.n, sizeof(req), NDA_VLAN, vid); @@ -2340,16 +2380,29 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, } addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex); - if (IS_ZEBRA_DEBUG_KERNEL) + if (IS_ZEBRA_DEBUG_KERNEL) { + char ipbuf[PREFIX_STRLEN]; + char buf[ETHER_ADDR_STRLEN]; + char dst_buf[PREFIX_STRLEN + 10]; + + inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf)); + snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf); + prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf)); + zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s", nl_msg_type_to_str(cmd), nl_family_to_str(req.ndm.ndm_family), ifp->name, ifp->ifindex, vid_present ? vid_buf : "", - sticky ? "sticky " : "", - prefix_mac2str(mac, buf, sizeof(buf)), dst_buf); + dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "", + buf, dst_buf); + } - return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + ret = netlink_talk_info(netlink_talk_filter, &req.n, + dplane_ctx_get_ns(ctx), 0); + if (ret == 0) + return ZEBRA_DPLANE_REQUEST_SUCCESS; + else + return ZEBRA_DPLANE_REQUEST_FAILURE; } /* @@ -2762,17 +2815,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, 0); } -int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, - struct in_addr vtep_ip, bool sticky) -{ - return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_NEWNEIGH, - sticky); -} - -int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, - struct in_addr vtep_ip) +/* + * Update MAC, using dataplane context object. + */ +enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx) { - return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_DELNEIGH, 0); + return netlink_macfdb_update_ctx(ctx); } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 8d8bdd0a6d..7e9a42a617 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -386,16 +386,12 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) return 0; } -int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, - struct in_addr vtep_ip, bool sticky) -{ - return 0; -} - -int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, - struct in_addr vtep_ip) +/* + * Update MAC, using dataplane context object. No-op here for now. + */ +enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx) { - return 0; + return ZEBRA_DPLANE_REQUEST_SUCCESS; } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index c90e027f02..512a9b4021 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -109,8 +109,6 @@ struct dplane_route_info { * Pseudowire info for the dataplane */ struct dplane_pw_info { - char ifname[IF_NAMESIZE]; - ifindex_t ifindex; int type; int af; int status; @@ -130,16 +128,13 @@ struct dplane_pw_info { */ struct dplane_intf_info { - char ifname[INTERFACE_NAMSIZ]; - ifindex_t ifindex; - uint32_t metric; uint32_t flags; #define DPLANE_INTF_CONNECTED (1 << 0) /* Connected peer, p2p */ #define DPLANE_INTF_SECONDARY (1 << 1) #define DPLANE_INTF_BROADCAST (1 << 2) -#define DPLANE_INTF_HAS_DEST (1 << 3) +#define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED #define DPLANE_INTF_HAS_LABEL (1 << 4) /* Interface address/prefix */ @@ -153,6 +148,17 @@ struct dplane_intf_info { }; /* + * MAC address info for the dataplane. + */ +struct dplane_mac_info { + vlanid_t vid; + struct ethaddr mac; + struct in_addr vtep_ip; + bool is_sticky; + +}; + +/* * The context block used to exchange info about route updates across * the boundary between the zebra main context (and pthread) and the * dataplane layer (and pthread). @@ -188,12 +194,16 @@ struct zebra_dplane_ctx { vrf_id_t zd_vrf_id; uint32_t zd_table_id; + char zd_ifname[INTERFACE_NAMSIZ]; + ifindex_t zd_ifindex; + /* Support info for different kinds of updates */ union { struct dplane_route_info rinfo; zebra_lsp_t lsp; struct dplane_pw_info pw; struct dplane_intf_info intf; + struct dplane_mac_info macinfo; } u; /* Namespace info, used especially for netlink kernel communication */ @@ -273,8 +283,8 @@ static struct zebra_dplane_globals { /* Sentinel for end of shutdown */ volatile bool dg_run; - /* Route-update context queue inbound to the dataplane */ - TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_route_ctx_q; + /* Update context queue inbound to the dataplane */ + TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q; /* Ordered list of providers */ TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q; @@ -308,6 +318,9 @@ static struct zebra_dplane_globals { _Atomic uint32_t dg_intf_addrs_in; _Atomic uint32_t dg_intf_addr_errors; + _Atomic uint32_t dg_macs_in; + _Atomic uint32_t dg_mac_errors; + _Atomic uint32_t dg_update_yields; /* Dataplane pthread */ @@ -348,6 +361,10 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw, static enum zebra_dplane_result intf_addr_update_internal( const struct interface *ifp, const struct connected *ifc, enum dplane_op_e op); +static enum zebra_dplane_result mac_update_internal( + enum dplane_op_e op, const struct interface *ifp, + vlanid_t vid, const struct ethaddr *mac, + struct in_addr vtep_ip, bool sticky); /* * Public APIs @@ -466,6 +483,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx) } break; + case DPLANE_OP_MAC_INSTALL: + case DPLANE_OP_MAC_DELETE: case DPLANE_OP_NONE: break; } @@ -626,6 +645,12 @@ const char *dplane_op2str(enum dplane_op_e op) ret = "ADDR_UNINSTALL"; break; + case DPLANE_OP_MAC_INSTALL: + ret = "MAC_INSTALL"; + break; + case DPLANE_OP_MAC_DELETE: + ret = "MAC_DELETE"; + break; } return ret; @@ -744,6 +769,19 @@ void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx, ctx->zd_notif_provider = id; } +const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_ifname; +} + +ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_ifindex; +} void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type) { @@ -1030,13 +1068,6 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx) return ctx->u.lsp.num_ecmp; } -const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx) -{ - DPLANE_CTX_VALID(ctx); - - return ctx->u.pw.ifname; -} - mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1104,20 +1135,6 @@ dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx) } /* Accessors for interface information */ -const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx) -{ - DPLANE_CTX_VALID(ctx); - - return ctx->u.intf.ifname; -} - -ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx) -{ - DPLANE_CTX_VALID(ctx); - - return ctx->u.intf.ifindex; -} - uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1187,6 +1204,33 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx) return ctx->u.intf.label; } +/* Accessors for MAC information */ +vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return ctx->u.macinfo.vid; +} + +bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return ctx->u.macinfo.is_sticky; +} + +const struct ethaddr *dplane_ctx_mac_get_addr( + const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return &(ctx->u.macinfo.mac); +} + +const struct in_addr *dplane_ctx_mac_get_vtep_ip( + const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return &(ctx->u.macinfo.vtep_ip); +} + /* * End of dplane context accessors */ @@ -1422,10 +1466,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx, memset(&ctx->u.pw, 0, sizeof(ctx->u.pw)); /* This name appears to be c-string, so we use string copy. */ - strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname)); + strlcpy(ctx->zd_ifname, pw->ifname, sizeof(ctx->zd_ifname)); ctx->zd_vrf_id = pw->vrf_id; - ctx->u.pw.ifindex = pw->ifindex; + ctx->zd_ifindex = pw->ifindex; ctx->u.pw.type = pw->type; ctx->u.pw.af = pw->af; ctx->u.pw.local_label = pw->local_label; @@ -1467,10 +1511,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx, } /* - * Enqueue a new route update, + * Enqueue a new update, * and ensure an event is active for the dataplane pthread. */ -static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx) +static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx) { int ret = EINVAL; uint32_t high, curr; @@ -1478,7 +1522,7 @@ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx) /* Enqueue for processing by the dataplane pthread */ DPLANE_LOCK(); { - TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx, + TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx, zd_q_entries); } DPLANE_UNLOCK(); @@ -1558,7 +1602,7 @@ dplane_route_update_internal(struct route_node *rn, } /* Enqueue context for processing */ - ret = dplane_route_enqueue(ctx); + ret = dplane_update_enqueue(ctx); } /* Update counter */ @@ -1724,7 +1768,7 @@ dplane_route_notif_update(struct route_node *rn, dplane_ctx_set_notif_provider(new_ctx, dplane_ctx_get_notif_provider(ctx)); - dplane_route_enqueue(new_ctx); + dplane_update_enqueue(new_ctx); ret = ZEBRA_DPLANE_REQUEST_QUEUED; @@ -1791,7 +1835,7 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp, ctx, dplane_ctx_get_notif_provider(notif_ctx)); - ret = dplane_route_enqueue(ctx); + ret = dplane_update_enqueue(ctx); done: /* Update counter */ @@ -1842,7 +1886,7 @@ static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp, if (ret != AOK) goto done; - ret = dplane_route_enqueue(ctx); + ret = dplane_update_enqueue(ctx); done: /* Update counter */ @@ -1876,7 +1920,7 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw, if (ret != AOK) goto done; - ret = dplane_route_enqueue(ctx); + ret = dplane_update_enqueue(ctx); done: /* Update counter */ @@ -1967,8 +2011,8 @@ static enum zebra_dplane_result intf_addr_update_internal( /* Init the interface-addr-specific area */ memset(&ctx->u.intf, 0, sizeof(ctx->u.intf)); - strlcpy(ctx->u.intf.ifname, ifp->name, sizeof(ctx->u.intf.ifname)); - ctx->u.intf.ifindex = ifp->ifindex; + strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname)); + ctx->zd_ifindex = ifp->ifindex; ctx->u.intf.prefix = *(ifc->address); if (if_is_broadcast(ifp)) @@ -1978,9 +2022,6 @@ static enum zebra_dplane_result intf_addr_update_internal( ctx->u.intf.dest_prefix = *(ifc->destination); ctx->u.intf.flags |= (DPLANE_INTF_CONNECTED | DPLANE_INTF_HAS_DEST); - } else if (ifc->destination) { - ctx->u.intf.dest_prefix = *(ifc->destination); - ctx->u.intf.flags |= DPLANE_INTF_HAS_DEST; } if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) @@ -2003,7 +2044,7 @@ static enum zebra_dplane_result intf_addr_update_internal( } } - ret = dplane_route_enqueue(ctx); + ret = dplane_update_enqueue(ctx); /* Increment counter */ atomic_fetch_add_explicit(&zdplane_info.dg_intf_addrs_in, 1, @@ -2022,6 +2063,104 @@ static enum zebra_dplane_result intf_addr_update_internal( } /* + * Enqueue vxlan/evpn mac add (or update). + */ +enum zebra_dplane_result dplane_mac_add(const struct interface *ifp, + vlanid_t vid, + const struct ethaddr *mac, + struct in_addr vtep_ip, + bool sticky) +{ + enum zebra_dplane_result result; + + /* Use common helper api */ + result = mac_update_internal(DPLANE_OP_MAC_INSTALL, ifp, vid, + mac, vtep_ip, sticky); + return result; +} + +/* + * Enqueue vxlan/evpn mac delete. + */ +enum zebra_dplane_result dplane_mac_del(const struct interface *ifp, + vlanid_t vid, + const struct ethaddr *mac, + struct in_addr vtep_ip) +{ + enum zebra_dplane_result result; + + /* Use common helper api */ + result = mac_update_internal(DPLANE_OP_MAC_DELETE, ifp, vid, mac, + vtep_ip, false); + return result; +} + +/* + * Common helper api for MAC address/vxlan updates + */ +static enum zebra_dplane_result +mac_update_internal(enum dplane_op_e op, + const struct interface *ifp, + vlanid_t vid, + const struct ethaddr *mac, + struct in_addr vtep_ip, + bool sticky) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + int ret; + struct zebra_dplane_ctx *ctx = NULL; + struct zebra_ns *zns; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN]; + + zlog_debug("init mac ctx %s: mac %s, ifp %s, vtep %s", + dplane_op2str(op), + prefix_mac2str(mac, buf1, sizeof(buf1)), + ifp->name, + inet_ntop(AF_INET, &vtep_ip, buf2, sizeof(buf2))); + } + + ctx = dplane_ctx_alloc(); + + ctx->zd_op = op; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + ctx->zd_vrf_id = ifp->vrf_id; + + zns = zebra_ns_lookup(ifp->vrf_id); + dplane_ctx_ns_init(ctx, zns, false); + + strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname)); + ctx->zd_ifindex = ifp->ifindex; + + /* Init the mac-specific data area */ + memset(&ctx->u.macinfo, 0, sizeof(ctx->u.macinfo)); + + ctx->u.macinfo.vtep_ip = vtep_ip; + ctx->u.macinfo.mac = *mac; + ctx->u.macinfo.vid = vid; + ctx->u.macinfo.is_sticky = sticky; + + /* Enqueue for processing on the dplane pthread */ + ret = dplane_update_enqueue(ctx); + + /* Increment counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_macs_in, 1, + memory_order_relaxed); + + if (ret == AOK) + result = ZEBRA_DPLANE_REQUEST_QUEUED; + else { + /* Error counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors, 1, + memory_order_relaxed); + dplane_ctx_free(&ctx); + } + + return result; +} + +/* * Handler for 'show dplane' */ int dplane_show_helper(struct vty *vty, bool detailed) @@ -2054,7 +2193,35 @@ int dplane_show_helper(struct vty *vty, bool detailed) vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit); vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued); vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max); - vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields); + vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields); + + incoming = atomic_load_explicit(&zdplane_info.dg_lsps_in, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_lsp_errors, + memory_order_relaxed); + vty_out(vty, "LSP updates: %"PRIu64"\n", incoming); + vty_out(vty, "LSP update errors: %"PRIu64"\n", errs); + + incoming = atomic_load_explicit(&zdplane_info.dg_pws_in, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_pw_errors, + memory_order_relaxed); + vty_out(vty, "PW updates: %"PRIu64"\n", incoming); + vty_out(vty, "PW update errors: %"PRIu64"\n", errs); + + incoming = atomic_load_explicit(&zdplane_info.dg_intf_addrs_in, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_intf_addr_errors, + memory_order_relaxed); + vty_out(vty, "Intf addr updates: %"PRIu64"\n", incoming); + vty_out(vty, "Intf addr errors: %"PRIu64"\n", errs); + + incoming = atomic_load_explicit(&zdplane_info.dg_macs_in, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_mac_errors, + memory_order_relaxed); + vty_out(vty, "EVPN MAC updates: %"PRIu64"\n", incoming); + vty_out(vty, "EVPN MAC errors: %"PRIu64"\n", errs); return CMD_SUCCESS; } @@ -2374,7 +2541,7 @@ kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx) if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u", - dplane_ctx_get_pw_ifname(ctx), + dplane_ctx_get_ifname(ctx), dplane_op2str(ctx->zd_op), dplane_ctx_get_pw_af(ctx), dplane_ctx_get_pw_local_label(ctx), @@ -2428,7 +2595,6 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx) { enum zebra_dplane_result res; - if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { char dest_str[PREFIX_STRLEN]; @@ -2450,6 +2616,34 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx) } /* + * Handler for kernel-facing MAC address updates + */ +static enum zebra_dplane_result +kernel_dplane_mac_update(struct zebra_dplane_ctx *ctx) +{ + enum zebra_dplane_result res; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + char buf[ETHER_ADDR_STRLEN]; + + prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, + sizeof(buf)); + + zlog_debug("Dplane %s, mac %s, ifindex %u", + dplane_op2str(dplane_ctx_get_op(ctx)), + buf, dplane_ctx_get_ifindex(ctx)); + } + + res = kernel_mac_update_ctx(ctx); + + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors, + 1, memory_order_relaxed); + + return res; +} + +/* * Kernel provider callback */ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) @@ -2503,6 +2697,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) res = kernel_dplane_address_update(ctx); break; + case DPLANE_OP_MAC_INSTALL: + case DPLANE_OP_MAC_DELETE: + res = kernel_dplane_mac_update(ctx); + break; + /* Ignore 'notifications' - no-op */ case DPLANE_OP_SYS_ROUTE_ADD: case DPLANE_OP_SYS_ROUTE_DELETE: @@ -2682,7 +2881,7 @@ static bool dplane_work_pending(void) */ DPLANE_LOCK(); { - ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q); + ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q); prov = TAILQ_FIRST(&zdplane_info.dg_providers_q); } DPLANE_UNLOCK(); @@ -2810,9 +3009,9 @@ static int dplane_thread_loop(struct thread *event) /* Move new work from incoming list to temp list */ for (counter = 0; counter < limit; counter++) { - ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q); + ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q); if (ctx) { - TAILQ_REMOVE(&zdplane_info.dg_route_ctx_q, ctx, + TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx, zd_q_entries); ctx->zd_provider = prov->dp_id; @@ -2997,7 +3196,7 @@ static void zebra_dplane_init_internal(void) pthread_mutex_init(&zdplane_info.dg_mutex, NULL); - TAILQ_INIT(&zdplane_info.dg_route_ctx_q); + TAILQ_INIT(&zdplane_info.dg_update_ctx_q); TAILQ_INIT(&zdplane_info.dg_providers_q); zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK; diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 6238026bcf..912fda45d3 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -25,6 +25,7 @@ #include "lib/nexthop.h" #include "lib/nexthop_group.h" #include "lib/queue.h" +#include "lib/vlan.h" #include "zebra/zebra_ns.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -124,6 +125,10 @@ enum dplane_op_e { /* Interface address update */ DPLANE_OP_ADDR_INSTALL, DPLANE_OP_ADDR_UNINSTALL, + + /* MAC address update */ + DPLANE_OP_MAC_INSTALL, + DPLANE_OP_MAC_DELETE, }; /* Enable system route notifications */ @@ -180,6 +185,8 @@ const char *dplane_op2str(enum dplane_op_e op); const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx); void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx, const struct prefix *dest); +const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx); +ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx); /* Retrieve last/current provider id */ uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx); @@ -262,7 +269,6 @@ const zebra_nhlfe_t *dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx, uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx); /* Accessors for pseudowire information */ -const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx); mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx); mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx); int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx); @@ -277,8 +283,6 @@ const struct nexthop_group *dplane_ctx_get_pw_nhg( const struct zebra_dplane_ctx *ctx); /* Accessors for interface information */ -const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx); -ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx); /* Is interface addr p2p? */ bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx); @@ -292,6 +296,14 @@ const struct prefix *dplane_ctx_get_intf_dest( bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx); const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx); +/* Accessors for MAC information */ +vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx); +bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx); +const struct ethaddr *dplane_ctx_mac_get_addr( + const struct zebra_dplane_ctx *ctx); +const struct in_addr *dplane_ctx_mac_get_vtep_ip( + const struct zebra_dplane_ctx *ctx); + /* Namespace info - esp. for netlink communication */ const struct zebra_dplane_info *dplane_ctx_get_ns( const struct zebra_dplane_ctx *ctx); @@ -353,6 +365,19 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp, enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp, const struct connected *ifc); +/* + * Enqueue evpn mac operations for the dataplane. + */ +enum zebra_dplane_result dplane_mac_add(const struct interface *ifp, + vlanid_t vid, + const struct ethaddr *mac, + struct in_addr vtep_ip, + bool sticky); + +enum zebra_dplane_result dplane_mac_del(const struct interface *ifp, + vlanid_t vid, + const struct ethaddr *mac, + struct in_addr vtep_ip); /* Retrieve the limit on the number of pending, unprocessed updates. */ uint32_t dplane_get_in_queue_limit(void); diff --git a/zebra/zebra_errors.c b/zebra/zebra_errors.c index 5f0a9ec011..a7e5147af3 100644 --- a/zebra/zebra_errors.c +++ b/zebra/zebra_errors.c @@ -659,7 +659,7 @@ static struct log_ref ferr_zebra_err[] = { { .code = EC_ZEBRA_RTM_VERSION_MISMATCH, .title = - "Zebra received kernel message with uknown version", + "Zebra received kernel message with unknown version", .description = "Zebra received a message from the kernel with a message version that does not match Zebra's internal version. Depending on version compatibility, this may cause issues sending and receiving messages to the kernel.", .suggestion = diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index e7fdaf127d..9f3ea70c77 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -369,7 +369,7 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx) /* ioctl */ memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx), + strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx), sizeof(ifr.ifr_name)); ifr.ifr_data = (caddr_t)&imr; if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) { @@ -388,7 +388,7 @@ static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx) memset(&ifr, 0, sizeof(ifr)); memset(&imr, 0, sizeof(imr)); - strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx), + strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx), sizeof(ifr.ifr_name)); ifr.ifr_data = (caddr_t)&imr; if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) { diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 3608b887ee..335cc8294c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3178,7 +3178,7 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx) if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) { vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); - pw = zebra_pw_find(vrf, dplane_ctx_get_pw_ifname(ctx)); + pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx)); if (pw) zebra_pw_install_failure(pw); } @@ -3270,6 +3270,11 @@ static int rib_process_dplane_results(struct thread *thread) dplane_ctx_fini(&ctx); break; + case DPLANE_OP_MAC_INSTALL: + case DPLANE_OP_MAC_DELETE: + zebra_vxlan_handle_result(ctx); + break; + default: /* Don't expect this: just return the struct? */ dplane_ctx_fini(&ctx); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 1450072aa9..bb31247b6a 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -3733,13 +3733,14 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) } /* - * Install remote MAC into the kernel. + * Install remote MAC into the forwarding plane. */ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) { struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; bool sticky; + enum zebra_dplane_result res; if (!(mac->flags & ZEBRA_MAC_REMOTE)) return 0; @@ -3752,12 +3753,16 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) sticky = !!CHECK_FLAG(mac->flags, (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)); - return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr, - mac->fwd_info.r_vtep_ip, sticky); + res = dplane_mac_add(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr, + mac->fwd_info.r_vtep_ip, sticky); + if (res != ZEBRA_DPLANE_REQUEST_FAILURE) + return 0; + else + return -1; } /* - * Uninstall remote MAC from the kernel. + * Uninstall remote MAC from the forwarding plane. */ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac) { @@ -3765,6 +3770,7 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac) struct zebra_l2info_vxlan *vxl; struct in_addr vtep_ip; struct interface *ifp; + enum zebra_dplane_result res; if (!(mac->flags & ZEBRA_MAC_REMOTE)) return 0; @@ -3783,7 +3789,11 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac) ifp = zvni->vxlan_if; vtep_ip = mac->fwd_info.r_vtep_ip; - return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip); + res = dplane_mac_del(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip); + if (res != ZEBRA_DPLANE_REQUEST_FAILURE) + return 0; + else + return -1; } /* @@ -4470,12 +4480,13 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) } /* - * Install remote RMAC into the kernel. + * Install remote RMAC into the forwarding plane. */ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) { struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; + enum zebra_dplane_result res; if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE)) || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC))) @@ -4487,18 +4498,23 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) vxl = &zif->l2info.vxl; - return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan, - &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0); + res = dplane_mac_add(zl3vni->vxlan_if, vxl->access_vlan, + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0); + if (res != ZEBRA_DPLANE_REQUEST_FAILURE) + return 0; + else + return -1; } /* - * Uninstall remote RMAC from the kernel. + * Uninstall remote RMAC from the forwarding plane. */ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) { char buf[ETHER_ADDR_STRLEN]; struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; + enum zebra_dplane_result res; if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE)) || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC))) @@ -4518,8 +4534,12 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) vxl = &zif->l2info.vxl; - return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan, - &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip); + res = dplane_mac_del(zl3vni->vxlan_if, vxl->access_vlan, + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip); + if (res != ZEBRA_DPLANE_REQUEST_FAILURE) + return 0; + else + return -1; } /* handle rmac add */ @@ -6772,7 +6792,7 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty, if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) { vty_out(vty, - "%% Requsted host IP %s is not duplicate detected\n", + "%% Requested host IP %s is not duplicate detected\n", buf); return CMD_WARNING; } @@ -9913,6 +9933,15 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client) return 0; } +/* + * Handle results for vxlan dataplane operations. + */ +extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx) +{ + /* TODO -- anything other than freeing the context? */ + dplane_ctx_fini(&ctx); +} + /* Cleanup BGP EVPN configuration upon client disconnect */ extern void zebra_evpn_init(void) { diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index c71953d6bb..bb80ae1c9a 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -35,6 +35,7 @@ #include "lib/json.h" #include "zebra/zebra_vrf.h" #include "zebra/zserv.h" +#include "zebra/zebra_dplane.h" #ifdef __cplusplus extern "C" { @@ -213,6 +214,8 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty, extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni); +extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx); + extern void zebra_evpn_init(void); #ifdef __cplusplus |
