Skip to content

Commit

Permalink
Merge pull request #16184 from LabNConsulting/chopps/fe-notify-select
Browse files Browse the repository at this point in the history
mgmtd: add notification selection to front-end API
  • Loading branch information
Jafaral authored Jun 13, 2024
2 parents d8e3121 + 27e3694 commit 2e02bd2
Show file tree
Hide file tree
Showing 8 changed files with 506 additions and 47 deletions.
37 changes: 37 additions & 0 deletions lib/darr.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
* - darr_ensure_i
* - darr_ensure_i_mt
* - darr_free
* - darr_free_free
* - darr_free_func
* - darr_insert
* - darr_insert_mt
* - darr_insertz
Expand Down Expand Up @@ -217,6 +219,41 @@ void *__darr_resize(void *a, uint count, size_t esize, struct memtype *mt);
} \
} while (0)

/**
* Free memory allocated for the dynamic array `A`, calling `darr_free` for
* each element of the array first.
*
* Args:
* A: The dynamic array, can be NULL.
*/
#define darr_free_free(A) \
do { \
for (uint __i = 0; __i < darr_len(A); __i++) \
if ((A)[__i]) { \
struct darr_metadata *__meta = \
_darr_meta((A)[__i]); \
XFREE(__meta->mtype, __meta); \
} \
darr_free(A); \
} while (0)

/**
* Free memory allocated for the dynamic array `A`, calling `F` routine
* for each element of the array first.
*
* Args:
* A: The dynamic array, can be NULL.
* F: The function to call for each element.
*/

#define darr_free_func(A, F) \
do { \
for (uint __i = 0; __i < darr_len(A); __i++) { \
F((A)[__i]); \
} \
darr_free(A); \
} while (0)

/**
* Make sure that there is room in the dynamic array `A` to add `C` elements.
*
Expand Down
45 changes: 45 additions & 0 deletions lib/mgmt_msg_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*
*/
#include <zebra.h>
#include "darr.h"
#include "mgmt_msg_native.h"

DEFINE_MGROUP(MSG_NATIVE, "Native message allocations");
Expand All @@ -18,6 +19,33 @@ DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT, "native edit msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT_REPLY, "native edit reply msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC, "native RPC msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC_REPLY, "native RPC reply msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_SESSION_REQ, "native session-req msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_SESSION_REPLY, "native session-reply msg");


size_t mgmt_msg_min_sizes[] = {
[MGMT_MSG_CODE_ERROR] = sizeof(struct mgmt_msg_error),
[MGMT_MSG_CODE_GET_TREE] = sizeof(struct mgmt_msg_get_tree),
[MGMT_MSG_CODE_TREE_DATA] = sizeof(struct mgmt_msg_tree_data),
[MGMT_MSG_CODE_GET_DATA] = sizeof(struct mgmt_msg_get_data),
[MGMT_MSG_CODE_NOTIFY] = sizeof(struct mgmt_msg_notify_data),
[MGMT_MSG_CODE_EDIT] = sizeof(struct mgmt_msg_edit),
[MGMT_MSG_CODE_EDIT_REPLY] = sizeof(struct mgmt_msg_edit_reply),
[MGMT_MSG_CODE_RPC] = sizeof(struct mgmt_msg_rpc),
[MGMT_MSG_CODE_RPC_REPLY] = sizeof(struct mgmt_msg_rpc_reply),
[MGMT_MSG_CODE_NOTIFY_SELECT] = sizeof(struct mgmt_msg_notify_select),
[MGMT_MSG_CODE_SESSION_REQ] = sizeof(struct mgmt_msg_session_req),
[MGMT_MSG_CODE_SESSION_REPLY] = sizeof(struct mgmt_msg_session_reply),
};
size_t nmgmt_msg_min_sizes = sizeof(mgmt_msg_min_sizes) /
sizeof(*mgmt_msg_min_sizes);

size_t mgmt_msg_get_min_size(uint code)
{
if (code >= nmgmt_msg_min_sizes)
return 0;
return mgmt_msg_min_sizes[code];
}

int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id,
uint64_t req_id, bool short_circuit_ok,
Expand Down Expand Up @@ -50,3 +78,20 @@ int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id,
mgmt_msg_native_free_msg(msg);
return ret;
}

const char **_mgmt_msg_native_strings_decode(const void *_sdata, int sdlen)
{
const char *sdata = _sdata;
const char **strings = NULL;
int len;

if (sdata[sdlen - 1] != 0)
return NULL;

for (; sdlen; sdata += len, sdlen -= len) {
*darr_append(strings) = darr_strdup(sdata);
len = 1 + darr_strlen(strings[darr_lasti(strings)]);
}

return strings;
}
105 changes: 105 additions & 0 deletions lib/mgmt_msg_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ DECLARE_MTYPE(MSG_NATIVE_EDIT);
DECLARE_MTYPE(MSG_NATIVE_EDIT_REPLY);
DECLARE_MTYPE(MSG_NATIVE_RPC);
DECLARE_MTYPE(MSG_NATIVE_RPC_REPLY);
DECLARE_MTYPE(MSG_NATIVE_SESSION_REQ);
DECLARE_MTYPE(MSG_NATIVE_SESSION_REPLY);

