summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/dplane_fpm_nl.c8
-rw-r--r--zebra/kernel_netlink.c13
-rw-r--r--zebra/kernel_netlink.h3
-rw-r--r--zebra/rib.h3
-rw-r--r--zebra/rt_netlink.c55
-rw-r--r--zebra/sample_plugin.c1
-rw-r--r--zebra/subdir.am11
-rw-r--r--zebra/zebra_dplane.c26
-rw-r--r--zebra/zebra_evpn_mac.c311
-rw-r--r--zebra/zebra_evpn_mac.h1
-rw-r--r--zebra/zebra_fpm.c22
-rw-r--r--zebra/zebra_fpm_netlink.c10
-rw-r--r--zebra/zebra_nhg.c6
-rw-r--r--zebra/zebra_rib.c145
-rw-r--r--zebra/zebra_routemap.c63
15 files changed, 474 insertions, 204 deletions
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 51ce59c477..bf733e38f7 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -1236,7 +1236,13 @@ static int fpm_process_queue(struct thread *t)
if (ctx == NULL)
break;
- fpm_nl_enqueue(fnc, ctx);
+ /*
+ * Intentionally ignoring the return value
+ * as that we are ensuring that we can write to
+ * the output data in the STREAM_WRITEABLE
+ * check above, so we can ignore the return
+ */
+ (void)fpm_nl_enqueue(fnc, ctx);
/* Account the processed entries. */
processed_contexts++;
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 5d64f57b3e..bbe2fccc60 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -489,6 +489,19 @@ static void netlink_install_filter(int sock, __u32 pid, __u32 dplane_pid)
safe_strerror(errno));
}
+void netlink_parse_rtattr_flags(struct rtattr **tb, int max,
+ struct rtattr *rta, int len, unsigned short flags)
+{
+ unsigned short type;
+
+ while (RTA_OK(rta, len)) {
+ type = rta->rta_type & ~flags;
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+}
+
void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
int len)
{
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 696f9be4f6..a7b152b31b 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -79,6 +79,9 @@ extern void nl_attr_rtnh_end(struct nlmsghdr *n, struct rtnexthop *rtnh);
extern void netlink_parse_rtattr(struct rtattr **tb, int max,
struct rtattr *rta, int len);
+extern void netlink_parse_rtattr_flags(struct rtattr **tb, int max,
+ struct rtattr *rta, int len,
+ unsigned short flags);
extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
struct rtattr *rta);
extern const char *nl_msg_type_to_str(uint16_t msg_type);
diff --git a/zebra/rib.h b/zebra/rib.h
index d653425f0d..86766b8175 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -406,9 +406,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
vrf_id_t vrf_id);
extern void rib_update(enum rib_update_event event);
-extern void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event);
extern void rib_update_table(struct route_table *table,
- enum rib_update_event event);
+ enum rib_update_event event, int rtype);
extern int rib_sweep_route(struct thread *t);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 547700d0c5..d96d77e77c 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -77,16 +77,7 @@
/* Re-defining as I am unable to include <linux/if_bridge.h> which has the
* UAPI for MAC sync. */
#ifndef _UAPI_LINUX_IF_BRIDGE_H
-/* FDB notification bits for NDA_NOTIFY:
- * - BR_FDB_NFY_STATIC - notify on activity/expire even for a static entry
- * - BR_FDB_NFY_INACTIVE - mark as inactive to avoid double notification,
- * used with BR_FDB_NFY_STATIC (kernel controlled)
- */
-enum {
- BR_FDB_NFY_STATIC,
- BR_FDB_NFY_INACTIVE,
- BR_FDB_NFY_MAX
-};
+#define BR_SPH_LIST_SIZE 10
#endif
static vlanid_t filter_vlan = 0;
@@ -2766,11 +2757,23 @@ static ssize_t netlink_neigh_update_msg_encode(
}
if (nfy) {
- if (!nl_attr_put(&req->n, datalen, NDA_NOTIFY,
- &nfy_flags, sizeof(nfy_flags)))
+ struct rtattr *nest;
+
+ nest = nl_attr_nest(&req->n, datalen,
+ NDA_FDB_EXT_ATTRS | NLA_F_NESTED);
+ if (!nest)
+ return 0;
+
+ if (!nl_attr_put(&req->n, datalen, NFEA_ACTIVITY_NOTIFY,
+ &nfy_flags, sizeof(nfy_flags)))
+ return 0;
+ if (!nl_attr_put(&req->n, datalen, NFEA_DONT_REFRESH, NULL, 0))
return 0;
+
+ nl_attr_nest_end(&req->n, nest);
}
+
if (ext) {
if (!nl_attr_put(&req->n, datalen, NDA_EXT_FLAGS, &ext_flags,
sizeof(ext_flags)))
@@ -2855,7 +2858,8 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* validation of the fields.
*/
memset(tb, 0, sizeof tb);
- netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
+ netlink_parse_rtattr_flags(tb, NDA_MAX, NDA_RTA(ndm), len,
+ NLA_F_NESTED);
if (!tb[NDA_LLADDR]) {
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -2897,14 +2901,21 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (ndm->ndm_state & NUD_STALE)
local_inactive = true;
- if (tb[NDA_NOTIFY]) {
- uint8_t nfy_flags;
+ if (tb[NDA_FDB_EXT_ATTRS]) {
+ struct rtattr *attr = tb[NDA_FDB_EXT_ATTRS];
+ struct rtattr *nfea_tb[NFEA_MAX + 1] = {0};
- dp_static = true;
- nfy_flags = *(uint8_t *)RTA_DATA(tb[NDA_NOTIFY]);
- /* local activity has not been detected on the entry */
- if (nfy_flags & (1 << BR_FDB_NFY_INACTIVE))
- local_inactive = true;
+ netlink_parse_rtattr_nested(nfea_tb, NFEA_MAX, attr);
+ if (nfea_tb[NFEA_ACTIVITY_NOTIFY]) {
+ uint8_t nfy_flags;
+
+ nfy_flags = *(uint8_t *)RTA_DATA(
+ nfea_tb[NFEA_ACTIVITY_NOTIFY]);
+ if (nfy_flags & FDB_NOTIFY_BIT)
+ dp_static = true;
+ if (nfy_flags & FDB_NOTIFY_INACTIVE_BIT)
+ local_inactive = true;
+ }
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -3206,12 +3217,12 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
} else {
/* local mac */
if (update_flags & DPLANE_MAC_SET_STATIC) {
- nfy_flags |= (1 << BR_FDB_NFY_STATIC);
+ nfy_flags |= FDB_NOTIFY_BIT;
state |= NUD_NOARP;
}
if (update_flags & DPLANE_MAC_SET_INACTIVE)
- nfy_flags |= (1 << BR_FDB_NFY_INACTIVE);
+ nfy_flags |= FDB_NOTIFY_INACTIVE_BIT;
nfy = true;
}
diff --git a/zebra/sample_plugin.c b/zebra/sample_plugin.c
index c96a86cc73..464205f2f3 100644
--- a/zebra/sample_plugin.c
+++ b/zebra/sample_plugin.c
@@ -92,7 +92,6 @@ static int sample_process(struct zebra_dplane_provider *prov)
static int init_sample_plugin(struct thread_master *tm)
{
int ret;
- struct zebra_dplane_provider *prov = NULL;
/* Note that we don't use or store the thread_master 'tm'. We
* don't use the zebra main pthread: our plugin code will run in
diff --git a/zebra/subdir.am b/zebra/subdir.am
index cdacabc102..f842a8c0f3 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -40,6 +40,11 @@ if LINUX
module_LTLIBRARIES += zebra/zebra_cumulus_mlag.la
endif
+# Dataplane sample plugin
+if DEV_BUILD
+module_LTLIBRARIES += zebra/dplane_sample_plugin.la
+endif
+
man8 += $(MANBUILD)/frr-zebra.8
## endif ZEBRA
endif
@@ -206,6 +211,12 @@ zebra/zebra_fpm_dt.lo: fpm/fpm.pb-c.h qpb/qpb.pb-c.h
endif
endif
+# Sample dataplane plugin
+if DEV_BUILD
+zebra_dplane_sample_plugin_la_SOURCES = zebra/sample_plugin.c
+zebra_dplane_sample_plugin_la_LDFLAGS = -module -shared -avoid-version -export-dynamic
+endif
+
nodist_zebra_zebra_SOURCES = \
yang/frr-zebra.yang.c \
# end
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index da7f4cf64e..db2b9e002e 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -3684,7 +3684,7 @@ int dplane_show_helper(struct vty *vty, bool detailed)
int dplane_show_provs_helper(struct vty *vty, bool detailed)
{
struct zebra_dplane_provider *prov;
- uint64_t in, in_max, out, out_max;
+ uint64_t in, in_q, in_max, out, out_q, out_max;
vty_out(vty, "Zebra dataplane providers:\n");
@@ -3697,17 +3697,20 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
in = atomic_load_explicit(&prov->dp_in_counter,
memory_order_relaxed);
+ in_q = atomic_load_explicit(&prov->dp_in_queued,
+ memory_order_relaxed);
in_max = atomic_load_explicit(&prov->dp_in_max,
memory_order_relaxed);
out = atomic_load_explicit(&prov->dp_out_counter,
memory_order_relaxed);
+ out_q = atomic_load_explicit(&prov->dp_out_queued,
+ memory_order_relaxed);
out_max = atomic_load_explicit(&prov->dp_out_max,
memory_order_relaxed);
- vty_out(vty,
- "%s (%u): in: %" PRIu64 ", q_max: %" PRIu64
- ", out: %" PRIu64 ", q_max: %" PRIu64 "\n",
- prov->dp_name, prov->dp_id, in, in_max, out, out_max);
+ vty_out(vty, "%s (%u): in: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64"\n",
+ prov->dp_name, prov->dp_id, in, in_q, in_max,
+ out, out_q, out_max);
DPLANE_LOCK();
prov = TAILQ_NEXT(prov, dp_prov_link);
@@ -3912,11 +3915,24 @@ uint32_t dplane_provider_out_ctx_queue_len(struct zebra_dplane_provider *prov)
void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
struct zebra_dplane_ctx *ctx)
{
+ uint64_t curr, high;
+
dplane_provider_lock(prov);
TAILQ_INSERT_TAIL(&(prov->dp_ctx_out_q), ctx,
zd_q_entries);
+ /* Maintain out-queue counters */
+ atomic_fetch_add_explicit(&(prov->dp_out_queued), 1,
+ memory_order_relaxed);
+ curr = atomic_load_explicit(&prov->dp_out_queued,
+ memory_order_relaxed);
+ high = atomic_load_explicit(&prov->dp_out_max,
+ memory_order_relaxed);
+ if (curr > high)
+ atomic_store_explicit(&prov->dp_out_max, curr,
+ memory_order_relaxed);
+
dplane_provider_unlock(prov);
atomic_fetch_add_explicit(&(prov->dp_out_counter), 1,
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 376721f83a..6753bf520c 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -29,6 +29,7 @@
#include "prefix.h"
#include "vlan.h"
#include "json.h"
+#include "printfrr.h"
#include "zebra/zserv.h"
#include "zebra/debug.h"
@@ -254,6 +255,37 @@ static void zebra_evpn_mac_get_access_info(zebra_mac_t *mac,
}
}
+#define MAC_BUF_SIZE 256
+static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac_t_ *mac, char *buf,
+ size_t len)
+{
+ if (mac->flags == 0) {
+ snprintfrr(buf, len, "None ");
+ return buf;
+ }
+
+ snprintfrr(
+ buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router "
+ : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW "
+ : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "LOC Active "
+ : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)
+ ? "LOC Inactive "
+ : "");
+ return buf;
+}
+
static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)
{
struct zebra_vrf *zvrf = NULL;
@@ -278,12 +310,17 @@ static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)
if (!mac)
return 0;
- if (IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
+ "%s: duplicate addr mac %s flags %slearn count %u host count %u auto recovery expired",
__func__,
prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->flags, mac->dad_count, listcount(mac->neigh_list));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ mac->dad_count, listcount(mac->neigh_list));
+ }
/* Remove all IPs as duplicate associcated with this MAC */
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
@@ -350,14 +387,17 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
* Remote MAC event -> hold on installing it.
*/
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
- if (IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
+ "%s: duplicate addr MAC %s flags %sskip update to client, learn count %u recover time %u",
__func__,
prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->flags, mac->dad_count,
- zvrf->dad_freeze_time);
-
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ mac->dad_count, zvrf->dad_freeze_time);
+ }
/* For duplicate MAC do not update
* client but update neigh due to
* this MAC update.
@@ -385,12 +425,17 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
}
if (reset_params) {
- if (IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u",
+ "%s: duplicate addr MAC %s flags %sdetection time passed, reset learn count %u",
__func__,
prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->flags, mac->dad_count);
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ mac->dad_count);
+ }
mac->dad_count = 0;
/* Start dup. addr detection (DAD) start time,
@@ -452,13 +497,18 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
/* Start auto recovery timer for this MAC */
THREAD_OFF(mac->dad_mac_auto_recovery_timer);
if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
- if (IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start",
+ "%s: duplicate addr MAC %s flags %sauto recovery time %u start",
__func__,
prefix_mac2str(&mac->macaddr, buf,
sizeof(buf)),
- mac->flags, zvrf->dad_freeze_time);
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)),
+ zvrf->dad_freeze_time);
+ }
thread_add_timer(zrouter.master,
zebra_evpn_dad_mac_auto_recovery_exp,
@@ -694,7 +744,7 @@ void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
}
static char *zebra_evpn_print_mac_flags(zebra_mac_t *mac, char *flags_buf,
- uint32_t flags_buf_sz)
+ size_t flags_buf_sz)
{
snprintf(flags_buf, flags_buf_sz, "%s%s%s%s",
mac->sync_neigh_cnt ?
@@ -903,14 +953,19 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
- if (IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char flag_buf[MACIP_BUF_SIZE];
+
zlog_debug(
- "Send MACIP %s f 0x%x MAC %s IP %s seq %u L2-VNI %u ESI %s to %s",
- (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags,
+ "Send MACIP %s f %s MAC %s IP %s seq %u L2-VNI %u ESI %s to %s",
+ (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
+ zclient_evpn_dump_macip_flags(flags, flag_buf,
+ sizeof(flag_buf)),
prefix_mac2str(macaddr, buf, sizeof(buf)),
ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni,
es ? es->esi_str : "-",
zebra_route_string(client->proto));
+ }
if (cmd == ZEBRA_MACIP_ADD)
client->macipadd_cnt++;
@@ -982,10 +1037,12 @@ zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr)
mac->uptime = monotime(NULL);
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char buf[ETHER_ADDR_STRLEN];
+ char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %s flags 0x%x", __func__,
+ zlog_debug("%s: MAC %s flags %s", __func__,
prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)));
}
return mac;
}
@@ -999,10 +1056,12 @@ int zebra_evpn_mac_del(zebra_evpn_t *zevpn, zebra_mac_t *mac)
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char buf[ETHER_ADDR_STRLEN];
+ char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %s flags 0x%x", __func__,
+ zlog_debug("%s: MAC %s flags %s", __func__,
prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)));
}
/* If the MAC is freed before the neigh we will end up
@@ -1047,11 +1106,13 @@ static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
&& !listcount(mac->neigh_list)) {
if (IS_ZEBRA_DEBUG_VXLAN) {
char buf[ETHER_ADDR_STRLEN];
+ char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: Del MAC %s flags 0x%x", __func__,
+ "%s: Del MAC %s flags %s", __func__,
prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
}
wctx->uninstall = 0;
@@ -1204,24 +1265,34 @@ int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
if (!ifp) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no access-port",
+ "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port",
caller, zevpn->vni, &mac->macaddr,
- mac->es ? mac->es->esi_str : "-", mac->flags,
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
set_inactive ? "inactive " : "");
+ }
return -1;
}
zif = ifp->info;
br_ifp = zif->brslave_info.br_if;
if (!br_ifp) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no br",
+ "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br",
caller, zevpn->vni, &mac->macaddr,
- mac->es ? mac->es->esi_str : "-", mac->flags,
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
set_inactive ? "inactive " : "");
+ }
return -1;
}
@@ -1236,13 +1307,18 @@ int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
* supported and if the local ES is oper-down.
*/
if (mac->es && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "dp-%s sync-nw-mac vni %u mac %pEA es %s 0x%x %s",
+ "dp-%s sync-nw-mac vni %u mac %pEA es %s %s%s",
set_static ? "install" : "uninstall",
zevpn->vni, &mac->macaddr,
- mac->es ? mac->es->esi_str : "-", mac->flags,
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
set_inactive ? "inactive " : "");
+ }
if (set_static)
/* XXX - old_static needs to be computed more
* accurately
@@ -1256,13 +1332,17 @@ int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
return 0;
}
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
- zlog_debug(
- "dp-install sync-mac vni %u mac %pEA es %s 0x%x %s%s",
- zevpn->vni, &mac->macaddr,
- mac->es ? mac->es->esi_str : "-", mac->flags,
- set_static ? "static " : "",
- set_inactive ? "inactive " : "");
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
+ zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s",
+ zevpn->vni, &mac->macaddr,
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ set_static ? "static " : "",
+ set_inactive ? "inactive " : "");
+ }
dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
set_static, set_inactive);
@@ -1310,12 +1390,17 @@ static int zebra_evpn_mac_hold_exp_cb(struct thread *t)
new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
new_static = zebra_evpn_mac_is_static(mac);
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "sync-mac vni %u mac %s es %s 0x%x hold expired",
+ "sync-mac vni %u mac %s es %s %shold expired",
mac->zevpn->vni,
prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
- mac->es ? mac->es->esi_str : "-", mac->flags);
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)));
+ }
/* re-program the local mac in the dataplane if the mac is no
* longer static
@@ -1340,12 +1425,17 @@ static inline void zebra_evpn_mac_start_hold_timer(zebra_mac_t *mac)
if (mac->hold_timer)
return;
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "sync-mac vni %u mac %s es %s 0x%x hold started",
+ "sync-mac vni %u mac %s es %s %shold started",
mac->zevpn->vni,
prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
- mac->es ? mac->es->esi_str : "-", mac->flags);
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)));
+ }
thread_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac,
zmh_info->mac_hold_time, &mac->hold_timer);
}
@@ -1357,12 +1447,18 @@ void zebra_evpn_mac_stop_hold_timer(zebra_mac_t *mac)
if (!mac->hold_timer)
return;
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "sync-mac vni %u mac %s es %s 0x%x hold stopped",
+ "sync-mac vni %u mac %s es %s %shold stopped",
mac->zevpn->vni,
prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
- mac->es ? mac->es->esi_str : "-", mac->flags);
+ mac->es ? mac->es->esi_str : "-",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)));
+ }
+
THREAD_OFF(mac->hold_timer);
}
@@ -1372,13 +1468,18 @@ void zebra_evpn_sync_mac_del(zebra_mac_t *mac)
bool old_static;
bool new_static;
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "sync-mac del vni %u mac %s es %s seq %d f 0x%x",
+ "sync-mac del vni %u mac %s es %s seq %d f %s",
mac->zevpn->vni,
prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
- mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)));
+ }
+
old_static = zebra_evpn_mac_is_static(mac);
UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
@@ -1418,9 +1519,12 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
*/
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
&& !zebra_evpn_mac_is_ready_for_bgp(mac->flags)) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
+ || IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s-macip accept vni %u %s-mac %s%s%s lower seq %u f 0x%x",
+ "%s-macip accept vni %u %s-mac %s%s%s lower seq %u f %s",
sync ? "sync" : "rem", zevpn->vni,
n_type,
prefix_mac2str(&mac->macaddr, macbuf,
@@ -1429,13 +1533,19 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
ipa_len ? ipaddr2str(ipaddr, ipbuf,
sizeof(ipbuf))
: "",
- tmp_seq, mac->flags);
+ tmp_seq,
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
+ }
+
return true;
}
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "%s-macip ignore vni %u %s-mac %s%s%s as existing has higher seq %u f 0x%x",
+ "%s-macip ignore vni %u %s-mac %s%s%s as existing has higher seq %u f %s",
sync ? "sync" : "rem", zevpn->vni, n_type,
prefix_mac2str(&mac->macaddr, macbuf,
sizeof(macbuf)),
@@ -1443,7 +1553,10 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
ipa_len ? ipaddr2str(ipaddr, ipbuf,
sizeof(ipbuf))
: "",
- tmp_seq, mac->flags);
+ tmp_seq,
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
+ }
return false;
}
@@ -1574,12 +1687,20 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->flags = new_flags;
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags))
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) {
+ char mac_buf[MAC_BUF_SIZE], omac_buf[MAC_BUF_SIZE];
+ struct zebra_mac_t_ omac;
+
+ omac.flags = old_flags;
zlog_debug(
- "sync-mac vni %u mac %s old_f 0x%x new_f 0x%x",
+ "sync-mac vni %u mac %s old_f %snew_f %s",
zevpn->vni,
prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
- old_flags, mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(
+ &omac, omac_buf, sizeof(omac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
+ }
/* update es */
es_change = zebra_evpn_es_mac_ref(mac, esi);
@@ -1613,13 +1734,18 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
inform_bgp = true;
}
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
- zlog_debug("sync-mac %s vni %u mac %s es %s seq %d f 0x%x%s%s",
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
+ zlog_debug("sync-mac %s vni %u mac %s es %s seq %d f %s%s%s",
ctx->mac_created ? "created" : "updated", zevpn->vni,
prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
- mac->flags, inform_bgp ? " inform_bgp" : "",
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ inform_bgp ? "inform_bgp" : "",
inform_dataplane ? " inform_dp" : "");
+ }
if (inform_bgp)
zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
@@ -1869,14 +1995,20 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
/* force drop the sync flags */
old_static = zebra_evpn_mac_is_static(mac);
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "sync-mac->remote vni %u mac %s es %s seq %d f 0x%x",
+ "sync-mac->remote vni %u mac %s es %s seq %d f %s",
zevpn->vni,
prefix_mac2str(macaddr, buf,
sizeof(buf)),
mac->es ? mac->es->esi_str : "-",
- mac->loc_seq, mac->flags);
+ mac->loc_seq,
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
+ }
+
zebra_evpn_mac_clear_sync_info(mac);
zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr,
mac->flags,
@@ -1970,14 +2102,18 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
inform_client = true;
} else {
- if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags 0x%x",
+ "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags %s",
sticky ? "sticky " : "",
prefix_mac2str(macaddr, buf, sizeof(buf)),
ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? "local-inactive " : "",
- mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
+ }
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
struct interface *old_ifp;
@@ -2125,14 +2261,19 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
*/
if ((old_local_inactive != local_inactive)
|| (new_bgp_ready != old_bgp_ready)) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "local mac vni %u mac %s es %s seq %d f 0x%x%s",
+ "local mac vni %u mac %s es %s seq %d f %s%s",
zevpn->vni,
prefix_mac2str(macaddr, buf, sizeof(buf)),
mac->es ? mac->es->esi_str : "", mac->loc_seq,
- mac->flags,
- local_inactive ? " local-inactive" : "");
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ local_inactive ? "local-inactive" : "");
+ }
+
if (!is_dup_detect)
inform_client = true;
}
@@ -2177,12 +2318,18 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
return 0;
- if (IS_ZEBRA_DEBUG_VXLAN)
+ if (IS_ZEBRA_DEBUG_VXLAN) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
+ "DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags %snbr count %u",
prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
ifp->ifindex, mac->fwd_info.local.vid, zevpn->vni,
- mac->loc_seq, mac->flags, listcount(mac->neigh_list));
+ mac->loc_seq,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
+ sizeof(mac_buf)),
+ listcount(mac->neigh_list));
+ }
old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
if (zebra_evpn_mac_is_static(mac)) {
@@ -2191,13 +2338,17 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
*/
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
+ char mac_buf[MAC_BUF_SIZE];
+
zlog_debug(
- "re-add sync-mac vni %u mac %s es %s seq %d f 0x%x",
+ "re-add sync-mac vni %u mac %s es %s seq %d f %s",
zevpn->vni,
prefix_mac2str(macaddr, buf, sizeof(buf)),
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
- mac->flags);
+ zebra_evpn_zebra_mac_flag_dump(
+ mac, mac_buf, sizeof(mac_buf)));
+ }
/* inform-bgp about change in local-activity if any */
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
diff --git a/zebra/zebra_evpn_mac.h b/zebra/zebra_evpn_mac.h
index 1730991f1e..e21b610501 100644
--- a/zebra/zebra_evpn_mac.h
+++ b/zebra/zebra_evpn_mac.h
@@ -56,6 +56,7 @@ struct zebra_mac_t_ {
/* MAC address. */
struct ethaddr macaddr;
+ /* When modifying flags please fixup zebra_evpn_zebra_mac_flag_dump */
uint32_t flags;
#define ZEBRA_MAC_LOCAL 0x01
#define ZEBRA_MAC_REMOTE 0x02
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 2bf48c6277..18ccbb79fb 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -273,6 +273,11 @@ struct zfpm_glob {
* If non-zero, the last time when statistics were cleared.
*/
time_t last_stats_clear_time;
+
+ /*
+ * Flag to track the MAC dump status to FPM
+ */
+ bool fpm_mac_dump_done;
};
static struct zfpm_glob zfpm_glob_space;
@@ -517,8 +522,6 @@ static int zfpm_conn_up_thread_cb(struct thread *thread)
struct zfpm_rnodes_iter *iter;
rib_dest_t *dest;
- zfpm_g->t_conn_up = NULL;
-
iter = &zfpm_g->t_conn_up_state.iter;
if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) {
@@ -528,8 +531,13 @@ static int zfpm_conn_up_thread_cb(struct thread *thread)
goto done;
}
- /* Enqueue FPM updates for all the RMAC entries */
- hash_iterate(zrouter.l3vni_table, zfpm_iterate_rmac_table, NULL);
+ if (!zfpm_g->fpm_mac_dump_done) {
+ /* Enqueue FPM updates for all the RMAC entries */
+ hash_iterate(zrouter.l3vni_table, zfpm_iterate_rmac_table,
+ NULL);
+ /* mark dump done so that its not repeated after yield */
+ zfpm_g->fpm_mac_dump_done = true;
+ }
while ((rnode = zfpm_rnodes_iter_next(iter))) {
dest = rib_dest_from_rnode(rnode);
@@ -547,7 +555,6 @@ static int zfpm_conn_up_thread_cb(struct thread *thread)
zfpm_g->stats.t_conn_up_yields++;
zfpm_rnodes_iter_pause(iter);
- zfpm_g->t_conn_up = NULL;
thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb,
NULL, 0, &zfpm_g->t_conn_up);
return 0;
@@ -575,12 +582,13 @@ static void zfpm_connection_up(const char *detail)
/*
* Start thread to push existing routes to the FPM.
*/
- assert(!zfpm_g->t_conn_up);
+ thread_cancel(&zfpm_g->t_conn_up);
zfpm_rnodes_iter_init(&zfpm_g->t_conn_up_state.iter);
+ zfpm_g->fpm_mac_dump_done = false;
zfpm_debug("Starting conn_up thread");
- zfpm_g->t_conn_up = NULL;
+
thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0,
&zfpm_g->t_conn_up);
zfpm_g->stats.t_conn_up_starts++;
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 44f574073c..f7c5da5dec 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -133,6 +133,7 @@ struct netlink_nh_info {
* A structure for holding information for a netlink route message.
*/
struct netlink_route_info {
+ uint32_t nlmsg_pid;
uint16_t nlmsg_type;
uint8_t rtm_type;
uint32_t rtm_table;
@@ -244,14 +245,20 @@ static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd,
rib_dest_t *dest, struct route_entry *re)
{
struct nexthop *nexthop;
+ struct rib_table_info *table_info =
+ rib_table_info(rib_dest_table(dest));
+ struct zebra_vrf *zvrf = table_info->zvrf;
memset(ri, 0, sizeof(*ri));
ri->prefix = rib_dest_prefix(dest);
ri->af = rib_dest_af(dest);
+ if (zvrf && zvrf->zns)
+ ri->nlmsg_pid = zvrf->zns->netlink_dplane.snl.nl_pid;
+
ri->nlmsg_type = cmd;
- ri->rtm_table = rib_table_info(rib_dest_table(dest))->table_id;
+ ri->rtm_table = table_info->table_id;
ri->rtm_protocol = RTPROT_UNSPEC;
/*
@@ -357,6 +364,7 @@ static int netlink_route_info_encode(struct netlink_route_info *ri,
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+ req->n.nlmsg_pid = ri->nlmsg_pid;
req->n.nlmsg_type = ri->nlmsg_type;
req->r.rtm_family = ri->af;
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 375be45df0..0a692feb35 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -2120,7 +2120,6 @@ static unsigned nexthop_active_check(struct route_node *rn,
struct interface *ifp;
route_map_result_t ret = RMAP_PERMITMATCH;
int family;
- char buf[SRCDEST2STR_BUFFER];
const struct prefix *p, *src_p;
struct zebra_vrf *zvrf;
@@ -2230,10 +2229,9 @@ static unsigned nexthop_active_check(struct route_node *rn,
zvrf, re->tag);
if (ret == RMAP_DENYMATCH) {
if (IS_ZEBRA_DEBUG_RIB) {
- srcdest_rnode2str(rn, buf, sizeof(buf));
zlog_debug(
- "%u:%s: Filtering out with NH out %s due to route map",
- re->vrf_id, buf,
+ "%u:%pRN: Filtering out with NH out %s due to route map",
+ re->vrf_id, rn,
ifindex2ifname(nexthop->ifindex,
nexthop->vrf_id));
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 1f92c43a69..8914f9c59c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -38,6 +38,7 @@
#include "workqueue.h"
#include "nexthop_group_private.h"
#include "frr_pthread.h"
+#include "printfrr.h"
#include "zebra/zebra_router.h"
#include "zebra/connected.h"
@@ -148,6 +149,30 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn,
zlog(priority, "%s: (%u:%u):%s: %s", _func, vrf_id, table, buf, msgbuf);
}
+static char *_dump_re_status(const struct route_entry *re, char *buf,
+ size_t len)
+{
+ if (re->status == 0) {
+ snprintfrr(buf, len, "None ");
+ return buf;
+ }
+
+ snprintfrr(
+ buf, len, "%s%s%s%s%s%s%s",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) ? "Removed " : "",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) ? "Changed " : "",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED)
+ ? "Label Changed "
+ : "",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) ? "Queued " : "",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) ? "Installed "
+ : "",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED) ? "Failed " : "",
+ CHECK_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG) ? "Fib NHG "
+ : "");
+ return buf;
+}
+
#define rnode_debug(node, vrf_id, ...) \
_rnode_zlog(__func__, vrf_id, node, LOG_DEBUG, __VA_ARGS__)
#define rnode_info(node, ...) \
@@ -1080,12 +1105,20 @@ static void rib_process(struct route_node *rn)
}
RNODE_FOREACH_RE_SAFE (rn, re, next) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ char flags_buf[128];
+ char status_buf[128];
+
zlog_debug(
- "%s(%u:%u):%s: Examine re %p (%s) status %x flags %x dist %d metric %d",
+ "%s(%u:%u):%s: Examine re %p (%s) status: %sflags: %sdist %d metric %d",
VRF_LOGNAME(vrf), vrf_id, re->table, buf, re,
- zebra_route_string(re->type), re->status,
- re->flags, re->distance, re->metric);
+ zebra_route_string(re->type),
+ _dump_re_status(re, status_buf,
+ sizeof(status_buf)),
+ zclient_dump_route_flags(re->flags, flags_buf,
+ sizeof(flags_buf)),
+ re->distance, re->metric);
+ }
/* Currently selected re. */
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
@@ -1107,6 +1140,9 @@ static void rib_process(struct route_node *rn)
*/
if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) {
if (!nexthop_active_update(rn, re)) {
+ const struct prefix *p;
+ struct rib_table_info *info;
+
if (re->type == ZEBRA_ROUTE_TABLE) {
/* XXX: HERE BE DRAGONS!!!!!
* In all honesty, I have not yet
@@ -1136,6 +1172,11 @@ static void rib_process(struct route_node *rn)
ROUTE_ENTRY_REMOVED);
}
+ info = srcdest_rnode_table_info(rn);
+ srcdest_rnode_prefixes(rn, &p, NULL);
+ zsend_route_notify_owner(re, p,
+ ZAPI_ROUTE_FAIL_INSTALL,
+ info->afi, info->safi);
continue;
}
} else {
@@ -2791,6 +2832,8 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
bool is_srcdst = src_p && src_p->prefixlen;
char straddr[PREFIX_STRLEN];
char srcaddr[PREFIX_STRLEN];
+ char flags_buf[128];
+ char status_buf[128];
struct nexthop *nexthop;
struct vrf *vrf = vrf_lookup_by_id(re->vrf_id);
struct nexthop_group *nhg;
@@ -2804,9 +2847,12 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d",
straddr, (unsigned long)re->uptime, re->type, re->instance,
re->table);
- zlog_debug("%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
- straddr, re->metric, re->mtu, re->distance, re->flags,
- re->status);
+ zlog_debug(
+ "%s: metric == %u, mtu == %u, distance == %u, flags == %sstatus == %s",
+ straddr, re->metric, re->mtu, re->distance,
+ zclient_dump_route_flags(re->flags, flags_buf,
+ sizeof(flags_buf)),
+ _dump_re_status(re, status_buf, sizeof(status_buf)));
zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
nexthop_group_nexthop_num(&(re->nhe->nhg)),
nexthop_group_active_nexthop_num(&(re->nhe->nhg)));
@@ -2941,8 +2987,10 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
struct nhg_hash_entry *nhe = NULL;
struct route_table *table;
struct route_node *rn;
- struct route_entry *same = NULL;
+ struct route_entry *same = NULL, *first_same = NULL;
int ret = 0;
+ int same_count = 0;
+ rib_dest_t *dest;
if (!re || !re_nhe)
return -1;
@@ -3010,14 +3058,22 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
* for the install don't do a route replace.
*/
RNODE_FOREACH_RE (rn, same) {
- if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
+ if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) {
+ same_count++;
continue;
+ }
/* Compare various route_entry properties */
- if (rib_compare_routes(re, same))
- break;
+ if (rib_compare_routes(re, same)) {
+ same_count++;
+
+ if (first_same == NULL)
+ first_same = same;
+ }
}
+ same = first_same;
+
/* If this route is kernel/connected route, notify the dataplane. */
if (RIB_SYSTEM_ROUTE(re)) {
/* Notify dataplane */
@@ -3027,8 +3083,9 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
/* Link new re to node.*/
if (IS_ZEBRA_DEBUG_RIB) {
rnode_debug(rn, re->vrf_id,
- "Inserting route rn %p, re %p (%s) existing %p",
- rn, re, zebra_route_string(re->type), same);
+ "Inserting route rn %p, re %p (%s) existing %p, same_count %d",
+ rn, re, zebra_route_string(re->type), same,
+ same_count);
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
route_entry_dump(p, src_p, re);
@@ -3042,6 +3099,24 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
if (same)
rib_delnode(rn, same);
+ /* See if we can remove some RE entries that are queued for
+ * removal, but won't be considered in rib processing.
+ */
+ dest = rib_dest_from_rnode(rn);
+ RNODE_FOREACH_RE_SAFE (rn, re, same) {
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
+ /* If the route was used earlier, must retain it. */
+ if (dest && re == dest->selected_fib)
+ continue;
+
+ if (IS_ZEBRA_DEBUG_RIB)
+ rnode_debug(rn, re->vrf_id, "rn %p, removing unneeded re %p",
+ rn, re);
+
+ rib_unlink(rn, re);
+ }
+ }
+
route_unlock_node(rn);
return ret;
}
@@ -3378,7 +3453,8 @@ static void rib_update_route_node(struct route_node *rn, int type)
}
/* Schedule routes of a particular table (address-family) based on event. */
-void rib_update_table(struct route_table *table, enum rib_update_event event)
+void rib_update_table(struct route_table *table, enum rib_update_event event,
+ int rtype)
{
struct route_node *rn;
@@ -3391,12 +3467,12 @@ void rib_update_table(struct route_table *table, enum rib_update_event event)
: NULL;
vrf = zvrf ? zvrf->vrf : NULL;
- zlog_debug("%s: %s VRF %s Table %u event %s", __func__,
+ zlog_debug("%s: %s VRF %s Table %u event %s Route type: %s", __func__,
table->info ? afi2str(
((struct rib_table_info *)table->info)->afi)
: "Unknown",
VRF_LOGNAME(vrf), zvrf ? zvrf->table_id : 0,
- rib_update_event2str(event));
+ rib_update_event2str(event), zebra_route_string(rtype));
}
/* Walk all routes and queue for processing, if appropriate for
@@ -3419,7 +3495,7 @@ void rib_update_table(struct route_table *table, enum rib_update_event event)
break;
case RIB_UPDATE_RMAP_CHANGE:
case RIB_UPDATE_OTHER:
- rib_update_route_node(rn, ZEBRA_ROUTE_ALL);
+ rib_update_route_node(rn, rtype);
break;
default:
break;
@@ -3427,7 +3503,8 @@ void rib_update_table(struct route_table *table, enum rib_update_event event)
}
}
-static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event)
+static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event,
+ int rtype)
{
struct route_table *table;
@@ -3438,14 +3515,14 @@ static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event)
/* Process routes of interested address-families. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
if (table)
- rib_update_table(table, event);
+ rib_update_table(table, event, rtype);
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
if (table)
- rib_update_table(table, event);
+ rib_update_table(table, event, rtype);
}
-static void rib_update_handle_vrf_all(enum rib_update_event event)
+static void rib_update_handle_vrf_all(enum rib_update_event event, int rtype)
{
struct zebra_router_table *zrt;
@@ -3455,7 +3532,7 @@ static void rib_update_handle_vrf_all(enum rib_update_event event)
/* Just iterate over all the route tables, rather than vrf lookups */
RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables)
- rib_update_table(zrt->table, event);
+ rib_update_table(zrt->table, event, rtype);
}
struct rib_update_ctx {
@@ -3489,9 +3566,9 @@ static int rib_update_handler(struct thread *thread)
ctx = THREAD_ARG(thread);
if (ctx->vrf_all)
- rib_update_handle_vrf_all(ctx->event);
+ rib_update_handle_vrf_all(ctx->event, ZEBRA_ROUTE_ALL);
else
- rib_update_handle_vrf(ctx->vrf_id, ctx->event);
+ rib_update_handle_vrf(ctx->vrf_id, ctx->event, ZEBRA_ROUTE_ALL);
rib_update_ctx_fini(&ctx);
@@ -3504,26 +3581,6 @@ static int rib_update_handler(struct thread *thread)
*/
static struct thread *t_rib_update_threads[RIB_UPDATE_MAX];
-/* Schedule a RIB update event for specific vrf */
-void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event)
-{
- struct rib_update_ctx *ctx;
-
- ctx = rib_update_ctx_init(vrf_id, event);
-
- /* Don't worry about making sure multiple rib updates for specific vrf
- * are scheduled at once for now. If it becomes a problem, we can use a
- * lookup of some sort to keep track of running threads via t_vrf_id
- * like how we are doing it in t_rib_update_threads[].
- */
- thread_add_event(zrouter.master, rib_update_handler, ctx, 0, NULL);
-
- if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: Scheduled VRF %s, event %s", __func__,
- vrf_id_to_name(ctx->vrf_id),
- rib_update_event2str(event));
-}
-
/* Schedule a RIB update event for all vrfs */
void rib_update(enum rib_update_event event)
{
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index bbc8b6f19d..229b705ec9 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -267,7 +267,8 @@ static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
/* Process routes of interested address-families. */
table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
if (table)
- rib_update_table(table, RIB_UPDATE_RMAP_CHANGE);
+ rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
+ rtype);
}
return CMD_SUCCESS;
@@ -294,7 +295,8 @@ static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
/* Process routes of interested address-families. */
table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
if (table)
- rib_update_table(table, RIB_UPDATE_RMAP_CHANGE);
+ rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
+ rtype);
}
XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
}
@@ -576,7 +578,7 @@ DEFUN (zebra_route_map_timer,
ZEBRA_STR
"Set route-map parameters\n"
"Time to wait before route-map updates are processed\n"
- "0 means event-driven updates are disabled\n")
+ "0 means route-map changes are run immediately instead of delaying\n")
{
int idx_number = 3;
uint32_t rmap_delay_timer;
@@ -594,7 +596,7 @@ DEFUN (no_zebra_route_map_timer,
ZEBRA_STR
"Set route-map parameters\n"
"Reset delay-timer to default value, 30 secs\n"
- "0 means event-driven updates are disabled\n")
+ "0 means route-map changes are run immediately instead of delaying\n")
{
zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
@@ -1454,8 +1456,6 @@ static void zebra_rib_table_rm_update(const char *rmap)
struct vrf *vrf = NULL;
struct zebra_vrf *zvrf = NULL;
char *rmap_name;
- char afi_ip = 0;
- char afi_ipv6 = 0;
struct route_map *old = NULL;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
@@ -1486,16 +1486,12 @@ static void zebra_rib_table_rm_update(const char *rmap)
PROTO_RM_MAP(zvrf, AFI_IP, i));
/* There is single rib table for all protocols
*/
- if (afi_ip == 0) {
- table = zvrf->table[AFI_IP]
- [SAFI_UNICAST];
- if (table) {
-
- afi_ip = 1;
- rib_update_table(
- table,
- RIB_UPDATE_RMAP_CHANGE);
- }
+ table = zvrf->table[AFI_IP][SAFI_UNICAST];
+ if (table) {
+ rib_update_table(
+ table,
+ RIB_UPDATE_RMAP_CHANGE,
+ i);
}
}
rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
@@ -1515,16 +1511,12 @@ static void zebra_rib_table_rm_update(const char *rmap)
PROTO_RM_MAP(zvrf, AFI_IP6, i));
/* There is single rib table for all protocols
*/
- if (afi_ipv6 == 0) {
- table = zvrf->table[AFI_IP6]
- [SAFI_UNICAST];
- if (table) {
-
- afi_ipv6 = 1;
- rib_update_table(
- table,
- RIB_UPDATE_RMAP_CHANGE);
- }
+ table = zvrf->table[AFI_IP6][SAFI_UNICAST];
+ if (table) {
+ rib_update_table(
+ table,
+ RIB_UPDATE_RMAP_CHANGE,
+ i);
}
}
}
@@ -1628,8 +1620,6 @@ static void zebra_route_map_process_update_cb(char *rmap_name)
static int zebra_route_map_update_timer(struct thread *thread)
{
- zebra_t_rmap_update = NULL;
-
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("Event driven route-map update triggered");
@@ -1654,8 +1644,8 @@ static void zebra_route_map_set_delay_timer(uint32_t value)
if (!value && zebra_t_rmap_update) {
/* Event driven route map updates is being disabled */
/* But there's a pending timer. Fire it off now */
- thread_cancel(&zebra_t_rmap_update);
- zebra_route_map_update_timer(zebra_t_rmap_update);
+ THREAD_OFF(zebra_t_rmap_update);
+ zebra_route_map_update_timer(NULL);
}
}
@@ -1664,7 +1654,7 @@ void zebra_routemap_finish(void)
/* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
zebra_rmap_update_timer = 0;
/* Thread off if any scheduled already */
- thread_cancel(&zebra_t_rmap_update);
+ THREAD_OFF(zebra_t_rmap_update);
route_map_finish();
}
@@ -1780,12 +1770,11 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
static void zebra_route_map_mark_update(const char *rmap_name)
{
/* rmap_update_timer of 0 means don't do route updates */
- if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
- zebra_t_rmap_update = NULL;
- thread_add_timer(zrouter.master, zebra_route_map_update_timer,
- NULL, zebra_rmap_update_timer,
- &zebra_t_rmap_update);
- }
+ if (zebra_rmap_update_timer)
+ THREAD_OFF(zebra_t_rmap_update);
+
+ thread_add_timer(zrouter.master, zebra_route_map_update_timer,
+ NULL, zebra_rmap_update_timer, &zebra_t_rmap_update);
}
static void zebra_route_map_add(const char *rmap_name)