summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/connected.c21
-rw-r--r--zebra/main.c15
-rw-r--r--zebra/rt_netlink.c14
-rw-r--r--zebra/zapi_msg.c27
-rw-r--r--zebra/zapi_msg.h3
-rw-r--r--zebra/zebra_nb_config.c28
-rw-r--r--zebra/zebra_rib.c38
-rw-r--r--zebra/zebra_routemap.c283
-rw-r--r--zebra/zebra_router.c10
-rw-r--r--zebra/zebra_router.h5
-rw-r--r--zebra/zebra_vty.c47
11 files changed, 293 insertions, 198 deletions
diff --git a/zebra/connected.c b/zebra/connected.c
index 6a1efc3e65..70ea2e3805 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -41,6 +41,7 @@
#include "zebra/zebra_mpls.h"
#include "zebra/debug.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_router.h"
/* communicate the withdrawal of a connected address */
static void connected_withdraw(struct connected *ifc)
@@ -207,6 +208,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
};
struct zebra_vrf *zvrf;
uint32_t metric;
+ uint32_t flags = 0;
zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
if (!zvrf) {
@@ -251,11 +253,22 @@ void connected_up(struct interface *ifp, struct connected *ifc)
metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
ifc->metric : ifp->metric;
- rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
- 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
- rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
- 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
+ /*
+ * Since we are hand creating the connected routes
+ * in our main routing table, *if* we are working
+ * in an offloaded environment then we need to
+ * pretend like the route is offloaded so everything
+ * else will work
+ */
+ if (zrouter.asic_offloaded)
+ flags |= ZEBRA_FLAG_OFFLOADED;
+
+ rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
+ flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
+
+ rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
+ flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
diff --git a/zebra/main.c b/zebra/main.c
index ced29e1a25..55fd3244cb 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -83,6 +83,8 @@ uint32_t nl_rcvbufsize = 4194304;
#endif /* HAVE_NETLINK */
#define OPTION_V6_RR_SEMANTICS 2000
+#define OPTION_ASIC_OFFLOAD 2001
+
/* Command line options. */
const struct option longopts[] = {
{"batch", no_argument, NULL, 'b'},
@@ -92,6 +94,7 @@ const struct option longopts[] = {
{"retain", no_argument, NULL, 'r'},
{"vrfdefaultname", required_argument, NULL, 'o'},
{"graceful_restart", required_argument, NULL, 'K'},
+ {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD},
#ifdef HAVE_NETLINK
{"vrfwnetns", no_argument, NULL, 'n'},
{"nl-bufsize", required_argument, NULL, 's'},
@@ -281,6 +284,8 @@ int main(int argc, char **argv)
char *vrf_default_name_configured = NULL;
struct sockaddr_storage dummy;
socklen_t dummylen;
+ bool asic_offload = false;
+ bool notify_on_ack = true;
graceful_restart = 0;
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
@@ -301,6 +306,7 @@ int main(int argc, char **argv)
" -r, --retain When program terminates, retain added route by zebra.\n"
" -o, --vrfdefaultname Set default VRF name.\n"
" -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
+ " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
#ifdef HAVE_NETLINK
" -n, --vrfwnetns Use NetNS as VRF backend\n"
" -s, --nl-bufsize Set netlink receive buffer size\n"
@@ -366,6 +372,13 @@ int main(int argc, char **argv)
case OPTION_V6_RR_SEMANTICS:
v6_rr_semantics = true;
break;
+ case OPTION_ASIC_OFFLOAD:
+ if (!strcmp(optarg, "notify_on_offload"))
+ notify_on_ack = false;
+ if (!strcmp(optarg, "notify_on_ack"))
+ notify_on_ack = true;
+ asic_offload = true;
+ break;
#endif /* HAVE_NETLINK */
default:
frr_help_exit(1);
@@ -376,7 +389,7 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
/* Zebra related initialize. */
- zebra_router_init();
+ zebra_router_init(asic_offload, notify_on_ack);
zserv_init();
rib_init();
zebra_if_init();
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index ef51989a0c..3402edf467 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -642,7 +642,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
selfroute = is_selfroute(rtm->rtm_protocol);
- if (!startup && selfroute && h->nlmsg_type == RTM_NEWROUTE) {
+ if (!startup && selfroute
+ && h->nlmsg_type == RTM_NEWROUTE
+ && !zrouter.asic_offloaded) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Route type: %d Received that we think we have originated, ignoring",
rtm->rtm_protocol);
@@ -672,6 +674,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
flags |= ZEBRA_FLAG_TRAPPED;
if (rtm->rtm_flags & RTM_F_OFFLOAD)
flags |= ZEBRA_FLAG_OFFLOADED;
+ if (rtm->rtm_flags & RTM_F_OFFLOAD_FAILED)
+ flags |= ZEBRA_FLAG_OFFLOAD_FAILED;
/* Route which inserted by Zebra. */
if (selfroute) {
@@ -3179,10 +3183,14 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
update_flags = dplane_ctx_mac_get_update_flags(ctx);
if (update_flags & DPLANE_MAC_REMOTE) {
flags |= NTF_SELF;
- if (dplane_ctx_mac_is_sticky(ctx))
+ if (dplane_ctx_mac_is_sticky(ctx)) {
+ /* NUD_NOARP prevents the entry from expiring */
+ state |= NUD_NOARP;
+ /* sticky the entry from moving */
flags |= NTF_STICKY;
- else
+ } else {
flags |= NTF_EXT_LEARNED;
+ }
/* if it was static-local previously we need to clear the
* notify flags on replace with remote
*/
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 18017c9700..1d68019909 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -742,7 +742,8 @@ static int nhg_notify(uint16_t type, uint16_t instance, uint32_t id,
static int route_notify_internal(const struct prefix *p, int type,
uint16_t instance, vrf_id_t vrf_id,
uint32_t table_id,
- enum zapi_route_notify_owner note)
+ enum zapi_route_notify_owner note,
+ afi_t afi, safi_t safi)
{
struct zserv *client;
struct stream *s;
@@ -778,16 +779,21 @@ static int route_notify_internal(const struct prefix *p, int type,
stream_putl(s, table_id);
+ /* Encode AFI, SAFI in the message */
+ stream_putc(s, afi);
+ stream_putc(s, safi);
+
stream_putw_at(s, 0, stream_get_endp(s));
return zserv_send_message(client, s);
}
int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
- enum zapi_route_notify_owner note)
+ enum zapi_route_notify_owner note,
+ afi_t afi, safi_t safi)
{
return (route_notify_internal(p, re->type, re->instance, re->vrf_id,
- re->table, note));
+ re->table, note, afi, safi));
}
/*
@@ -801,7 +807,19 @@ int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
dplane_ctx_get_instance(ctx),
dplane_ctx_get_vrf(ctx),
dplane_ctx_get_table(ctx),
- note));
+ note,
+ dplane_ctx_get_afi(ctx),
+ dplane_ctx_get_safi(ctx)));
+}
+
+static void zread_route_notify_request(ZAPI_HANDLER_ARGS)
+{
+ uint8_t notify;
+
+ STREAM_GETC(msg, notify);
+ client->notify_owner = notify;
+stream_failure:
+ return;
}
void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
@@ -3275,6 +3293,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
[ZEBRA_NHG_ADD] = zread_nhg_add,
[ZEBRA_NHG_DEL] = zread_nhg_del,
+ [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
};
/*
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index 9f23a313bf..efc52059b6 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -77,7 +77,8 @@ extern int zsend_interface_link_params(struct zserv *zclient,
extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw);
extern int zsend_route_notify_owner(struct route_entry *re,
const struct prefix *p,
- enum zapi_route_notify_owner note);
+ enum zapi_route_notify_owner note,
+ afi_t afi, safi_t safi);
extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
enum zapi_route_notify_owner note);
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index df95770307..ea2e20ed3b 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -1550,12 +1550,14 @@ int lib_route_map_entry_set_action_source_v4_modify(
if (pif != NULL)
break;
}
- if (pif == NULL) {
- snprintf(args->errmsg, args->errmsg_len,
- "is not a local address: %s",
- yang_dnode_get_string(args->dnode, NULL));
- return NB_ERR_VALIDATION;
- }
+ /*
+ * On startup the local address *may* not have come up
+ * yet. We need to allow startup configuration of
+ * set src or we are fudged. Log it for future fun
+ */
+ if (pif == NULL)
+ zlog_warn("set src %pI4 is not a local address",
+ &p.u.prefix4);
return NB_OK;
case NB_EV_PREPARE:
case NB_EV_ABORT:
@@ -1618,12 +1620,14 @@ int lib_route_map_entry_set_action_source_v6_modify(
if (pif != NULL)
break;
}
- if (pif == NULL) {
- snprintf(args->errmsg, args->errmsg_len,
- "is not a local adddress: %s",
- yang_dnode_get_string(args->dnode, NULL));
- return NB_ERR_VALIDATION;
- }
+ /*
+ * On startup the local address *may* not have come up
+ * yet. We need to allow startup configuration of
+ * set src or we are fudged. Log it for future fun
+ */
+ if (pif == NULL)
+ zlog_warn("set src %pI6 is not a local address",
+ &p.u.prefix6);
return NB_OK;
case NB_EV_PREPARE:
case NB_EV_ABORT:
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index e76ecc85a6..569b23573c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -481,7 +481,8 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
* know that they've lost
*/
if (old && (old != re) && (old->type != re->type))
- zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON);
+ zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON,
+ info->afi, info->safi);
/* Update fib selection */
dest->selected_fib = re;
@@ -1748,6 +1749,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
uint32_t seq;
rib_dest_t *dest;
bool fib_changed = false;
+ struct rib_table_info *info;
zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx));
vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
@@ -1767,6 +1769,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
dest = rib_dest_from_rnode(rn);
srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
+ info = srcdest_rnode_table_info(rn);
op = dplane_ctx_get_op(ctx);
status = dplane_ctx_get_status(ctx);
@@ -1818,8 +1821,12 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
"%s(%u):%pFX Stale dplane result for re %p",
VRF_LOGNAME(vrf),
dplane_ctx_get_vrf(ctx), dest_pfx, re);
- } else
- UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ } else {
+ if (!zrouter.asic_offloaded ||
+ (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) ||
+ CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED)))
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ }
}
if (old_re) {
@@ -1896,8 +1903,23 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
zvrf->installs++;
/* Notify route owner */
- zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
-
+ if (zebra_router_notify_on_ack())
+ zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
+ else {
+ if (re) {
+ if (CHECK_FLAG(re->flags,
+ ZEBRA_FLAG_OFFLOADED))
+ zsend_route_notify_owner_ctx(
+ ctx,
+ ZAPI_ROUTE_INSTALLED);
+ if (CHECK_FLAG(
+ re->flags,
+ ZEBRA_FLAG_OFFLOAD_FAILED))
+ zsend_route_notify_owner_ctx(
+ ctx,
+ ZAPI_ROUTE_FAIL_INSTALL);
+ }
+ }
} else {
if (re) {
SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
@@ -1906,7 +1928,8 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
if (re)
zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_FAIL_INSTALL);
+ ZAPI_ROUTE_FAIL_INSTALL,
+ info->afi, info->safi);
zlog_warn("%s(%u:%u):%pFX: Route install failed",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
@@ -2063,7 +2086,8 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
}
/* Ensure we clear the QUEUED flag */
- UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ if (!zrouter.asic_offloaded)
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
/* Is this a notification that ... matters? We mostly care about
* the route that is currently selected for installation; we may also
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 294f2c17ff..7b0a1e3d9c 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -64,19 +64,17 @@ static void zebra_route_map_set_delay_timer(uint32_t value);
* Match function return 1 if match is success else return 0
*/
static enum route_map_cmd_result_t
-route_match_tag(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA) {
- tag = rule;
- nh_data = object;
+ tag = rule;
+ nh_data = object;
+
+ if (nh_data->tag == *tag)
+ return RMAP_MATCH;
- if (nh_data->tag == *tag)
- return RMAP_MATCH;
- }
return RMAP_NOMATCH;
}
@@ -92,25 +90,23 @@ static const struct route_map_rule_cmd route_match_tag_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
struct nh_rmap_obj *nh_data;
char *ifname = rule;
ifindex_t ifindex;
- if (type == RMAP_ZEBRA) {
- if (strcasecmp(ifname, "any") == 0)
- return RMAP_MATCH;
- nh_data = object;
- if (!nh_data || !nh_data->nexthop)
- return RMAP_NOMATCH;
- ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
- if (ifindex == 0)
- return RMAP_NOMATCH;
- if (nh_data->nexthop->ifindex == ifindex)
- return RMAP_MATCH;
- }
+ if (strcasecmp(ifname, "any") == 0)
+ return RMAP_MATCH;
+ nh_data = object;
+ if (!nh_data || !nh_data->nexthop)
+ return RMAP_NOMATCH;
+ ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
+ if (ifindex == 0)
+ return RMAP_NOMATCH;
+ if (nh_data->nexthop->ifindex == ifindex)
+ return RMAP_MATCH;
+
return RMAP_NOMATCH;
}
@@ -938,40 +934,35 @@ DEFPY_YANG (show_ipv6_protocol_nht,
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_ip_next_hop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
- if (type == RMAP_ZEBRA) {
- nh_data = object;
- if (!nh_data)
- return RMAP_NOMATCH;
-
- switch (nh_data->nexthop->type) {
- case NEXTHOP_TYPE_IFINDEX:
- /* Interface routes can't match ip next-hop */
- return RMAP_NOMATCH;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- case NEXTHOP_TYPE_IPV4:
- p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
- p.prefixlen = IPV4_MAX_BITLEN;
- break;
- default:
- return RMAP_NOMATCH;
- }
- alist = access_list_lookup(AFI_IP, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ nh_data = object;
+ if (!nh_data)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, &p) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
+ switch (nh_data->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ /* Interface routes can't match ip next-hop */
+ return RMAP_NOMATCH;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV4:
+ p.family = AF_INET;
+ p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ break;
+ default:
+ return RMAP_NOMATCH;
}
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_IP, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
+
+ return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `ip next-hop' match statement. `arg' should be
@@ -999,39 +990,35 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
static enum route_map_cmd_result_t
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
- return RMAP_NOMATCH;
-
- switch (nh_data->nexthop->type) {
- case NEXTHOP_TYPE_IFINDEX:
- /* Interface routes can't match ip next-hop */
- return RMAP_NOMATCH;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- case NEXTHOP_TYPE_IPV4:
- p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
- p.prefixlen = IPV4_MAX_BITLEN;
- break;
- default:
- return RMAP_NOMATCH;
- }
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, &p) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
+ switch (nh_data->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ /* Interface routes can't match ip next-hop */
+ return RMAP_NOMATCH;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV4:
+ p.family = AF_INET;
+ p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ break;
+ default:
+ return RMAP_NOMATCH;
}
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
+
+ return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
@@ -1058,34 +1045,28 @@ static const struct route_map_rule_cmd
zero. */
static enum route_map_cmd_result_t
route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct access_list *alist;
- if (type == RMAP_ZEBRA) {
- alist = access_list_lookup(afi, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(afi, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, prefix) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static enum route_map_cmd_result_t
-route_match_ip_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
{
- return route_match_address(AFI_IP, rule, prefix, type, object);
+ return route_match_address(AFI_IP, rule, prefix, object);
}
static enum route_map_cmd_result_t
-route_match_ipv6_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
{
- return route_match_address(AFI_IP6, rule, prefix, type, object);
+ return route_match_address(AFI_IP6, rule, prefix, object);
}
/* Route map `ip address' match statement. `arg' should be
@@ -1121,28 +1102,23 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
static enum route_map_cmd_result_t
route_match_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object, afi_t afi)
+ void *object, afi_t afi)
{
struct prefix_list *plist;
- if (type == RMAP_ZEBRA) {
- plist = prefix_list_lookup(afi, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(afi, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, prefix) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static enum route_map_cmd_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
- return (route_match_address_prefix_list(rule, prefix, type, object,
- AFI_IP));
+ return (route_match_address_prefix_list(rule, prefix, object, AFI_IP));
}
static void *route_match_address_prefix_list_compile(const char *arg)
@@ -1165,10 +1141,9 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
- return (route_match_address_prefix_list(rule, prefix, type, object,
- AFI_IP6));
+ return (route_match_address_prefix_list(rule, prefix, object, AFI_IP6));
}
static const struct route_map_rule_cmd
@@ -1183,11 +1158,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA && prefix->family == AF_INET6) {
+ if (prefix->family == AF_INET6) {
nh_data = (struct nh_rmap_obj *)object;
if (!nh_data)
return RMAP_NOMATCH;
@@ -1195,6 +1170,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -1220,15 +1196,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_address_prefix_len(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
- if (type == RMAP_ZEBRA) {
- return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
- : RMAP_NOMATCH);
- }
- return RMAP_NOMATCH;
+ return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
}
static void *route_match_address_prefix_len_compile(const char *arg)
@@ -1277,34 +1249,30 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data || !nh_data->nexthop)
- return RMAP_NOMATCH;
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data || !nh_data->nexthop)
+ return RMAP_NOMATCH;
- switch (nh_data->nexthop->type) {
- case NEXTHOP_TYPE_IFINDEX:
- /* Interface routes can't match ip next-hop */
- return RMAP_NOMATCH;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- case NEXTHOP_TYPE_IPV4:
- p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
- p.prefixlen = IPV4_MAX_BITLEN;
- break;
- default:
- return RMAP_NOMATCH;
- }
- return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
- : RMAP_NOMATCH);
+ switch (nh_data->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ /* Interface routes can't match ip next-hop */
+ return RMAP_NOMATCH;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV4:
+ p.family = AF_INET;
+ p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ break;
+ default:
+ return RMAP_NOMATCH;
}
- return RMAP_NOMATCH;
+ return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
}
static const struct route_map_rule_cmd
@@ -1319,11 +1287,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
nh_data = (struct nh_rmap_obj *)object;
if (!nh_data)
return RMAP_NOMATCH;
@@ -1331,6 +1299,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -1355,21 +1324,17 @@ static const struct route_map_rule_cmd
/* `match source-protocol PROTOCOL' */
static enum route_map_cmd_result_t
-route_match_source_protocol(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_match_source_protocol(void *rule, const struct prefix *p, void *object)
{
uint32_t *rib_type = (uint32_t *)rule;
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
- return RMAP_NOMATCH;
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data)
+ return RMAP_NOMATCH;
- return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
- : RMAP_NOMATCH);
- }
- return RMAP_NOMATCH;
+ return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
+ : RMAP_NOMATCH);
}
static void *route_match_source_protocol_compile(const char *arg)
@@ -1399,15 +1364,11 @@ static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
/* `source-instance` */
static enum route_map_cmd_result_t
-route_match_source_instance(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_match_source_instance(void *rule, const struct prefix *p, void *object)
{
uint8_t *instance = (uint8_t *)rule;
struct nh_rmap_obj *nh_data;
- if (type != RMAP_ZEBRA)
- return RMAP_NOMATCH;
-
nh_data = (struct nh_rmap_obj *)object;
if (!nh_data)
return RMAP_NOMATCH;
@@ -1444,15 +1405,13 @@ static const struct route_map_rule_cmd route_match_source_instance_cmd = {
/* Set src. */
static enum route_map_cmd_result_t
-route_set_src(void *rule, const struct prefix *prefix, route_map_object_t type,
- void *object)
+route_set_src(void *rule, const struct prefix *prefix, void *object)
{
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- nh_data->nexthop->rmap_src = *(union g_addr *)rule;
- }
+ nh_data = (struct nh_rmap_obj *)object;
+ nh_data->nexthop->rmap_src = *(union g_addr *)rule;
+
return RMAP_OKAY;
}
@@ -1738,7 +1697,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance,
if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX))
rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
if (rmap) {
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, &nh_obj);
}
return (ret);
@@ -1782,7 +1741,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
rmap = route_map_lookup_by_name(rmap_name);
if (rmap) {
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, &nh_obj);
}
return (ret);
@@ -1810,7 +1769,7 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
if (rmap)
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, &nh_obj);
return ret;
}
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index fc4390f7f8..249ec38a69 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -257,7 +257,12 @@ void zebra_router_terminate(void)
hash_free(zrouter.iptable_hash);
}
-void zebra_router_init(void)
+bool zebra_router_notify_on_ack(void)
+{
+ return !zrouter.asic_offloaded || zrouter.notify_on_ack;
+}
+
+void zebra_router_init(bool asic_offload, bool notify_on_ack)
{
zrouter.sequence_num = 0;
@@ -291,5 +296,6 @@ void zebra_router_init(void)
hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal,
"Zebra Router Nexthop Groups ID index");
- zrouter.asic_offloaded = false;
+ zrouter.asic_offloaded = asic_offload;
+ zrouter.notify_on_ack = notify_on_ack;
}
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 8651a01e9f..08c5fcaf8d 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -210,13 +210,14 @@ struct zebra_router {
* Does the underlying system provide an asic offload
*/
bool asic_offloaded;
+ bool notify_on_ack;
};
#define GRACEFUL_RESTART_TIME 60
extern struct zebra_router zrouter;
-extern void zebra_router_init(void);
+extern void zebra_router_init(bool asic_offload, bool notify_on_ack);
extern void zebra_router_cleanup(void);
extern void zebra_router_terminate(void);
@@ -255,6 +256,8 @@ extern void multicast_mode_ipv4_set(enum multicast_mode mode);
extern enum multicast_mode multicast_mode_ipv4_get(void);
+extern bool zebra_router_notify_on_ack(void);
+
/* zebra_northbound.c */
extern const struct frr_yang_module_info frr_zebra_info;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index ab7d2845e7..ea7baa2565 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -204,12 +204,16 @@ static char re_status_output_char(const struct route_entry *re,
star_p = true;
}
+ if (zrouter.asic_offloaded &&
+ CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
+ return 'q';
+
if (zrouter.asic_offloaded
&& CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED))
return 't';
if (zrouter.asic_offloaded
- && !CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED))
+ && CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
return 'o';
if (star_p)
@@ -870,6 +874,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED))
json_object_boolean_true_add(json_route, "offloaded");
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
+ json_object_boolean_false_add(json_route, "offloaded");
+
if (re->tag)
json_object_int_add(json_route, "tag", re->tag);
@@ -2005,6 +2012,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
+ uint32_t offload_cnt[ZEBRA_ROUTE_TOTAL + 1];
+ uint32_t trap_cnt[ZEBRA_ROUTE_TOTAL + 1];
uint32_t i;
uint32_t is_ibgp;
json_object *json_route_summary = NULL;
@@ -2012,6 +2021,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
+ memset(&offload_cnt, 0, sizeof(offload_cnt));
+ memset(&trap_cnt, 0, sizeof(trap_cnt));
if (use_json) {
json_route_summary = json_object_new_object();
@@ -2039,6 +2050,20 @@ static void vty_show_ip_route_summary(struct vty *vty,
else
fib_cnt[re->type]++;
}
+
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) {
+ if (is_ibgp)
+ trap_cnt[ZEBRA_ROUTE_IBGP]++;
+ else
+ trap_cnt[re->type]++;
+ }
+
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) {
+ if (is_ibgp)
+ offload_cnt[ZEBRA_ROUTE_IBGP]++;
+ else
+ offload_cnt[re->type]++;
+ }
}
if (!use_json)
@@ -2062,6 +2087,13 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(
json_route_ebgp, "rib",
rib_cnt[ZEBRA_ROUTE_BGP]);
+ json_object_int_add(
+ json_route_ebgp, "fibOffLoaded",
+ offload_cnt[ZEBRA_ROUTE_BGP]);
+ json_object_int_add(
+ json_route_ebgp, "fibTrapped",
+ trap_cnt[ZEBRA_ROUTE_BGP]);
+
json_object_string_add(json_route_ebgp,
"type", "ebgp");
json_object_array_add(json_route_routes,
@@ -2076,6 +2108,12 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(
json_route_ibgp, "rib",
rib_cnt[ZEBRA_ROUTE_IBGP]);
+ json_object_int_add(
+ json_route_ibgp, "fibOffLoaded",
+ offload_cnt[ZEBRA_ROUTE_IBGP]);
+ json_object_int_add(
+ json_route_ibgp, "fibTrapped",
+ trap_cnt[ZEBRA_ROUTE_IBGP]);
json_object_string_add(json_route_ibgp,
"type", "ibgp");
json_object_array_add(json_route_routes,
@@ -2099,6 +2137,13 @@ static void vty_show_ip_route_summary(struct vty *vty,
"fib", fib_cnt[i]);
json_object_int_add(json_route_type,
"rib", rib_cnt[i]);
+
+ json_object_int_add(json_route_type,
+ "fibOffLoaded",
+ offload_cnt[i]);
+ json_object_int_add(json_route_type,
+ "fibTrapped",
+ trap_cnt[i]);
json_object_string_add(
json_route_type, "type",
zebra_route_string(i));