/*
* Native message codes
Expand All @@ -176,6 +178,9 @@ DECLARE_MTYPE(MSG_NATIVE_RPC_REPLY);
#define MGMT_MSG_CODE_EDIT_REPLY 6 /* Public API */
#define MGMT_MSG_CODE_RPC 7 /* Public API */
#define MGMT_MSG_CODE_RPC_REPLY 8 /* Public API */
#define MGMT_MSG_CODE_NOTIFY_SELECT 9 /* Public API */
#define MGMT_MSG_CODE_SESSION_REQ 10 /* Public API */
#define MGMT_MSG_CODE_SESSION_REPLY 11 /* Public API */

/*
* Datastores
Expand Down Expand Up @@ -426,12 +431,72 @@ _Static_assert(sizeof(struct mgmt_msg_rpc_reply) ==
offsetof(struct mgmt_msg_rpc_reply, data),
"Size mismatch");

/**
* struct mgmt_msg_notify_select - Add notification selectors for FE client.
*
* Add xpath prefix notification selectors to limit the notifications sent
* to the front-end client.
*
* @selectors: the xpath prefixes to selectors notifications through.
* @replace: if true replace existing selectors with `selectors`.
*/
struct mgmt_msg_notify_select {
struct mgmt_msg_header;
uint8_t replace;
uint8_t resv2[7];

alignas(8) char selectors[];
};

_Static_assert(sizeof(struct mgmt_msg_notify_select) ==
offsetof(struct mgmt_msg_notify_select, selectors),
"Size mismatch");

/**
* struct mgmt_msg_session_req - Create or delete a front-end session.
*
* @refer_id: Zero for create, otherwise the session-id to delete.
* @req_id: For create will use as client-id.
* @client_name: For first session request the client name, otherwise empty.
*/
struct mgmt_msg_session_req {
struct mgmt_msg_header;
uint8_t resv2[8]; /* bug in compiler produces error w/o this */

alignas(8) char client_name[];
};

_Static_assert(sizeof(struct mgmt_msg_session_req) ==
offsetof(struct mgmt_msg_session_req, client_name),
"Size mismatch");

/**
* struct mgmt_msg_session_reply - Reply to session request message.
*
* @created: true if this is a reply to a create request, otherwise 0.
* @refer_id: The session-id for the action (create or delete) just taken.
*/
struct mgmt_msg_session_reply {
struct mgmt_msg_header;
uint8_t created;
uint8_t resv2[7];
};

/*
* Validate that the message ends in a NUL terminating byte
*/
#define MGMT_MSG_VALIDATE_NUL_TERM(msgp, len) \
((len) >= sizeof(*msgp) + 1 && ((char *)msgp)[(len)-1] == 0)

/**
* mgmt_msg_get_min_size() - Get minimum message size given the type
* @code: The type of the message (MGMT_MSG_CODE_*)
*
* Return:
* The minimum size of a message of the given type or 0 if the message
* code is unknown.
*/
size_t mgmt_msg_get_min_size(uint code);

/**
* Send a native message error to the other end of the connection.
Expand Down Expand Up @@ -524,6 +589,25 @@ extern int vmgmt_msg_native_send_error(struct msg_conn *conn,
p; \
})

/**
* mgmt_msg_native_add_str() - Append [another] string to the msg.
* @msg: (IN/OUT) Pointer to the native message, variable may be updated.
* @s: string to append.
*
* Append string @s to the native message @msg. @msg is assumed to have a
* sequence of NUL-terminated strings at the end of it. This function appends
* the string @s and it's NUL terminating octet to the message.
*
* NOTE: Be aware @msg pointer may change as a result of reallocating the
* message to fit the new data. Any other pointers into the old message should
* be discarded.
*/
#define mgmt_msg_native_add_str(msg, s) \
do { \
int __len = strlen(s) + 1; \
mgmt_msg_native_append(msg, s, __len); \
} while (0)

/**
* mgmt_msg_native_send_msg(msg, short_circuit_ok) - Send a native msg.
* @conn: the mgmt_msg connection.
Expand Down Expand Up @@ -689,6 +773,27 @@ extern int vmgmt_msg_native_send_error(struct msg_conn *conn,
#define mgmt_msg_native_data_len_decode(msg, msglen) \
((msglen) - sizeof(*msg) - msg->vsplit)

/**
* mgmt_msg_native_strings_decode() - Get dynamic array of str ptrs from the msg.
* @msg: Pointer to the native message.
* @msglen: Length of the message.
* @sdata: pointer to the variable length string data at end of @msg.
*
* Given a pointer to a sequence of NUL-terminated strings allocate
* and return a dynamic array of dynamic array strings. This function
* can be used to decode a message that was built using
* mgmt_msg_native_add_str().
*
* Return: a dynamic array (darr) of string pointers, or NULL if the message
* is corrupt.
*/
#define mgmt_msg_native_strings_decode(msg, msg_len, sdata) \
_mgmt_msg_native_strings_decode(sdata, \
(msg_len) - ((sdata) - (char *)(msg)))

extern const char **_mgmt_msg_native_strings_decode(const void *sdata,
int sdlen);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion lib/yang.c
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ char *yang_convert_lyd_format(const char *data, size_t data_len,

assert(out_format != LYD_LYB);

if (in_format != LYD_LYB && !MGMT_MSG_VALIDATE_NUL_TERM(data, data_len)) {
if (in_format != LYD_LYB && (!data_len || data[data_len - 1] != 0)) {
zlog_err("Corrupt input data, no NUL terminating byte");
return NULL;
}
Expand Down
Loading

0 comments on commit 2e02bd2

Please sign in to comment.