summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJafar Al-Gharaibeh <jafar@atcorp.com>2024-06-13 00:20:09 -0500
committerGitHub <noreply@github.com>2024-06-13 00:20:09 -0500
commit2e02bd2366ebf877963802d79e66b805ccffbf4c (patch)
tree4131dc2e92ef2678f6c1cc1de6e1dddc56d4b1bc /lib
parentd8e3121cb8470fe9a934100de9170b4ef48b17a6 (diff)
parent27e369487eb602b75ea353e8c21333bd83032a86 (diff)
Merge pull request #16184 from LabNConsulting/chopps/fe-notify-select
mgmtd: add notification selection to front-end API
Diffstat (limited to 'lib')
-rw-r--r--lib/darr.h37
-rw-r--r--lib/mgmt_msg_native.c45
-rw-r--r--lib/mgmt_msg_native.h105
-rw-r--r--lib/yang.c2
4 files changed, 188 insertions, 1 deletions
diff --git a/lib/darr.h b/lib/darr.h
index 404869d9a2..2b9a0a0c02 100644
--- a/lib/darr.h
+++ b/lib/darr.h
@@ -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
@@ -218,6 +220,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.
*
* Available space is `darr_cap(a) - darr_len(a)`.
diff --git a/lib/mgmt_msg_native.c b/lib/mgmt_msg_native.c
index 39ce9abae6..b85c7d1b61 100644
--- a/lib/mgmt_msg_native.c
+++ b/lib/mgmt_msg_native.c
@@ -6,6 +6,7 @@
*
*/
#include <zebra.h>
+#include "darr.h"
#include "mgmt_msg_native.h"
DEFINE_MGROUP(MSG_NATIVE, "Native message allocations");
@@ -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,
@@ -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;
+}
diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h
index 21f702cc61..76a52658cd 100644
--- a/lib/mgmt_msg_native.h
+++ b/lib/mgmt_msg_native.h
@@ -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
@@ -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
@@ -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.
@@ -525,6 +590,25 @@ extern int vmgmt_msg_native_send_error(struct msg_conn *conn,
})
/**
+ * 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.
* @msg: the native message.
@@ -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
diff --git a/lib/yang.c b/lib/yang.c
index 702fcf436d..44459df4a5 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -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;
}