diff options
-rw-r--r-- | doc/user/zebra.rst | 13 | ||||
-rw-r--r-- | zebra/connected.c | 21 | ||||
-rw-r--r-- | zebra/main.c | 15 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 4 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 30 | ||||
-rw-r--r-- | zebra/zebra_router.c | 10 | ||||
-rw-r--r-- | zebra/zebra_router.h | 5 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 4 |
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'; |