summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c2
-rw-r--r--bgpd/bgp_io.c14
-rw-r--r--bgpd/bgp_keepalives.c4
-rw-r--r--bgpd/bgp_labelpool.c6
-rw-r--r--bgpd/bgp_main.c15
-rw-r--r--bgpd/bgp_nexthop.c90
-rw-r--r--bgpd/bgp_nht.c48
-rw-r--r--bgpd/bgp_pbr.c6
-rw-r--r--bgpd/bgp_route.c91
-rw-r--r--bgpd/bgp_table.h59
-rw-r--r--bgpd/bgp_zebra.c3
-rw-r--r--bgpd/bgp_zebra.h3
-rw-r--r--bgpd/bgpd.c27
-rw-r--r--bgpd/bgpd.h10
-rw-r--r--doc/manpages/bgpd.rst7
-rw-r--r--doc/user/ospfd.rst114
-rw-r--r--isisd/isis_lsp.c2
-rw-r--r--ldpd/lde.c2
-rw-r--r--lib/frr_pthread.c144
-rw-r--r--lib/frr_pthread.h24
-rw-r--r--lib/if.c6
-rw-r--r--lib/log.c1
-rw-r--r--lib/vrf.h2
-rw-r--r--lib/zclient.c16
-rw-r--r--lib/zclient.h3
-rw-r--r--ospfd/ospf_vty.c6
-rw-r--r--ospfd/ospf_zebra.c20
-rw-r--r--pimd/pim_cmd.c5
-rw-r--r--pimd/pim_mroute.c26
-rw-r--r--pimd/pim_zebra.c9
-rw-r--r--tests/bgpd/test_aspath.c6
-rw-r--r--tests/bgpd/test_capability.c2
-rw-r--r--tests/bgpd/test_peer_attr.c2
-rw-r--r--tests/test_lblmgr.c2
-rwxr-xr-xtools/checkpatch.pl1
-rw-r--r--tools/permutations.c3
-rw-r--r--tools/start-stop-daemon.c4
-rw-r--r--zebra/if_netlink.c14
-rw-r--r--zebra/interface.c33
-rw-r--r--zebra/interface.h1
-rw-r--r--zebra/label_manager.c28
-rw-r--r--zebra/rt.h5
-rw-r--r--zebra/rt_netlink.c35
-rw-r--r--zebra/rt_socket.c4
-rw-r--r--zebra/zapi_msg.c61
-rw-r--r--zebra/zebra_pbr.h1
-rw-r--r--zebra/zebra_vxlan.c223
-rw-r--r--zebra/zebra_vxlan.h6
-rw-r--r--zebra/zserv.c1
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
diff --git a/lib/if.c b/lib/if.c
index 6b551a9fa..67e2d366c 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -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);
diff --git a/lib/log.c b/lib/log.c
index 52ea8d900..2d800baae 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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),
diff --git a/lib/vrf.h b/lib/vrf.h
index f0dabf5b2..04a8f70f5 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -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
};