diff options
49 files changed, 673 insertions, 524 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 1f8a910f2..0924223dd 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -900,7 +900,7 @@ size_t aspath_put(struct stream *s, struct aspath *as, int use32bit) while ((seg->length - written) > AS_SEGMENT_MAX) { assegment_header_put(s, seg->type, AS_SEGMENT_MAX); - assegment_data_put(s, seg->as, AS_SEGMENT_MAX, + assegment_data_put(s, (seg->as + written), AS_SEGMENT_MAX, use32bit); written += AS_SEGMENT_MAX; bytes += ASSEGMENT_SIZE(AS_SEGMENT_MAX, diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index c3bfbe4a9..95c3f15a6 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -23,7 +23,7 @@ #include <zebra.h> #include <pthread.h> // for pthread_mutex_unlock, pthread_mutex_lock -#include "frr_pthread.h" // for frr_pthread_get, frr_pthread +#include "frr_pthread.h" #include "linklist.h" // for list_delete, list_delete_all_node, lis... #include "log.h" // for zlog_debug, safe_strerror, zlog_err #include "memory.h" // for MTYPE_TMP, XCALLOC, XFREE @@ -56,7 +56,7 @@ static bool validate_header(struct peer *); void bgp_writes_on(struct peer *peer) { - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); + struct frr_pthread *fpt = bgp_pth_io; assert(fpt->running); assert(peer->status != Deleted); @@ -74,7 +74,7 @@ void bgp_writes_on(struct peer *peer) void bgp_writes_off(struct peer *peer) { - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); + struct frr_pthread *fpt = bgp_pth_io; assert(fpt->running); thread_cancel_async(fpt->master, &peer->t_write, NULL); @@ -85,7 +85,7 @@ void bgp_writes_off(struct peer *peer) void bgp_reads_on(struct peer *peer) { - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); + struct frr_pthread *fpt = bgp_pth_io; assert(fpt->running); assert(peer->status != Deleted); @@ -105,7 +105,7 @@ void bgp_reads_on(struct peer *peer) void bgp_reads_off(struct peer *peer) { - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); + struct frr_pthread *fpt = bgp_pth_io; assert(fpt->running); thread_cancel_async(fpt->master, &peer->t_read, NULL); @@ -130,7 +130,7 @@ static int bgp_process_writes(struct thread *thread) if (peer->fd < 0) return -1; - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); + struct frr_pthread *fpt = bgp_pth_io; pthread_mutex_lock(&peer->io_mtx); { @@ -182,7 +182,7 @@ static int bgp_process_reads(struct thread *thread) if (peer->fd < 0 || bm->terminating) return -1; - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); + struct frr_pthread *fpt = bgp_pth_io; pthread_mutex_lock(&peer->io_mtx); { diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index aeb95f91b..91fa8fa37 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -229,7 +229,7 @@ void bgp_keepalives_on(struct peer *peer) if (CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON)) return; - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_KEEPALIVES); + struct frr_pthread *fpt = bgp_pth_ka; assert(fpt->running); /* placeholder bucket data to use for fast key lookups */ @@ -259,7 +259,7 @@ void bgp_keepalives_off(struct peer *peer) if (!CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON)) return; - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_KEEPALIVES); + struct frr_pthread *fpt = bgp_pth_ka; assert(fpt->running); /* placeholder bucket data to use for fast key lookups */ diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c index 7a7a40027..73d3dc67e 100644 --- a/bgpd/bgp_labelpool.c +++ b/bgpd/bgp_labelpool.c @@ -530,6 +530,7 @@ void bgp_lp_event_zebra_up(void) int chunks_needed; void *labelid; struct lp_lcb *lcb; + int lm_init_ok; /* * Get label chunk allocation request dispatched to zebra @@ -541,6 +542,11 @@ void bgp_lp_event_zebra_up(void) chunks_needed = (labels_needed / LP_CHUNK_SIZE) + 1; labels_needed = chunks_needed * LP_CHUNK_SIZE; + lm_init_ok = lm_label_manager_connect(zclient, 1) == 0; + + if (!lm_init_ok) + zlog_err("%s: label manager connection error", __func__); + zclient_send_get_label_chunk(zclient, 0, labels_needed); lp->pending_count = labels_needed; diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index d888090e6..6643795f5 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -77,6 +77,7 @@ static const struct option longopts[] = { {"no_kernel", no_argument, NULL, 'n'}, {"skip_runas", no_argument, NULL, 'S'}, {"ecmp", required_argument, NULL, 'e'}, + {"int_num", required_argument, NULL, 'I'}, {0}}; /* signal definitions */ @@ -371,15 +372,17 @@ int main(int argc, char **argv) char *bgp_address = NULL; int no_fib_flag = 0; int skip_runas = 0; + int instance = 0; frr_preinit(&bgpd_di, argc, argv); frr_opt_add( - "p:l:Sne:" DEPRECATED_OPTIONS, longopts, + "p:l:Sne:I:" DEPRECATED_OPTIONS, longopts, " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n" " -l, --listenon Listen on specified address (implies -n)\n" " -n, --no_kernel Do not install route to kernel.\n" " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n" - " -e, --ecmp Specify ECMP to use.\n"); + " -e, --ecmp Specify ECMP to use.\n" + " -I, --int_num Set instance number (label-manager)\n"); /* Command line argument treatment. */ while (1) { @@ -426,6 +429,12 @@ int main(int argc, char **argv) case 'S': skip_runas = 1; break; + case 'I': + instance = atoi(optarg); + if (instance > (unsigned short)-1) + zlog_err("Instance %i out of range (0..%u)", + instance, (unsigned short)-1); + break; default: frr_help_exit(1); break; @@ -448,7 +457,7 @@ int main(int argc, char **argv) bgp_vrf_init(); /* BGP related initialization. */ - bgp_init(); + bgp_init((unsigned short)instance); snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d", (bm->address ? bm->address : "<all>"), bm->port); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 76bfa73fe..15f42e26d 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -80,12 +80,14 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table) struct bgp_node *rn; struct bgp_nexthop_cache *bnc; - for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - if ((bnc = rn->info) != NULL) { + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + bnc = bgp_nexthop_get_node_info(rn); + if (bnc != NULL) { bnc_free(bnc); - rn->info = NULL; + bgp_nexthop_set_node_info(rn, NULL); bgp_unlock_node(rn); } + } } static void *bgp_tip_hash_alloc(void *p) @@ -278,14 +280,14 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) rn = bgp_node_get(bgp->connected_table[AFI_IP], (struct prefix *)&p); - if (rn->info) { - bc = rn->info; + bc = bgp_connected_get_node_info(rn); + if (bc) bc->refcnt++; - } else { + else { bc = XCALLOC(MTYPE_BGP_CONN, sizeof(struct bgp_connected_ref)); bc->refcnt = 1; - rn->info = bc; + bgp_connected_set_node_info(rn, bc); } for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { @@ -310,14 +312,15 @@ void bgp_connected_add(struct bgp *bgp, struct connected *ifc) rn = bgp_node_get(bgp->connected_table[AFI_IP6], (struct prefix *)&p); - if (rn->info) { - bc = rn->info; + + bc = bgp_connected_get_node_info(rn); + if (bc) bc->refcnt++; - } else { + else { bc = XCALLOC(MTYPE_BGP_CONN, sizeof(struct bgp_connected_ref)); bc->refcnt = 1; - rn->info = bc; + bgp_connected_set_node_info(rn, bc); } } } @@ -354,11 +357,11 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc) if (!rn) return; - bc = rn->info; + bc = bgp_connected_get_node_info(rn); bc->refcnt--; if (bc->refcnt == 0) { XFREE(MTYPE_BGP_CONN, bc); - rn->info = NULL; + bgp_connected_set_node_info(rn, NULL); } bgp_unlock_node(rn); bgp_unlock_node(rn); @@ -368,15 +371,16 @@ static void bgp_connected_cleanup(struct route_table *table, struct route_node *rn) { struct bgp_connected_ref *bc; + struct bgp_node *bn = bgp_node_from_rnode(rn); - bc = rn->info; + bc = bgp_connected_get_node_info(bn); if (!bc) return; bc->refcnt--; if (bc->refcnt == 0) { XFREE(MTYPE_BGP_CONN, bc); - rn->info = NULL; + bgp_connected_set_node_info(bn, NULL); } } @@ -528,35 +532,35 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail) for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next(rn)) { - if ((bnc = rn->info) != NULL) { - if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) { - vty_out(vty, - " %s valid [IGP metric %d], #paths %d\n", - inet_ntop(rn->p.family, - &rn->p.u.prefix, buf, - sizeof(buf)), - bnc->metric, bnc->path_count); - - if (!detail) - continue; - - bgp_show_nexthops_detail(vty, bgp, bnc); - - } else { - vty_out(vty, " %s invalid\n", - inet_ntop(rn->p.family, - &rn->p.u.prefix, buf, - sizeof(buf))); - if (CHECK_FLAG(bnc->flags, - BGP_NEXTHOP_CONNECTED)) - vty_out(vty, - " Must be Connected\n"); + bnc = bgp_nexthop_get_node_info(rn); + if (!bnc) + continue; + + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) { + vty_out(vty, + " %s valid [IGP metric %d], #paths %d\n", + inet_ntop(rn->p.family, + &rn->p.u.prefix, buf, + sizeof(buf)), + bnc->metric, bnc->path_count); + + if (!detail) + continue; + + bgp_show_nexthops_detail(vty, bgp, bnc); + + } else { + vty_out(vty, " %s invalid\n", + inet_ntop(rn->p.family, + &rn->p.u.prefix, buf, + sizeof(buf))); + if (CHECK_FLAG(bnc->flags, + BGP_NEXTHOP_CONNECTED)) + vty_out(vty, " Must be Connected\n"); } - tbuf = time(NULL) - - (bgp_clock() - bnc->last_update); - vty_out(vty, " Last update: %s", ctime(&tbuf)); - vty_out(vty, "\n"); - } + tbuf = time(NULL) - (bgp_clock() - bnc->last_update); + vty_out(vty, " Last update: %s", ctime(&tbuf)); + vty_out(vty, "\n"); } } } diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 3ef7604b1..dd1ffe9f3 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -97,7 +97,7 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc) } unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)); - bnc->node->info = NULL; + bgp_nexthop_set_node_info(bnc->node, NULL); bgp_unlock_node(bnc->node); bnc->node = NULL; bnc_free(bnc); @@ -128,11 +128,10 @@ void bgp_unlink_nexthop_by_peer(struct peer *peer) rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p); - if (!rn->info) + bnc = bgp_nexthop_get_node_info(rn); + if (!bnc) return; - bnc = rn->info; - /* cleanup the peer reference */ bnc->nht_info = NULL; @@ -191,9 +190,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, else rn = bgp_node_get(bgp_nexthop->nexthop_cache_table[afi], &p); - if (!rn->info) { + bnc = bgp_nexthop_get_node_info(rn); + if (!bnc) { bnc = bnc_new(); - rn->info = bnc; + bgp_nexthop_set_node_info(rn, bnc); bnc->node = rn; bnc->bgp = bgp_nexthop; bgp_lock_node(rn); @@ -205,7 +205,6 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, } } - bnc = rn->info; bgp_unlock_node(rn); if (is_bgp_static_route) { SET_FLAG(bnc->flags, BGP_STATIC_ROUTE); @@ -297,16 +296,21 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) rn = bgp_node_lookup( peer->bgp->nexthop_cache_table[family2afi(p.family)], &p); - if (!rn || !rn->info) { + if (!rn) { if (BGP_DEBUG(nht, NHT)) zlog_debug("Cannot find connected NHT node for peer %s", peer->host); - if (rn) - bgp_unlock_node(rn); return; } - bnc = rn->info; + bnc = bgp_nexthop_get_node_info(rn); + if (!bnc) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug("Cannot find connected NHT node for peer %s on route_node as expected", + peer->host); + bgp_unlock_node(rn); + return; + } bgp_unlock_node(rn); if (bnc->nht_info != peer) { @@ -324,7 +328,7 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) zlog_debug("Freeing connected NHT node %p for peer %s", bnc, peer->host); unregister_zebra_rnh(bnc, 0); - bnc->node->info = NULL; + bgp_nexthop_set_node_info(bnc->node, NULL); bgp_unlock_node(bnc->node); bnc_free(bnc); } @@ -367,19 +371,29 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) bgp->import_check_table[family2afi(nhr.prefix.family)], &nhr.prefix); - if (!rn || !rn->info) { + if (!rn) { if (BGP_DEBUG(nht, NHT)) { char buf[PREFIX2STR_BUFFER]; prefix2str(&nhr.prefix, buf, sizeof(buf)); zlog_debug("parse nexthop update(%s): rn not found", buf); } - if (rn) - bgp_unlock_node(rn); return; } - bnc = rn->info; + bnc = bgp_nexthop_get_node_info(rn); + if (!bnc) { + if (BGP_DEBUG(nht, NHT)) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&nhr.prefix, buf, sizeof(buf)); + zlog_debug("parse nexthop update(%s): bnc node info not found", + buf); + } + bgp_unlock_node(rn); + return; + } + bgp_unlock_node(rn); bnc->last_update = bgp_clock(); bnc->change_flags = 0; @@ -505,7 +519,7 @@ void bgp_cleanup_nexthops(struct bgp *bgp) for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next(rn)) { - bnc = rn->info; + bnc = bgp_nexthop_get_node_info(rn); if (!bnc) continue; diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 552eb253e..a74b584e9 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -1882,14 +1882,14 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, } /* ipset create */ - if (bpm && !bpm->installed) + if (!bpm->installed) bgp_send_pbr_ipset_match(bpm, true); /* ipset add */ - if (bpme && !bpme->installed) + if (!bpme->installed) bgp_send_pbr_ipset_entry_match(bpme, true); /* iptables */ - if (bpm && !bpm->installed_in_iptable) + if (!bpm->installed_in_iptable) bgp_send_pbr_iptable(bpa, bpm, true); /* A previous entry may already exist diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 5c65d5e61..a04ed8eef 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4845,7 +4845,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, return CMD_WARNING_CONFIG_FAILED; } - bgp_static = rn->info; + bgp_static = bgp_static_get_node_info(rn); if ((label_index != BGP_INVALID_LABEL_INDEX) && (label_index != bgp_static->label_index)) { @@ -4867,7 +4867,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, /* Clear configuration. */ bgp_static_free(bgp_static); - rn->info = NULL; + bgp_static_set_node_info(rn, NULL); bgp_unlock_node(rn); bgp_unlock_node(rn); } else { @@ -4875,10 +4875,9 @@ static int bgp_static_set(struct vty *vty, const char *negate, /* Set BGP static route configuration. */ rn = bgp_node_get(bgp->route[afi][safi], &p); - if (rn->info) { + bgp_static = bgp_static_get_node_info(rn); + if (bgp_static) { /* Configuration change. */ - bgp_static = rn->info; - /* Label index cannot be changed. */ if (bgp_static->label_index != label_index) { vty_out(vty, "%% cannot change label-index\n"); @@ -4927,7 +4926,7 @@ static int bgp_static_set(struct vty *vty, const char *negate, bgp_static->rmap.map = route_map_lookup_by_name(rmap); } - rn->info = bgp_static; + bgp_static_set_node_info(rn, bgp_static); } bgp_static->valid = 1; @@ -4962,14 +4961,16 @@ void bgp_static_add(struct bgp *bgp) for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { - bgp_static = rm->info; + bgp_static = + bgp_static_get_node_info(rm); bgp_static_update_safi(bgp, &rm->p, bgp_static, afi, safi); } } else { - bgp_static_update(bgp, &rn->p, rn->info, afi, - safi); + bgp_static_update(bgp, &rn->p, + bgp_static_get_node_info(rn), + afi, safi); } } } @@ -4997,19 +4998,20 @@ void bgp_static_delete(struct bgp *bgp) for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { - bgp_static = rm->info; + bgp_static = + bgp_static_get_node_info(rm); bgp_static_withdraw_safi( bgp, &rm->p, AFI_IP, safi, (struct prefix_rd *)&rn->p); bgp_static_free(bgp_static); - rn->info = NULL; + bgp_static_set_node_info(rn, NULL); bgp_unlock_node(rn); } } else { - bgp_static = rn->info; + bgp_static = bgp_static_get_node_info(rn); bgp_static_withdraw(bgp, &rn->p, afi, safi); bgp_static_free(bgp_static); - rn->info = NULL; + bgp_static_set_node_info(rn, NULL); bgp_unlock_node(rn); } } @@ -5038,13 +5040,14 @@ void bgp_static_redo_import_check(struct bgp *bgp) for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { - bgp_static = rm->info; + bgp_static = + bgp_static_get_node_info(rm); bgp_static_update_safi(bgp, &rm->p, bgp_static, afi, safi); } } else { - bgp_static = rn->info; + bgp_static = bgp_static_get_node_info(rn); bgp_static_update(bgp, &rn->p, bgp_static, afi, safi); } @@ -5216,7 +5219,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, if (gwip) prefix_copy(&bgp_static->gatewayIp, &gw_ip); } - rn->info = bgp_static; + bgp_static_set_node_info(rn, bgp_static); bgp_static->valid = 1; bgp_static_update_safi(bgp, &p, bgp_static, afi, safi); @@ -5278,9 +5281,9 @@ int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, if (rn) { bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd); - bgp_static = rn->info; + bgp_static = bgp_static_get_node_info(rn); bgp_static_free(bgp_static); - rn->info = NULL; + bgp_static_set_node_info(rn, NULL); bgp_unlock_node(rn); bgp_unlock_node(rn); } else @@ -5769,13 +5772,14 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, child = bgp_node_get(table, p); /* Aggregate address configuration check. */ - for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) - if ((aggregate = rn->info) != NULL - && rn->p.prefixlen < p->prefixlen) { + for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) { + aggregate = bgp_aggregate_get_node_info(rn); + if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL, aggregate); } + } bgp_unlock_node(child); } @@ -5799,13 +5803,14 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, child = bgp_node_get(table, p); /* Aggregate address configuration check. */ - for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) - if ((aggregate = rn->info) != NULL - && rn->p.prefixlen < p->prefixlen) { + for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) { + aggregate = bgp_aggregate_get_node_info(rn); + if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del, aggregate); } + } bgp_unlock_node(child); } @@ -5838,12 +5843,12 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, return CMD_WARNING_CONFIG_FAILED; } - aggregate = rn->info; + aggregate = bgp_aggregate_get_node_info(rn); bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, 0, aggregate); /* Unlock aggregate address configuration. */ - rn->info = NULL; + bgp_aggregate_set_node_info(rn, NULL); bgp_aggregate_free(aggregate); bgp_unlock_node(rn); bgp_unlock_node(rn); @@ -5894,7 +5899,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, aggregate->summary_only = summary_only; aggregate->as_set = as_set; aggregate->safi = safi; - rn->info = aggregate; + bgp_aggregate_set_node_info(rn, aggregate); /* Aggregate address insert into BGP routing table. */ bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate); @@ -10769,12 +10774,12 @@ static int bgp_distance_set(struct vty *vty, const char *distance_str, /* Get BGP distance node. */ rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p); - if (rn->info) { - bdistance = rn->info; + bdistance = bgp_distance_get_node(rn); + if (bdistance) bgp_unlock_node(rn); - } else { + else { bdistance = bgp_distance_new(); - rn->info = bdistance; + bgp_distance_set_node_info(rn, bdistance); } /* Set distance value. */ @@ -10819,7 +10824,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, return CMD_WARNING_CONFIG_FAILED; } - bdistance = rn->info; + bdistance = bgp_distance_get_node(rn); distance = atoi(distance_str); if (bdistance->distance != distance) { @@ -10858,7 +10863,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi, sockunion2hostprefix(&peer->su, &q); rn = bgp_node_match(bgp_distance_table[afi][safi], &q); if (rn) { - bdistance = rn->info; + bdistance = bgp_distance_get_node(rn); bgp_unlock_node(rn); if (bdistance->access_list) { @@ -10873,7 +10878,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi, /* Backdoor check. */ rn = bgp_node_lookup(bgp->route[afi][safi], p); if (rn) { - bgp_static = rn->info; + bgp_static = bgp_static_get_node_info(rn); bgp_unlock_node(rn); if (bgp_static->backdoor) { @@ -11288,7 +11293,8 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - if ((bgp_static = rn->info) == NULL) + bgp_static = bgp_static_get_node_info(rn); + if (bgp_static == NULL) continue; p = &rn->p; @@ -11337,7 +11343,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - if ((bgp_static = rn->info) == NULL) + bgp_static = bgp_static_get_node_info(rn); + if (bgp_static == NULL) continue; char *macrouter = NULL; @@ -11412,7 +11419,8 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, /* Network configuration. */ for (rn = bgp_table_top(bgp->route[afi][safi]); rn; rn = bgp_route_next(rn)) { - if ((bgp_static = rn->info) == NULL) + bgp_static = bgp_static_get_node_info(rn); + if (bgp_static == NULL) continue; p = &rn->p; @@ -11458,7 +11466,8 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, /* Aggregate-address configuration. */ for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn; rn = bgp_route_next(rn)) { - if ((bgp_aggregate = rn->info) == NULL) + bgp_aggregate = bgp_aggregate_get_node_info(rn); + if (bgp_aggregate == NULL) continue; p = &rn->p; @@ -11508,8 +11517,9 @@ void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, } for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn; - rn = bgp_route_next(rn)) - if ((bdistance = rn->info) != NULL) { + rn = bgp_route_next(rn)) { + bdistance = bgp_distance_get_node(rn); + if (bdistance != NULL) { char buf[PREFIX_STRLEN]; vty_out(vty, " distance %d %s %s\n", @@ -11518,6 +11528,7 @@ void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, bdistance->access_list ? bdistance->access_list : ""); } + } } /* Allocate routing table structure and install commands. */ diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 60c2cbd4a..bec95c71a 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -313,4 +313,63 @@ static inline uint64_t bgp_table_version(struct bgp_table *table) void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, uint8_t maxlen, struct list *matches); + +static inline struct bgp_aggregate * +bgp_aggregate_get_node_info(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_aggregate_set_node_info(struct bgp_node *node, + struct bgp_aggregate *aggregate) +{ + node->info = aggregate; +} + +static inline struct bgp_distance *bgp_distance_get_node(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_distance_set_node_info(struct bgp_node *node, + struct bgp_distance *distance) +{ + node->info = distance; +} + +static inline struct bgp_static *bgp_static_get_node_info(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_static_set_node_info(struct bgp_node *node, + struct bgp_static *bgp_static) +{ + node->info = bgp_static; +} + +static inline struct bgp_connected_ref * +bgp_connected_get_node_info(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_connected_set_node_info(struct bgp_node *node, + struct bgp_connected_ref *bc) +{ + node->info = bc; +} + +static inline struct bgp_nexthop_cache * +bgp_nexthop_get_node_info(struct bgp_node *node) +{ + return node->info; +} + +static inline void bgp_nexthop_set_node_info(struct bgp_node *node, + struct bgp_nexthop_cache *bnc) +{ + node->info = bnc; +} + #endif /* _QUAGGA_BGP_TABLE_H */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index deed8788e..3b762a362 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2528,7 +2528,7 @@ stream_failure: /* for STREAM_GETX */ extern struct zebra_privs_t bgpd_privs; -void bgp_zebra_init(struct thread_master *master) +void bgp_zebra_init(struct thread_master *master, unsigned short instance) { zclient_num_connects = 0; @@ -2567,6 +2567,7 @@ void bgp_zebra_init(struct thread_master *master) zclient->ipset_notify_owner = ipset_notify_owner; zclient->ipset_entry_notify_owner = ipset_entry_notify_owner; zclient->iptable_notify_owner = iptable_notify_owner; + zclient->instance = instance; } void bgp_zebra_destroy(void) diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index c00d9925e..0223c423d 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -23,7 +23,8 @@ #include "vxlan.h" -extern void bgp_zebra_init(struct thread_master *master); +extern void bgp_zebra_init(struct thread_master *master, + unsigned short instance); extern void bgp_zebra_init_tm_connect(struct bgp *bgp); extern uint32_t bgp_zebra_tm_get_id(void); extern bool bgp_zebra_tm_chunk_obtained(void); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 7df8de55f..e4dedc242 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7750,35 +7750,36 @@ static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = { {.completions = NULL}, }; +struct frr_pthread *bgp_pth_io; +struct frr_pthread *bgp_pth_ka; + static void bgp_pthreads_init() { + assert(!bgp_pth_io); + assert(!bgp_pth_ka); + frr_pthread_init(); struct frr_pthread_attr io = { - .id = PTHREAD_IO, .start = frr_pthread_attr_default.start, .stop = frr_pthread_attr_default.stop, }; struct frr_pthread_attr ka = { - .id = PTHREAD_KEEPALIVES, .start = bgp_keepalives_start, .stop = bgp_keepalives_stop, }; - frr_pthread_new(&io, "BGP I/O thread", "bgpd_io"); - frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka"); + bgp_pth_io = frr_pthread_new(&io, "BGP I/O thread", "bgpd_io"); + bgp_pth_ka = frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka"); } void bgp_pthreads_run() { - struct frr_pthread *io = frr_pthread_get(PTHREAD_IO); - struct frr_pthread *ka = frr_pthread_get(PTHREAD_KEEPALIVES); - - frr_pthread_run(io, NULL); - frr_pthread_run(ka, NULL); + frr_pthread_run(bgp_pth_io, NULL); + frr_pthread_run(bgp_pth_ka, NULL); /* Wait until threads are ready. */ - frr_pthread_wait_running(io); - frr_pthread_wait_running(ka); + frr_pthread_wait_running(bgp_pth_io); + frr_pthread_wait_running(bgp_pth_ka); } void bgp_pthreads_finish() @@ -7787,7 +7788,7 @@ void bgp_pthreads_finish() frr_pthread_finish(); } -void bgp_init(void) +void bgp_init(unsigned short instance) { /* allocates some vital data structures used by peer commands in @@ -7797,7 +7798,7 @@ void bgp_init(void) bgp_pthreads_init(); /* Init zebra. */ - bgp_zebra_init(bm->master); + bgp_zebra_init(bm->master, instance); #if ENABLE_BGP_VNC vnc_zebra_init(bm->master); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 0a8962b4c..861435c03 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -24,6 +24,7 @@ #include "qobj.h" #include <pthread.h> +#include "frr_pthread.h" #include "lib/json.h" #include "vrf.h" #include "vty.h" @@ -97,6 +98,9 @@ enum bgp_af_index { for (afi = AFI_IP; afi < AFI_MAX; afi++) \ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +extern struct frr_pthread *bgp_pth_io; +extern struct frr_pthread *bgp_pth_ka; + /* BGP master for system wide configurations and variables. */ struct bgp_master { /* BGP instance list. */ @@ -105,10 +109,6 @@ struct bgp_master { /* BGP thread master. */ struct thread_master *master; -/* BGP pthreads. */ -#define PTHREAD_IO (1 << 1) -#define PTHREAD_KEEPALIVES (1 << 2) - /* work queues */ struct work_queue *process_main_queue; @@ -1518,7 +1518,7 @@ extern int bgp_config_write(struct vty *); extern void bgp_master_init(struct thread_master *master); -extern void bgp_init(void); +extern void bgp_init(unsigned short instance); extern void bgp_pthreads_run(void); extern void bgp_pthreads_finish(void); extern void bgp_route_map_init(void); diff --git a/doc/manpages/bgpd.rst b/doc/manpages/bgpd.rst index 94213db4d..f1736ffd0 100644 --- a/doc/manpages/bgpd.rst +++ b/doc/manpages/bgpd.rst @@ -21,6 +21,13 @@ OPTIONS available for the |DAEMON| command: .. include:: common-options.rst +LABEL MANAGER +------------- + +.. option:: -I, --int_num + + Set zclient id. This is required when using Zebra label manager in proxy mode. + FILES ===== diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 63e04a049..e84313639 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -15,49 +15,91 @@ enterprise networks. .. _configuring-ospfd: -Configuring ospfd -================= +Configuring OSPF +================ -There are no *ospfd* specific options. Common options can be specified -(:ref:`common-invocation-options`) to *ospfd*. *ospfd* needs to acquire -interface information from *zebra* in order to function. Therefore *zebra* must -be running before invoking *ospfd*. Also, if *zebra* is restarted then *ospfd* -must be too. +*ospfd* accepts all :ref:`common-invocation-options`. + +.. option:: -n, --instance + + Specify the instance number for this invocation of *ospfd*. + +.. option:: -a, --apiserver + + Enable the OSPF API server + +*ospfd* must acquire interface information from *zebra* in order to function. +Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is +restarted then *ospfd* must be too. Like other daemons, *ospfd* configuration is done in :abbr:`OSPF` specific -configuration file :file:`ospfd.conf`. +configuration file :file:`ospfd.conf` when the integrated config is not used. + +.. _ospf-multi-instance: + +Multi-instance Support +---------------------- + +OSPF supports multiple instances. Each instance is identified by a positive +nonzero integer that must be provided when adding configuration items specific +to that instance. Enabling instances is done with :file:`/etc/frr/daemons` in +the following manner: + +:: + + ... + ospfd=yes + ospfd_instances=1,5,6 + ... + +The ``ospfd_instances`` variable controls which instances are started and what +their IDs are. In this example, after starting FRR you should see the following +processes: + +.. code-block:: shell + + # ps -ef | grep "ospfd" + frr 11816 1 0 17:30 ? 00:00:00 /usr/lib/frr/ospfd --daemon -A 127.0.0.1 -n 1 + frr 11822 1 0 17:30 ? 00:00:00 /usr/lib/frr/ospfd --daemon -A 127.0.0.1 -n 2 + frr 11828 1 0 17:30 ? 00:00:00 /usr/lib/frr/ospfd --daemon -A 127.0.0.1 -n 3 + + +The instance number should be specified in the config when addressing a particular instance: + +.. code-block:: frr + + router ospf 5 + router-id 1.2.3.4 + area 0.0.0.0 authentication message-digest + ... .. _ospf-router: -OSPF router -=========== +Routers +------- -To start OSPF process you have to specify the OSPF router. As of this -writing, *ospfd* does not support multiple OSPF processes. +To start OSPF process you have to specify the OSPF router. -.. index:: router ospf -.. clicmd:: router ospf +.. index:: router ospf [(1-65535)] vrf NAME +.. clicmd:: router ospf [(1-65535)] vrf NAME -.. index:: no router ospf -.. clicmd:: no router ospf +.. index:: no router ospf [(1-65535)] vrf NAME +.. clicmd:: no router ospf [(1-65535)] vrf NAME - Enable or disable the OSPF process. *ospfd* does not yet - support multiple OSPF processes. So you can not specify an OSPF process - number. + Enable or disable the OSPF process. .. index:: ospf router-id A.B.C.D .. clicmd:: ospf router-id A.B.C.D -.. index:: no ospf router-id -.. clicmd:: no ospf router-id +.. index:: no ospf router-id [A.B.C.D] +.. clicmd:: no ospf router-id [A.B.C.D] - This sets the router-ID of the OSPF process. The - router-ID may be an IP address of the router, but need not be - it can - be any arbitrary 32bit number. However it MUST be unique within the - entire OSPF domain to the OSPF speaker - bad things will happen if - multiple OSPF speakers are configured with the same router-ID! If one - is not specified then *ospfd* will obtain a router-ID - automatically from *zebra*. + This sets the router-ID of the OSPF process. The router-ID may be an IP + address of the router, but need not be - it can be any arbitrary 32bit + number. However it MUST be unique within the entire OSPF domain to the OSPF + speaker - bad things will happen if multiple OSPF speakers are configured + with the same router-ID! If one is not specified then *ospfd* will obtain a + router-ID automatically from *zebra*. .. index:: ospf abr-type TYPE .. clicmd:: ospf abr-type TYPE @@ -271,8 +313,8 @@ writing, *ospfd* does not support multiple OSPF processes. .. _ospf-area: -OSPF area -========= +Areas +----- .. index:: area A.B.C.D range A.B.C.D/M .. clicmd:: area A.B.C.D range A.B.C.D/M @@ -510,8 +552,8 @@ OSPF area .. _ospf-interface: -OSPF interface -============== +Interfaces +---------- .. index:: ip ospf area AREA [ADDR] .. clicmd:: ip ospf area AREA [ADDR] @@ -664,8 +706,8 @@ OSPF interface .. _redistribute-routes-to-ospf: -Redistribute routes to OSPF -=========================== +Redistribution +-------------- .. index:: redistribute (kernel|connected|static|rip|bgp) .. clicmd:: redistribute (kernel|connected|static|rip|bgp) @@ -785,8 +827,8 @@ Redistribute routes to OSPF .. _showing-ospf-information: -Showing OSPF information -======================== +Showing Information +=================== .. _show-ip-ospf: diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 8cfe480ef..b2c6f092e 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -1905,7 +1905,7 @@ int lsp_tick(struct thread *thread) dnode); } - if (fabricd_init_c) { + if (fabricd_init_c && lsp) { fabricd_sync_incomplete |= ISIS_CHECK_FLAG(lsp->SSNflags, fabricd_init_c); diff --git a/ldpd/lde.c b/ldpd/lde.c index 810439888..4f74d9304 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1641,7 +1641,7 @@ static void zclient_sync_init(unsigned short instance) sock_set_nonblock(zclient_sync->sock); /* Connect to label manager */ - while (lm_label_manager_connect(zclient_sync) != 0) { + while (lm_label_manager_connect(zclient_sync, 0) != 0) { log_warnx("Error connecting to label manager!"); sleep(1); } diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index d48b23f38..c1ce57e24 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -26,108 +26,77 @@ #include "frr_pthread.h" #include "memory.h" -#include "hash.h" +#include "linklist.h" DEFINE_MTYPE(LIB, FRR_PTHREAD, "FRR POSIX Thread"); DEFINE_MTYPE(LIB, PTHREAD_PRIM, "POSIX synchronization primitives"); -/* id for next created pthread */ -static _Atomic uint32_t next_id = 0; - /* default frr_pthread start/stop routine prototypes */ static void *fpt_run(void *arg); static int fpt_halt(struct frr_pthread *fpt, void **res); /* default frr_pthread attributes */ struct frr_pthread_attr frr_pthread_attr_default = { - .id = 0, .start = fpt_run, .stop = fpt_halt, }; -/* hash table to keep track of all frr_pthreads */ -static struct hash *frr_pthread_hash; -static pthread_mutex_t frr_pthread_hash_mtx = PTHREAD_MUTEX_INITIALIZER; - -/* frr_pthread_hash->hash_cmp */ -static int frr_pthread_hash_cmp(const void *value1, const void *value2) -{ - const struct frr_pthread *tq1 = value1; - const struct frr_pthread *tq2 = value2; - - return (tq1->attr.id == tq2->attr.id); -} - -/* frr_pthread_hash->hash_key */ -static unsigned int frr_pthread_hash_key(void *value) -{ - return ((struct frr_pthread *)value)->attr.id; -} +/* list to keep track of all frr_pthreads */ +static pthread_mutex_t frr_pthread_list_mtx = PTHREAD_MUTEX_INITIALIZER; +static struct list *frr_pthread_list; /* ------------------------------------------------------------------------ */ void frr_pthread_init() { - pthread_mutex_lock(&frr_pthread_hash_mtx); + pthread_mutex_lock(&frr_pthread_list_mtx); { - frr_pthread_hash = hash_create(frr_pthread_hash_key, - frr_pthread_hash_cmp, NULL); + frr_pthread_list = list_new(); + frr_pthread_list->del = (void (*)(void *))&frr_pthread_destroy; } - pthread_mutex_unlock(&frr_pthread_hash_mtx); + pthread_mutex_unlock(&frr_pthread_list_mtx); } void frr_pthread_finish() { - pthread_mutex_lock(&frr_pthread_hash_mtx); + pthread_mutex_lock(&frr_pthread_list_mtx); { - hash_clean(frr_pthread_hash, - (void (*)(void *))frr_pthread_destroy); - hash_free(frr_pthread_hash); + list_delete_and_null(&frr_pthread_list); } - pthread_mutex_unlock(&frr_pthread_hash_mtx); + pthread_mutex_unlock(&frr_pthread_list_mtx); } struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr, const char *name, const char *os_name) { - static struct frr_pthread holder = {}; struct frr_pthread *fpt = NULL; attr = attr ? attr : &frr_pthread_attr_default; - pthread_mutex_lock(&frr_pthread_hash_mtx); + fpt = XCALLOC(MTYPE_FRR_PTHREAD, sizeof(struct frr_pthread)); + /* initialize mutex */ + pthread_mutex_init(&fpt->mtx, NULL); + /* create new thread master */ + fpt->master = thread_master_create(name); + /* set attributes */ + fpt->attr = *attr; + name = (name ? name : "Anonymous thread"); + fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); + if (os_name) + snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name); + /* initialize startup synchronization primitives */ + fpt->running_cond_mtx = XCALLOC( + MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t)); + fpt->running_cond = XCALLOC(MTYPE_PTHREAD_PRIM, + sizeof(pthread_cond_t)); + pthread_mutex_init(fpt->running_cond_mtx, NULL); + pthread_cond_init(fpt->running_cond, NULL); + + pthread_mutex_lock(&frr_pthread_list_mtx); { - holder.attr.id = attr->id; - - if (!hash_lookup(frr_pthread_hash, &holder)) { - fpt = XCALLOC(MTYPE_FRR_PTHREAD, - sizeof(struct frr_pthread)); - /* initialize mutex */ - pthread_mutex_init(&fpt->mtx, NULL); - /* create new thread master */ - fpt->master = thread_master_create(name); - /* set attributes */ - fpt->attr = *attr; - name = (name ? name : "Anonymous thread"); - fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); - if (os_name) - snprintf(fpt->os_name, OS_THREAD_NAMELEN, - "%s", os_name); - if (attr == &frr_pthread_attr_default) - fpt->attr.id = frr_pthread_get_id(); - /* initialize startup synchronization primitives */ - fpt->running_cond_mtx = XCALLOC( - MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t)); - fpt->running_cond = XCALLOC(MTYPE_PTHREAD_PRIM, - sizeof(pthread_cond_t)); - pthread_mutex_init(fpt->running_cond_mtx, NULL); - pthread_cond_init(fpt->running_cond, NULL); - - /* insert into global thread hash */ - hash_get(frr_pthread_hash, fpt, hash_alloc_intern); - } + listnode_add(frr_pthread_list, fpt); } - pthread_mutex_unlock(&frr_pthread_hash_mtx); + pthread_mutex_unlock(&frr_pthread_list_mtx); return fpt; } @@ -180,21 +149,6 @@ int frr_pthread_set_name(struct frr_pthread *fpt, const char *name, return ret; } -struct frr_pthread *frr_pthread_get(uint32_t id) -{ - static struct frr_pthread holder = {}; - struct frr_pthread *fpt; - - pthread_mutex_lock(&frr_pthread_hash_mtx); - { - holder.attr.id = id; - fpt = hash_lookup(frr_pthread_hash, &holder); - } - pthread_mutex_unlock(&frr_pthread_hash_mtx); - - return fpt; -} - int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr) { int ret; @@ -239,36 +193,16 @@ int frr_pthread_stop(struct frr_pthread *fpt, void **result) return ret; } -/* - * Callback for hash_iterate to stop all frr_pthread's. - */ -static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg) -{ - struct frr_pthread *fpt = hb->data; - frr_pthread_stop(fpt, NULL); -} - void frr_pthread_stop_all() { - pthread_mutex_lock(&frr_pthread_hash_mtx); + pthread_mutex_lock(&frr_pthread_list_mtx); { - hash_iterate(frr_pthread_hash, frr_pthread_stop_all_iter, NULL); + struct listnode *n; + struct frr_pthread *fpt; + for (ALL_LIST_ELEMENTS_RO(frr_pthread_list, n, fpt)) + frr_pthread_stop(fpt, NULL); } - pthread_mutex_unlock(&frr_pthread_hash_mtx); -} - -uint32_t frr_pthread_get_id(void) -{ - _Atomic uint32_t nxid; - nxid = atomic_fetch_add_explicit(&next_id, 1, memory_order_seq_cst); - /* just a sanity check, this should never happen */ - assert(nxid <= (UINT32_MAX - 1)); - return nxid; -} - -void frr_pthread_yield(void) -{ - (void)sched_yield(); + pthread_mutex_unlock(&frr_pthread_list_mtx); } /* diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index 732e2925f..b9e60511d 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -34,7 +34,6 @@ struct frr_pthread; struct frr_pthread_attr; struct frr_pthread_attr { - _Atomic uint32_t id; void *(*start)(void *); int (*stop)(struct frr_pthread *, void **); }; @@ -155,13 +154,6 @@ int frr_pthread_set_name(struct frr_pthread *fpt, const char *name, void frr_pthread_destroy(struct frr_pthread *fpt); /* - * Gets an existing frr_pthread by its id. - * - * @return frr_thread associated with the provided id, or NULL on error - */ -struct frr_pthread *frr_pthread_get(uint32_t id); - -/* * Creates a new pthread and binds it to a frr_pthread. * * This function is a wrapper for pthread_create. The first parameter is the @@ -218,22 +210,6 @@ int frr_pthread_stop(struct frr_pthread *fpt, void **result); /* Stops all frr_pthread's. */ void frr_pthread_stop_all(void); -/* Yields the current thread of execution */ -void frr_pthread_yield(void); - -/* - * Returns a unique identifier for use with frr_pthread_new(). - * - * Internally, this is an integer that increments after each call to this - * function. Because the number of pthreads created should never exceed INT_MAX - * during the life of the program, there is no overflow protection. If by - * chance this function returns an ID which is already in use, - * frr_pthread_new() will fail when it is provided. - * - * @return unique identifier - */ -uint32_t frr_pthread_get_id(void); - #ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK #define pthread_condattr_setclock(A, B) #endif @@ -656,7 +656,8 @@ DEFUN_NOSH (interface, int idx_ifname = 1; int idx_vrf = 3; const char *ifname = argv[idx_ifname]->arg; - const char *vrfname = (argc > 2) ? argv[idx_vrf]->arg : NULL; + const char *vrfname = + (argc > 2) ? argv[idx_vrf]->arg : VRF_DEFAULT_NAME; struct interface *ifp; vrf_id_t vrf_id = VRF_DEFAULT; @@ -681,7 +682,8 @@ DEFUN_NOSH (interface, #endif /* SUNOS_5 */ if (!ifp) { - vty_out(vty, "%% interface %s not in %s\n", ifname, vrfname); + vty_out(vty, "%% interface %s not in %s vrf\n", ifname, + vrfname); return CMD_WARNING_CONFIG_FAILED; } VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp); @@ -945,6 +945,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE), DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS), DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT), + DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC), DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK), DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK), DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI), @@ -201,7 +201,7 @@ extern int vrf_bitmap_check(vrf_bitmap_t, vrf_id_t); */ extern void vrf_init(int (*create)(struct vrf *vrf), int (*enable)(struct vrf *vrf), int (*disable)(struct vrf *vrf), int (*delete)(struct vrf *vrf), - int ((*update)(struct vrf *vrf))); + int (*update)(struct vrf *vrf)); /* * Call vrf_terminate when the protocol is being shutdown diff --git a/lib/zclient.c b/lib/zclient.c index 1cdf4ff22..e6626a178 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1839,24 +1839,29 @@ static int zclient_read_sync_response(struct zclient *zclient, * immediately reads the answer from the input buffer. * * @param zclient Zclient used to connect to label manager (zebra) + * @param async Synchronous (0) or asynchronous (1) operation * @result Result of response */ -int lm_label_manager_connect(struct zclient *zclient) +int lm_label_manager_connect(struct zclient *zclient, int async) { int ret; struct stream *s; uint8_t result; + uint16_t cmd = async ? ZEBRA_LABEL_MANAGER_CONNECT_ASYNC : + ZEBRA_LABEL_MANAGER_CONNECT; if (zclient_debug) zlog_debug("Connecting to Label Manager (LM)"); - if (zclient->sock < 0) + if (zclient->sock < 0) { + zlog_debug("%s: invalid zclient socket", __func__); return -1; + } /* send request */ s = zclient->obuf; stream_reset(s); - zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, VRF_DEFAULT); + zclient_create_header(s, cmd, VRF_DEFAULT); /* proto */ stream_putc(s, zclient->redist_default); @@ -1882,8 +1887,11 @@ int lm_label_manager_connect(struct zclient *zclient) if (zclient_debug) zlog_debug("LM connect request sent (%d bytes)", ret); + if (async) + return 0; + /* read response */ - if (zclient_read_sync_response(zclient, ZEBRA_LABEL_MANAGER_CONNECT) + if (zclient_read_sync_response(zclient, cmd) != 0) return -1; diff --git a/lib/zclient.h b/lib/zclient.h index cab734ae5..54f363590 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -112,6 +112,7 @@ typedef enum { ZEBRA_MPLS_LABELS_DELETE, ZEBRA_IPMR_ROUTE_STATS, ZEBRA_LABEL_MANAGER_CONNECT, + ZEBRA_LABEL_MANAGER_CONNECT_ASYNC, ZEBRA_GET_LABEL_CHUNK, ZEBRA_RELEASE_LABEL_CHUNK, ZEBRA_FEC_REGISTER, @@ -572,7 +573,7 @@ extern int zclient_send_get_label_chunk( uint8_t keep, uint32_t chunk_size); -extern int lm_label_manager_connect(struct zclient *zclient); +extern int lm_label_manager_connect(struct zclient *zclient, int async); extern int lm_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t chunk_size, uint32_t *start, uint32_t *end); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index aa877903f..e25d1a31d 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -8201,6 +8201,8 @@ DEFUN (no_ospf_redistribute_source, return CMD_SUCCESS; ospf_routemap_unset(red); + ospf_redist_del(ospf, source, 0); + return ospf_redistribute_unset(ospf, source, 0); } @@ -8315,6 +8317,8 @@ DEFUN (no_ospf_redistribute_instance_source, return CMD_SUCCESS; ospf_routemap_unset(red); + ospf_redist_del(ospf, source, instance); + return ospf_redistribute_unset(ospf, source, instance); } @@ -8447,6 +8451,8 @@ DEFUN (no_ospf_default_information_originate, return CMD_SUCCESS; ospf_routemap_unset(red); + ospf_redist_del(ospf, DEFAULT_ROUTE, 0); + return ospf_redistribute_default_unset(ospf); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 912142b78..8a7f38b74 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -740,8 +740,6 @@ int ospf_redistribute_unset(struct ospf *ospf, int type, zlog_debug("Redistribute[%s][%d] vrf id %u: Stop", ospf_redist_string(type), instance, ospf->vrf_id); - ospf_redist_del(ospf, type, instance); - /* Remove the routes from OSPF table. */ ospf_redistribute_withdraw(ospf, type, instance); @@ -755,30 +753,17 @@ int ospf_redistribute_unset(struct ospf *ospf, int type, int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, int mvalue) { - struct ospf_redist *red; - ospf->default_originate = originate; - red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); - red->dmetric.type = mtype; - red->dmetric.value = mvalue; - ospf_external_add(ospf, DEFAULT_ROUTE, 0); - if (ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) { - /* if ospf->default_originate changes value, is calling - ospf_external_lsa_refresh_default sufficient to implement - the change? */ - ospf_external_lsa_refresh_default(ospf); - + if (ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug( "Redistribute[%s]: Refresh Type[%d], Metric[%d]", ospf_redist_string(DEFAULT_ROUTE), metric_type(ospf, DEFAULT_ROUTE, 0), metric_value(ospf, DEFAULT_ROUTE, 0)); - return CMD_SUCCESS; - } zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, ospf->vrf_id); @@ -788,6 +773,8 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, metric_type(ospf, DEFAULT_ROUTE, 0), metric_value(ospf, DEFAULT_ROUTE, 0)); + ospf_external_lsa_refresh_default(ospf); + if (ospf->router_id.s_addr == 0) ospf->external_origin |= (1 << DEFAULT_ROUTE); else @@ -805,7 +792,6 @@ int ospf_redistribute_default_unset(struct ospf *ospf) return CMD_SUCCESS; ospf->default_originate = DEFAULT_ORIGINATE_NONE; - ospf_redist_del(ospf, DEFAULT_ROUTE, 0); zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, ospf->vrf_id); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 1f3336811..26932eea2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1187,8 +1187,9 @@ static void pim_show_interfaces_single(struct pim_instance *pim, vty_out(vty, "Designated Router\n"); vty_out(vty, "-----------------\n"); vty_out(vty, "Address : %s\n", dr_str); - vty_out(vty, "Priority : %d\n", - pim_ifp->pim_dr_priority); + vty_out(vty, "Priority : %d(%d)\n", + pim_ifp->pim_dr_priority, + pim_ifp->pim_dr_num_nondrpri_neighbors); vty_out(vty, "Uptime : %s\n", dr_uptime); vty_out(vty, "Elections : %d\n", pim_ifp->pim_dr_election_count); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index c69e2939e..436e0508f 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -154,12 +154,12 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, * the Interface type is SSM we don't need to * do anything here */ - if (!rpg || (pim_rpf_addr_is_inaddr_none(rpg)) - || (!(PIM_I_am_DR(pim_ifp)))) { + if (!rpg || pim_rpf_addr_is_inaddr_none(rpg)) { if (PIM_DEBUG_MROUTE_DETAIL) zlog_debug( - "%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", + "%s: Interface is not configured correctly to handle incoming packet: Could be !pim_ifp, !SM, !RP", __PRETTY_FUNCTION__); + return 0; } @@ -179,6 +179,26 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, sg.src = msg->im_src; sg.grp = msg->im_dst; + if (!(PIM_I_am_DR(pim_ifp))) { + struct channel_oil *c_oil; + + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug("%s: Interface is not the DR blackholing incoming traffic for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + + /* + * We are not the DR, but we are still receiving packets + * Let's blackhole those packets for the moment + * As that they will be coming up to the cpu + * and causing us to consider them. + */ + c_oil = pim_channel_oil_add(pim_ifp->pim, &sg, + pim_ifp->mroute_vif_index); + pim_mroute_add(c_oil, __PRETTY_FUNCTION__); + + return 0; + } + up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); if (!up) { diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 4fa4ea857..4ff9bd6bd 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -1044,9 +1044,14 @@ void igmp_source_forward_start(struct pim_instance *pim, return; } - if (!(PIM_I_am_DR(pim_oif))) + if (!(PIM_I_am_DR(pim_oif))) { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug("%s: %s was received on %s interface but we are not DR for that interface", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg), + group->group_igmp_sock->interface->name); return; - + } /* Feed IGMPv3-gathered local membership information into PIM per-interface (S,G) state. diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index 247591580..d2d960f27 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -1273,9 +1273,6 @@ static int handle_attr_test(struct aspath_tests *t) struct aspath *asp; size_t datalen; - bgp_pthreads_init(); - frr_pthread_get(PTHREAD_KEEPALIVES)->running = true; - asp = make_aspath(t->segment->asdata, t->segment->len, 0); peer.curr = stream_new(BGP_MAX_PACKET_SIZE); @@ -1382,6 +1379,9 @@ int main(void) i = 0; + bgp_pthreads_init(); + bgp_pth_ka->running = true; + while (aspath_tests[i].desc) { printf("aspath_attr test %d\n", i); attr_test(&aspath_tests[i++]); diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index 83af5e9c6..968f9ac44 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -917,7 +917,7 @@ int main(void) bgp_option_set(BGP_OPT_NO_LISTEN); bgp_pthreads_init(); - frr_pthread_get(PTHREAD_KEEPALIVES)->running = true; + bgp_pth_ka->running = true; if (fileno(stdout) >= 0) tty = isatty(fileno(stdout)); diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index 452245ec1..e40fba245 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -1388,7 +1388,7 @@ static void bgp_startup(void) bgp_master_init(master); bgp_option_set(BGP_OPT_NO_LISTEN); vrf_init(NULL, NULL, NULL, NULL, NULL); - bgp_init(); + bgp_init(0); bgp_pthreads_run(); } diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c index 652d7618a..9d1c05436 100644 --- a/tests/test_lblmgr.c +++ b/tests/test_lblmgr.c @@ -59,7 +59,7 @@ static int zebra_send_label_manager_connect() printf("Connect to Label Manager\n"); - ret = lm_label_manager_connect(zclient); + ret = lm_label_manager_connect(zclient, 0); printf("Label Manager connection result: %u \n", ret); if (ret != 0) { fprintf(stderr, "Error %d connecting to Label Manager %s\n", diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index 55b3e1e56..3b861e4f8 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -359,6 +359,7 @@ our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeIni # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check our $Attribute = qr{ const| + _Atomic| __percpu| __nocast| __safe| diff --git a/tools/permutations.c b/tools/permutations.c index c5109dc3e..f51d4a4ec 100644 --- a/tools/permutations.c +++ b/tools/permutations.c @@ -39,7 +39,8 @@ int main(int argc, char *argv[]) fprintf(stdout, USAGE "\n"); exit(EXIT_SUCCESS); } - struct cmd_element *cmd = calloc(1, sizeof(struct cmd_element)); + struct cmd_element *cmd = XCALLOC(MTYPE_TMP, + sizeof(struct cmd_element)); cmd->string = strdup(argv[1]); struct graph *graph = graph_new(); diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c index cc0315c13..8daeda740 100644 --- a/tools/start-stop-daemon.c +++ b/tools/start-stop-daemon.c @@ -1030,7 +1030,9 @@ int main(int argc, char **argv) /* change tty */ fd = open("/dev/tty", O_RDWR); if (fd >= 0) { - ioctl(fd, TIOCNOTTY, 0); + if (ioctl(fd, TIOCNOTTY, 0) < 0) + printf("ioctl TIOCNOTTY failed: %s\n", + strerror(errno)); close(fd); } chdir("/"); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 47a101e61..bf5d83427 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -585,6 +585,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; ifindex_t bridge_ifindex = IFINDEX_INTERNAL; ifindex_t link_ifindex = IFINDEX_INTERNAL; + struct zebra_if *zif; zns = zebra_ns_lookup(ns_id); ifi = NLMSG_DATA(h); @@ -679,8 +680,14 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (IS_ZEBRA_IF_VRF(ifp)) SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - /* Update link. */ - zebra_if_update_link(ifp, link_ifindex, ns_id); + /* + * Just set the @link/lower-device ifindex. During nldump interfaces are + * not ordered in any fashion so we may end up getting upper devices + * before lower devices. We will setup the real linkage once the dump + * is complete. + */ + zif = (struct zebra_if *)ifp->info; + zif->link_ifindex = link_ifindex; /* Hardware type and address. */ ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type); @@ -754,6 +761,9 @@ int interface_lookup_netlink(struct zebra_ns *zns) if (ret < 0) return ret; + /* fixup linkages */ + zebra_if_update_all_links(); + /* Get IPv4 address of the interfaces. */ ret = netlink_request_intf_addr(zns, AF_INET, RTM_GETADDR, 0); if (ret < 0) diff --git a/zebra/interface.c b/zebra/interface.c index 95a8bd870..96b244635 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1032,6 +1032,39 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, link_ifindex); } +/* + * during initial link dump kernel does not order lower devices before + * upper devices so we need to fixup link dependencies at the end of dump + */ +void zebra_if_update_all_links(void) +{ + struct route_node *rn; + struct interface *ifp; + struct zebra_if *zif; + struct zebra_ns *ns; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_info("fixup link dependencies"); + + ns = zebra_ns_lookup(NS_DEFAULT); + for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) { + ifp = (struct interface *)rn->info; + if (!ifp) + continue; + zif = ifp->info; + if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) { + zif->link = if_lookup_by_index_per_ns(ns, + zif->link_ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface %s/%d's lower fixup to %s/%d", + ifp->name, ifp->ifindex, + zif->link?zif->link->name:"unk", + zif->link_ifindex); + } + } +} + + /* Output prefix string to vty. */ static int prefix_vty_out(struct vty *vty, struct prefix *p) diff --git a/zebra/interface.h b/zebra/interface.h index b632d25c2..e4c05e8dc 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -353,6 +353,7 @@ extern int ipv6_address_configured(struct interface *ifp); extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id); extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex, ns_id_t ns_id); +extern void zebra_if_update_all_links(void); extern void vrf_add_update(struct vrf *vrfp); diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 378a8ade4..2b0508099 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -88,7 +88,23 @@ static int relay_response_back(void) strerror(errno)); return -1; } - zlog_debug("Label Manager response received, %d bytes", size); + + /* do not relay a msg that has nothing to do with LM */ + switch (resp_cmd) { + case ZEBRA_LABEL_MANAGER_CONNECT: + case ZEBRA_LABEL_MANAGER_CONNECT_ASYNC: /* should not be seen */ + case ZEBRA_GET_LABEL_CHUNK: + case ZEBRA_RELEASE_LABEL_CHUNK: + break; + default: + zlog_debug("Not relaying '%s' response (size %d) from LM", + zserv_command_string(resp_cmd), size); + return -1; + } + + zlog_debug("Received '%s' response (size %d) from LM", + zserv_command_string(resp_cmd), size); + if (size == 0) return -1; @@ -139,6 +155,11 @@ static int lm_zclient_read(struct thread *t) /* read response and send it back */ ret = relay_response_back(); + /* on error, schedule another read */ + if (ret == -1) + if (!zclient->t_read) + thread_add_read(zclient->master, lm_zclient_read, NULL, + zclient->sock, &zclient->t_read); return ret; } @@ -228,8 +249,9 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv, zserv->proto = proto; /* in case there's any incoming message enqueued, read and forward it */ - while (ret == 0) - ret = relay_response_back(); + if (zserv->is_synchronous) + while (ret == 0) + ret = relay_response_back(); /* get the msg buffer used toward the 'master' Label Manager */ dst = zclient->obuf; diff --git a/zebra/rt.h b/zebra/rt.h index e40bae3a3..95b48a9a5 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -116,10 +116,9 @@ 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, - uint8_t sticky); + bool sticky); extern int kernel_del_mac(struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - int local); + 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); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index b600a7db5..9e02193df 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1959,7 +1959,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) char buf[ETHER_ADDR_STRLEN]; char vid_buf[20]; char dst_buf[30]; - uint8_t sticky = 0; + bool sticky; ndm = NLMSG_DATA(h); @@ -2030,7 +2030,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4)); } - sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0; + sticky = !!(ndm->ndm_state & NUD_NOARP); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s", @@ -2178,7 +2178,7 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, struct in_addr vtep_ip, - int local, int cmd, uint8_t sticky) + int cmd, bool sticky) { struct zebra_ns *zns; struct { @@ -2223,12 +2223,10 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); req.ndm.ndm_ifindex = ifp->ifindex; - if (!local) { - dst_alen = 4; // TODO: hardcoded - addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen); - dst_present = 1; - sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip)); - } + dst_alen = 4; // TODO: hardcoded + addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen); + dst_present = 1; + 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); @@ -2266,8 +2264,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; int mac_present = 0; - uint8_t ext_learned; - uint8_t router_flag; + bool is_ext; + bool is_router; ndm = NLMSG_DATA(h); @@ -2357,8 +2355,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETH_ALEN); } - ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; - router_flag = (ndm->ndm_flags & NTF_ROUTER) ? 1 : 0; + is_ext = !!(ndm->ndm_flags & NTF_EXT_LEARNED); + is_router = !!(ndm->ndm_flags & NTF_ROUTER); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( @@ -2381,7 +2379,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) if (ndm->ndm_state & NUD_VALID) return zebra_vxlan_handle_kernel_neigh_update( ifp, link_if, &ip, &mac, ndm->ndm_state, - ext_learned, router_flag); + is_ext, is_router); return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip); } @@ -2563,17 +2561,16 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, } int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, - struct in_addr vtep_ip, uint8_t sticky) + struct in_addr vtep_ip, bool sticky) { - return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, + 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, int local) + struct in_addr vtep_ip) { - return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local, - RTM_DELNEIGH, 0); + return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_DELNEIGH, 0); } int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index a6de84d56..e733b4b26 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -453,13 +453,13 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) } int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, - struct in_addr vtep_ip, uint8_t sticky) + 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, int local) + struct in_addr vtep_ip) { return 0; } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 55c5b934f..b9897bea0 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1829,7 +1829,8 @@ static void zread_label_manager_connect(struct zserv *client, flog_err(EC_ZEBRA_TM_WRONG_PROTO, "client %d has wrong protocol %s", client->sock, zebra_route_string(proto)); - zsend_label_manager_connect_response(client, vrf_id, 1); + if (client->is_synchronous) + zsend_label_manager_connect_response(client, vrf_id, 1); return; } zlog_notice("client %d with vrf %u instance %u connected as %s", @@ -1847,33 +1848,12 @@ static void zread_label_manager_connect(struct zserv *client, " Label Manager client connected: sock %d, proto %s, vrf %u instance %u", client->sock, zebra_route_string(proto), vrf_id, instance); /* send response back */ - zsend_label_manager_connect_response(client, vrf_id, 0); + if (client->is_synchronous) + zsend_label_manager_connect_response(client, vrf_id, 0); stream_failure: return; } -static int msg_client_id_mismatch(const char *op, struct zserv *client, - uint8_t proto, unsigned int instance) -{ - if (proto != client->proto) { - flog_err(EC_ZEBRA_PROTO_OR_INSTANCE_MISMATCH, - "%s: msg vs client proto mismatch, client=%u msg=%u", - op, client->proto, proto); - /* TODO: fail when BGP sets proto and instance */ - /* return 1; */ - } - - if (instance != client->instance) { - flog_err( - EC_ZEBRA_PROTO_OR_INSTANCE_MISMATCH, - "%s: msg vs client instance mismatch, client=%u msg=%u", - op, client->instance, instance); - /* TODO: fail when BGP sets proto and instance */ - /* return 1; */ - } - - return 0; -} static void zread_get_label_chunk(struct zserv *client, struct stream *msg, vrf_id_t vrf_id) @@ -1894,21 +1874,16 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg, STREAM_GETC(s, keep); STREAM_GETL(s, size); - /* detect client vs message (proto,instance) mismatch */ - if (msg_client_id_mismatch("Get-label-chunk", client, proto, instance)) - return; - - lmc = assign_label_chunk(client->proto, client->instance, keep, size); + lmc = assign_label_chunk(proto, instance, keep, size); if (!lmc) flog_err( EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK, "Unable to assign Label Chunk of size %u to %s instance %u", - size, zebra_route_string(client->proto), - client->instance); + size, zebra_route_string(proto), instance); else zlog_debug("Assigned Label Chunk %u - %u to %s instance %u", lmc->start, lmc->end, - zebra_route_string(client->proto), client->instance); + zebra_route_string(proto), instance); /* send response back */ zsend_assign_label_chunk_response(client, vrf_id, lmc); @@ -1932,12 +1907,7 @@ static void zread_release_label_chunk(struct zserv *client, struct stream *msg) STREAM_GETL(s, start); STREAM_GETL(s, end); - /* detect client vs message (proto,instance) mismatch */ - if (msg_client_id_mismatch("Release-label-chunk", client, proto, - instance)) - return; - - release_label_chunk(client->proto, client->instance, start, end); + release_label_chunk(proto, instance, start, end); stream_failure: return; @@ -1945,8 +1915,8 @@ stream_failure: static void zread_label_manager_request(ZAPI_HANDLER_ARGS) { /* to avoid sending other messages like ZERBA_INTERFACE_UP */ - if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT) - client->is_synchronous = 1; + client->is_synchronous = hdr->command == + ZEBRA_LABEL_MANAGER_CONNECT; /* external label manager */ if (lm_is_external) @@ -1954,16 +1924,10 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS) zvrf_id(zvrf)); /* this is a label manager */ else { - if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT) + if (hdr->command == ZEBRA_LABEL_MANAGER_CONNECT || + hdr->command == ZEBRA_LABEL_MANAGER_CONNECT_ASYNC) zread_label_manager_connect(client, msg, zvrf_id(zvrf)); else { - /* Sanity: don't allow 'unidentified' requests */ - if (!client->proto) { - flog_err( - EC_ZEBRA_LM_ALIENS, - "Got label request from an unidentified client"); - return; - } if (hdr->command == ZEBRA_GET_LABEL_CHUNK) zread_get_label_chunk(client, msg, zvrf_id(zvrf)); @@ -2448,6 +2412,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels, [ZEBRA_IPMR_ROUTE_STATS] = zebra_ipmr_route_stats, [ZEBRA_LABEL_MANAGER_CONNECT] = zread_label_manager_request, + [ZEBRA_LABEL_MANAGER_CONNECT_ASYNC] = zread_label_manager_request, [ZEBRA_GET_LABEL_CHUNK] = zread_label_manager_request, [ZEBRA_RELEASE_LABEL_CHUNK] = zread_label_manager_request, [ZEBRA_FEC_REGISTER] = zread_fec_register, diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 0db33d1f8..12c712e4c 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -187,7 +187,6 @@ extern enum dp_req_result kernel_del_pbr_rule(struct zebra_pbr_rule *rule); */ extern void kernel_read_pbr_rules(struct zebra_ns *zns); -enum dp_results; /* * Handle success or failure of rule (un)install in the kernel. */ diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 469aceafb..ea0bef371 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -153,7 +153,7 @@ static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr, static zebra_vni_t *zvni_map_vlan(struct interface *ifp, struct interface *br_if, vlanid_t vid); static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac); -static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local); +static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac); static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt); static unsigned int vni_hash_keymake(void *p); @@ -180,8 +180,8 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni, struct ipaddr *ip); struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp); static int advertise_gw_macip_enabled(zebra_vni_t *zvni); -static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac, - int uninstall); +static int remote_neigh_count(zebra_mac_t *zmac); +static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac); /* Private functions */ static int host_rb_entry_compare(const struct host_rb_entry *hle1, @@ -1876,7 +1876,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni, /* see if the mac needs to be deleted as well*/ if (mac) - zvni_deref_ip2mac(zvni, mac, 0); + zvni_deref_ip2mac(zvni, mac); return 0; } @@ -1963,7 +1963,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, struct interface *ifp, struct ipaddr *ip, struct ethaddr *macaddr, - uint8_t router_flag) + bool is_router) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -2028,51 +2028,60 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, check_rbit = true; } else { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - /* If there is no MAC change, BGP isn't interested. */ - if (router_flag != - (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) - ? 1 : 0)) - check_rbit = true; - - if (memcmp(n->emac.octet, macaddr->octet, - ETH_ALEN) == 0) { - /* Update any params and return - client doesn't - * care about a purely local change. - */ + bool mac_different; + bool cur_is_router; + + /* Note any changes and see if of interest to BGP. */ + mac_different = (memcmp(n->emac.octet, + macaddr->octet, ETH_ALEN) != 0) ? 1 : 0; + cur_is_router = !!CHECK_FLAG(n->flags, + ZEBRA_NEIGH_ROUTER_FLAG); + if (!mac_different && is_router == cur_is_router) { n->ifindex = ifp->ifindex; - } else { + return 0; + } - /* If the MAC has changed, need to issue a - * delete first as this means a different - * MACIP route. Also, need to do some - * unlinking/relinking. We also need to - * update the MAC's sequence number - * in different situations. - */ - if (IS_ZEBRA_NEIGH_ACTIVE(n)) - zvni_neigh_send_del_to_client( - zvni->vni, &n->ip, &n->emac, 0); - old_zmac = zvni_mac_lookup(zvni, &n->emac); - if (old_zmac) { - old_mac_seq = - CHECK_FLAG(old_zmac->flags, - ZEBRA_MAC_REMOTE) ? - old_zmac->rem_seq : - old_zmac->loc_seq; - neigh_mac_change = upd_mac_seq = true; - listnode_delete( - old_zmac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_zmac, 0); - } + if (!mac_different) { + /* Only the router flag has changed. */ + if (is_router) + SET_FLAG(n->flags, + ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, + ZEBRA_NEIGH_ROUTER_FLAG); - /* Update the forwarding info. */ - n->ifindex = ifp->ifindex; - memcpy(&n->emac, macaddr, ETH_ALEN); + if (IS_ZEBRA_NEIGH_ACTIVE(n)) + return zvni_neigh_send_add_to_client( + zvni->vni, ip, macaddr, + n->flags, n->loc_seq); + return 0; + } - /* Link to new MAC */ - listnode_add_sort(zmac->neigh_list, n); + /* The MAC has changed, need to issue a delete + * first as this means a different MACIP route. + * Also, need to do some unlinking/relinking. + * We also need to update the MAC's sequence number + * in different situations. + */ + if (IS_ZEBRA_NEIGH_ACTIVE(n)) + zvni_neigh_send_del_to_client(zvni->vni, &n->ip, + &n->emac, 0); + old_zmac = zvni_mac_lookup(zvni, &n->emac); + if (old_zmac) { + old_mac_seq = CHECK_FLAG(old_zmac->flags, + ZEBRA_MAC_REMOTE) ? + old_zmac->rem_seq : old_zmac->loc_seq; + neigh_mac_change = upd_mac_seq = true; + listnode_delete(old_zmac->neigh_list, n); + zvni_deref_ip2mac(zvni, old_zmac); } + /* Update the forwarding info. */ + n->ifindex = ifp->ifindex; + memcpy(&n->emac, macaddr, ETH_ALEN); + + /* Link to new MAC */ + listnode_add_sort(zmac->neigh_list, n); } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { /* * Neighbor has moved from remote to local. Its @@ -2090,7 +2099,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, neigh_mac_change = upd_mac_seq = true; listnode_delete(old_zmac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_zmac, 0); + zvni_deref_ip2mac(zvni, old_zmac); } /* Link to new MAC */ @@ -2121,7 +2130,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, } /*Mark Router flag (R-bit) */ - if (router_flag) + if (is_router) SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); else UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); @@ -2309,7 +2318,7 @@ static void zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg) } if (wctx->uninstall) - zvni_mac_uninstall(wctx->zvni, mac, 0); + zvni_mac_uninstall(wctx->zvni, mac); zvni_mac_del(wctx->zvni, mac); } @@ -2593,7 +2602,7 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) { struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; - uint8_t sticky; + bool sticky; if (!(mac->flags & ZEBRA_MAC_REMOTE)) return 0; @@ -2603,26 +2612,24 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) return -1; vxl = &zif->l2info.vxl; - sticky = CHECK_FLAG(mac->flags, - (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)) ? 1 : 0; + 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); } /* - * Uninstall remote MAC from the kernel. In the scenario where the MAC - * moves to remote, we have to uninstall any existing local entry first. + * Uninstall remote MAC from the kernel. */ -static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local) +static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac) { struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; - struct in_addr vtep_ip = {.s_addr = 0}; - struct zebra_ns *zns; + struct in_addr vtep_ip; struct interface *ifp; - if (!local && !(mac->flags & ZEBRA_MAC_REMOTE)) + if (!(mac->flags & ZEBRA_MAC_REMOTE)) return 0; if (!zvni->vxlan_if) { @@ -2636,19 +2643,10 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local) return -1; vxl = &zif->l2info.vxl; - if (local) { - zns = zebra_ns_lookup(NS_DEFAULT); - ifp = if_lookup_by_index_per_ns(zns, - mac->fwd_info.local.ifindex); - if (!ifp) // unexpected - return -1; - } else { - ifp = zvni->vxlan_if; - vtep_ip = mac->fwd_info.r_vtep_ip; - } + ifp = zvni->vxlan_if; + vtep_ip = mac->fwd_info.r_vtep_ip; - return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip, - local); + return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip); } /* @@ -2666,20 +2664,43 @@ static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt) } /* + * Count of remote neighbors referencing this MAC. + */ +static int remote_neigh_count(zebra_mac_t *zmac) +{ + zebra_neigh_t *n = NULL; + struct listnode *node = NULL; + int count = 0; + + for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) + count++; + } + + return count; +} + +/* * Decrement neighbor refcount of MAC; uninstall and free it if * appropriate. */ -static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac, - int uninstall) +static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac) { - if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) - || !list_isempty(mac->neigh_list)) + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) return; - if (uninstall) - zvni_mac_uninstall(zvni, mac, 0); + /* If all remote neighbors referencing a remote MAC go away, + * we need to uninstall the MAC. + */ + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && + remote_neigh_count(mac) == 0) { + zvni_mac_uninstall(zvni, mac); + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + } - zvni_mac_del(zvni, mac); + /* If no neighbors, delete the MAC. */ + if (list_isempty(mac->neigh_list)) + zvni_mac_del(zvni, mac); } /* @@ -3290,7 +3311,7 @@ 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, 0); + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip); } /* handle rmac add */ @@ -4046,9 +4067,9 @@ static void process_remote_macip_add(vni_t vni, struct interface *ifp = NULL; struct zebra_if *zif = NULL; uint32_t tmp_seq; - uint8_t sticky = 0; - uint8_t remote_gw = 0; - uint8_t router_flag = 0; + bool sticky; + bool remote_gw; + bool is_router; /* Locate VNI hash entry - expected to exist. */ zvni = zvni_lookup(vni); @@ -4086,9 +4107,9 @@ static void process_remote_macip_add(vni_t vni, zvni_vtep_install(zvni, &vtep_ip); } - sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); + remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); mac = zvni_mac_lookup(zvni, macaddr); @@ -4112,9 +4133,8 @@ static void process_remote_macip_add(vni_t vni, */ if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) - || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) != sticky - || (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? 1 : 0) - != remote_gw + || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) + || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip) || seq != mac->rem_seq) update_mac = 1; @@ -4205,10 +4225,9 @@ static void process_remote_macip_add(vni_t vni, n = zvni_neigh_lookup(zvni, ipaddr); if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) - || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0) - != router_flag) || seq != n->rem_seq) update_neigh = 1; @@ -4272,7 +4291,7 @@ static void process_remote_macip_add(vni_t vni, old_mac = zvni_mac_lookup(zvni, &n->emac); if (old_mac) { listnode_delete(old_mac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_mac, 1); + zvni_deref_ip2mac(zvni, old_mac); } listnode_add_sort(mac->neigh_list, n); memcpy(&n->emac, macaddr, ETH_ALEN); @@ -4384,16 +4403,22 @@ static void process_remote_macip_del(vni_t vni, && (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) { zvni_neigh_uninstall(zvni, n); zvni_neigh_del(zvni, n); - zvni_deref_ip2mac(zvni, mac, 1); + zvni_deref_ip2mac(zvni, mac); } } else { if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { zvni_process_neigh_on_remote_mac_del(zvni, mac); - if (list_isempty(mac->neigh_list)) { - zvni_mac_uninstall(zvni, mac, 0); + /* If all remote neighbors referencing a remote MAC + * go away, we need to uninstall the MAC. + */ + if (remote_neigh_count(mac) == 0) { + zvni_mac_uninstall(zvni, mac); + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + } + if (list_isempty(mac->neigh_list)) zvni_mac_del(zvni, mac); - } else + else SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); } } @@ -5388,8 +5413,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, struct ipaddr *ip, struct ethaddr *macaddr, uint16_t state, - uint8_t ext_learned, - uint8_t router_flag) + bool is_ext, + bool is_router) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -5415,14 +5440,14 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, - ifp->ifindex, state, ext_learned ? "ext-learned " : "", - router_flag ? "router " : "", + ifp->ifindex, state, is_ext ? "ext-learned " : "", + is_router ? "router " : "", zvni->vni); /* Is this about a local neighbor or a remote one? */ - if (!ext_learned) + if (!is_ext) return zvni_local_neigh_update(zvni, ifp, ip, macaddr, - router_flag); + is_router); return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state); } @@ -5735,7 +5760,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, int zebra_vxlan_local_mac_add_update(struct interface *ifp, struct interface *br_if, struct ethaddr *macaddr, vlanid_t vid, - uint8_t sticky) + bool sticky) { zebra_vni_t *zvni; zebra_mac_t *mac; diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 5097757b1..a6c668785 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -122,15 +122,15 @@ extern int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if); extern int zebra_vxlan_handle_kernel_neigh_update( struct interface *ifp, struct interface *link_if, struct ipaddr *ip, - struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned, - uint8_t router_flag); + struct ethaddr *macaddr, uint16_t state, bool is_ext, + bool is_router); extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, struct interface *link_if, struct ipaddr *ip); extern int zebra_vxlan_local_mac_add_update(struct interface *ifp, struct interface *br_if, struct ethaddr *mac, vlanid_t vid, - uint8_t sticky); + bool sticky); extern int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, struct ethaddr *mac, vlanid_t vid); diff --git a/zebra/zserv.c b/zebra/zserv.c index 2f4bb22ff..8cc462577 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -703,7 +703,6 @@ static struct zserv *zserv_client_create(int sock) listnode_add(zebrad.client_list, client); struct frr_pthread_attr zclient_pthr_attrs = { - .id = frr_pthread_get_id(), .start = frr_pthread_attr_default.start, .stop = frr_pthread_attr_default.stop }; |