From 00249e255ee651eefb027f3a3c8deb0f130f6193 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Nov 2021 14:12:39 -0500 Subject: [PATCH 1/3] zebra: When we get an implicit or ack or full failure mark status When nl_batch_read_resp gets a full on failure -1 or an implicit ack 0 from the kernel for a batch of code. Let's immediately mark all of those in the batch pass/fail as needed. Instead of having them marked else where. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index d614aa26d0..26ceea2057 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1125,8 +1125,25 @@ static int nl_batch_read_resp(struct nl_batch *bth) while (true) { status = netlink_recv_msg(nl, msg, nl_batch_rx_buf, sizeof(nl_batch_rx_buf)); - if (status == -1 || status == 0) + /* + * status == -1 is a full on failure somewhere + * since we don't know where the problem happened + * we must mark all as failed + * + * Else we mark everything as worked + * + */ + if (status == -1 || status == 0) { + while ((ctx = dplane_ctx_dequeue(&(bth->ctx_list))) != + NULL) { + if (status == -1) + dplane_ctx_set_status( + ctx, + ZEBRA_DPLANE_REQUEST_FAILURE); + dplane_ctx_enqueue_tail(bth->ctx_out_q, ctx); + } return status; + } h = (struct nlmsghdr *)nl_batch_rx_buf; ignore_msg = false; From e3ee55d4bde5de9d39a91b53b30f67a6e45bbdb8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Nov 2021 15:09:37 -0500 Subject: [PATCH 2/3] zebra: set zd_is_update in 1 spot The ctx->zd_is_update is being set in various spots based upon the same value that we are passing into dplane_ctx_ns_init. Let's just consolidate all this into the dplane_ctx_ns_init so that the zd_is_udpate value is set at the same time that we increment the sequence numbers to use. As a note for future me's reading this. The sequence number choosen for the seq number passed to the kernel is that each context gets a copy of the appropriate nlsock to use. Since it's a copy at a point in time, we know we have a unique sequence number value. Signed-off-by: Donald Sharp --- zebra/zebra_dplane.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index bf34fb54a9..96a606af98 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -2296,6 +2296,8 @@ static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx, { dplane_info_from_zns(&(ctx->zd_ns_info), zns); + ctx->zd_is_update = is_update; + #if defined(HAVE_NETLINK) /* Increment message counter after copying to context struct - may need * two messages in some 'update' cases. @@ -2514,7 +2516,6 @@ int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, * it probably won't require two messages */ dplane_ctx_ns_init(ctx, zns, (op == DPLANE_OP_NH_UPDATE)); - ctx->zd_is_update = (op == DPLANE_OP_NH_UPDATE); ret = AOK; @@ -2537,7 +2538,6 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, /* Capture namespace info */ dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), (op == DPLANE_OP_LSP_UPDATE)); - ctx->zd_is_update = (op == DPLANE_OP_LSP_UPDATE); memset(&ctx->u.lsp, 0, sizeof(ctx->u.lsp)); @@ -2813,7 +2813,6 @@ static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx, dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), op == DPLANE_OP_RULE_UPDATE); - ctx->zd_is_update = (op == DPLANE_OP_RULE_UPDATE); ctx->zd_vrf_id = new_rule->vrf_id; strlcpy(ctx->zd_ifname, new_rule->ifname, sizeof(ctx->zd_ifname)); @@ -2859,7 +2858,6 @@ static int dplane_ctx_iptable_init(struct zebra_dplane_ctx *ctx, ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false); - ctx->zd_is_update = false; ctx->zd_vrf_id = iptable->vrf_id; memcpy(&ctx->u.iptable, iptable, sizeof(struct zebra_pbr_iptable)); @@ -2899,7 +2897,6 @@ static int dplane_ctx_ipset_init(struct zebra_dplane_ctx *ctx, ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false); - ctx->zd_is_update = false; ctx->zd_vrf_id = ipset->vrf_id; @@ -2934,7 +2931,6 @@ dplane_ctx_ipset_entry_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false); - ctx->zd_is_update = false; ctx->zd_vrf_id = ipset->vrf_id; @@ -3015,7 +3011,6 @@ dplane_route_update_internal(struct route_node *rn, */ if ((op == DPLANE_OP_ROUTE_UPDATE) && old_re && (old_re != re)) { - ctx->zd_is_update = true; old_re->dplane_sequence = zebra_router_get_next_sequence(); From c8453cd77e92d90ee580f15d6c05788a3da10aed Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 10 Nov 2021 16:58:58 -0500 Subject: [PATCH 3/3] zebra: Fix v6 route replace failure turned into success Currently when we have a route replace operation for v6 routes with a new nexthop group the order of kernel installation is this: a) New nexthop group insertion seq 1 b) Route delete operation seq 3 c) Route insertion operation seq 2 Currently the code in nl_batch_read_resp is attempting to handle this situation by skipping the delete operation. *BUT* it is enqueuing the context into the zebra dplane queue before we read the response. Since we create the ctx with an implied success, success is being reported to the upper level dplane and the zebra rib thinks the route has been properly handled. This is showing up in the zebra_seg6_route test code because the test code is installing a seg6 route w/ sharpd and it is failing to install because the route's nexthop is rejected: First installation: 2021/10/29 09:28:10.218 ZEBRA: [JGWSB-SMNVE] dplane: incoming new work counter: 2 2021/10/29 09:28:10.218 ZEBRA: [Q52A7-211QJ] dplane enqueues 2 new work to provider 'Kernel' 2021/10/29 09:28:10.218 ZEBRA: [JVY1P-93VFY] dplane provider 'Kernel': processing 2021/10/29 09:28:10.218 ZEBRA: [TX9N0-9JKDF] ID (9) Dplane nexthop update ctx 0x56125390a820 op NH_INSTALL 2021/10/29 09:28:10.218 ZEBRA: [PM9ZJ-07RCP] 0:1::1/128 Dplane route update ctx 0x56125390add0 op ROUTE_INSTALL 2021/10/29 09:28:10.218 ZEBRA: [TJ327-ET8HE] netlink_send_msg: >> netlink message dump [sent] 2021/10/29 09:28:10.218 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=104 type=(104) NEWNEXTHOP flags=(0x0501) {REQUEST,DUMP,(ROOT|REPLACE|CAPPED),(ATOMIC|CREATE)} seq=9 pid=3539131282] 2021/10/29 09:28:10.218 ZEBRA: [WCX94-SW894] nhm [family=(10) AF_INET6 scope=(0) UNIVERSE protocol=(11) ZEBRA flags=0x00000000 {}] 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(1) ID] 2021/10/29 09:28:10.218 ZEBRA: [Z4E9C-GD9EP] 9 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=20 (payload=16) type=(6) GATEWAY] 2021/10/29 09:28:10.218 ZEBRA: [STTSM-27M81] 2001::1 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(5) OIF] 2021/10/29 09:28:10.218 ZEBRA: [JR4EA-BKPTA] 6 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=6 (payload=2) type=(7) ENCAP_TYPE] 2021/10/29 09:28:10.218 ZEBRA: [JR4EA-BKPTA] 5 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=36 (payload=32) type=(32776) UNKNOWN] 2021/10/29 09:28:10.218 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=64 type=(24) NEWROUTE flags=(0x0401) {REQUEST,(ATOMIC|CREATE)} seq=10 pid=3539131282] 2021/10/29 09:28:10.218 ZEBRA: [GCEGC-W8YBF] rtmsg [family=(10) AF_INET6 dstlen=128 srclen=0 tos=0 table=254 protocol=(194) UNKNOWN scope=(0) UNIVERSE type=(1) UNICAST flags=0x0000 {}] 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=20 (payload=16) type=(1) DST] 2021/10/29 09:28:10.218 ZEBRA: [STTSM-27M81] 1::1 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(6) PRIORITY] 2021/10/29 09:28:10.218 ZEBRA: [Z4E9C-GD9EP] 20 2021/10/29 09:28:10.218 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(30) NH_ID] 2021/10/29 09:28:10.218 ZEBRA: [Z4E9C-GD9EP] 9 2021/10/29 09:28:10.218 ZEBRA: [V8KNF-8EXH8] netlink_recv_msg: << netlink message dump [recv] 2021/10/29 09:28:10.218 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=76 type=(2) ERROR flags=(0x0300) {DUMP,(ROOT|REPLACE|CAPPED),(MATCH|EXCLUDE|ACK_TLVS)} seq=9 pid=3539131282] 2021/10/29 09:28:10.218 ZEBRA: [KWP1C-6CSXF] nlmsgerr [error=(-22) Invalid argument] 2021/10/29 09:28:10.218 ZEBRA: [HSYZM-HV7HF] Extended Error: Gateway can not be a local address 2021/10/29 09:28:10.218 ZEBRA: [WVJCK-PPMGD][EC 4043309093] netlink-dp (NS 0) error: Invalid argument, type=RTM_NEWNEXTHOP(104), seq=9, pid=3539131282 2021/10/29 09:28:10.218 ZEBRA: [V8KNF-8EXH8] netlink_recv_msg: << netlink message dump [recv] 2021/10/29 09:28:10.218 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=68 type=(2) ERROR flags=(0x0300) {DUMP,(ROOT|REPLACE|CAPPED),(MATCH|EXCLUDE|ACK_TLVS)} seq=10 pid=3539131282] 2021/10/29 09:28:10.218 ZEBRA: [KWP1C-6CSXF] nlmsgerr [error=(-22) Invalid argument] 2021/10/29 09:28:10.218 ZEBRA: [HSYZM-HV7HF] Extended Error: Nexthop id does not exist 2021/10/29 09:28:10.218 ZEBRA: [WVJCK-PPMGD][EC 4043309093] netlink-dp (NS 0) error: Invalid argument, type=RTM_NEWROUTE(24), seq=10, pid=3539131282 2021/10/29 09:28:10.218 ZEBRA: [VCDW6-A7ZF1] dplane dequeues 2 completed work from provider Kernel 2021/10/29 09:28:10.218 ZEBRA: [JTWAB-1MH4Y] dplane has 2 completed, 0 errors, for zebra main 2021/10/29 09:28:10.218 ZEBRA: [J7K9Z-9M7DT] Nexthop dplane ctx 0x56125390a820, op NH_INSTALL, nexthop ID (9), result FAILURE 2021/10/29 09:28:10.218 ZEBRA: [P2XBZ-RAFQ5][EC 4043309074] Failed to install Nexthop ID (9) into the kernel 2021/10/29 09:28:10.218 ZEBRA: [RMK34-61HV5] default(0:254):1::1/128 Processing dplane result ctx 0x56125390add0, op ROUTE_INSTALL result FAILURE Note the last line `op ROUTE_INSTALL result FAILURE` because we are attempting to use a a gw nexthop that is local. This is the result. Then the test code was installing the route again: 2021/10/29 09:30:00.493 ZEBRA: [JGWSB-SMNVE] dplane: incoming new work counter: 2 2021/10/29 09:30:00.493 ZEBRA: [Q52A7-211QJ] dplane enqueues 2 new work to provider 'Kernel' 2021/10/29 09:30:00.493 ZEBRA: [JVY1P-93VFY] dplane provider 'Kernel': processing 2021/10/29 09:30:00.493 ZEBRA: [TX9N0-9JKDF] ID (9) Dplane nexthop update ctx 0x561253916a00 op NH_INSTALL 2021/10/29 09:30:00.493 ZEBRA: [PM9ZJ-07RCP] 0:1::1/128 Dplane route update ctx 0x561253915f40 op ROUTE_UPDATE 2021/10/29 09:30:00.493 ZEBRA: [TJ327-ET8HE] netlink_send_msg: >> netlink message dump [sent] 2021/10/29 09:30:00.493 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=104 type=(104) NEWNEXTHOP flags=(0x0501) {REQUEST,DUMP,(ROOT|REPLACE|CAPPED),(ATOMIC|CREATE)} seq=11 pid=3539131282] 2021/10/29 09:30:00.493 ZEBRA: [WCX94-SW894] nhm [family=(10) AF_INET6 scope=(0) UNIVERSE protocol=(11) ZEBRA flags=0x00000000 {}] 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(1) ID] 2021/10/29 09:30:00.493 ZEBRA: [Z4E9C-GD9EP] 9 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=20 (payload=16) type=(6) GATEWAY] 2021/10/29 09:30:00.493 ZEBRA: [STTSM-27M81] 2001::1 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(5) OIF] 2021/10/29 09:30:00.493 ZEBRA: [JR4EA-BKPTA] 6 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=6 (payload=2) type=(7) ENCAP_TYPE] 2021/10/29 09:30:00.493 ZEBRA: [JR4EA-BKPTA] 5 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=36 (payload=32) type=(32776) UNKNOWN] 2021/10/29 09:30:00.493 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=56 type=(25) DELROUTE flags=(0x0401) {REQUEST,(ATOMIC|CREATE)} seq=13 pid=3539131282] 2021/10/29 09:30:00.493 ZEBRA: [GCEGC-W8YBF] rtmsg [family=(10) AF_INET6 dstlen=128 srclen=0 tos=0 table=254 protocol=(194) UNKNOWN scope=(0) UNIVERSE type=(0) UNSPEC flags=0x0000 {}] 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=20 (payload=16) type=(1) DST] 2021/10/29 09:30:00.493 ZEBRA: [STTSM-27M81] 1::1 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(6) PRIORITY] 2021/10/29 09:30:00.493 ZEBRA: [Z4E9C-GD9EP] 20 2021/10/29 09:30:00.493 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=64 type=(24) NEWROUTE flags=(0x0401) {REQUEST,(ATOMIC|CREATE)} seq=12 pid=3539131282] 2021/10/29 09:30:00.493 ZEBRA: [GCEGC-W8YBF] rtmsg [family=(10) AF_INET6 dstlen=128 srclen=0 tos=0 table=254 protocol=(194) UNKNOWN scope=(0) UNIVERSE type=(1) UNICAST flags=0x0000 {}] 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=20 (payload=16) type=(1) DST] 2021/10/29 09:30:00.493 ZEBRA: [STTSM-27M81] 1::1 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(6) PRIORITY] 2021/10/29 09:30:00.493 ZEBRA: [Z4E9C-GD9EP] 20 2021/10/29 09:30:00.493 ZEBRA: [KFBSR-XYJV1] rta [len=8 (payload=4) type=(30) NH_ID] 2021/10/29 09:30:00.493 ZEBRA: [Z4E9C-GD9EP] 9 2021/10/29 09:30:00.493 ZEBRA: [V8KNF-8EXH8] netlink_recv_msg: << netlink message dump [recv] 2021/10/29 09:30:00.493 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=76 type=(2) ERROR flags=(0x0300) {DUMP,(ROOT|REPLACE|CAPPED),(MATCH|EXCLUDE|ACK_TLVS)} seq=11 pid=3539131282] 2021/10/29 09:30:00.493 ZEBRA: [KWP1C-6CSXF] nlmsgerr [error=(-22) Invalid argument] 2021/10/29 09:30:00.493 ZEBRA: [HSYZM-HV7HF] Extended Error: Gateway can not be a local address 2021/10/29 09:30:00.493 ZEBRA: [WVJCK-PPMGD][EC 4043309093] netlink-dp (NS 0) error: Invalid argument, type=RTM_NEWNEXTHOP(104), seq=11, pid=3539131282 2021/10/29 09:30:00.493 ZEBRA: [V8KNF-8EXH8] netlink_recv_msg: << netlink message dump [recv] 2021/10/29 09:30:00.493 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=36 type=(2) ERROR flags=(0x0100) {DUMP,(ROOT|REPLACE|CAPPED)} seq=13 pid=3539131282] 2021/10/29 09:30:00.493 ZEBRA: [KWP1C-6CSXF] nlmsgerr [error=(-3) No such process] 2021/10/29 09:30:00.493 ZEBRA: [V8KNF-8EXH8] netlink_recv_msg: << netlink message dump [recv] 2021/10/29 09:30:00.493 ZEBRA: [JAS4D-NCWGP] nlmsghdr [len=68 type=(2) ERROR flags=(0x0300) {DUMP,(ROOT|REPLACE|CAPPED),(MATCH|EXCLUDE|ACK_TLVS)} seq=12 pid=3539131282] 2021/10/29 09:30:00.493 ZEBRA: [KWP1C-6CSXF] nlmsgerr [error=(-22) Invalid argument] 2021/10/29 09:30:00.493 ZEBRA: [VCDW6-A7ZF1] dplane dequeues 2 completed work from provider Kernel 2021/10/29 09:30:00.493 ZEBRA: [JTWAB-1MH4Y] dplane has 2 completed, 0 errors, for zebra main 2021/10/29 09:30:00.493 ZEBRA: [J7K9Z-9M7DT] Nexthop dplane ctx 0x561253916a00, op NH_INSTALL, nexthop ID (9), result FAILURE 2021/10/29 09:30:00.493 ZEBRA: [P2XBZ-RAFQ5][EC 4043309074] Failed to install Nexthop ID (9) into the kernel 2021/10/29 09:30:00.493 ZEBRA: [RMK34-61HV5] default(0:254):1::1/128 Processing dplane result ctx 0x561253915f40, op ROUTE_UPDATE result SUCCESS Note that this time we do these three operations a) nexthop installation seq 11 b) route delete seq 13 c) route add seq 12 Note the last line, we report the install as a success but it clearly failed from the seq=12 decode. When we look at the v6 rib it thinks it is installed: unet> r1 show ipv6 route Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued, r - rejected, b - backup t - trapped, o - offload failure D>* 1::1/128 [150/0] via 2001::1, dum0, seg6local unspec unknown(seg6local_context2str), seg6 a::, weight 1, 00:00:17 So let's modify nl_batch_read_resp to not dequeue/enqueue the context until we are sure we have the right one. This fixes the test code to do the right thing on the second installation. Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 46 +++++++++++++++++++++++++++++++++--------- zebra/zebra_dplane.c | 7 +++++++ zebra/zebra_dplane.h | 1 + 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 26ceea2057..08f9782cf7 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1155,15 +1155,18 @@ static int nl_batch_read_resp(struct nl_batch *bth) * requests at same time. */ while (true) { - ctx = dplane_ctx_dequeue(&(bth->ctx_list)); - if (ctx == NULL) - break; - - dplane_ctx_enqueue_tail(bth->ctx_out_q, ctx); - - /* We have found corresponding context object. */ - if (dplane_ctx_get_ns(ctx)->nls.seq == seq) + ctx = dplane_ctx_get_head(&(bth->ctx_list)); + if (ctx == NULL) { + /* + * This is a situation where we have gotten + * into a bad spot. We need to know that + * this happens( does it? ) + */ + zlog_err( + "%s:WARNING Received netlink Response for an error and no Contexts to associate with it", + __func__); break; + } /* * 'update' context objects take two consecutive @@ -1178,10 +1181,35 @@ static int nl_batch_read_resp(struct nl_batch *bth) ignore_msg = true; break; } + + ctx = dplane_ctx_dequeue(&(bth->ctx_list)); + dplane_ctx_enqueue_tail(bth->ctx_out_q, ctx); + + /* We have found corresponding context object. */ + if (dplane_ctx_get_ns(ctx)->nls.seq == seq) + break; + + if (dplane_ctx_get_ns(ctx)->nls.seq > seq) + zlog_warn( + "%s:WARNING Recieved %u is less than any context on the queue ctx->seq %u", + __func__, seq, + dplane_ctx_get_ns(ctx)->nls.seq); } - if (ignore_msg) + if (ignore_msg) { + /* + * If we ignore the message due to an update + * above we should still fricking decode the + * message for our operator to understand + * what is going on + */ + int err = netlink_parse_error(nl, h, bth->zns->is_cmd, + false); + + zlog_debug("%s: netlink error message seq=%d %d", + __func__, h->nlmsg_seq, err); continue; + } /* * We received a message with the sequence number that isn't diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 96a606af98..656ebcf3b7 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -833,6 +833,13 @@ void dplane_ctx_list_append(struct dplane_ctx_q *to_list, } } +struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_q *q) +{ + struct zebra_dplane_ctx *ctx = TAILQ_FIRST(q); + + return ctx; +} + /* Dequeue a context block from the head of a list */ struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_q *q) { diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 977f00bd2a..1d55181388 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -274,6 +274,7 @@ void dplane_ctx_list_append(struct dplane_ctx_q *to_list, /* Dequeue a context block from the head of caller's tailq */ struct zebra_dplane_ctx *dplane_ctx_dequeue(struct dplane_ctx_q *q); +struct zebra_dplane_ctx *dplane_ctx_get_head(struct dplane_ctx_q *q); /* * Accessors for information from the context object