Merge pull request #13887 from FRRouting/mergify/bp/dev/9.0/pr-13866

Changes for inclusive language and other cleanup (backport #13866)
This commit is contained in:
Jafar Al-Gharaibeh 2023-07-16 10:37:20 -05:00 committed by GitHub
commit 71b0e94261
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1451 additions and 1163 deletions

View File

@ -25,6 +25,8 @@ CommentPragmas: '\$(FRR|clippy)'
ContinuationIndentWidth: 8 ContinuationIndentWidth: 8
ForEachMacros: ForEachMacros:
# lib # lib
- darr_foreach_p
- darr_foreach_i
- frr_each - frr_each
- frr_each_safe - frr_each_safe
- frr_each_from - frr_each_from

114
lib/darr.c Normal file
View File

@ -0,0 +1,114 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* June 23 2023, Christian Hopps <chopps@labn.net>
*
* Copyright (c) 2023, LabN Consulting, L.L.C.
*
*/
#include <zebra.h>
#include "darr.h"
void __dar_resize(void **a, uint count, size_t esize);
static uint _msb(uint count)
{
uint bit = 0;
int msb = 0;
while (count) {
if (count & 1)
msb = bit;
count >>= 1;
bit += 1;
}
return msb;
}
static uint darr_next_count(uint count, size_t esize)
{
uint ncount;
if (esize > sizeof(long long) && count == 1)
/* treat like a pointer */
ncount = 1;
else {
uint msb = _msb(count);
ncount = 1ull << msb;
/* if the users count wasn't a pow2 make it the next pow2. */
if (ncount != count) {
assert(ncount < count);
ncount <<= 1;
if (esize < sizeof(long long) && ncount < 8)
ncount = 8;
}
}
return ncount;
}
static size_t darr_size(uint count, size_t esize)
{
return count * esize + sizeof(struct darr_metadata);
}
void *__darr_resize(void *a, uint count, size_t esize)
{
uint ncount = darr_next_count(count, esize);
size_t osz = (a == NULL) ? 0 : darr_size(darr_cap(a), esize);
size_t sz = darr_size(ncount, esize);
struct darr_metadata *dm = realloc(a ? _darr_meta(a) : NULL, sz);
/* do *not* use a */
assert(dm);
if (sz > osz)
memset((char *)dm + osz, 0, sz - osz);
dm->cap = ncount;
return (void *)(dm + 1);
}
void *__darr_insert_n(void *a, uint at, uint count, size_t esize, bool zero)
{
struct darr_metadata *dm;
uint olen, nlen;
if (!a)
a = __darr_resize(NULL, at + count, esize);
dm = (struct darr_metadata *)a - 1;
olen = dm->len;
// at == 1
// count == 100
// olen == 2
/* see if the user is expanding first using `at` */
if (at >= olen)
nlen = at + count;
else
nlen = olen + count;
if (nlen > dm->cap) {
a = __darr_resize(a, nlen, esize);
dm = (struct darr_metadata *)a - 1;
}
#define _a_at(i) ((char *)a + ((i)*esize))
if (at < olen)
memmove(_a_at(at + count), _a_at(at), esize * (olen - at));
dm->len = nlen;
if (zero) {
if (at >= olen) {
at -= olen;
count += olen;
}
memset(_a_at(at), 0, esize * count);
}
return (void *)a;
#undef _a_at
}

363
lib/darr.h Normal file
View File

@ -0,0 +1,363 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* June 23 2023, Christian Hopps <chopps@labn.net>
*
* Copyright (c) 2023, LabN Consulting, L.L.C.
*
* API functions:
* ==============
* - darr_append
* - darr_append_n
* - darr_append_nz
* - darr_cap
* - darr_ensure_cap
* - darr_ensure_i
* - darr_foreach_i
* - darr_foreach_p
* - darr_free
* - darr_insert
* - darr_insertz
* - darr_insert_n
* - darr_insert_nz
* - darr_len
* - darr_maxi
* - darr_pop
* - darr_push
* - darr_pushz
* - darr_remove
* - darr_remove_n
* - darr_reset
* - darr_setlen
*/
/*
* A few assured items
*
* - DAs will never have capacity 0 unless they are NULL pointers.
*/
#include <zebra.h>
struct darr_metadata {
uint len;
uint cap;
};
void *__darr_insert_n(void *a, uint at, uint count, size_t esize, bool zero);
void *__darr_resize(void *a, uint count, size_t esize);
#define _darr_esize(A) sizeof((A)[0])
#define darr_esize(A) sizeof((A)[0])
#define _darr_len(A) _darr_meta(A)->len
#define _darr_meta(A) (((struct darr_metadata *)(A)) - 1)
#define _darr_resize(A, C) ({ (A) = __darr_resize((A), C, _darr_esize(A)); })
/* Get the current capacity of the array */
#define darr_cap(A) (((A) == NULL) ? 0 : _darr_meta(A)->cap)
/* Get the largest possible index one can `darr_ensure_i` w/o resizing */
#define darr_maxi(A) ((int)darr_cap(A) - 1)
/**
* Get the current length of the array.
*
* As long as `A` is non-NULL, this macro may be used as an L-value to modify
* the length of the array.
*
* Args:
* A: The dynamic array, can be NULL.
*
* Return:
* The current length of the array.
*/
#define darr_len(A) (((A) == NULL) ? 0 : _darr_meta(A)->len)
/**
* Set the current length of the array `A` to 0.
*
* Args:
* A: The dynamic array, can be NULL.
*/
#define darr_reset(A) \
do { \
if ((A)) \
_darr_len(A) = 0; \
} while (0)
/**
* Set the current length of the array `A` to `L`.
*
* This function does *not* guarantee the memory is valid to L,
* use `darr_ensure` or `darr_ensure_cap` for that.
*
* Args:
* A: The dynamic array, can only be NULL if (L) == 0.
* L: The new length of the array.
*/
#define darr_setlen(A, L) \
do { \
assert((A) || !(L)); \
if ((A)) { \
/* have to cast to avoid compiler warning for "0" */ \
assert((long long)darr_cap(A) >= (L)); \
_darr_len(A) = (L); \
} \
} while (0)
/**
* Free memory allocated for the dynamic array `A`
*
* Args:
* A: The dynamic array, can be NULL.
*/
#define darr_free(A) \
do { \
if ((A)) { \
free(_darr_meta(A)); \
(A) = NULL; \
} \
} while (0)
/**
* Make sure that there is room in the dynamic array `A` for `C` elements.
*
* The value `A` may be changed as a result of this call in which case any
* pointers into the previous memory block are no longer valid. The `A` value
* is guaranteed not to change if there is sufficient capacity in the array.
*
* Args:
* A: (IN/OUT) the dynamic array, can be NULL.
* I: the index to guarantee memory exists for
*
* Return:
* A pointer to the (possibly moved) array.
*/
#define darr_ensure_cap(A, C) \
({ \
if (darr_cap(A) < (C)) \
_darr_resize((A), (C)); \
(A); \
})
/**
* Return a pointer to the (I)th element of array `A`, making sure there is
* room for the element.
*
* If the array length is less than `I + 1` then the length is set to `I + 1`.
*
* The value `A` may be changed as a result of this call in which case any
* pointers into the previous memory block are no longer valid. The `A` value
* is guaranteed not to change if there is sufficient capacity in the array.
*
* Args:
*
* A: (IN/OUT) the dynamic array, can be NULL.
* I: the index to guarantee memory exists for
*
* Return:
* A pointer to the (I)th element in `A`
*/
#define darr_ensure_i(A, I) \
({ \
if ((int)(I) > darr_maxi(A)) \
_darr_resize((A), (I) + 1); \
if ((I) + 1 > _darr_len(A)) \
_darr_len(A) = (I) + 1; \
&(A)[I]; \
})
#define _darr_insert_n(A, I, N, Z) \
({ \
(A) = __darr_insert_n(A, I, N, _darr_esize(A), Z); \
&(A)[I]; \
})
/**
* Insert N uninitialized elements in the array at index `I`.
*
* Previous elements from `I` are shifted right by `N`. Array length is
* increased by `N`.
*
* The value `A` may be changed as a result of this call in which case any
* pointers into the previous memory block are no longer valid. The `A` value
* is guaranteed not to change if there is sufficient capacity in the array.
*
* The `z` variant zeros new elements.
*
* Args:
* A: The dynamic array, can be NULL.
*
* Return:
* A pointer to the first inserted element in the array.
*/
#define darr_insert_n(A, I, N) _darr_insert_n(A, I, N, false)
#define darr_insert_nz(A, I, N) _darr_insert_n(A, I, N, true)
/**
* Insert an uninitialized element in the array at index `I`.
*
* Previous elements from `I` are shifted right by 1. Array length is
* increased by 1.
*
* The value `A` may be changed as a result of this call in which case any
* pointers into the previous memory block are no longer valid. The `A` value
* is guaranteed not to change if there is sufficient capacity in the array.
*
* The `z` variant zeros the new element.
*
* Args:
* A: The dynamic array, can be NULL.
*
* Return:
* A pointer to the element in the array.
*/
#define darr_insert(A, I) _darr_insert_n(A, I, 1, false)
#define darr_insertz(A, I) _darr_insert_n(A, I, 1, true)
/**
* Remove `N` elements from the array starting at index `I`.
*
* Elements from `I` + `N` are shifted left by `N`. Array length is reduced by
* `N`.
*
* Args:
* A: The dynamic array, can be NULL.
*/
#define darr_remove_n(A, I, N) \
do { \
uint __i = (I); \
uint __n = (N); \
uint __len = darr_len(A); \
if (!__len) \
break; \
else if (__i + __n < __len) { \
memmove(&(A)[__i], &(A)[__i + __n], \
_darr_esize(A) * (__len - (__i + __n))); \
_darr_len(A) = __len - __n; \
} else \
_darr_len(A) = __i; \
} while (0)
/**
* Remove the `I`th element from the array.
*
* Previous elements from `I` + 1 are shifted left by 1, Array length is reduced
* by 1.
*
* Args:
* A: The dynamic array, can be NULL.
*/
#define darr_remove(A, I) darr_remove_n(A, I, 1)
#define _darr_append_n(A, N, Z) \
({ \
uint __len = darr_len(A); \
darr_ensure_cap(A, __len + (N)); \
_darr_len(A) = __len + (N); \
if (Z) \
memset(&(A)[__len], 0, (N)*_darr_esize(A)); \
&(A)[__len]; \
})
/**
* Extending the array's length by N.
*
* Args:
* A: The dynamic array, can be NULL.
*
* The `z` variant zeros new elements.
*
* Return:
* A pointer to the first of the added elements at the end of the array.
*/
#define darr_append_n(A, N) _darr_append_n(A, N, false)
#define darr_append_nz(A, N) _darr_append_n(A, N, true)
/**
* Extending the array's length by 1.
*
* Args:
* A: The dynamic array, can be NULL.
*
* The `z` variant zeros the new element.
*
* Return:
* A pointer to the new element at the end of the array.
*/
#define darr_append(A) _darr_append_n(A, 1, false)
#define darr_appendz(A) _darr_append_n(A, 1, true)
/**
* Append an element `E` onto the array `A`, extending it's length by 1.
*
* The `z` variant zeros the new element.
*
* Args:
* A: The dynamic array, can be NULL.
*
* Return:
* A pointer to the element in the array.
*/
#define darr_push(A, E) (*darr_append(A) = (E))
#define darr_pushz(A) (darr_appendz(A))
/**
* Pop the last `N` elements from the array decrementing the length by `N`.
*
* Args:
* A: The dynamic array, can be NULL.
*/
#define darr_pop_n(A, N) \
do { \
if ((A) && (N) >= _darr_len(A)) \
darr_reset(A); \
else \
_darr_len(A) -= (N); \
} while (0)
/**
* Pop the last element from the array decrementing the length by 1.
*
* Args:
* A: The dynamic array, can be NULL.
*
* Return:
* The element just popped.
*/
#define darr_pop(A) \
({ \
uint __len = _darr_len(A); \
assert(__len); \
darr_remove(A, __len - 1); \
/* count on fact that we don't resize */ \
(A)[__len - 1]; \
})
/**
* Return the address at the end of the array -- useful for iterating
*
* Args:
* A: The dynamic array, can be NULL.
*
* Return:
* The address of the end of the array (past the last elment) or NULL
* if `A` is NULL.
*/
#define darr_end(A) ((A) + darr_len(A))
/**
* Iterate over array `A` using a pointer to each element in `P`.
*
* Args:
* A: The dynamic array, can be NULL.
* P: A variable with the same type as A used as the iterator.
*/
#define darr_foreach_p(A, P) for ((P) = (A); (P) < darr_end(A); (P)++)
/**
* Iterate over array `A`s indices.
*
* Args:
* A: The dynamic array, can be NULL.
* I: A uint variable to store the current element index in.
*/
#define darr_foreach_i(A, I) for ((I) = 0; (I) < darr_len(A); (I)++)

View File

@ -136,28 +136,6 @@ message BeOperDataGetReply {
optional YangDataReply data = 5; optional YangDataReply data = 5;
} }
message BeOperDataNotify {
required YangDataReply data = 5;
}
message BeConfigCmdReq {
required string cmd = 1;
}
message BeConfigCmdReply {
required bool success = 1;
required string error_if_any = 2;
}
message BeShowCmdReq {
required string cmd = 1;
}
message BeShowCmdReply {
required bool success = 1;
required string cmd_ouput = 2;
}
// //
// Any message on the MGMTD Backend Interface. // Any message on the MGMTD Backend Interface.
// //
@ -173,11 +151,6 @@ message BeMessage {
BeCfgDataApplyReply cfg_apply_reply = 9; BeCfgDataApplyReply cfg_apply_reply = 9;
BeOperDataGetReq get_req = 10; BeOperDataGetReq get_req = 10;
BeOperDataGetReply get_reply = 11; BeOperDataGetReply get_reply = 11;
BeOperDataNotify notify_data = 12;
BeConfigCmdReq cfg_cmd_req = 13;
BeConfigCmdReply cfg_cmd_reply = 14;
BeShowCmdReq show_cmd_req = 15;
BeShowCmdReply show_cmd_reply = 16;
} }
} }
@ -267,36 +240,22 @@ message FeCommitConfigReply {
optional string error_if_any = 8; optional string error_if_any = 8;
} }
message FeGetConfigReq { message FeGetReq {
required uint64 session_id = 1; required uint64 session_id = 1;
required DatastoreId ds_id = 2; required bool config = 2;
required uint64 req_id = 3; required DatastoreId ds_id = 3;
repeated YangGetDataReq data = 4; required uint64 req_id = 4;
repeated YangGetDataReq data = 5;
} }
message FeGetConfigReply { message FeGetReply {
required uint64 session_id = 1; required uint64 session_id = 1;
required DatastoreId ds_id = 2; required bool config = 2;
required uint64 req_id = 3; required DatastoreId ds_id = 3;
required bool success = 4; required uint64 req_id = 4;
optional string error_if_any = 5; required bool success = 5;
optional YangDataReply data = 6; optional string error_if_any = 6;
} optional YangDataReply data = 7;
message FeGetDataReq {
required uint64 session_id = 1;
required DatastoreId ds_id = 2;
required uint64 req_id = 3;
repeated YangGetDataReq data = 4;
}
message FeGetDataReply {
required uint64 session_id = 1;
required DatastoreId ds_id = 2;
required uint64 req_id = 3;
required bool success = 4;
optional string error_if_any = 5;
optional YangDataReply data = 6;
} }
message FeNotifyDataReq { message FeNotifyDataReq {
@ -322,10 +281,8 @@ message FeMessage {
FeSetConfigReply setcfg_reply = 8; FeSetConfigReply setcfg_reply = 8;
FeCommitConfigReq commcfg_req = 9; FeCommitConfigReq commcfg_req = 9;
FeCommitConfigReply commcfg_reply = 10; FeCommitConfigReply commcfg_reply = 10;
FeGetConfigReq getcfg_req = 11; FeGetReq get_req = 11;
FeGetConfigReply getcfg_reply = 12; FeGetReply get_reply = 12;
FeGetDataReq getdata_req = 13;
FeGetDataReply getdata_reply = 14;
FeNotifyDataReq notify_data_req = 15; FeNotifyDataReq notify_data_req = 15;
FeRegisterNotifyReq regnotify_req = 16; FeRegisterNotifyReq regnotify_req = 16;
} }

View File

@ -768,9 +768,6 @@ static int mgmt_be_client_handle_msg(struct mgmt_be_client *client_ctx,
client_ctx, (uint64_t)be_msg->cfg_apply_req->txn_id); client_ctx, (uint64_t)be_msg->cfg_apply_req->txn_id);
break; break;
case MGMTD__BE_MESSAGE__MESSAGE_GET_REQ: case MGMTD__BE_MESSAGE__MESSAGE_GET_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_CMD_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_SHOW_CMD_REQ:
MGMTD_BE_CLIENT_ERR("Got unhandled message type %u", MGMTD_BE_CLIENT_ERR("Got unhandled message type %u",
be_msg->message_case); be_msg->message_case);
/* /*
@ -781,13 +778,11 @@ static int mgmt_be_client_handle_msg(struct mgmt_be_client *client_ctx,
* NOTE: The following messages are always sent from Backend * NOTE: The following messages are always sent from Backend
* clients to MGMTd only and/or need not be handled here. * clients to MGMTd only and/or need not be handled here.
*/ */
case MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_GET_REPLY: case MGMTD__BE_MESSAGE__MESSAGE_GET_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_TXN_REPLY: case MGMTD__BE_MESSAGE__MESSAGE_TXN_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_DATA_REPLY: case MGMTD__BE_MESSAGE__MESSAGE_CFG_DATA_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_APPLY_REPLY: case MGMTD__BE_MESSAGE__MESSAGE_CFG_APPLY_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_CMD_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_SHOW_CMD_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_NOTIFY_DATA:
case MGMTD__BE_MESSAGE__MESSAGE__NOT_SET: case MGMTD__BE_MESSAGE__MESSAGE__NOT_SET:
default: default:
/* /*

View File

@ -247,58 +247,31 @@ int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
return mgmt_fe_client_send_msg(client, &fe_msg, false); return mgmt_fe_client_send_msg(client, &fe_msg, false);
} }
int mgmt_fe_send_getcfg_req(struct mgmt_fe_client *client, uint64_t session_id, int mgmt_fe_send_get_req(struct mgmt_fe_client *client, uint64_t session_id,
uint64_t req_id, Mgmtd__DatastoreId ds_id, uint64_t req_id, bool is_config,
Mgmtd__YangGetDataReq *data_req[], Mgmtd__DatastoreId ds_id,
int num_data_reqs) Mgmtd__YangGetDataReq *data_req[], int num_data_reqs)
{ {
(void)req_id; (void)req_id;
Mgmtd__FeMessage fe_msg; Mgmtd__FeMessage fe_msg;
Mgmtd__FeGetConfigReq getcfg_req; Mgmtd__FeGetReq getcfg_req;
mgmtd__fe_get_config_req__init(&getcfg_req); mgmtd__fe_get_req__init(&getcfg_req);
getcfg_req.session_id = session_id; getcfg_req.session_id = session_id;
getcfg_req.config = is_config;
getcfg_req.ds_id = ds_id; getcfg_req.ds_id = ds_id;
getcfg_req.req_id = req_id; getcfg_req.req_id = req_id;
getcfg_req.data = data_req; getcfg_req.data = data_req;
getcfg_req.n_data = (size_t)num_data_reqs; getcfg_req.n_data = (size_t)num_data_reqs;
mgmtd__fe_message__init(&fe_msg); mgmtd__fe_message__init(&fe_msg);
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ; fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GET_REQ;
fe_msg.getcfg_req = &getcfg_req; fe_msg.get_req = &getcfg_req;
MGMTD_FE_CLIENT_DBG( MGMTD_FE_CLIENT_DBG("Sending GET_REQ (iscfg %d) message for DS:%s session-id %" PRIu64
"Sending GET_CONFIG_REQ message for DS:%s session-id %" PRIu64 " (#xpaths:%d)",
" (#xpaths:%d)", is_config, dsid2name(ds_id), session_id,
dsid2name(ds_id), session_id, num_data_reqs); num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false);
}
int mgmt_fe_send_getdata_req(struct mgmt_fe_client *client, uint64_t session_id,
uint64_t req_id, Mgmtd__DatastoreId ds_id,
Mgmtd__YangGetDataReq *data_req[],
int num_data_reqs)
{
(void)req_id;
Mgmtd__FeMessage fe_msg;
Mgmtd__FeGetDataReq getdata_req;
mgmtd__fe_get_data_req__init(&getdata_req);
getdata_req.session_id = session_id;
getdata_req.ds_id = ds_id;
getdata_req.req_id = req_id;
getdata_req.data = data_req;
getdata_req.n_data = (size_t)num_data_reqs;
mgmtd__fe_message__init(&fe_msg);
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ;
fe_msg.getdata_req = &getdata_req;
MGMTD_FE_CLIENT_DBG(
"Sending GET_CONFIG_REQ message for DS:%s session-id %" PRIu64
" (#xpaths:%d)",
dsid2name(ds_id), session_id, num_data_reqs);
return mgmt_fe_client_send_msg(client, &fe_msg, false); return mgmt_fe_client_send_msg(client, &fe_msg, false);
} }
@ -434,58 +407,33 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
fe_msg->commcfg_reply->validate_only, fe_msg->commcfg_reply->validate_only,
fe_msg->commcfg_reply->error_if_any); fe_msg->commcfg_reply->error_if_any);
break; break;
case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY: case MGMTD__FE_MESSAGE__MESSAGE_GET_REPLY:
MGMTD_FE_CLIENT_DBG("Got GETCFG_REPLY for session-id %" PRIu64, MGMTD_FE_CLIENT_DBG("Got GET_REPLY for session-id %" PRIu64,
fe_msg->getcfg_reply->session_id); fe_msg->get_reply->session_id);
session = mgmt_fe_find_session_by_session_id( session =
client, fe_msg->getcfg_reply->session_id); mgmt_fe_find_session_by_session_id(client,
fe_msg->get_reply
->session_id);
if (session && session->client && if (session && session->client &&
session->client->cbs.get_data_notify) session->client->cbs.get_data_notify)
(*session->client->cbs.get_data_notify)( (*session->client->cbs.get_data_notify)(
client, client->user_data, session->client_id, client, client->user_data, session->client_id,
fe_msg->getcfg_reply->session_id, fe_msg->get_reply->session_id,
session->user_ctx, fe_msg->getcfg_reply->req_id, session->user_ctx, fe_msg->get_reply->req_id,
fe_msg->getcfg_reply->success, fe_msg->get_reply->success,
fe_msg->getcfg_reply->ds_id, fe_msg->get_reply->ds_id,
fe_msg->getcfg_reply->data fe_msg->get_reply->data
? fe_msg->getcfg_reply->data->data ? fe_msg->get_reply->data->data
: NULL, : NULL,
fe_msg->getcfg_reply->data fe_msg->get_reply->data
? fe_msg->getcfg_reply->data->n_data ? fe_msg->get_reply->data->n_data
: 0, : 0,
fe_msg->getcfg_reply->data fe_msg->get_reply->data
? fe_msg->getcfg_reply->data->next_indx ? fe_msg->get_reply->data->next_indx
: 0, : 0,
fe_msg->getcfg_reply->error_if_any); fe_msg->get_reply->error_if_any);
break;
case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY:
MGMTD_FE_CLIENT_DBG("Got GETDATA_REPLY for session-id %" PRIu64,
fe_msg->getdata_reply->session_id);
session = mgmt_fe_find_session_by_session_id(
client, fe_msg->getdata_reply->session_id);
if (session && session->client &&
session->client->cbs.get_data_notify)
(*session->client->cbs.get_data_notify)(
client, client->user_data, session->client_id,
fe_msg->getdata_reply->session_id,
session->user_ctx,
fe_msg->getdata_reply->req_id,
fe_msg->getdata_reply->success,
fe_msg->getdata_reply->ds_id,
fe_msg->getdata_reply->data
? fe_msg->getdata_reply->data->data
: NULL,
fe_msg->getdata_reply->data
? fe_msg->getdata_reply->data->n_data
: 0,
fe_msg->getdata_reply->data
? fe_msg->getdata_reply->data->next_indx
: 0,
fe_msg->getdata_reply->error_if_any);
break; break;
case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ: case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ: case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ:
@ -502,8 +450,7 @@ static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ: case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ: case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ: case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ: case MGMTD__FE_MESSAGE__MESSAGE_GET_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ:
case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET: case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET:
default: default:
/* /*

View File

@ -294,7 +294,10 @@ extern int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
bool validate_only, bool abort); bool validate_only, bool abort);
/* /*
* Send GET_CONFIG_REQ to MGMTD for one or more config data item(s). * Send GET_REQ to MGMTD for one or more config data item(s).
*
* If is_config is true gets config from the MGMTD datastore, otherwise
* operational state is queried from the backend clients.
* *
* lib_hndl * lib_hndl
* Client library handler. * Client library handler.
@ -302,6 +305,9 @@ extern int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
* session_id * session_id
* Client session ID. * Client session ID.
* *
* is_config
* True if get-config else get-data.
*
* req_id * req_id
* Client request ID. * Client request ID.
* *
@ -309,31 +315,19 @@ extern int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client *client,
* Datastore ID (Running/Candidate) * Datastore ID (Running/Candidate)
* *
* data_req * data_req
* Get config requested. * Get xpaths requested.
* *
* num_req * num_req
* Number of get config requests. * Number of get xpath requests.
* *
* Returns: * Returns:
* 0 on success, otherwise msg_conn_send_msg() return values. * 0 on success, otherwise msg_conn_send_msg() return values.
*/ */
extern int mgmt_fe_send_getcfg_req(struct mgmt_fe_client *client, extern int mgmt_fe_send_get_req(struct mgmt_fe_client *client,
uint64_t session_id, uint64_t req_id, uint64_t session_id, uint64_t req_id,
Mgmtd__DatastoreId ds_id, bool is_config, Mgmtd__DatastoreId ds_id,
Mgmtd__YangGetDataReq **data_req, Mgmtd__YangGetDataReq **data_req, int num_reqs);
int num_reqs);
/*
* Send GET_DATA_REQ to MGMTD for one or more data item(s).
*
* Similar to get config request but supports getting data
* from operational ds aka backend clients directly.
*/
extern int mgmt_fe_send_getdata_req(struct mgmt_fe_client *client,
uint64_t session_id, uint64_t req_id,
Mgmtd__DatastoreId ds_id,
Mgmtd__YangGetDataReq **data_req,
int num_reqs);
/* /*
* Send NOTIFY_REGISTER_REQ to MGMTD daemon. * Send NOTIFY_REGISTER_REQ to MGMTD daemon.

View File

@ -25,6 +25,7 @@ lib_libfrr_la_SOURCES = \
lib/command_parse.y \ lib/command_parse.y \
lib/cspf.c \ lib/cspf.c \
lib/csv.c \ lib/csv.c \
lib/darr.c \
lib/debug.c \ lib/debug.c \
lib/defaults.c \ lib/defaults.c \
lib/distribute.c \ lib/distribute.c \
@ -209,6 +210,7 @@ pkginclude_HEADERS += \
lib/compiler.h \ lib/compiler.h \
lib/cspf.h \ lib/cspf.h \
lib/csv.h \ lib/csv.h \
lib/darr.h \
lib/db.h \ lib/db.h \
lib/debug.h \ lib/debug.h \
lib/defaults.h \ lib/defaults.h \

View File

@ -3822,8 +3822,9 @@ int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only, bool abort)
return 0; return 0;
} }
int vty_mgmt_send_get_config(struct vty *vty, Mgmtd__DatastoreId datastore, int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
const char **xpath_list, int num_req) Mgmtd__DatastoreId datastore, const char **xpath_list,
int num_req)
{ {
Mgmtd__YangData yang_data[VTY_MAXCFGCHANGES]; Mgmtd__YangData yang_data[VTY_MAXCFGCHANGES];
Mgmtd__YangGetDataReq get_req[VTY_MAXCFGCHANGES]; Mgmtd__YangGetDataReq get_req[VTY_MAXCFGCHANGES];
@ -3841,13 +3842,11 @@ int vty_mgmt_send_get_config(struct vty *vty, Mgmtd__DatastoreId datastore,
get_req[i].data = &yang_data[i]; get_req[i].data = &yang_data[i];
getreq[i] = &get_req[i]; getreq[i] = &get_req[i];
} }
if (mgmt_fe_send_getcfg_req(mgmt_fe_client, vty->mgmt_session_id, if (mgmt_fe_send_get_req(mgmt_fe_client, vty->mgmt_session_id,
vty->mgmt_req_id, datastore, getreq, vty->mgmt_req_id, is_config, datastore, getreq,
num_req)) { num_req)) {
zlog_err( zlog_err("Failed to send GET- to MGMTD for req-id %" PRIu64 ".",
"Failed to send GET-CONFIG to MGMTD for req-id %" PRIu64 vty->mgmt_req_id);
".",
vty->mgmt_req_id);
vty_out(vty, "Failed to send GET-CONFIG to MGMTD!\n"); vty_out(vty, "Failed to send GET-CONFIG to MGMTD!\n");
return -1; return -1;
} }
@ -3857,40 +3856,6 @@ int vty_mgmt_send_get_config(struct vty *vty, Mgmtd__DatastoreId datastore,
return 0; return 0;
} }
int vty_mgmt_send_get_data(struct vty *vty, Mgmtd__DatastoreId datastore,
const char **xpath_list, int num_req)
{
Mgmtd__YangData yang_data[VTY_MAXCFGCHANGES];
Mgmtd__YangGetDataReq get_req[VTY_MAXCFGCHANGES];
Mgmtd__YangGetDataReq *getreq[VTY_MAXCFGCHANGES];
int i;
vty->mgmt_req_id++;
for (i = 0; i < num_req; i++) {
mgmt_yang_get_data_req_init(&get_req[i]);
mgmt_yang_data_init(&yang_data[i]);
yang_data->xpath = (char *)xpath_list[i];
get_req[i].data = &yang_data[i];
getreq[i] = &get_req[i];
}
if (mgmt_fe_send_getdata_req(mgmt_fe_client, vty->mgmt_session_id,
vty->mgmt_req_id, datastore, getreq,
num_req)) {
zlog_err("Failed to send GET-DATA to MGMTD for req-id %" PRIu64
".",
vty->mgmt_req_id);
vty_out(vty, "Failed to send GET-DATA to MGMTD!\n");
return -1;
}
vty->mgmt_req_pending_cmd = "MESSAGE_GETDATA_REQ";
return 0;
}
/* Install vty's own commands like `who' command. */ /* Install vty's own commands like `who' command. */
void vty_init(struct event_loop *master_thread, bool do_command_logging) void vty_init(struct event_loop *master_thread, bool do_command_logging)
{ {

View File

@ -411,11 +411,9 @@ extern bool mgmt_vty_read_configs(void);
extern int vty_mgmt_send_config_data(struct vty *vty, bool implicit_commit); extern int vty_mgmt_send_config_data(struct vty *vty, bool implicit_commit);
extern int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only, extern int vty_mgmt_send_commit_config(struct vty *vty, bool validate_only,
bool abort); bool abort);
extern int vty_mgmt_send_get_config(struct vty *vty, extern int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
Mgmtd__DatastoreId datastore, Mgmtd__DatastoreId datastore,
const char **xpath_list, int num_req); const char **xpath_list, int num_req);
extern int vty_mgmt_send_get_data(struct vty *vty, Mgmtd__DatastoreId datastore,
const char **xpath_list, int num_req);
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id, extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
bool lock, bool scok); bool lock, bool scok);
extern void vty_mgmt_resume_response(struct vty *vty, bool success); extern void vty_mgmt_resume_response(struct vty *vty, bool success);

View File

@ -8,6 +8,7 @@
*/ */
#include <zebra.h> #include <zebra.h>
#include "darr.h"
#include "frrevent.h" #include "frrevent.h"
#include "sockopt.h" #include "sockopt.h"
#include "network.h" #include "network.h"
@ -28,23 +29,9 @@
frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter)) frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter))
/* /*
* Static mapping of YANG XPath regular expressions and * Mapping of YANG XPath regular expressions to
* the corresponding interested backend clients. * their corresponding backend clients.
* NOTE: Thiis is a static mapping defined by all MGMTD
* backend client modules (for now, till we develop a
* more dynamic way of creating and updating this map).
* A running map is created by MGMTD in run-time to
* handle real-time mapping of YANG xpaths to one or
* more interested backend client adapters.
*
* Please see xpath_map_reg[] in lib/mgmt_be_client.c
* for the actual map
*/ */
struct mgmt_be_xpath_map_init {
const char *xpath_regexp;
uint subscr_info[MGMTD_BE_CLIENT_ID_MAX];
};
struct mgmt_be_xpath_map { struct mgmt_be_xpath_map {
char *xpath_regexp; char *xpath_regexp;
uint subscr_info[MGMTD_BE_CLIENT_ID_MAX]; uint subscr_info[MGMTD_BE_CLIENT_ID_MAX];
@ -66,55 +53,6 @@ struct mgmt_be_get_adapter_config_params {
uint32_t seq; uint32_t seq;
}; };
/*
* Static mapping of YANG XPath regular expressions and
* the corresponding interested backend clients.
* NOTE: Thiis is a static mapping defined by all MGMTD
* backend client modules (for now, till we develop a
* more dynamic way of creating and updating this map).
* A running map is created by MGMTD in run-time to
* handle real-time mapping of YANG xpaths to one or
* more interested backend client adapters.
*/
static const struct mgmt_be_xpath_map_init mgmt_xpath_map_init[] = {
{
.xpath_regexp = "/frr-vrf:lib/*",
.subscr_info =
{
#if HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] =
MGMT_SUBSCR_VALIDATE_CFG |
MGMT_SUBSCR_NOTIFY_CFG,
#endif
},
},
{
.xpath_regexp = "/frr-interface:lib/*",
.subscr_info =
{
#if HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] =
MGMT_SUBSCR_VALIDATE_CFG |
MGMT_SUBSCR_NOTIFY_CFG,
#endif
},
},
{
.xpath_regexp =
"/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/*",
.subscr_info =
{
#if HAVE_STATICD
[MGMTD_BE_CLIENT_ID_STATICD] =
MGMT_SUBSCR_VALIDATE_CFG |
MGMT_SUBSCR_NOTIFY_CFG,
#endif
},
},
};
/* /*
* Each client gets their own map, but also union all the strings into the * Each client gets their own map, but also union all the strings into the
* above map as well. * above map as well.
@ -145,12 +83,15 @@ static struct mgmt_be_client_xpath_map
#endif #endif
}; };
#define MGMTD_BE_MAX_NUM_XPATH_MAP 256 /*
* We would like to have a better ADT than one with O(n) comparisons
/* We would like to have a better ADT than one with O(n) *
comparisons */ * Perhaps it's possible to sort this array in a way that allows binary search
* to find the start, then walk until no possible match can follow? Intuition
* says this probably involves exact match/no-match on a stem in the map array
* or something like that.
*/
static struct mgmt_be_xpath_map *mgmt_xpath_map; static struct mgmt_be_xpath_map *mgmt_xpath_map;
static uint mgmt_num_xpath_maps;
static struct event_loop *mgmt_loop; static struct event_loop *mgmt_loop;
static struct msg_server mgmt_be_server = {.fd = -1}; static struct msg_server mgmt_be_server = {.fd = -1};
@ -193,34 +134,52 @@ mgmt_be_find_adapter_by_name(const char *name)
return NULL; return NULL;
} }
static void mgmt_register_client_xpath(enum mgmt_be_client_id id,
const char *xpath, uint subscribed)
{
struct mgmt_be_xpath_map *map;
darr_foreach_p (mgmt_xpath_map, map)
if (!strcmp(xpath, map->xpath_regexp)) {
map->subscr_info[id] = subscribed;
return;
}
/* we didn't find a matching entry */
map = darr_append(mgmt_xpath_map);
map->xpath_regexp = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
map->subscr_info[id] = subscribed;
}
/*
* Load the initial mapping from static init map
*/
static void mgmt_be_xpath_map_init(void) static void mgmt_be_xpath_map_init(void)
{ {
uint i; struct mgmt_be_client_xpath *init, *end;
enum mgmt_be_client_id id;
MGMTD_BE_ADAPTER_DBG("Init XPath Maps"); MGMTD_BE_ADAPTER_DBG("Init XPath Maps");
mgmt_num_xpath_maps = array_size(mgmt_xpath_map_init); FOREACH_MGMTD_BE_CLIENT_ID (id) {
mgmt_xpath_map = init = mgmt_client_xpaths[id].xpaths;
calloc(1, sizeof(*mgmt_xpath_map) * mgmt_num_xpath_maps); end = init + mgmt_client_xpaths[id].nxpaths;
for (i = 0; i < mgmt_num_xpath_maps; i++) { for (; init < end; init++) {
MGMTD_BE_ADAPTER_DBG(" - XPATH: '%s'", MGMTD_BE_ADAPTER_DBG(" - XPATH: '%s'", init->xpath);
mgmt_xpath_map_init[i].xpath_regexp); mgmt_register_client_xpath(id, init->xpath,
mgmt_xpath_map[i].xpath_regexp = XSTRDUP( init->subscribed);
MTYPE_MGMTD_XPATH, mgmt_xpath_map_init[i].xpath_regexp); }
memcpy(mgmt_xpath_map[i].subscr_info,
mgmt_xpath_map_init[i].subscr_info,
sizeof(mgmt_xpath_map_init[i].subscr_info));
} }
MGMTD_BE_ADAPTER_DBG("Total XPath Maps: %u", mgmt_num_xpath_maps);
MGMTD_BE_ADAPTER_DBG("Total XPath Maps: %u", darr_len(mgmt_xpath_map));
} }
static void mgmt_be_xpath_map_cleanup(void) static void mgmt_be_xpath_map_cleanup(void)
{ {
uint i; struct mgmt_be_xpath_map *map;
for (i = 0; i < mgmt_num_xpath_maps; i++) darr_foreach_p (mgmt_xpath_map, map)
XFREE(MTYPE_MGMTD_XPATH, mgmt_xpath_map[i].xpath_regexp); XFREE(MTYPE_MGMTD_XPATH, map->xpath_regexp);
free(mgmt_xpath_map); darr_free(mgmt_xpath_map);
} }
static int mgmt_be_eval_regexp_match(const char *xpath_regexp, static int mgmt_be_eval_regexp_match(const char *xpath_regexp,
@ -532,9 +491,6 @@ mgmt_be_adapter_handle_msg(struct mgmt_be_client_adapter *adapter,
be_msg->cfg_apply_reply->error_if_any, adapter); be_msg->cfg_apply_reply->error_if_any, adapter);
break; break;
case MGMTD__BE_MESSAGE__MESSAGE_GET_REPLY: case MGMTD__BE_MESSAGE__MESSAGE_GET_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_CMD_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_SHOW_CMD_REPLY:
case MGMTD__BE_MESSAGE__MESSAGE_NOTIFY_DATA:
/* /*
* TODO: Add handling code in future. * TODO: Add handling code in future.
*/ */
@ -548,8 +504,6 @@ mgmt_be_adapter_handle_msg(struct mgmt_be_client_adapter *adapter,
case MGMTD__BE_MESSAGE__MESSAGE_TXN_REQ: case MGMTD__BE_MESSAGE__MESSAGE_TXN_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_DATA_REQ: case MGMTD__BE_MESSAGE__MESSAGE_CFG_DATA_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_APPLY_REQ: case MGMTD__BE_MESSAGE__MESSAGE_CFG_APPLY_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_CFG_CMD_REQ:
case MGMTD__BE_MESSAGE__MESSAGE_SHOW_CMD_REQ:
case MGMTD__BE_MESSAGE__MESSAGE__NOT_SET: case MGMTD__BE_MESSAGE__MESSAGE__NOT_SET:
default: default:
/* /*
@ -835,19 +789,17 @@ int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
void mgmt_be_get_subscr_info_for_xpath( void mgmt_be_get_subscr_info_for_xpath(
const char *xpath, struct mgmt_be_client_subscr_info *subscr_info) const char *xpath, struct mgmt_be_client_subscr_info *subscr_info)
{ {
struct mgmt_be_xpath_map *map;
enum mgmt_be_client_id id; enum mgmt_be_client_id id;
uint i;
memset(subscr_info, 0, sizeof(*subscr_info)); memset(subscr_info, 0, sizeof(*subscr_info));
MGMTD_BE_ADAPTER_DBG("XPATH: '%s'", xpath); MGMTD_BE_ADAPTER_DBG("XPATH: '%s'", xpath);
for (i = 0; i < mgmt_num_xpath_maps; i++) { darr_foreach_p (mgmt_xpath_map, map) {
if (!mgmt_be_eval_regexp_match(mgmt_xpath_map[i].xpath_regexp, if (!mgmt_be_eval_regexp_match(map->xpath_regexp, xpath))
xpath))
continue; continue;
FOREACH_MGMTD_BE_CLIENT_ID (id) { FOREACH_MGMTD_BE_CLIENT_ID (id) {
subscr_info->xpath_subscr[id] |= subscr_info->xpath_subscr[id] |= map->subscr_info[id];
mgmt_xpath_map[i].subscr_info[id];
} }
} }
@ -928,18 +880,17 @@ void mgmt_be_adapter_status_write(struct vty *vty)
void mgmt_be_xpath_register_write(struct vty *vty) void mgmt_be_xpath_register_write(struct vty *vty)
{ {
uint indx; struct mgmt_be_xpath_map *map;
enum mgmt_be_client_id id; enum mgmt_be_client_id id;
struct mgmt_be_client_adapter *adapter; struct mgmt_be_client_adapter *adapter;
uint info; uint info;
vty_out(vty, "MGMTD Backend XPath Registry\n"); vty_out(vty, "MGMTD Backend XPath Registry\n");
for (indx = 0; indx < mgmt_num_xpath_maps; indx++) { darr_foreach_p (mgmt_xpath_map, map) {
vty_out(vty, " - XPATH: '%s'\n", vty_out(vty, " - XPATH: '%s'\n", map->xpath_regexp);
mgmt_xpath_map[indx].xpath_regexp);
FOREACH_MGMTD_BE_CLIENT_ID (id) { FOREACH_MGMTD_BE_CLIENT_ID (id) {
info = mgmt_xpath_map[indx].subscr_info[id]; info = map->subscr_info[id];
if (!info) if (!info)
continue; continue;
vty_out(vty, vty_out(vty,
@ -954,7 +905,7 @@ void mgmt_be_xpath_register_write(struct vty *vty)
} }
} }
vty_out(vty, "Total XPath Registries: %u\n", mgmt_num_xpath_maps); vty_out(vty, "Total XPath Registries: %u\n", darr_len(mgmt_xpath_map));
} }
void mgmt_be_xpath_subscr_info_write(struct vty *vty, const char *xpath) void mgmt_be_xpath_subscr_info_write(struct vty *vty, const char *xpath)

View File

@ -273,9 +273,8 @@ mgmt_fe_create_session(struct mgmt_fe_client_adapter *adapter,
return session; return session;
} }
static int mgmt_fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter, static int fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter,
Mgmtd__FeMessage *fe_msg, Mgmtd__FeMessage *fe_msg, bool short_circuit_ok)
bool short_circuit_ok)
{ {
return msg_conn_send_msg( return msg_conn_send_msg(
adapter->conn, MGMT_MSG_VERSION_PROTOBUF, fe_msg, adapter->conn, MGMT_MSG_VERSION_PROTOBUF, fe_msg,
@ -284,10 +283,9 @@ static int mgmt_fe_adapter_send_msg(struct mgmt_fe_client_adapter *adapter,
short_circuit_ok); short_circuit_ok);
} }
static int static int fe_adapter_send_session_reply(struct mgmt_fe_client_adapter *adapter,
mgmt_fe_send_session_reply(struct mgmt_fe_client_adapter *adapter, struct mgmt_fe_session_ctx *session,
struct mgmt_fe_session_ctx *session, bool create, bool success)
bool create, bool success)
{ {
Mgmtd__FeMessage fe_msg; Mgmtd__FeMessage fe_msg;
Mgmtd__FeSessionReply session_reply; Mgmtd__FeSessionReply session_reply;
@ -309,13 +307,13 @@ mgmt_fe_send_session_reply(struct mgmt_fe_client_adapter *adapter,
"Sending SESSION_REPLY message to MGMTD Frontend client '%s'", "Sending SESSION_REPLY message to MGMTD Frontend client '%s'",
adapter->name); adapter->name);
return mgmt_fe_adapter_send_msg(adapter, &fe_msg, true); return fe_adapter_send_msg(adapter, &fe_msg, true);
} }
static int mgmt_fe_send_lockds_reply(struct mgmt_fe_session_ctx *session, static int fe_adapter_send_lockds_reply(struct mgmt_fe_session_ctx *session,
Mgmtd__DatastoreId ds_id, Mgmtd__DatastoreId ds_id,
uint64_t req_id, bool lock_ds, uint64_t req_id, bool lock_ds,
bool success, const char *error_if_any) bool success, const char *error_if_any)
{ {
Mgmtd__FeMessage fe_msg; Mgmtd__FeMessage fe_msg;
Mgmtd__FeLockDsReply lockds_reply; Mgmtd__FeLockDsReply lockds_reply;
@ -340,10 +338,10 @@ static int mgmt_fe_send_lockds_reply(struct mgmt_fe_session_ctx *session,
"Sending LOCK_DS_REPLY message to MGMTD Frontend client '%s' scok: %d", "Sending LOCK_DS_REPLY message to MGMTD Frontend client '%s' scok: %d",
session->adapter->name, scok); session->adapter->name, scok);
return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg, scok); return fe_adapter_send_msg(session->adapter, &fe_msg, scok);
} }
static int mgmt_fe_send_setcfg_reply(struct mgmt_fe_session_ctx *session, static int fe_adapter_send_set_cfg_reply(struct mgmt_fe_session_ctx *session,
Mgmtd__DatastoreId ds_id, Mgmtd__DatastoreId ds_id,
uint64_t req_id, bool success, uint64_t req_id, bool success,
const char *error_if_any, const char *error_if_any,
@ -387,10 +385,10 @@ static int mgmt_fe_send_setcfg_reply(struct mgmt_fe_session_ctx *session,
gettimeofday(&session->adapter->setcfg_stats.last_end, NULL); gettimeofday(&session->adapter->setcfg_stats.last_end, NULL);
mgmt_fe_adapter_compute_set_cfg_timers(&session->adapter->setcfg_stats); mgmt_fe_adapter_compute_set_cfg_timers(&session->adapter->setcfg_stats);
return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg, false); return fe_adapter_send_msg(session->adapter, &fe_msg, false);
} }
static int mgmt_fe_send_commitcfg_reply( static int fe_adapter_send_commit_cfg_reply(
struct mgmt_fe_session_ctx *session, Mgmtd__DatastoreId src_ds_id, struct mgmt_fe_session_ctx *session, Mgmtd__DatastoreId src_ds_id,
Mgmtd__DatastoreId dst_ds_id, uint64_t req_id, enum mgmt_result result, Mgmtd__DatastoreId dst_ds_id, uint64_t req_id, enum mgmt_result result,
bool validate_only, const char *error_if_any) bool validate_only, const char *error_if_any)
@ -433,83 +431,43 @@ static int mgmt_fe_send_commitcfg_reply(
if (mm->perf_stats_en) if (mm->perf_stats_en)
gettimeofday(&session->adapter->cmt_stats.last_end, NULL); gettimeofday(&session->adapter->cmt_stats.last_end, NULL);
mgmt_fe_session_compute_commit_timers(&session->adapter->cmt_stats); mgmt_fe_session_compute_commit_timers(&session->adapter->cmt_stats);
return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg, false); return fe_adapter_send_msg(session->adapter, &fe_msg, false);
} }
static int mgmt_fe_send_getcfg_reply(struct mgmt_fe_session_ctx *session, static int fe_adapter_send_get_reply(struct mgmt_fe_session_ctx *session,
Mgmtd__DatastoreId ds_id, Mgmtd__DatastoreId ds_id, uint64_t req_id,
uint64_t req_id, bool success, bool success, Mgmtd__YangDataReply *data,
Mgmtd__YangDataReply *data, const char *error_if_any)
const char *error_if_any)
{ {
Mgmtd__FeMessage fe_msg; Mgmtd__FeMessage fe_msg;
Mgmtd__FeGetConfigReply getcfg_reply; Mgmtd__FeGetReply get_reply;
assert(session->adapter); assert(session->adapter);
mgmtd__fe_get_config_reply__init(&getcfg_reply); mgmtd__fe_get_reply__init(&get_reply);
getcfg_reply.session_id = session->session_id; get_reply.session_id = session->session_id;
getcfg_reply.ds_id = ds_id; get_reply.ds_id = ds_id;
getcfg_reply.req_id = req_id; get_reply.req_id = req_id;
getcfg_reply.success = success; get_reply.success = success;
getcfg_reply.data = data; get_reply.data = data;
if (error_if_any) if (error_if_any)
getcfg_reply.error_if_any = (char *)error_if_any; get_reply.error_if_any = (char *)error_if_any;
mgmtd__fe_message__init(&fe_msg); mgmtd__fe_message__init(&fe_msg);
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY; fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GET_REPLY;
fe_msg.getcfg_reply = &getcfg_reply; fe_msg.get_reply = &get_reply;
MGMTD_FE_ADAPTER_DBG( MGMTD_FE_ADAPTER_DBG("Sending GET_REPLY message to MGMTD Frontend client '%s'",
"Sending GET_CONFIG_REPLY message to MGMTD Frontend client '%s'", session->adapter->name);
session->adapter->name);
/* /*
* Cleanup the SHOW transaction associated with this session. * Cleanup the SHOW transaction associated with this session.
*/ */
if (session->txn_id && (!success || (data && data->next_indx < 0))) if (session->txn_id && (!success || (data && data->next_indx < 0)))
mgmt_fe_session_register_event( mgmt_fe_session_register_event(session,
session, MGMTD_FE_SESSION_SHOW_TXN_CLNUP); MGMTD_FE_SESSION_SHOW_TXN_CLNUP);
return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg, false); return fe_adapter_send_msg(session->adapter, &fe_msg, false);
}
static int mgmt_fe_send_getdata_reply(struct mgmt_fe_session_ctx *session,
Mgmtd__DatastoreId ds_id,
uint64_t req_id, bool success,
Mgmtd__YangDataReply *data,
const char *error_if_any)
{
Mgmtd__FeMessage fe_msg;
Mgmtd__FeGetDataReply getdata_reply;
assert(session->adapter);
mgmtd__fe_get_data_reply__init(&getdata_reply);
getdata_reply.session_id = session->session_id;
getdata_reply.ds_id = ds_id;
getdata_reply.req_id = req_id;
getdata_reply.success = success;
getdata_reply.data = data;
if (error_if_any)
getdata_reply.error_if_any = (char *)error_if_any;
mgmtd__fe_message__init(&fe_msg);
fe_msg.message_case = MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY;
fe_msg.getdata_reply = &getdata_reply;
MGMTD_FE_ADAPTER_DBG(
"Sending GET_DATA_REPLY message to MGMTD Frontend client '%s'",
session->adapter->name);
/*
* Cleanup the SHOW transaction associated with this session.
*/
if (session->txn_id && (!success || (data && data->next_indx < 0)))
mgmt_fe_session_register_event(
session, MGMTD_FE_SESSION_SHOW_TXN_CLNUP);
return mgmt_fe_adapter_send_msg(session->adapter, &fe_msg, false);
} }
static void mgmt_fe_session_cfg_txn_clnup(struct event *thread) static void mgmt_fe_session_cfg_txn_clnup(struct event *thread)
@ -562,19 +520,6 @@ mgmt_fe_find_adapter_by_fd(int conn_fd)
return NULL; return NULL;
} }
static struct mgmt_fe_client_adapter *
mgmt_fe_find_adapter_by_name(const char *name)
{
struct mgmt_fe_client_adapter *adapter;
FOREACH_ADAPTER_IN_LIST (adapter) {
if (!strncmp(adapter->name, name, sizeof(adapter->name)))
return adapter;
}
return NULL;
}
static void mgmt_fe_adapter_delete(struct mgmt_fe_client_adapter *adapter) static void mgmt_fe_adapter_delete(struct mgmt_fe_client_adapter *adapter)
{ {
struct mgmt_fe_session_ctx *session; struct mgmt_fe_session_ctx *session;
@ -631,7 +576,7 @@ mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
if (lockds_req->ds_id != MGMTD_DS_CANDIDATE && if (lockds_req->ds_id != MGMTD_DS_CANDIDATE &&
lockds_req->ds_id != MGMTD_DS_RUNNING) { lockds_req->ds_id != MGMTD_DS_RUNNING) {
mgmt_fe_send_lockds_reply( fe_adapter_send_lockds_reply(
session, lockds_req->ds_id, lockds_req->req_id, session, lockds_req->ds_id, lockds_req->req_id,
lockds_req->lock, false, lockds_req->lock, false,
"Lock/Unlock on DS other than candidate or running DS not supported"); "Lock/Unlock on DS other than candidate or running DS not supported");
@ -640,10 +585,10 @@ mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
ds_ctx = mgmt_ds_get_ctx_by_id(mm, lockds_req->ds_id); ds_ctx = mgmt_ds_get_ctx_by_id(mm, lockds_req->ds_id);
if (!ds_ctx) { if (!ds_ctx) {
mgmt_fe_send_lockds_reply( fe_adapter_send_lockds_reply(session, lockds_req->ds_id,
session, lockds_req->ds_id, lockds_req->req_id, lockds_req->req_id,
lockds_req->lock, false, lockds_req->lock, false,
"Failed to retrieve handle for DS!"); "Failed to retrieve handle for DS!");
return -1; return -1;
} }
@ -651,7 +596,7 @@ mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
if (mgmt_fe_session_write_lock_ds(lockds_req->ds_id, if (mgmt_fe_session_write_lock_ds(lockds_req->ds_id,
ds_ctx, session) ds_ctx, session)
!= 0) { != 0) {
mgmt_fe_send_lockds_reply( fe_adapter_send_lockds_reply(
session, lockds_req->ds_id, lockds_req->req_id, session, lockds_req->ds_id, lockds_req->req_id,
lockds_req->lock, false, lockds_req->lock, false,
"Lock already taken on DS by another session!"); "Lock already taken on DS by another session!");
@ -659,7 +604,7 @@ mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
} }
} else { } else {
if (!session->ds_locked[lockds_req->ds_id]) { if (!session->ds_locked[lockds_req->ds_id]) {
mgmt_fe_send_lockds_reply( fe_adapter_send_lockds_reply(
session, lockds_req->ds_id, lockds_req->req_id, session, lockds_req->ds_id, lockds_req->req_id,
lockds_req->lock, false, lockds_req->lock, false,
"Lock on DS was not taken by this session!"); "Lock on DS was not taken by this session!");
@ -669,10 +614,9 @@ mgmt_fe_session_handle_lockds_req_msg(struct mgmt_fe_session_ctx *session,
mgmt_fe_session_unlock_ds(lockds_req->ds_id, ds_ctx, session); mgmt_fe_session_unlock_ds(lockds_req->ds_id, ds_ctx, session);
} }
if (mgmt_fe_send_lockds_reply(session, lockds_req->ds_id, if (fe_adapter_send_lockds_reply(session, lockds_req->ds_id,
lockds_req->req_id, lockds_req->lock, lockds_req->req_id, lockds_req->lock,
true, NULL) true, NULL) != 0) {
!= 0) {
MGMTD_FE_ADAPTER_DBG( MGMTD_FE_ADAPTER_DBG(
"Failed to send LOCK_DS_REPLY for DS %u session-id: %" PRIu64 "Failed to send LOCK_DS_REPLY for DS %u session-id: %" PRIu64
" from %s", " from %s",
@ -700,7 +644,7 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
/* MGMTD currently only supports editing the candidate DS. */ /* MGMTD currently only supports editing the candidate DS. */
if (setcfg_req->ds_id != MGMTD_DS_CANDIDATE) { if (setcfg_req->ds_id != MGMTD_DS_CANDIDATE) {
mgmt_fe_send_setcfg_reply( fe_adapter_send_set_cfg_reply(
session, setcfg_req->ds_id, setcfg_req->req_id, false, session, setcfg_req->ds_id, setcfg_req->req_id, false,
"Set-Config on datastores other than Candidate DS not supported", "Set-Config on datastores other than Candidate DS not supported",
setcfg_req->implicit_commit); setcfg_req->implicit_commit);
@ -712,7 +656,7 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
/* MGMTD currently only supports targetting the running DS. */ /* MGMTD currently only supports targetting the running DS. */
if (setcfg_req->implicit_commit && if (setcfg_req->implicit_commit &&
setcfg_req->commit_ds_id != MGMTD_DS_RUNNING) { setcfg_req->commit_ds_id != MGMTD_DS_RUNNING) {
mgmt_fe_send_setcfg_reply( fe_adapter_send_set_cfg_reply(
session, setcfg_req->ds_id, setcfg_req->req_id, false, session, setcfg_req->ds_id, setcfg_req->req_id, false,
"Implicit commit on datastores other than running DS not supported", "Implicit commit on datastores other than running DS not supported",
setcfg_req->implicit_commit); setcfg_req->implicit_commit);
@ -723,10 +667,10 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
/* User should have write lock to change the DS */ /* User should have write lock to change the DS */
if (!session->ds_locked[setcfg_req->ds_id]) { if (!session->ds_locked[setcfg_req->ds_id]) {
mgmt_fe_send_setcfg_reply(session, setcfg_req->ds_id, fe_adapter_send_set_cfg_reply(session, setcfg_req->ds_id,
setcfg_req->req_id, false, setcfg_req->req_id, false,
"Candidate DS is not locked", "Candidate DS is not locked",
setcfg_req->implicit_commit); setcfg_req->implicit_commit);
return 0; return 0;
} }
@ -738,7 +682,7 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
session->cfg_txn_id = mgmt_create_txn(session->session_id, session->cfg_txn_id = mgmt_create_txn(session->session_id,
MGMTD_TXN_TYPE_CONFIG); MGMTD_TXN_TYPE_CONFIG);
if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) { if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) {
mgmt_fe_send_setcfg_reply( fe_adapter_send_set_cfg_reply(
session, setcfg_req->ds_id, setcfg_req->req_id, session, setcfg_req->ds_id, setcfg_req->req_id,
false, false,
"Failed to create a Configuration session!", "Failed to create a Configuration session!",
@ -761,7 +705,7 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
* In this scenario need to skip cleanup of the txn, * In this scenario need to skip cleanup of the txn,
* so setting implicit commit to false. * so setting implicit commit to false.
*/ */
mgmt_fe_send_setcfg_reply( fe_adapter_send_set_cfg_reply(
session, setcfg_req->ds_id, setcfg_req->req_id, session, setcfg_req->ds_id, setcfg_req->req_id,
false, false,
"A Configuration transaction is already in progress!", "A Configuration transaction is already in progress!",
@ -771,16 +715,16 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
} }
/* Create the SETConfig request under the transaction. */ /* Create the SETConfig request under the transaction. */
if (mgmt_txn_send_set_config_req( if (mgmt_txn_send_set_config_req(session->cfg_txn_id, setcfg_req->req_id,
session->cfg_txn_id, setcfg_req->req_id, setcfg_req->ds_id, setcfg_req->ds_id, ds_ctx,
ds_ctx, setcfg_req->data, setcfg_req->n_data, setcfg_req->data, setcfg_req->n_data,
setcfg_req->implicit_commit, setcfg_req->commit_ds_id, setcfg_req->implicit_commit,
dst_ds_ctx) setcfg_req->commit_ds_id,
!= 0) { dst_ds_ctx) != 0) {
mgmt_fe_send_setcfg_reply( fe_adapter_send_set_cfg_reply(session, setcfg_req->ds_id,
session, setcfg_req->ds_id, setcfg_req->req_id, false, setcfg_req->req_id, false,
"Request processing for SET-CONFIG failed!", "Request processing for SET-CONFIG failed!",
setcfg_req->implicit_commit); setcfg_req->implicit_commit);
/* delete transaction if we just created it */ /* delete transaction if we just created it */
if (txn_created) if (txn_created)
@ -790,33 +734,27 @@ mgmt_fe_session_handle_setcfg_req_msg(struct mgmt_fe_session_ctx *session,
return 0; return 0;
} }
static int static int mgmt_fe_session_handle_get_req_msg(struct mgmt_fe_session_ctx *session,
mgmt_fe_session_handle_getcfg_req_msg(struct mgmt_fe_session_ctx *session, Mgmtd__FeGetReq *get_req)
Mgmtd__FeGetConfigReq *getcfg_req)
{ {
struct mgmt_ds_ctx *ds_ctx; struct mgmt_ds_ctx *ds_ctx;
struct nb_config *cfg_root = NULL; struct nb_config *cfg_root = NULL;
Mgmtd__DatastoreId ds_id = get_req->ds_id;
uint64_t req_id = get_req->req_id;
bool is_cfg = get_req->config;
bool ds_ok = true;
/* if (is_cfg && ds_id != MGMTD_DS_CANDIDATE && ds_id != MGMTD_DS_RUNNING)
* Get the DS handle. ds_ok = false;
*/ else if (!is_cfg && ds_id != MGMTD_DS_OPERATIONAL)
ds_ctx = mgmt_ds_get_ctx_by_id(mm, getcfg_req->ds_id); ds_ok = false;
if (!ds_ctx) { if (!ds_ok) {
mgmt_fe_send_getcfg_reply(session, getcfg_req->ds_id, fe_adapter_send_get_reply(session, ds_id, req_id, false, NULL,
getcfg_req->req_id, false, NULL, "get-req on unsupported datastore");
"No such DS exists!");
return 0;
}
/* GETCFG must be on candidate or running DS */
if (getcfg_req->ds_id != MGMTD_DS_CANDIDATE
&& getcfg_req->ds_id != MGMTD_DS_RUNNING) {
mgmt_fe_send_getcfg_reply(
session, getcfg_req->ds_id, getcfg_req->req_id, false,
NULL,
"Get-Config on datastores other than Candidate or Running DS not permitted!");
return 0; return 0;
} }
ds_ctx = mgmt_ds_get_ctx_by_id(mm, ds_id);
assert(ds_ctx);
if (session->txn_id == MGMTD_TXN_ID_NONE) { if (session->txn_id == MGMTD_TXN_ID_NONE) {
/* /*
@ -825,44 +763,43 @@ mgmt_fe_session_handle_getcfg_req_msg(struct mgmt_fe_session_ctx *session,
session->txn_id = mgmt_create_txn(session->session_id, session->txn_id = mgmt_create_txn(session->session_id,
MGMTD_TXN_TYPE_SHOW); MGMTD_TXN_TYPE_SHOW);
if (session->txn_id == MGMTD_SESSION_ID_NONE) { if (session->txn_id == MGMTD_SESSION_ID_NONE) {
mgmt_fe_send_getcfg_reply( fe_adapter_send_get_reply(session, ds_id, req_id, false,
session, getcfg_req->ds_id, getcfg_req->req_id, NULL,
false, NULL, "Failed to create a Show transaction!");
"Failed to create a Show transaction!"); return -1;
goto mgmt_fe_sess_handle_getcfg_req_failed;
} }
MGMTD_FE_ADAPTER_DBG("Created new show txn-id: %" PRIu64 MGMTD_FE_ADAPTER_DBG("Created new show txn-id: %" PRIu64
" for session-id: %" PRIu64, " for session-id: %" PRIu64,
session->txn_id, session->session_id); session->txn_id, session->session_id);
} else { } else {
MGMTD_FE_ADAPTER_DBG("Show txn-id: %" PRIu64 fe_adapter_send_get_reply(session, ds_id, req_id, false, NULL,
" for session-id: %" PRIu64 "Request processing for GET failed!");
" already created", MGMTD_FE_ADAPTER_DBG("Transaction in progress txn-id: %" PRIu64
" for session-id: %" PRIu64,
session->txn_id, session->session_id); session->txn_id, session->session_id);
return -1;
} }
/* /*
* Get a copy of the datastore config root, avoids locking. * Get a copy of the datastore config root, avoids locking.
*/ */
cfg_root = nb_config_dup(mgmt_ds_get_nb_config(ds_ctx)); if (is_cfg)
cfg_root = nb_config_dup(mgmt_ds_get_nb_config(ds_ctx));
/* /*
* Create a GETConfig request under the transaction. * Create a GET request under the transaction.
*/ */
if (mgmt_txn_send_get_config_req( if (mgmt_txn_send_get_req(session->txn_id, req_id, ds_id, cfg_root,
session->txn_id, getcfg_req->req_id, getcfg_req->ds_id, get_req->data, get_req->n_data)) {
cfg_root, getcfg_req->data, getcfg_req->n_data) != 0) { fe_adapter_send_get_reply(session, ds_id, req_id, false, NULL,
mgmt_fe_send_getcfg_reply( "Request processing for GET failed!");
session, getcfg_req->ds_id, getcfg_req->req_id, false,
NULL, "Request processing for GET-CONFIG failed!"); goto failed;
goto mgmt_fe_sess_handle_getcfg_req_failed;
} }
return 0; return 0;
failed:
mgmt_fe_sess_handle_getcfg_req_failed:
if (cfg_root) if (cfg_root)
nb_config_free(cfg_root); nb_config_free(cfg_root);
/* /*
@ -874,79 +811,6 @@ mgmt_fe_sess_handle_getcfg_req_failed:
return -1; return -1;
} }
static int
mgmt_fe_session_handle_getdata_req_msg(struct mgmt_fe_session_ctx *session,
Mgmtd__FeGetDataReq *getdata_req)
{
struct mgmt_ds_ctx *ds_ctx;
/*
* Get the DS handle.
*/
ds_ctx = mgmt_ds_get_ctx_by_id(mm, getdata_req->ds_id);
if (!ds_ctx) {
mgmt_fe_send_getdata_reply(session, getdata_req->ds_id,
getdata_req->req_id, false, NULL,
"No such DS exists!");
return 0;
}
/* GETDATA must be on operational DS */
if (getdata_req->ds_id != MGMTD_DS_OPERATIONAL) {
mgmt_fe_send_getdata_reply(
session, getdata_req->ds_id, getdata_req->req_id, false,
NULL,
"Get-Data on datastore other than Operational DS not permitted!");
return 0;
}
if (session->txn_id == MGMTD_TXN_ID_NONE) {
/*
* Start a SHOW Transaction (if not started already)
*/
session->txn_id = mgmt_create_txn(session->session_id,
MGMTD_TXN_TYPE_SHOW);
if (session->txn_id == MGMTD_SESSION_ID_NONE) {
mgmt_fe_send_getdata_reply(
session, getdata_req->ds_id,
getdata_req->req_id, false, NULL,
"Failed to create a Show transaction!");
goto mgmt_fe_sess_handle_getdata_req_failed;
}
MGMTD_FE_ADAPTER_DBG("Created new Show Txn %" PRIu64
" for session %" PRIu64,
session->txn_id, session->session_id);
} else {
MGMTD_FE_ADAPTER_DBG("Show txn-id: %" PRIu64
" for session %" PRIu64 " already created",
session->txn_id, session->session_id);
}
/*
* Create a GETData request under the transaction.
*/
if (mgmt_txn_send_get_data_req(session->txn_id, getdata_req->req_id,
getdata_req->ds_id, getdata_req->data,
getdata_req->n_data) != 0) {
mgmt_fe_send_getdata_reply(
session, getdata_req->ds_id, getdata_req->req_id, false,
NULL, "Request processing for GET-CONFIG failed!");
goto mgmt_fe_sess_handle_getdata_req_failed;
}
return 0;
mgmt_fe_sess_handle_getdata_req_failed:
/*
* Destroy the transaction created recently.
*/
if (session->txn_id != MGMTD_TXN_ID_NONE)
mgmt_destroy_txn(&session->txn_id);
return -1;
}
static int mgmt_fe_session_handle_commit_config_req_msg( static int mgmt_fe_session_handle_commit_config_req_msg(
struct mgmt_fe_session_ctx *session, struct mgmt_fe_session_ctx *session,
@ -961,7 +825,7 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
/* Validate source and dest DS */ /* Validate source and dest DS */
if (commcfg_req->src_ds_id != MGMTD_DS_CANDIDATE || if (commcfg_req->src_ds_id != MGMTD_DS_CANDIDATE ||
commcfg_req->dst_ds_id != MGMTD_DS_RUNNING) { commcfg_req->dst_ds_id != MGMTD_DS_RUNNING) {
mgmt_fe_send_commitcfg_reply( fe_adapter_send_commit_cfg_reply(
session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id, session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
commcfg_req->req_id, MGMTD_INTERNAL_ERROR, commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
commcfg_req->validate_only, commcfg_req->validate_only,
@ -976,7 +840,7 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
/* User should have lock on both source and dest DS */ /* User should have lock on both source and dest DS */
if (!session->ds_locked[commcfg_req->dst_ds_id] || if (!session->ds_locked[commcfg_req->dst_ds_id] ||
!session->ds_locked[commcfg_req->src_ds_id]) { !session->ds_locked[commcfg_req->src_ds_id]) {
mgmt_fe_send_commitcfg_reply( fe_adapter_send_commit_cfg_reply(
session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id, session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
commcfg_req->req_id, MGMTD_DS_LOCK_FAILED, commcfg_req->req_id, MGMTD_DS_LOCK_FAILED,
commcfg_req->validate_only, commcfg_req->validate_only,
@ -991,11 +855,10 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
session->cfg_txn_id = mgmt_create_txn(session->session_id, session->cfg_txn_id = mgmt_create_txn(session->session_id,
MGMTD_TXN_TYPE_CONFIG); MGMTD_TXN_TYPE_CONFIG);
if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) { if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) {
mgmt_fe_send_commitcfg_reply( fe_adapter_send_commit_cfg_reply(
session, commcfg_req->src_ds_id, session, commcfg_req->src_ds_id,
commcfg_req->dst_ds_id, commcfg_req->req_id, commcfg_req->dst_ds_id, commcfg_req->req_id,
MGMTD_INTERNAL_ERROR, MGMTD_INTERNAL_ERROR, commcfg_req->validate_only,
commcfg_req->validate_only,
"Failed to create a Configuration session!"); "Failed to create a Configuration session!");
return 0; return 0;
} }
@ -1013,7 +876,7 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
commcfg_req->src_ds_id, src_ds_ctx, commcfg_req->dst_ds_id, commcfg_req->src_ds_id, src_ds_ctx, commcfg_req->dst_ds_id,
dst_ds_ctx, commcfg_req->validate_only, commcfg_req->abort, dst_ds_ctx, commcfg_req->validate_only, commcfg_req->abort,
false) != 0) { false) != 0) {
mgmt_fe_send_commitcfg_reply( fe_adapter_send_commit_cfg_reply(
session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id, session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
commcfg_req->req_id, MGMTD_INTERNAL_ERROR, commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
commcfg_req->validate_only, commcfg_req->validate_only,
@ -1058,8 +921,8 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
session = mgmt_fe_create_session( session = mgmt_fe_create_session(
adapter, fe_msg->session_req->client_conn_id); adapter, fe_msg->session_req->client_conn_id);
mgmt_fe_send_session_reply(adapter, session, true, fe_adapter_send_session_reply(adapter, session, true,
session ? true : false); session ? true : false);
} else if ( } else if (
!fe_msg->session_req->create !fe_msg->session_req->create
&& fe_msg->session_req->id_case && fe_msg->session_req->id_case
@ -1071,8 +934,8 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
session = mgmt_session_id2ctx( session = mgmt_session_id2ctx(
fe_msg->session_req->session_id); fe_msg->session_req->session_id);
mgmt_fe_send_session_reply(adapter, session, false, fe_adapter_send_session_reply(adapter, session, false,
true); true);
mgmt_fe_cleanup_session(&session); mgmt_fe_cleanup_session(&session);
} }
break; break;
@ -1116,29 +979,15 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
mgmt_fe_session_handle_commit_config_req_msg( mgmt_fe_session_handle_commit_config_req_msg(
session, fe_msg->commcfg_req); session, fe_msg->commcfg_req);
break; break;
case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REQ: case MGMTD__FE_MESSAGE__MESSAGE_GET_REQ:
session = mgmt_session_id2ctx( session = mgmt_session_id2ctx(fe_msg->get_req->session_id);
fe_msg->getcfg_req->session_id); MGMTD_FE_ADAPTER_DBG("Got GET_REQ (iscfg %d) for DS:%s (xpaths: %d) on session-id %" PRIu64
MGMTD_FE_ADAPTER_DBG( " from '%s'",
"Got GETCFG_REQ for DS:%s (xpaths: %d) on session-id %" PRIu64 (int)fe_msg->get_req->config,
" from '%s'", mgmt_ds_id2name(fe_msg->get_req->ds_id),
mgmt_ds_id2name(fe_msg->getcfg_req->ds_id), (int)fe_msg->get_req->n_data,
(int)fe_msg->getcfg_req->n_data, fe_msg->get_req->session_id, adapter->name);
fe_msg->getcfg_req->session_id, adapter->name); mgmt_fe_session_handle_get_req_msg(session, fe_msg->get_req);
mgmt_fe_session_handle_getcfg_req_msg(
session, fe_msg->getcfg_req);
break;
case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REQ:
session = mgmt_session_id2ctx(
fe_msg->getdata_req->session_id);
MGMTD_FE_ADAPTER_DBG(
"Got GETDATA_REQ for DS:%s (xpaths: %d) on session-id %" PRIu64
" from '%s'",
mgmt_ds_id2name(fe_msg->getdata_req->ds_id),
(int)fe_msg->getdata_req->n_data,
fe_msg->getdata_req->session_id, adapter->name);
mgmt_fe_session_handle_getdata_req_msg(
session, fe_msg->getdata_req);
break; break;
case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ: case MGMTD__FE_MESSAGE__MESSAGE_NOTIFY_DATA_REQ:
case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ: case MGMTD__FE_MESSAGE__MESSAGE_REGNOTIFY_REQ:
@ -1157,8 +1006,7 @@ mgmt_fe_adapter_handle_msg(struct mgmt_fe_client_adapter *adapter,
case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY: case MGMTD__FE_MESSAGE__MESSAGE_LOCKDS_REPLY:
case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY: case MGMTD__FE_MESSAGE__MESSAGE_SETCFG_REPLY:
case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY: case MGMTD__FE_MESSAGE__MESSAGE_COMMCFG_REPLY:
case MGMTD__FE_MESSAGE__MESSAGE_GETCFG_REPLY: case MGMTD__FE_MESSAGE__MESSAGE_GET_REPLY:
case MGMTD__FE_MESSAGE__MESSAGE_GETDATA_REPLY:
case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET: case MGMTD__FE_MESSAGE__MESSAGE__NOT_SET:
default: default:
/* /*
@ -1293,11 +1141,6 @@ struct msg_conn *mgmt_fe_create_adapter(int conn_fd, union sockunion *from)
return adapter->conn; return adapter->conn;
} }
struct mgmt_fe_client_adapter *mgmt_fe_get_adapter(const char *name)
{
return mgmt_fe_find_adapter_by_name(name);
}
int mgmt_fe_send_set_cfg_reply(uint64_t session_id, uint64_t txn_id, int mgmt_fe_send_set_cfg_reply(uint64_t session_id, uint64_t txn_id,
Mgmtd__DatastoreId ds_id, uint64_t req_id, Mgmtd__DatastoreId ds_id, uint64_t req_id,
enum mgmt_result result, enum mgmt_result result,
@ -1316,9 +1159,10 @@ int mgmt_fe_send_set_cfg_reply(uint64_t session_id, uint64_t txn_id,
return -1; return -1;
} }
return mgmt_fe_send_setcfg_reply( return fe_adapter_send_set_cfg_reply(session, ds_id, req_id,
session, ds_id, req_id, result == MGMTD_SUCCESS ? true : false, result == MGMTD_SUCCESS ? true
error_if_any, implicit_commit); : false,
error_if_any, implicit_commit);
} }
int mgmt_fe_send_commit_cfg_reply(uint64_t session_id, uint64_t txn_id, int mgmt_fe_send_commit_cfg_reply(uint64_t session_id, uint64_t txn_id,
@ -1334,16 +1178,16 @@ int mgmt_fe_send_commit_cfg_reply(uint64_t session_id, uint64_t txn_id,
if (!session || session->cfg_txn_id != txn_id) if (!session || session->cfg_txn_id != txn_id)
return -1; return -1;
return mgmt_fe_send_commitcfg_reply(session, src_ds_id, dst_ds_id, return fe_adapter_send_commit_cfg_reply(session, src_ds_id, dst_ds_id,
req_id, result, validate_only, req_id, result, validate_only,
error_if_any); error_if_any);
} }
int mgmt_fe_send_get_cfg_reply(uint64_t session_id, uint64_t txn_id, int mgmt_fe_send_get_reply(uint64_t session_id, uint64_t txn_id,
Mgmtd__DatastoreId ds_id, uint64_t req_id, Mgmtd__DatastoreId ds_id, uint64_t req_id,
enum mgmt_result result, enum mgmt_result result,
Mgmtd__YangDataReply *data_resp, Mgmtd__YangDataReply *data_resp,
const char *error_if_any) const char *error_if_any)
{ {
struct mgmt_fe_session_ctx *session; struct mgmt_fe_session_ctx *session;
@ -1351,34 +1195,9 @@ int mgmt_fe_send_get_cfg_reply(uint64_t session_id, uint64_t txn_id,
if (!session || session->txn_id != txn_id) if (!session || session->txn_id != txn_id)
return -1; return -1;
return mgmt_fe_send_getcfg_reply(session, ds_id, req_id, return fe_adapter_send_get_reply(session, ds_id, req_id,
result == MGMTD_SUCCESS, data_resp, result == MGMTD_SUCCESS, data_resp,
error_if_any); error_if_any);
}
int mgmt_fe_send_get_data_reply(uint64_t session_id, uint64_t txn_id,
Mgmtd__DatastoreId ds_id, uint64_t req_id,
enum mgmt_result result,
Mgmtd__YangDataReply *data_resp,
const char *error_if_any)
{
struct mgmt_fe_session_ctx *session;
session = mgmt_session_id2ctx(session_id);
if (!session || session->txn_id != txn_id)
return -1;
return mgmt_fe_send_getdata_reply(session, ds_id, req_id,
result == MGMTD_SUCCESS,
data_resp, error_if_any);
}
int mgmt_fe_send_data_notify(Mgmtd__DatastoreId ds_id,
Mgmtd__YangData * data_resp[], int num_data)
{
/* struct mgmt_fe_session_ctx *session; */
return 0;
} }
struct mgmt_setcfg_stats * struct mgmt_setcfg_stats *

View File

@ -87,10 +87,6 @@ mgmt_fe_adapter_unlock(struct mgmt_fe_client_adapter **adapter);
extern struct msg_conn *mgmt_fe_create_adapter(int conn_fd, extern struct msg_conn *mgmt_fe_create_adapter(int conn_fd,
union sockunion *su); union sockunion *su);
/* Fetch frontend adapter given a name */
extern struct mgmt_fe_client_adapter *
mgmt_fe_get_adapter(const char *name);
/* /*
* Send set-config reply to the frontend client. * Send set-config reply to the frontend client.
* *
@ -134,29 +130,13 @@ extern int mgmt_fe_send_commit_cfg_reply(
enum mgmt_result result, const char *error_if_any); enum mgmt_result result, const char *error_if_any);
/* /*
* Send get-config reply to the frontend client. * Send get-config/get-data reply to the frontend client.
*/ */
extern int mgmt_fe_send_get_cfg_reply(uint64_t session_id, uint64_t txn_id, extern int mgmt_fe_send_get_reply(uint64_t session_id, uint64_t txn_id,
Mgmtd__DatastoreId ds_id, Mgmtd__DatastoreId ds_id, uint64_t req_id,
uint64_t req_id, enum mgmt_result result,
enum mgmt_result result, Mgmtd__YangDataReply *data_resp,
Mgmtd__YangDataReply *data_resp, const char *error_if_any);
const char *error_if_any);
/*
* Send get-data reply to the frontend client.
*/
extern int mgmt_fe_send_get_data_reply(
uint64_t session_id, uint64_t txn_id, Mgmtd__DatastoreId ds_id,
uint64_t req_id, enum mgmt_result result,
Mgmtd__YangDataReply *data_resp, const char *error_if_any);
/*
* Send data notify to the frontend client.
*/
extern int mgmt_fe_send_data_notify(Mgmtd__DatastoreId ds_id,
Mgmtd__YangData * data_resp[],
int num_data);
/* Fetch frontend client session set-config stats */ /* Fetch frontend client session set-config stats */
extern struct mgmt_setcfg_stats * extern struct mgmt_setcfg_stats *

File diff suppressed because it is too large Load Diff

View File

@ -177,25 +177,16 @@ extern int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
bool implicit); bool implicit);
/* /*
* Send get-config request to be processed later in transaction. * Send get-{cfg,data} request to be processed later in transaction.
* *
* Similar to set-config request. * Is get-config if cfg_root is provided and the config is gathered locally,
* otherwise it's get-data and data is fetched from backedn clients.
*/ */
extern int mgmt_txn_send_get_config_req(uint64_t txn_id, uint64_t req_id, extern int mgmt_txn_send_get_req(uint64_t txn_id, uint64_t req_id,
Mgmtd__DatastoreId ds_id, Mgmtd__DatastoreId ds_id,
struct nb_config *cfg_root, struct nb_config *cfg_root,
Mgmtd__YangGetDataReq **data_req, Mgmtd__YangGetDataReq **data_req,
size_t num_reqs); size_t num_reqs);
/*
* Send get-data request to be processed later in transaction.
*
* Similar to get-config request, but here data is fetched from backedn client.
*/
extern int mgmt_txn_send_get_data_req(uint64_t txn_id, uint64_t req_id,
Mgmtd__DatastoreId ds_id,
Mgmtd__YangGetDataReq **data_req,
size_t num_reqs);
/* /*
* Notifiy backend adapter on connection. * Notifiy backend adapter on connection.

View File

@ -194,7 +194,7 @@ DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
datastore = mgmt_ds_name2id(dsname); datastore = mgmt_ds_name2id(dsname);
xpath_list[0] = path; xpath_list[0] = path;
vty_mgmt_send_get_config(vty, datastore, xpath_list, 1); vty_mgmt_send_get_req(vty, true, datastore, xpath_list, 1);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -214,7 +214,7 @@ DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
datastore = mgmt_ds_name2id(dsname); datastore = mgmt_ds_name2id(dsname);
xpath_list[0] = path; xpath_list[0] = path;
vty_mgmt_send_get_data(vty, datastore, xpath_list, 1); vty_mgmt_send_get_req(vty, false, datastore, xpath_list, 1);
return CMD_SUCCESS; return CMD_SUCCESS;
} }

View File

@ -157,6 +157,13 @@ tests_lib_test_checksum_LDADD = $(ALL_TESTS_LDADD)
tests_lib_test_checksum_SOURCES = tests/lib/test_checksum.c tests/helpers/c/prng.c tests_lib_test_checksum_SOURCES = tests/lib/test_checksum.c tests/helpers/c/prng.c
check_PROGRAMS += tests/lib/test_darr
tests_lib_test_darr_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_darr_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_darr_LDADD = $(ALL_TESTS_LDADD)
tests_lib_test_darr_SOURCES = tests/lib/test_darr.c
check_PROGRAMS += tests/lib/test_graph check_PROGRAMS += tests/lib/test_graph
tests_lib_test_graph_CFLAGS = $(TESTS_CFLAGS) tests_lib_test_graph_CFLAGS = $(TESTS_CFLAGS)
tests_lib_test_graph_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_graph_CPPFLAGS = $(TESTS_CPPFLAGS)

279
tests/lib/test_darr.c Normal file
View File

@ -0,0 +1,279 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* June 23 2023, Christian Hopps <chopps@labn.net>
*
* Copyright (c) 2023, LabN Consulting, L.L.C.
*
*/
#include <zebra.h>
#include "darr.h"
/*
* Public functions to test:
* [x] - darr_append
* [x] - darr_append_n
* [x] - darr_append_nz
* [x] - darr_cap
* [-] - darr_ensure_cap
* [x] - darr_ensure_i
* [x] - darr_foreach_i
* [x] - darr_foreach_p
* [x] - darr_free
* [x] - darr_insert
* [ ] - darr_insertz
* [x] - darr_insert_n
* [x] - darr_insert_nz
* [x] - darr_maxi
* [x] - darr_pop
* [x] - darr_push
* [ ] - darr_pushz
* [x] - darr_remove
* [x] - darr_remove_n
* [x] - darr_reset
* [x] - darr_setlen
*/
static void test_int(void)
{
int z105[105] = {0};
int a1[] = {0, 1, 2, 3, 4};
int a2[] = {4, 3, 2, 1, 0};
int *da1 = NULL;
int *da2 = NULL;
int *dap;
uint i;
darr_ensure_i(da1, 0);
da1[0] = 0;
assert(darr_len(da1) == 1);
assert(darr_cap(da1) == 1);
*darr_ensure_i(da1, 1) = 1;
assert(darr_len(da1) == 2);
assert(darr_cap(da1) == 2);
darr_ensure_i(da1, 4);
darr_foreach_i (da1, i)
da1[i] = i;
assert(darr_len(da1) == 5);
/* minimum non-pow2 array size for long long and smaller */
assert(darr_cap(da1) == 8);
assert(!memcmp(da1, a1, sizeof(a1)));
/* reverse the numbers */
darr_foreach_p (da1, dap)
*dap = darr_end(da1) - dap - 1;
assert(!memcmp(da1, a2, sizeof(a2)));
darr_append_n(da1, 100);
darr_foreach_p (da1, dap)
*dap = darr_end(da1) - dap - 1;
darr_pop_n(da1, 100);
darr_append_nz(da1, 100);
assert(!memcmp(&da1[5], z105, _darr_esize(da1) * 100));
assert(darr_len(da1) == 105);
assert(darr_maxi(da1) == 127);
assert(darr_cap(da1) == 128);
darr_setlen(da1, 102);
assert(darr_len(da1) == 102);
assert(darr_maxi(da1) == 127);
int a3[] = { 0xdeadbeaf, 0x12345678 };
da1[0] = a3[0];
da1[101] = a3[1];
darr_remove_n(da1, 1, 100);
assert(darr_len(da1) == array_size(a3));
assert(!memcmp(da1, a3, sizeof(a3)));
da1[0] = a3[1];
da1[1] = a3[0];
darr_insert_n(da1, 1, 100);
assert(darr_len(da1) == 102);
assert(da1[0] == a3[1]);
assert(da1[101] == a3[0]);
darr_reset(da1);
assert(darr_len(da1) == 0);
assert(darr_maxi(da1) == 127);
assert(darr_cap(da1) == 128);
/* we touch the length field of the freed block here somehow */
darr_insert_n(da1, 100, 300);
assert(darr_len(da1) == 400);
assert(darr_cap(da1) == 512);
da1[400 - 1] = 0x0BAD;
*darr_insert(da1, 0) = 0xF00D;
assert(da1[0] == 0xF00D);
assert(da1[400] == 0x0BAD);
assert(darr_len(da1) == 401);
assert(darr_cap(da1) == 512);
darr_free(da1);
assert(da1 == NULL);
assert(darr_len(da1) == 0);
darr_setlen(da1, 0);
darr_reset(da1);
darr_free(da1);
*darr_append(da2) = 0;
*darr_append(da2) = 1;
darr_push(da2, 2);
darr_push(da2, 3);
darr_push(da2, 4);
assert(!memcmp(da2, a1, sizeof(a1)));
assert(darr_pop(da2) == 4);
assert(darr_pop(da2) == 3);
assert(darr_pop(da2) == 2);
assert(darr_len(da2) == 2);
assert(darr_pop(da2) == 1);
assert(darr_pop(da2) == 0);
assert(darr_len(da2) == 0);
darr_free(da2);
}
static void test_struct(void)
{
/*
*uwould like to use different sizes with padding but memcmp can't be
*used then.
*/
struct st {
long long a;
long long b;
};
struct st z102[102] = {{0, 0}};
struct st *da1 = NULL;
struct st *da2 = NULL;
struct st a1[] = {
{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4},
};
uint i;
darr_ensure_i(da1, 0);
da1[0].a = 0;
da1[0].b = 0;
assert(darr_len(da1) == 1);
assert(darr_cap(da1) == 1);
darr_ensure_i(da1, 1)->a = 1;
darr_ensure_i(da1, 1)->b = 1;
assert(darr_len(da1) == 2);
assert(darr_cap(da1) == 2);
darr_ensure_i(da1, 4);
da1[2].a = 2;
da1[2].b = 2;
da1[3].a = 3;
da1[3].b = 3;
da1[4].a = 4;
da1[4].b = 4;
assert(darr_len(da1) == 5);
/* minimum non-pow2 array size for long long and smaller */
assert(darr_cap(da1) == 8);
assert(!memcmp(da1, a1, sizeof(a1)));
darr_append_n(da1, 100);
assert(darr_len(da1) == 105);
assert(darr_maxi(da1) == 127);
assert(darr_cap(da1) == 128);
darr_setlen(da1, 102);
assert(darr_len(da1) == 102);
assert(darr_maxi(da1) == 127);
struct st a2[] = {
{0xdeadbeaf, 0xdeadbeaf},
{0x12345678, 0x12345678},
};
da1[0] = a2[0];
da1[101] = a2[1];
darr_remove_n(da1, 1, 100);
assert(darr_len(da1) == array_size(a2));
assert(!memcmp(da1, a2, sizeof(a2)));
da1[0] = a2[1];
da1[1] = a2[0];
darr_insert_n(da1, 1, 100);
assert(darr_len(da1) == 102);
darr_foreach_i (da1, i) {
da1[i].a = i;
da1[i].b = i;
}
darr_remove_n(da1, 1, 100);
assert(darr_len(da1) == 2);
darr_insert_nz(da1, 1, 100);
assert(!memcmp(&da1[1], z102, 100 * sizeof(da1[0])));
/* assert(da1[0] == a2[1]); */
/* assert(da1[101] == a2[0]); */
darr_reset(da1);
assert(darr_len(da1) == 0);
assert(darr_maxi(da1) == 127);
assert(darr_cap(da1) == 128);
/* we touch the length field of the freed block here somehow */
darr_insert_n(da1, 100, 300);
assert(darr_len(da1) == 400);
assert(darr_cap(da1) == 512);
darr_free(da1);
assert(da1 == NULL);
assert(darr_len(da1) == 0);
darr_setlen(da1, 0);
darr_reset(da1);
darr_free(da1);
struct st i0 = {0, 0};
struct st i1 = {1, 1};
struct st i2 = {2, 2};
struct st i3 = {3, 3};
struct st i4 = {4, 4};
*darr_append(da2) = i0;
*darr_append(da2) = i1;
darr_push(da2, i2);
darr_push(da2, i3);
darr_push(da2, i4);
assert(!memcmp(da2, a1, sizeof(a1)));
struct st p0, p1, p2, p3, p4;
p4 = darr_pop(da2);
p3 = darr_pop(da2);
p2 = darr_pop(da2);
p1 = darr_pop(da2);
p0 = darr_pop(da2);
assert(darr_len(da2) == 0);
assert(p4.a == i4.a && p4.b == i4.b);
assert(p3.a == i3.a && p3.b == i3.b);
assert(p2.a == i2.a && p2.b == i2.b);
assert(p1.a == i1.a && p1.b == i1.b);
assert(p0.a == i0.a && p0.b == i0.b);
darr_free(da2);
}
int main(int argc, char **argv)
{
test_int();
test_struct();
}