summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/irdp_main.c2
-rw-r--r--zebra/redistribute.c25
-rw-r--r--zebra/rib.h6
-rw-r--r--zebra/subdir.am4
-rw-r--r--zebra/zapi_msg.c38
-rw-r--r--zebra/zebra_fpm.c2
-rw-r--r--zebra/zebra_mlag_private.c2
-rw-r--r--zebra/zebra_mpls.c12
-rw-r--r--zebra/zebra_nhg.c94
-rw-r--r--zebra/zebra_nhg.h6
-rw-r--r--zebra/zebra_ptm.c2
-rw-r--r--zebra/zebra_rib.c181
-rw-r--r--zebra/zebra_routemap.c2
-rw-r--r--zebra/zebra_snmp.c2
-rw-r--r--zebra/zebra_vty.c29
15 files changed, 325 insertions, 82 deletions
diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c
index 600fc3f2fc..66a6bd0545 100644
--- a/zebra/irdp_main.c
+++ b/zebra/irdp_main.c
@@ -51,7 +51,7 @@
#include "privs.h"
#include "libfrr.h"
#include "lib_errors.h"
-#include "version.h"
+#include "lib/version.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
#include "zebra/rib.h"
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 9e675011ee..6f24ec4225 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -347,17 +347,12 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
zvrf_id(zvrf), afi);
}
} else {
- if (!vrf_bitmap_check(client->redist[afi][type],
- zvrf_id(zvrf))) {
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "%s: setting vrf %s(%u) redist bitmap",
- __func__, VRF_LOGNAME(zvrf->vrf),
- zvrf_id(zvrf));
- vrf_bitmap_set(client->redist[afi][type],
- zvrf_id(zvrf));
- zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
- }
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: setting vrf %s(%u) redist bitmap",
+ __func__, VRF_LOGNAME(zvrf->vrf),
+ zvrf_id(zvrf));
+ vrf_bitmap_set(client->redist[afi][type], zvrf_id(zvrf));
+ zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
}
stream_failure:
@@ -374,6 +369,14 @@ void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
STREAM_GETC(msg, type);
STREAM_GETW(msg, instance);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug(
+ "%s: client proto %s afi=%d, no longer wants %s, vrf %s(%u), instance=%d",
+ __func__, zebra_route_string(client->proto), afi,
+ zebra_route_string(type), VRF_LOGNAME(zvrf->vrf),
+ zvrf_id(zvrf), instance);
+
+
if (afi == 0 || afi >= AFI_MAX) {
flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
"%s: Specified afi %d does not exist", __func__, afi);
diff --git a/zebra/rib.h b/zebra/rib.h
index e7676a1324..75d7ae1b67 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -426,7 +426,11 @@ extern int rib_queue_add(struct route_node *rn);
struct nhg_ctx; /* Forward declaration */
-extern int rib_queue_nhg_add(struct nhg_ctx *ctx);
+/* Enqueue incoming nhg from OS for processing */
+extern int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx);
+
+/* Enqueue incoming nhg from proto daemon for processing */
+extern int rib_queue_nhe_add(struct nhg_hash_entry *nhe);
extern void meta_queue_free(struct meta_queue *mq);
extern int zebra_rib_labeled_unicast(struct route_entry *re);
diff --git a/zebra/subdir.am b/zebra/subdir.am
index 80ea9ac7b8..6fc8ef0df5 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -193,7 +193,7 @@ zebra_zebra_irdp_la_SOURCES = \
zebra_zebra_irdp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
zebra_zebra_snmp_la_SOURCES = zebra/zebra_snmp.c
-zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+zebra_zebra_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
zebra_zebra_snmp_la_LIBADD = lib/libfrrsnmp.la
@@ -232,7 +232,7 @@ zebra_dplane_fpm_nl_la_SOURCES = zebra/dplane_fpm_nl.c
zebra_dplane_fpm_nl_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
zebra_dplane_fpm_nl_la_LIBADD =
-vtysh_scan += $(top_srcdir)/zebra/dplane_fpm_nl.c
+vtysh_scan += zebra/dplane_fpm_nl.c
endif
if NETLINK_DEBUG
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index e854d7ff3a..77a9188fe8 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -727,8 +727,8 @@ int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,
}
if (IS_ZEBRA_DEBUG_SEND)
- zlog_debug("%s: type %d, id %d, note %d",
- __func__, type, id, note);
+ zlog_debug("%s: type %d, id %d, note %s",
+ __func__, type, id, zapi_nhg_notify_owner2str(note));
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
@@ -1921,27 +1921,35 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS)
return;
}
- /*
- * Create the nhg
- */
- nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, client->instance,
- client->session_id, nhg, 0);
+ /* Create a temporary nhe */
+ nhe = zebra_nhg_alloc();
+ nhe->id = api_nhg.id;
+ nhe->type = api_nhg.proto;
+ nhe->zapi_instance = client->instance;
+ nhe->zapi_session = client->session_id;
- nexthop_group_delete(&nhg);
- zebra_nhg_backup_free(&bnhg);
+ /* Take over the list(s) of nexthops */
+ nhe->nhg.nexthop = nhg->nexthop;
+ nhg->nexthop = NULL;
+
+ if (bnhg) {
+ nhe->backup_info = bnhg;
+ bnhg = NULL;
+ }
/*
* TODO:
* Assume fully resolved for now and install.
- *
* Resolution is going to need some more work.
*/
- /* If there's a failure, notify sender immediately */
- if (nhe == NULL)
- zsend_nhg_notify(api_nhg.proto, client->instance,
- client->session_id, api_nhg.id,
- ZAPI_NHG_FAIL_INSTALL);
+ /* Enqueue to workqueue for processing */
+ rib_queue_nhe_add(nhe);
+
+ /* Free any local allocations */
+ nexthop_group_delete(&nhg);
+ zebra_nhg_backup_free(&bnhg);
+
}
static void zread_route_add(ZAPI_HANDLER_ARGS)
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 5fe8934a82..07a8288605 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -29,7 +29,7 @@
#include "thread.h"
#include "network.h"
#include "command.h"
-#include "version.h"
+#include "lib/version.h"
#include "jhash.h"
#include "zebra/rib.h"
diff --git a/zebra/zebra_mlag_private.c b/zebra/zebra_mlag_private.c
index aaf93b4dc1..b1bba831d2 100644
--- a/zebra/zebra_mlag_private.c
+++ b/zebra/zebra_mlag_private.c
@@ -28,7 +28,7 @@
#include "thread.h"
#include "frr_pthread.h"
#include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
#include "network.h"
#include "lib/stream.h"
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 6d42957b24..a923782bfe 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -2018,6 +2018,7 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
int start_count = 0, end_count = 0; /* Installed counts */
bool changed_p = false;
bool is_debug = (IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_MPLS);
+ enum zebra_sr_policy_update_label_mode update_mode;
if (is_debug)
zlog_debug("LSP dplane notif, in-label %u",
@@ -2091,10 +2092,21 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
if (end_count > 0) {
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+ /* SR-TE update too */
+ if (start_count == 0)
+ update_mode = ZEBRA_SR_POLICY_LABEL_CREATED;
+ else
+ update_mode = ZEBRA_SR_POLICY_LABEL_UPDATED;
+ zebra_sr_policy_label_update(lsp->ile.in_label, update_mode);
+
if (changed_p)
dplane_lsp_notif_update(lsp, DPLANE_OP_LSP_UPDATE, ctx);
} else {
+ /* SR-TE update too */
+ zebra_sr_policy_label_update(lsp->ile.in_label,
+ ZEBRA_SR_POLICY_LABEL_REMOVED);
+
UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
clear_nhlfe_installed(lsp);
}
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 7edf022892..47651318a4 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -845,6 +845,8 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */
SET_FLAG(backup_nhe->flags, NEXTHOP_GROUP_RECURSIVE);
done:
+ /* Reset time since last update */
+ (*nhe)->uptime = monotime(NULL);
return created;
}
@@ -990,7 +992,7 @@ static struct nhg_ctx *nhg_ctx_new(void)
return new;
}
-static void nhg_ctx_free(struct nhg_ctx **ctx)
+void nhg_ctx_free(struct nhg_ctx **ctx)
{
struct nexthop *nh;
@@ -1191,6 +1193,13 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx)
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: nhe %p (%u) is new", __func__, nhe, nhe->id);
+ /*
+ * If daemon nhg from the kernel, add a refcnt here to indicate the
+ * daemon owns it.
+ */
+ if (PROTO_OWNED(nhe))
+ zebra_nhg_increment_ref(nhe);
+
SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
@@ -1233,7 +1242,7 @@ static int queue_add(struct nhg_ctx *ctx)
if (nhg_ctx_get_status(ctx) == NHG_CTX_QUEUED)
return 0;
- if (rib_queue_nhg_add(ctx)) {
+ if (rib_queue_nhg_ctx_add(ctx)) {
nhg_ctx_set_status(ctx, NHG_CTX_FAILURE);
return -1;
}
@@ -1811,12 +1820,11 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
int i, j, idx;
const struct nexthop *bnh;
struct nexthop *nh, *newnh;
+ mpls_label_t labels[MPLS_MAX_LABELS];
+ uint8_t num_labels;
assert(nexthop->backup_num <= NEXTHOP_MAX_BACKUPS);
- if (resolve_nhe->backup_info->nhe == NULL)
- resolve_nhe->backup_info->nhe = zebra_nhg_alloc();
-
/* Locate backups from the original nexthop's backup index and nhe */
for (i = 0; i < nexthop->backup_num; i++) {
idx = nexthop->backup_idx[i];
@@ -1832,6 +1840,8 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
map->map[j].new_idx;
resolved->backup_num++;
+ SET_FLAG(resolved->flags, NEXTHOP_FLAG_HAS_BACKUP);
+
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug("%s: found map idx orig %d, new %d",
__func__, map->map[j].orig_idx,
@@ -1856,9 +1866,46 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
if (bnh == NULL)
continue;
+ if (resolve_nhe->backup_info == NULL)
+ resolve_nhe->backup_info = zebra_nhg_backup_alloc();
+
/* Update backup info in the resolving nexthop and its nhe */
newnh = nexthop_dup_no_recurse(bnh, NULL);
+ /* We may need some special handling for mpls labels: the new
+ * backup needs to carry the recursive nexthop's labels,
+ * if any: they may be vrf labels e.g.
+ * The original/inner labels are in the stack of 'resolve_nhe',
+ * if that is longer than the stack in 'nexthop'.
+ */
+ if (newnh->nh_label && resolved->nh_label &&
+ nexthop->nh_label) {
+ if (resolved->nh_label->num_labels >
+ nexthop->nh_label->num_labels) {
+ /* Prepare new label stack */
+ num_labels = 0;
+ for (j = 0; j < newnh->nh_label->num_labels;
+ j++) {
+ labels[j] = newnh->nh_label->label[j];
+ num_labels++;
+ }
+
+ /* Include inner labels */
+ for (j = nexthop->nh_label->num_labels;
+ j < resolved->nh_label->num_labels;
+ j++) {
+ labels[num_labels] =
+ resolved->nh_label->label[j];
+ num_labels++;
+ }
+
+ /* Replace existing label stack in the backup */
+ nexthop_del_labels(newnh);
+ nexthop_add_labels(newnh, bnh->nh_label_type,
+ num_labels, labels);
+ }
+ }
+
/* Need to compute the new backup index in the new
* backup list, and add to map struct.
*/
@@ -1871,6 +1918,7 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
}
nh->next = newnh;
+ j++;
} else /* First one */
resolve_nhe->backup_info->nhe->nhg.nexthop = newnh;
@@ -1879,6 +1927,8 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
resolved->backup_idx[resolved->backup_num] = j;
resolved->backup_num++;
+ SET_FLAG(resolved->flags, NEXTHOP_FLAG_HAS_BACKUP);
+
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug("%s: added idx orig %d, new %d",
__func__, idx, j);
@@ -2559,7 +2609,7 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re)
struct nhg_hash_entry *curr_nhe;
uint32_t curr_active = 0, backup_active = 0;
- if (re->nhe->id >= ZEBRA_NHG_PROTO_LOWER)
+ if (PROTO_OWNED(re->nhe))
return proto_nhg_nexthop_active_update(&re->nhe->nhg);
afi_t rt_afi = family2afi(rn->p.family);
@@ -2861,13 +2911,13 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
zebra_nhg_handle_install(nhe);
/* If daemon nhg, send it an update */
- if (nhe->id >= ZEBRA_NHG_PROTO_LOWER)
+ if (PROTO_OWNED(nhe))
zsend_nhg_notify(nhe->type, nhe->zapi_instance,
nhe->zapi_session, nhe->id,
ZAPI_NHG_INSTALLED);
} else {
/* If daemon nhg, send it an update */
- if (nhe->id >= ZEBRA_NHG_PROTO_LOWER)
+ if (PROTO_OWNED(nhe))
zsend_nhg_notify(nhe->type, nhe->zapi_instance,
nhe->zapi_session, nhe->id,
ZAPI_NHG_FAIL_INSTALL);
@@ -2927,7 +2977,31 @@ static void zebra_nhg_sweep_entry(struct hash_bucket *bucket, void *arg)
nhe = (struct nhg_hash_entry *)bucket->data;
- /* If its being ref'd, just let it be uninstalled via a route removal */
+ /*
+ * same logic as with routes.
+ *
+ * If older than startup time, we know we read them in from the
+ * kernel and have not gotten and update for them since startup
+ * from an upper level proto.
+ */
+ if (zrouter.startup_time < nhe->uptime)
+ return;
+
+ /*
+ * If it's proto-owned and not being used by a route, remove it since
+ * we haven't gotten an update about it from the proto since startup.
+ * This means that either the config for it was removed or the daemon
+ * didn't get started. This handles graceful restart & retain scenario.
+ */
+ if (PROTO_OWNED(nhe) && nhe->refcnt == 1) {
+ zebra_nhg_decrement_ref(nhe);
+ return;
+ }
+
+ /*
+ * If its being ref'd by routes, just let it be uninstalled via a route
+ * removal.
+ */
if (ZEBRA_NHG_CREATED(nhe) && nhe->refcnt <= 0)
zebra_nhg_uninstall_kernel(nhe);
}
@@ -3201,7 +3275,7 @@ static void zebra_nhg_score_proto_entry(struct hash_bucket *bucket, void *arg)
iter = arg;
/* Needs to match type and outside zebra ID space */
- if (nhe->type == iter->type && nhe->id >= ZEBRA_NHG_PROTO_LOWER) {
+ if (nhe->type == iter->type && PROTO_OWNED(nhe)) {
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug(
"%s: found nhe %p (%u), vrf %d, type %s after client disconnect",
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 38015bf557..3fbf778be2 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -51,6 +51,9 @@ struct nhg_hash_entry {
afi_t afi;
vrf_id_t vrf_id;
+ /* Time since last update */
+ time_t uptime;
+
/* Source protocol - zebra or another daemon */
int type;
@@ -147,6 +150,8 @@ enum nhg_type {
/* Is this an NHE owned by zebra and not an upper level protocol? */
#define ZEBRA_OWNED(NHE) (NHE->type == ZEBRA_ROUTE_NHG)
+#define PROTO_OWNED(NHE) (NHE->id >= ZEBRA_NHG_PROTO_LOWER)
+
/*
* Backup nexthops: this is a group object itself, so
* that the backup nexthops can use the same code as a normal object.
@@ -269,6 +274,7 @@ extern bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2);
* the rib meta queue.
*/
extern int nhg_ctx_process(struct nhg_ctx *ctx);
+void nhg_ctx_free(struct nhg_ctx **ctx);
/* Find via kernel nh creation */
extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh,
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index bea855d1af..37d9399054 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -31,7 +31,7 @@
#include "ptm_lib.h"
#include "rib.h"
#include "stream.h"
-#include "version.h"
+#include "lib/version.h"
#include "vrf.h"
#include "vty.h"
#include "lib_errors.h"
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 82a0e6d015..bdacd411bd 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -62,6 +62,7 @@ DEFINE_MGROUP(ZEBRA, "zebra");
DEFINE_MTYPE(ZEBRA, RE, "Route Entry");
DEFINE_MTYPE_STATIC(ZEBRA, RIB_DEST, "RIB destination");
DEFINE_MTYPE_STATIC(ZEBRA, RIB_UPDATE_CTX, "Rib update context object");
+DEFINE_MTYPE_STATIC(ZEBRA, WQ_NHG_WRAPPER, "WQ nhg wrapper");
/*
* Event, list, and mutex for delivery of dataplane results
@@ -117,6 +118,20 @@ static const struct {
/* no entry/default: 150 */
};
+/* Wrapper struct for nhg workqueue items; a 'ctx' is an incoming update
+ * from the OS, and an 'nhe' is a nhe update.
+ */
+struct wq_nhg_wrapper {
+ int type;
+ union {
+ struct nhg_ctx *ctx;
+ struct nhg_hash_entry *nhe;
+ } u;
+};
+
+#define WQ_NHG_WRAPPER_TYPE_CTX 0x01
+#define WQ_NHG_WRAPPER_TYPE_NHG 0x02
+
static void PRINTFRR(5, 6)
_rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn,
int priority, const char *msgfmt, ...)
@@ -908,6 +923,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (nh_active) {
if (IS_ZEBRA_DEBUG_RIB) {
char buf[SRCDEST2STR_BUFFER];
+
srcdest_rnode2str(rn, buf, sizeof(buf));
if (new != old)
zlog_debug(
@@ -1068,12 +1084,6 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
return current;
}
-/* Core function for processing nexthop group contexts's off metaq */
-static void rib_nhg_process(struct nhg_ctx *ctx)
-{
- nhg_ctx_process(ctx);
-}
-
/* Core function for processing routing information base. */
static void rib_process(struct route_node *rn)
{
@@ -2289,21 +2299,60 @@ done:
dplane_ctx_fini(&ctx);
}
+/*
+ * Process the nexthop-group workqueue subqueue
+ */
static void process_subq_nhg(struct listnode *lnode)
{
- struct nhg_ctx *ctx = NULL;
+ struct nhg_ctx *ctx;
+ struct nhg_hash_entry *nhe, *newnhe;
+ struct wq_nhg_wrapper *w;
uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
- ctx = listgetdata(lnode);
+ w = listgetdata(lnode);
- if (!ctx)
+ if (!w)
return;
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug("NHG Context id=%u dequeued from sub-queue %u",
- ctx->id, qindex);
+ /* Two types of object - an update from the local kernel, or
+ * an nhg update from a daemon.
+ */
+ if (w->type == WQ_NHG_WRAPPER_TYPE_CTX) {
+ ctx = w->u.ctx;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug(
+ "NHG Context id=%u dequeued from sub-queue %u",
+ ctx->id, qindex);
+
+
+ /* Process nexthop group updates coming 'up' from the OS */
+ nhg_ctx_process(ctx);
- rib_nhg_process(ctx);
+ } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG) {
+ nhe = w->u.nhe;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("NHG %u dequeued from sub-queue %u",
+ nhe->id, qindex);
+
+ /* Process incoming nhg update, probably from a proto daemon */
+ newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
+ nhe->zapi_instance,
+ nhe->zapi_session,
+ &nhe->nhg, 0);
+
+ /* Report error to daemon via ZAPI */
+ if (newnhe == NULL)
+ zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+ nhe->zapi_session, nhe->id,
+ ZAPI_NHG_FAIL_INSTALL);
+
+ /* Free temp nhe - we own that memory. */
+ zebra_nhg_free(nhe);
+ }
+
+ XFREE(MTYPE_WQ_NHG_WRAPPER, w);
}
static void process_subq_route(struct listnode *lnode, uint8_t qindex)
@@ -2335,8 +2384,8 @@ static void process_subq_route(struct listnode *lnode, uint8_t qindex)
srcdest_rnode2str(rnode, buf, sizeof(buf));
zlog_debug("%s(%u:%u):%s: rn %p dequeued from sub-queue %u",
- zvrf_name(zvrf), zvrf_id(zvrf), re ? re->table : 0, buf,
- rnode, qindex);
+ zvrf_name(zvrf), zvrf_id(zvrf), re ? re->table : 0,
+ buf, rnode, qindex);
}
if (rnode->info)
@@ -2369,8 +2418,7 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
/* Dispatch the meta queue by picking, processing and unlocking the next RN from
* a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
- * data
- * is pointed to the meta queue structure.
+ * data is pointed to the meta queue structure.
*/
static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
{
@@ -2463,17 +2511,23 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
return 0;
}
-static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
{
struct nhg_ctx *ctx = NULL;
uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
+ struct wq_nhg_wrapper *w;
ctx = (struct nhg_ctx *)data;
if (!ctx)
return -1;
- listnode_add(mq->subq[qindex], ctx);
+ w = XCALLOC(MTYPE_WQ_NHG_WRAPPER, sizeof(struct wq_nhg_wrapper));
+
+ w->type = WQ_NHG_WRAPPER_TYPE_CTX;
+ w->u.ctx = ctx;
+
+ listnode_add(mq->subq[qindex], w);
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
@@ -2483,6 +2537,32 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
return 0;
}
+static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+{
+ struct nhg_hash_entry *nhe = NULL;
+ uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
+ struct wq_nhg_wrapper *w;
+
+ nhe = (struct nhg_hash_entry *)data;
+
+ if (!nhe)
+ return -1;
+
+ w = XCALLOC(MTYPE_WQ_NHG_WRAPPER, sizeof(struct wq_nhg_wrapper));
+
+ w->type = WQ_NHG_WRAPPER_TYPE_NHG;
+ w->u.nhe = nhe;
+
+ listnode_add(mq->subq[qindex], w);
+ mq->size++;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("NHG id=%u queued into sub-queue %u",
+ nhe->id, qindex);
+
+ return 0;
+}
+
static int mq_add_handler(void *data,
int (*mq_add_func)(struct meta_queue *mq, void *data))
{
@@ -2520,14 +2600,50 @@ int rib_queue_add(struct route_node *rn)
return -1;
}
- return mq_add_handler(rn, &rib_meta_queue_add);
+ return mq_add_handler(rn, rib_meta_queue_add);
}
-int rib_queue_nhg_add(struct nhg_ctx *ctx)
+/*
+ * Enqueue incoming nhg info from OS for processing
+ */
+int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx)
{
assert(ctx);
- return mq_add_handler(ctx, &rib_meta_queue_nhg_add);
+ return mq_add_handler(ctx, rib_meta_queue_nhg_ctx_add);
+}
+
+/*
+ * Enqueue incoming nhg from proto daemon for processing
+ */
+int rib_queue_nhe_add(struct nhg_hash_entry *nhe)
+{
+ if (nhe == NULL)
+ return -1;
+
+ return mq_add_handler(nhe, rib_meta_queue_nhg_add);
+}
+
+/* Clean up the nhg meta-queue list */
+static void nhg_meta_queue_free(struct list *l)
+{
+ struct wq_nhg_wrapper *w;
+ struct listnode *node;
+
+ /* Free the node wrapper object, and the struct it wraps */
+ while ((node = listhead(l)) != NULL) {
+ w = node->data;
+ node->data = NULL;
+
+ if (w->type == WQ_NHG_WRAPPER_TYPE_CTX)
+ nhg_ctx_free(&w->u.ctx);
+ else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG)
+ zebra_nhg_free(w->u.nhe);
+
+ XFREE(MTYPE_WQ_NHG_WRAPPER, w);
+
+ list_delete_node(l, node);
+ }
}
/* Create new meta queue.
@@ -2552,8 +2668,13 @@ void meta_queue_free(struct meta_queue *mq)
{
unsigned i;
- for (i = 0; i < MQ_SIZE; i++)
+ for (i = 0; i < MQ_SIZE; i++) {
+ /* Some subqueues may need cleanup - nhgs for example */
+ if (i == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
+ nhg_meta_queue_free(mq->subq[i]);
+
list_delete(&mq->subq[i]);
+ }
XFREE(MTYPE_WORK_QUEUE, mq);
}
@@ -2765,6 +2886,7 @@ static void _route_entry_dump_nh(const struct route_entry *re,
char backup_str[50];
char wgt_str[50];
char temp_str[10];
+ char label_str[MPLS_LABEL_STRLEN];
int i;
struct interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
@@ -2789,6 +2911,15 @@ static void _route_entry_dump_nh(const struct route_entry *re,
break;
}
+ /* Label stack */
+ label_str[0] = '\0';
+ if (nexthop->nh_label && nexthop->nh_label->num_labels > 0) {
+ mpls_label2str(nexthop->nh_label->num_labels,
+ nexthop->nh_label->label, label_str,
+ sizeof(label_str), 0 /*pretty*/);
+ strlcat(label_str, ", ", sizeof(label_str));
+ }
+
backup_str[0] = '\0';
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
snprintf(backup_str, sizeof(backup_str), "backup ");
@@ -2803,9 +2934,9 @@ static void _route_entry_dump_nh(const struct route_entry *re,
if (nexthop->weight)
snprintf(wgt_str, sizeof(wgt_str), "wgt %d,", nexthop->weight);
- zlog_debug("%s: %s %s[%u] vrf %s(%u) %s%s with flags %s%s%s%s%s%s%s%s",
+ zlog_debug("%s: %s %s[%u] %svrf %s(%u) %s%s with flags %s%s%s%s%s%s%s%s",
straddr, (nexthop->rparent ? " NH" : "NH"), nhname,
- nexthop->ifindex, vrf ? vrf->name : "Unknown",
+ nexthop->ifindex, label_str, vrf ? vrf->name : "Unknown",
nexthop->vrf_id,
wgt_str, backup_str,
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 6a42c682ad..d07a49fb6e 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -30,7 +30,7 @@
#include "plist.h"
#include "nexthop.h"
#include "northbound_cli.h"
-#include "route_types.h"
+#include "lib/route_types.h"
#include "vrf.h"
#include "frrstr.h"
diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c
index 3e08d83724..6fe24dfa54 100644
--- a/zebra/zebra_snmp.c
+++ b/zebra/zebra_snmp.c
@@ -36,7 +36,7 @@
#include "vrf.h"
#include "hook.h"
#include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 283a3e52d6..8061f34d2b 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -445,6 +445,16 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
}
}
+static void uptime2str(time_t uptime, char *buf, size_t bufsize)
+{
+ time_t cur;
+
+ cur = monotime(NULL);
+ cur -= uptime;
+
+ frrtime_to_interval(cur, buf, bufsize);
+}
+
/* New RIB. Detailed information for IPv4 route. */
static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
int mcast, bool use_fib, bool show_ng)
@@ -499,12 +509,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
vty_out(vty, ", best");
vty_out(vty, "\n");
- time_t uptime;
-
- uptime = monotime(NULL);
- uptime -= re->uptime;
-
- frrtime_to_interval(uptime, buf, sizeof(buf));
+ uptime2str(re->uptime, buf, sizeof(buf));
vty_out(vty, " Last update %s ago\n", buf);
@@ -839,17 +844,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_nexthops = NULL;
json_object *json_nexthop = NULL;
json_object *json_route = NULL;
- time_t uptime;
const rib_dest_t *dest = rib_dest_from_rnode(rn);
const struct nexthop_group *nhg;
char up_str[MONOTIME_STRLEN];
bool first_p = true;
bool nhg_from_backup = false;
- uptime = monotime(NULL);
- uptime -= re->uptime;
-
- frrtime_to_interval(uptime, up_str, sizeof(up_str));
+ uptime2str(re->uptime, up_str, sizeof(up_str));
/* If showing fib information, use the fib view of the
* nexthops.
@@ -1339,9 +1340,13 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
struct nexthop *nexthop = NULL;
struct nhg_connected *rb_node_dep = NULL;
struct nexthop_group *backup_nhg;
+ char up_str[MONOTIME_STRLEN];
+
+ uptime2str(nhe->uptime, up_str, sizeof(up_str));
vty_out(vty, "ID: %u (%s)\n", nhe->id, zebra_route_string(nhe->type));
- vty_out(vty, " RefCnt: %d\n", nhe->refcnt);
+ vty_out(vty, " RefCnt: %u\n", nhe->refcnt);
+ vty_out(vty, " Uptime: %s\n", up_str);
vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id));
if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {