Skip to content

Commit a0e1173

Browse files
committed
zebra: Read from the dplane_fpm_nl a route update
Read from the fpm dplane a route update that will include status about whether or not the asic was successfull in offloading the route. Have this data passed up to zebra for processing and disseminate this data as appropriate. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
1 parent 45f0a10 commit a0e1173

File tree

5 files changed

+158
-9
lines changed

5 files changed

+158
-9
lines changed

doc/developer/fpm.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,19 @@ Data
101101
^^^^
102102

103103
The netlink or protobuf message payload.
104+
105+
106+
Route Status Notification from ASIC
107+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
108+
109+
The dplane_fpm_nl has the ability to read route netlink messages
110+
from the underlying fpm implementation that can tell zebra
111+
whether or not the route has been Offloaded/Failed or Trapped.
112+
The end developer must send the data up the same socket that has
113+
been created to listen for FPM messages from Zebra. The data sent
114+
must have a Frame Header with Version set to 1, Message Type set to 1
115+
and an appropriate message Length. The message data must contain
116+
a RTM_NEWROUTE netlink message that sends the prefix and nexthops
117+
associated with the route. Finally rtm_flags must contain
118+
RTM_F_OFFLOAD, RTM_F_TRAP and or RTM_F_OFFLOAD_FAILED to signify
119+
what has happened to the route in the ASIC.

zebra/dplane_fpm_nl.c

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "zebra/kernel_netlink.h"
5252
#include "zebra/rt_netlink.h"
5353
#include "zebra/debug.h"
54+
#include "fpm/fpm.h"
5455

5556
#define SOUTHBOUND_DEFAULT_ADDR INADDR_LOOPBACK
5657
#define SOUTHBOUND_DEFAULT_PORT 2620
@@ -462,7 +463,13 @@ static void fpm_reconnect(struct fpm_nl_ctx *fnc)
462463
static void fpm_read(struct thread *t)
463464
{
464465
struct fpm_nl_ctx *fnc = THREAD_ARG(t);
466+
fpm_msg_hdr_t fpm;
465467
ssize_t rv;
468+
char buf[65535];
469+
struct nlmsghdr *hdr;
470+
struct zebra_dplane_ctx *ctx;
471+
size_t available_bytes;
472+
size_t hdr_available_bytes;
466473

467474
/* Let's ignore the input at the moment. */
468475
rv = stream_read_try(fnc->ibuf, fnc->socket,
@@ -494,11 +501,122 @@ static void fpm_read(struct thread *t)
494501
if (rv == -2)
495502
return;
496503

497-
stream_reset(fnc->ibuf);
498504

499505
/* Account all bytes read. */
500506
atomic_fetch_add_explicit(&fnc->counters.bytes_read, rv,
501507
memory_order_relaxed);
508+
509+
available_bytes = STREAM_READABLE(fnc->ibuf);
510+
while (available_bytes) {
511+
if (available_bytes < (ssize_t)FPM_MSG_HDR_LEN) {
512+
stream_pulldown(fnc->ibuf);
513+
return;
514+
}
515+
516+
fpm.version = stream_getc(fnc->ibuf);
517+
fpm.msg_type = stream_getc(fnc->ibuf);
518+
fpm.msg_len = stream_getw(fnc->ibuf);
519+
520+
if (fpm.version != FPM_PROTO_VERSION &&
521+
fpm.msg_type != FPM_MSG_TYPE_NETLINK) {
522+
stream_reset(fnc->ibuf);
523+
zlog_warn(
524+
"%s: Received version/msg_type %u/%u, expected 1/1",
525+
__func__, fpm.version, fpm.msg_type);
526+
527+
FPM_RECONNECT(fnc);
528+
return;
529+
}
530+
531+
/*
532+
* If the passed in length doesn't even fill in the header
533+
* something is wrong and reset.
534+
*/
535+
if (fpm.msg_len < FPM_MSG_HDR_LEN) {
536+
zlog_warn(
537+
"%s: Received message length: %u that does not even fill the FPM header",
538+
__func__, fpm.msg_len);
539+
FPM_RECONNECT(fnc);
540+
return;
541+
}
542+
543+
/*
544+
* If we have not received the whole payload, reset the stream
545+
* back to the beginning of the header and move it to the
546+
* top.
547+
*/
548+
if (fpm.msg_len > available_bytes) {
549+
stream_rewind_getp(fnc->ibuf, FPM_MSG_HDR_LEN);
550+
stream_pulldown(fnc->ibuf);
551+
return;
552+
}
553+
554+
available_bytes -= FPM_MSG_HDR_LEN;
555+
556+
/*
557+
* Place the data from the stream into a buffer
558+
*/
559+
hdr = (struct nlmsghdr *)buf;
560+
stream_get(buf, fnc->ibuf, fpm.msg_len - FPM_MSG_HDR_LEN);
561+
hdr_available_bytes = fpm.msg_len - FPM_MSG_HDR_LEN;
562+
available_bytes -= hdr_available_bytes;
563+
564+
/* Sanity check: must be at least header size. */
565+
if (hdr->nlmsg_len < sizeof(*hdr)) {
566+
zlog_warn(
567+
"%s: [seq=%u] invalid message length %u (< %zu)",
568+
__func__, hdr->nlmsg_seq, hdr->nlmsg_len,
569+
sizeof(*hdr));
570+
continue;
571+
}
572+
if (hdr->nlmsg_len > fpm.msg_len) {
573+
zlog_warn(
574+
"%s: Received a inner header length of %u that is greater than the fpm total length of %u",
575+
__func__, hdr->nlmsg_len, fpm.msg_len);
576+
FPM_RECONNECT(fnc);
577+
}
578+
/* Not enough bytes available. */
579+
if (hdr->nlmsg_len > hdr_available_bytes) {
580+
zlog_warn(
581+
"%s: [seq=%u] invalid message length %u (> %zu)",
582+
__func__, hdr->nlmsg_seq, hdr->nlmsg_len,
583+
available_bytes);
584+
continue;
585+
}
586+
587+
if (!(hdr->nlmsg_flags & NLM_F_REQUEST)) {
588+
if (IS_ZEBRA_DEBUG_FPM)
589+
zlog_debug(
590+
"%s: [seq=%u] not a request, skipping",
591+
__func__, hdr->nlmsg_seq);
592+
593+
/*
594+
* This request is a bust, go to the next one
595+
*/
596+
continue;
597+
}
598+
599+
switch (hdr->nlmsg_type) {
600+
case RTM_NEWROUTE:
601+
ctx = dplane_ctx_alloc();
602+
dplane_ctx_set_op(ctx, DPLANE_OP_ROUTE_NOTIFY);
603+
if (netlink_route_change_read_unicast_internal(
604+
hdr, 0, false, ctx) != 1) {
605+
dplane_ctx_fini(&ctx);
606+
stream_pulldown(fnc->ibuf);
607+
return;
608+
}
609+
break;
610+
default:
611+
if (IS_ZEBRA_DEBUG_FPM)
612+
zlog_debug(
613+
"%s: Received message type %u which is not currently handled",
614+
__func__, hdr->nlmsg_type);
615+
break;
616+
}
617+
}
618+
619+
stream_reset(fnc->ibuf);
502620
}
503621

504622
static void fpm_write(struct thread *t)

zebra/zebra_dplane.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,7 +2785,7 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx,
27852785
int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
27862786
enum dplane_op_e op, struct route_entry *re,
27872787
const struct prefix *p,
2788-
const struct prefix *src_p, afi_t afi,
2788+
const struct prefix_ipv6 *src_p, afi_t afi,
27892789
safi_t safi)
27902790
{
27912791
int ret = EINVAL;
@@ -2836,7 +2836,8 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
28362836
int ret = EINVAL;
28372837
const struct route_table *table = NULL;
28382838
const struct rib_table_info *info;
2839-
const struct prefix *p, *src_p;
2839+
const struct prefix *p;
2840+
const struct prefix_ipv6 *src_p;
28402841
struct zebra_ns *zns;
28412842
struct zebra_vrf *zvrf;
28422843
struct nexthop *nexthop;
@@ -2853,7 +2854,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
28532854
*/
28542855

28552856
/* Prefixes: dest, and optional source */
2856-
srcdest_rnode_prefixes(rn, &p, &src_p);
2857+
srcdest_rnode_prefixes(rn, &p, (const struct prefix **)&src_p);
28572858
table = srcdest_rnode_table(rn);
28582859
info = table->info;
28592860

@@ -6309,6 +6310,9 @@ void dplane_rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
63096310
if (!ctx)
63106311
rib_add_multipath(afi, safi, p, src_p, re, ng, startup);
63116312
else {
6313+
dplane_ctx_route_init_basic(ctx, dplane_ctx_get_op(ctx), re, p,
6314+
src_p, afi, safi);
6315+
dplane_provider_enqueue_to_zebra(ctx);
63126316
}
63136317
}
63146318

zebra/zebra_dplane.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
913913
int dplane_ctx_route_init_basic(struct zebra_dplane_ctx *ctx,
914914
enum dplane_op_e op, struct route_entry *re,
915915
const struct prefix *p,
916-
const struct prefix *src_p, afi_t afi,
916+
const struct prefix_ipv6 *src_p, afi_t afi,
917917
safi_t safi);
918918

919919
/* Encode next hop information into data plane context. */

zebra/zebra_rib.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,10 +2260,8 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
22602260
}
22612261

22622262
/* Ensure we clear the QUEUED flag */
2263-
if (!zrouter.asic_offloaded) {
2264-
UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
2265-
UNSET_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING);
2266-
}
2263+
UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
2264+
UNSET_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING);
22672265

22682266
/* Is this a notification that ... matters? We mostly care about
22692267
* the route that is currently selected for installation; we may also
@@ -2306,6 +2304,19 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
23062304
dplane_ctx_get_type(ctx)));
23072305
}
23082306
goto done;
2307+
} else {
2308+
uint32_t flags = dplane_ctx_get_flags(ctx);
2309+
2310+
if (CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED)) {
2311+
UNSET_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED);
2312+
SET_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED);
2313+
}
2314+
if (CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED)) {
2315+
UNSET_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED);
2316+
SET_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED);
2317+
}
2318+
if (CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED))
2319+
SET_FLAG(re->flags, ZEBRA_FLAG_TRAPPED);
23092320
}
23102321

23112322
/* We'll want to determine whether the installation status of the

0 commit comments

Comments
 (0)