summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/user/zebra.rst13
-rw-r--r--zebra/connected.c21
-rw-r--r--zebra/main.c15
-rw-r--r--zebra/rt_netlink.c4
-rw-r--r--zebra/zebra_rib.c30
-rw-r--r--zebra/zebra_router.c10
-rw-r--r--zebra/zebra_router.h5
-rw-r--r--zebra/zebra_vty.c4
8 files changed, 88 insertions, 14 deletions
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 624e3cfe1..5c7f4ac77 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -72,6 +72,19 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
option and we will use Route Replace Semantics instead of delete
than add.
+.. option:: --asic-offload [notify_on_offload|notify_on_ack]
+
+ The linux kernel has the ability to use asic-offload ( see switchdev
+ development ). When the operator knows that FRR will be working in
+ this way, allow them to specify this with FRR. At this point this
+ code only supports asynchronous notification of the offload state.
+ In other words the initial ACK received for linux kernel installation
+ does not give zebra any data about what the state of the offload
+ is. This option takes the optional paramegers notify_on_offload
+ or notify_on_ack. This signals to zebra to notify upper level
+ protocols about route installation/update on ack received from
+ the linux kernel or from offload notification.
+
.. _interface-commands:
Configuration Addresses behaviour
diff --git a/zebra/connected.c b/zebra/connected.c
index 6a1efc3e6..70ea2e380 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 ced29e1a2..55fd3244c 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 c0c1c4e7f..3402edf46 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);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index b68870496..569b23573 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1821,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) {
@@ -1899,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);
@@ -2067,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_router.c b/zebra/zebra_router.c
index fc4390f7f..249ec38a6 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 8651a01e9..08c5fcaf8 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 68487ea24..20f271a14 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -204,6 +204,10 @@ 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';