summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_bmp.c101
-rw-r--r--bgpd/bgp_bmp.h1
-rw-r--r--lib/resolver.c47
-rw-r--r--lib/resolver.h10
-rw-r--r--nhrpd/nhrp_nhs.c4
5 files changed, 127 insertions, 36 deletions
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index b8862c6049..24a9cab5d1 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -1662,34 +1662,31 @@ static void bmp_active_connect(struct bmp_active *ba)
bmp_active_setup(ba);
}
-static void bmp_active_resolved(struct resolver_query *resq, int numaddrs,
- union sockunion *addr)
+static void bmp_active_resolved(struct resolver_query *resq, const char *errstr,
+ int numaddrs, union sockunion *addr)
{
struct bmp_active *ba = container_of(resq, struct bmp_active, resq);
unsigned i;
if (numaddrs <= 0) {
- int ret;
-
- ba->addrpos = 0;
- ba->addrtotal = 1;
- ret = str2sockunion(ba->hostname, &ba->addrs[0]);
- if (ret < 0) {
- ba->addrtotal = 0;
- ba->curretry += ba->curretry / 2;
- bmp_active_setup(ba);
- return;
- }
- } else {
- if (numaddrs > (int)array_size(ba->addrs))
- numaddrs = array_size(ba->addrs);
-
+ zlog_warn("bmp[%s]: hostname resolution failed: %s",
+ ba->hostname, errstr);
+ ba->last_err = errstr;
+ ba->curretry += ba->curretry / 2;
ba->addrpos = 0;
- ba->addrtotal = numaddrs;
- for (i = 0; i < ba->addrtotal; i++)
- memcpy(&ba->addrs[i], &addr[i], sizeof(ba->addrs[0]));
+ ba->addrtotal = 0;
+ bmp_active_setup(ba);
+ return;
}
+ if (numaddrs > (int)array_size(ba->addrs))
+ numaddrs = array_size(ba->addrs);
+
+ ba->addrpos = 0;
+ ba->addrtotal = numaddrs;
+ for (i = 0; i < ba->addrtotal; i++)
+ memcpy(&ba->addrs[i], &addr[i], sizeof(ba->addrs[0]));
+
bmp_active_connect(ba);
}
@@ -1706,6 +1703,8 @@ static int bmp_active_thread(struct thread *t)
THREAD_OFF(ba->t_read);
THREAD_OFF(ba->t_write);
+ ba->last_err = NULL;
+
if (ba->socket == -1) {
resolver_resolve(&ba->resq, AF_UNSPEC, ba->hostname,
bmp_active_resolved);
@@ -1718,8 +1717,9 @@ static int bmp_active_thread(struct thread *t)
sockunion2str(&ba->addrs[ba->addrpos], buf, sizeof(buf));
if (ret < 0 || status != 0) {
- zlog_warn("bmp[%s]: failed to connect to %s:%d",
- ba->hostname, buf, ba->port);
+ ba->last_err = strerror(status);
+ zlog_warn("bmp[%s]: failed to connect to %s:%d: %s",
+ ba->hostname, buf, ba->port, ba->last_err);
goto out_next;
}
@@ -2079,9 +2079,12 @@ DEFPY(show_bmp,
struct bmp_bgp *bmpbgp;
struct bmp_targets *bt;
struct bmp_listener *bl;
+ struct bmp_active *ba;
struct bmp *bmp;
struct ttable *tt;
char buf[SU_ADDRSTRLEN];
+ char uptime[BGP_UPTIME_LEN];
+ char *out;
frr_each(bmp_bgph, &bmp_bgph, bmpbgp) {
vty_out(vty, "BMP state for BGP %s:\n\n",
@@ -2130,6 +2133,51 @@ DEFPY(show_bmp,
sockunion2str(&bl->addr, buf,
SU_ADDRSTRLEN), bl->port);
+ vty_out(vty, "\n Outbound connections:\n");
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "remote|state||timer");
+ ttable_rowseps(tt, 0, BOTTOM, true, '-');
+ frr_each (bmp_actives, &bt->actives, ba) {
+ const char *state_str = "?";
+
+ if (ba->bmp) {
+ peer_uptime(ba->bmp->t_up.tv_sec,
+ uptime, sizeof(uptime),
+ false, NULL);
+ ttable_add_row(tt, "%s:%d|Up|%s|%s",
+ ba->hostname, ba->port,
+ ba->bmp->remote, uptime);
+ continue;
+ }
+
+ uptime[0] = '\0';
+
+ if (ba->t_timer) {
+ long trem = thread_timer_remain_second(
+ ba->t_timer);
+
+ peer_uptime(monotime(NULL) - trem,
+ uptime, sizeof(uptime),
+ false, NULL);
+ state_str = "RetryWait";
+ } else if (ba->t_read) {
+ state_str = "Connecting";
+ } else if (ba->resq.callback) {
+ state_str = "Resolving";
+ }
+
+ ttable_add_row(tt, "%s:%d|%s|%s|%s",
+ ba->hostname, ba->port,
+ state_str,
+ ba->last_err ? ba->last_err : "",
+ uptime);
+ continue;
+ }
+ out = ttable_dump(tt, "\n");
+ vty_out(vty, "%s", out);
+ XFREE(MTYPE_TMP, out);
+ ttable_del(tt);
+
vty_out(vty, "\n %zu connected clients:\n",
bmp_session_count(&bt->sessions));
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
@@ -2142,14 +2190,17 @@ DEFPY(show_bmp,
pullwr_stats(bmp->pullwr, &total, &q, &kq);
- ttable_add_row(tt, "%s|-|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
- bmp->remote,
+ peer_uptime(bmp->t_up.tv_sec, uptime,
+ sizeof(uptime), false, NULL);
+
+ ttable_add_row(tt, "%s|%s|%Lu|%Lu|%Lu|%Lu|%zu|%zu",
+ bmp->remote, uptime,
bmp->cnt_update,
bmp->cnt_mirror,
bmp->cnt_mirror_overruns,
total, q, kq);
}
- char *out = ttable_dump(tt, "\n");
+ out = ttable_dump(tt, "\n");
vty_out(vty, "%s", out);
XFREE(MTYPE_TMP, out);
ttable_del(tt);
diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h
index 9d270e808c..94a17f70da 100644
--- a/bgpd/bgp_bmp.h
+++ b/bgpd/bgp_bmp.h
@@ -182,6 +182,7 @@ struct bmp_active {
unsigned addrpos, addrtotal;
union sockunion addrs[8];
int socket;
+ const char *last_err;
struct thread *t_timer, *t_read, *t_write;
};
diff --git a/lib/resolver.c b/lib/resolver.c
index fb8aeed92f..1be47bd6e1 100644
--- a/lib/resolver.c
+++ b/lib/resolver.c
@@ -145,7 +145,8 @@ static void ares_address_cb(void *arg, int status, int timeouts,
{
struct resolver_query *query = (struct resolver_query *)arg;
union sockunion addr[16];
- void (*callback)(struct resolver_query *, int, union sockunion *);
+ void (*callback)(struct resolver_query *, const char *, int,
+ union sockunion *);
size_t i;
callback = query->callback;
@@ -153,9 +154,10 @@ static void ares_address_cb(void *arg, int status, int timeouts,
if (status != ARES_SUCCESS) {
if (resolver_debug)
- zlog_debug("[%p] Resolving failed", query);
+ zlog_debug("[%p] Resolving failed (%s)",
+ query, ares_strerror(status));
- callback(query, -1, NULL);
+ callback(query, ares_strerror(status), -1, NULL);
return;
}
@@ -177,14 +179,29 @@ static void ares_address_cb(void *arg, int status, int timeouts,
if (resolver_debug)
zlog_debug("[%p] Resolved with %d results", query, (int)i);
- callback(query, i, &addr[0]);
+ callback(query, NULL, i, &addr[0]);
+}
+
+static int resolver_cb_literal(struct thread *t)
+{
+ struct resolver_query *query = THREAD_ARG(t);
+ void (*callback)(struct resolver_query *, const char *, int,
+ union sockunion *);
+
+ callback = query->callback;
+ query->callback = NULL;
+
+ callback(query, ARES_SUCCESS, 1, &query->literal_addr);
+ return 0;
}
void resolver_resolve(struct resolver_query *query, int af,
const char *hostname,
- void (*callback)(struct resolver_query *, int,
- union sockunion *))
+ void (*callback)(struct resolver_query *, const char *,
+ int, union sockunion *))
{
+ int ret;
+
if (query->callback != NULL) {
flog_err(
EC_LIB_RESOLVER,
@@ -193,10 +210,26 @@ void resolver_resolve(struct resolver_query *query, int af,
return;
}
+ query->callback = callback;
+ query->literal_cb = NULL;
+
+ ret = str2sockunion(hostname, &query->literal_addr);
+ if (ret == 0) {
+ if (resolver_debug)
+ zlog_debug("[%p] Resolving '%s' (IP literal)",
+ query, hostname);
+
+ /* for consistency with proper name lookup, don't call the
+ * callback immediately; defer to thread loop
+ */
+ thread_add_timer_msec(state.master, resolver_cb_literal,
+ query, 0, &query->literal_cb);
+ return;
+ }
+
if (resolver_debug)
zlog_debug("[%p] Resolving '%s'", query, hostname);
- query->callback = callback;
ares_gethostbyname(state.channel, hostname, af, ares_address_cb, query);
resolver_update_timeouts(&state);
}
diff --git a/lib/resolver.h b/lib/resolver.h
index bc6326edaa..59bf0d0f55 100644
--- a/lib/resolver.h
+++ b/lib/resolver.h
@@ -14,12 +14,18 @@
#include "sockunion.h"
struct resolver_query {
- void (*callback)(struct resolver_query *, int n, union sockunion *);
+ void (*callback)(struct resolver_query *, const char *errstr, int n,
+ union sockunion *);
+
+ /* used to immediate provide the result if IP literal is passed in */
+ union sockunion literal_addr;
+ struct thread *literal_cb;
};
void resolver_init(struct thread_master *tm);
void resolver_resolve(struct resolver_query *query, int af,
const char *hostname, void (*cb)(struct resolver_query *,
- int, union sockunion *));
+ const char *, int,
+ union sockunion *));
#endif /* _FRR_RESOLVER_H */
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index 360972c327..bec6c014a0 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -238,8 +238,8 @@ nhrp_reg_by_nbma(struct nhrp_nhs *nhs, const union sockunion *nbma_addr)
return NULL;
}
-static void nhrp_nhs_resolve_cb(struct resolver_query *q, int n,
- union sockunion *addrs)
+static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
+ int n, union sockunion *addrs)
{
struct nhrp_nhs *nhs = container_of(q, struct nhrp_nhs, dns_resolve);
struct nhrp_interface *nifp = nhs->ifp->info;