mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
lib: add simplified native msg support
This is intended to replace protobuf use in mgmtd. Signed-off-by: Christian Hopps <chopps@labn.net>
This commit is contained in:
parent
080299fe10
commit
8790457c46
49
gdb/lib.txt
49
gdb/lib.txt
|
@ -306,8 +306,9 @@ define mq_walk
|
||||||
end
|
end
|
||||||
set $mg = $mg->next
|
set $mg = $mg->next
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
document mg_walk
|
document mq_walk
|
||||||
Walk the memory data structures to show what is holding memory.
|
Walk the memory data structures to show what is holding memory.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
@ -315,3 +316,49 @@ Arguments:
|
||||||
sure where to start pass it mg_first, which is a global DS for
|
sure where to start pass it mg_first, which is a global DS for
|
||||||
all memory allocated in FRR
|
all memory allocated in FRR
|
||||||
end
|
end
|
||||||
|
|
||||||
|
define __darr_meta
|
||||||
|
set $_ = ((struct darr_metadata *)$arg0) - 1
|
||||||
|
end
|
||||||
|
document __darr_meta
|
||||||
|
Store a pointer to the struct darr_metadata in $_ for the given dynamic array.
|
||||||
|
|
||||||
|
Argument: a pointer to a darr dynamic array.
|
||||||
|
Returns: pointer to the struct darr_metadata in $_.
|
||||||
|
end
|
||||||
|
|
||||||
|
define darr_meta
|
||||||
|
__darr_meta $arg0
|
||||||
|
p *$_
|
||||||
|
end
|
||||||
|
document darr_meta
|
||||||
|
Print the struct darr_metadata for the given dynamic array. Store the value
|
||||||
|
in $_ as well.
|
||||||
|
|
||||||
|
Argument: a pointer to a darr dynamic array.
|
||||||
|
Returns: pointer to the struct darr_metadata in $_.
|
||||||
|
end
|
||||||
|
|
||||||
|
define darr_len
|
||||||
|
__darr_meta $arg0
|
||||||
|
set $_ = $_->len
|
||||||
|
p $_
|
||||||
|
end
|
||||||
|
document darr_len
|
||||||
|
Print the length of the given dynamic array, and store in $_.
|
||||||
|
|
||||||
|
Argument: a pointer to a darr dynamic array.
|
||||||
|
Returns: length of the array.
|
||||||
|
end
|
||||||
|
|
||||||
|
define darr_cap
|
||||||
|
__darr_meta $arg0
|
||||||
|
set $_ = $_->cap
|
||||||
|
p $_
|
||||||
|
end
|
||||||
|
document darr_len
|
||||||
|
Print the capacity of the given dynamic array, and store in $_.
|
||||||
|
|
||||||
|
Argument: a pointer to a darr dynamic array.
|
||||||
|
Returns: capacity of the array.
|
||||||
|
end
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "frrevent.h"
|
#include "frrevent.h"
|
||||||
#include "mgmt_msg.h"
|
#include "mgmt_msg.h"
|
||||||
|
#include "mgmt_msg_native.h"
|
||||||
|
|
||||||
|
|
||||||
#define MGMT_MSG_DBG(dbgtag, fmt, ...) \
|
#define MGMT_MSG_DBG(dbgtag, fmt, ...) \
|
||||||
|
@ -84,7 +85,7 @@ enum mgmt_msg_rsched mgmt_msg_read(struct mgmt_msg_state *ms, int fd,
|
||||||
*/
|
*/
|
||||||
assert(stream_get_getp(ms->ins) == 0);
|
assert(stream_get_getp(ms->ins) == 0);
|
||||||
left = stream_get_endp(ms->ins);
|
left = stream_get_endp(ms->ins);
|
||||||
while (left > (long)sizeof(struct mgmt_msg_hdr)) {
|
while (left > (ssize_t)sizeof(struct mgmt_msg_hdr)) {
|
||||||
mhdr = (struct mgmt_msg_hdr *)(STREAM_DATA(ms->ins) + total);
|
mhdr = (struct mgmt_msg_hdr *)(STREAM_DATA(ms->ins) + total);
|
||||||
if (!MGMT_MSG_IS_MARKER(mhdr->marker)) {
|
if (!MGMT_MSG_IS_MARKER(mhdr->marker)) {
|
||||||
MGMT_MSG_DBG(dbgtag, "recv corrupt buffer, disconnect");
|
MGMT_MSG_DBG(dbgtag, "recv corrupt buffer, disconnect");
|
||||||
|
@ -99,8 +100,25 @@ enum mgmt_msg_rsched mgmt_msg_read(struct mgmt_msg_state *ms, int fd,
|
||||||
mcount++;
|
mcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mcount)
|
if (!mcount) {
|
||||||
|
/* Didn't manage to read a full message */
|
||||||
|
if (mhdr && avail == 0) {
|
||||||
|
struct stream *news;
|
||||||
|
/*
|
||||||
|
* Message was longer than what was left and we have no
|
||||||
|
* available space to read more in. B/c mcount == 0 the
|
||||||
|
* message starts at the beginning of the stream so
|
||||||
|
* therefor the stream is too small to fit the message..
|
||||||
|
* Resize the stream to fit.
|
||||||
|
*/
|
||||||
|
news = stream_new(mhdr->len);
|
||||||
|
stream_put(news, mhdr, left);
|
||||||
|
stream_set_endp(news, left);
|
||||||
|
stream_free(ms->ins);
|
||||||
|
ms->ins = news;
|
||||||
|
}
|
||||||
return MSR_SCHED_STREAM;
|
return MSR_SCHED_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have read at least one message into the stream, queue it up.
|
* We have read at least one message into the stream, queue it up.
|
||||||
|
@ -108,7 +126,11 @@ enum mgmt_msg_rsched mgmt_msg_read(struct mgmt_msg_state *ms, int fd,
|
||||||
mhdr = (struct mgmt_msg_hdr *)(STREAM_DATA(ms->ins) + total);
|
mhdr = (struct mgmt_msg_hdr *)(STREAM_DATA(ms->ins) + total);
|
||||||
stream_set_endp(ms->ins, total);
|
stream_set_endp(ms->ins, total);
|
||||||
stream_fifo_push(&ms->inq, ms->ins);
|
stream_fifo_push(&ms->inq, ms->ins);
|
||||||
ms->ins = stream_new(ms->max_msg_sz);
|
if (left < (ssize_t)sizeof(struct mgmt_msg_hdr))
|
||||||
|
ms->ins = stream_new(ms->max_msg_sz);
|
||||||
|
else
|
||||||
|
/* handle case where message is greater than max */
|
||||||
|
ms->ins = stream_new(MAX(ms->max_msg_sz, mhdr->len));
|
||||||
if (left) {
|
if (left) {
|
||||||
stream_put(ms->ins, mhdr, left);
|
stream_put(ms->ins, mhdr, left);
|
||||||
stream_set_endp(ms->ins, left);
|
stream_set_endp(ms->ins, left);
|
||||||
|
@ -292,23 +314,26 @@ int mgmt_msg_send_msg(struct mgmt_msg_state *ms, uint8_t version, void *msg,
|
||||||
size_t endp, n;
|
size_t endp, n;
|
||||||
size_t mlen = len + sizeof(*mhdr);
|
size_t mlen = len + sizeof(*mhdr);
|
||||||
|
|
||||||
if (mlen > ms->max_msg_sz) {
|
if (mlen > ms->max_msg_sz)
|
||||||
MGMT_MSG_ERR(ms, "Message %zu > max size %zu, dropping", mlen,
|
MGMT_MSG_DBG(dbgtag, "Sending large msg size %zu > max size %zu",
|
||||||
ms->max_msg_sz);
|
mlen, ms->max_msg_sz);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ms->outs) {
|
if (!ms->outs) {
|
||||||
MGMT_MSG_DBG(dbgtag, "creating new stream for msg len %zu",
|
MGMT_MSG_DBG(dbgtag, "creating new stream for msg len %zu", mlen);
|
||||||
len);
|
ms->outs = stream_new(MAX(ms->max_msg_sz, mlen));
|
||||||
ms->outs = stream_new(ms->max_msg_sz);
|
} else if (mlen > ms->max_msg_sz && ms->outs->endp == 0) {
|
||||||
|
/* msg is larger than stream max size get a fit-to-size stream */
|
||||||
|
MGMT_MSG_DBG(dbgtag,
|
||||||
|
"replacing old stream with fit-to-size for msg len %zu",
|
||||||
|
mlen);
|
||||||
|
stream_free(ms->outs);
|
||||||
|
ms->outs = stream_new(mlen);
|
||||||
} else if (STREAM_WRITEABLE(ms->outs) < mlen) {
|
} else if (STREAM_WRITEABLE(ms->outs) < mlen) {
|
||||||
MGMT_MSG_DBG(
|
MGMT_MSG_DBG(dbgtag,
|
||||||
dbgtag,
|
"enq existing stream len %zu and creating new stream for msg len %zu",
|
||||||
"enq existing stream len %zu and creating new stream for msg len %zu",
|
STREAM_WRITEABLE(ms->outs), mlen);
|
||||||
STREAM_WRITEABLE(ms->outs), mlen);
|
|
||||||
stream_fifo_push(&ms->outq, ms->outs);
|
stream_fifo_push(&ms->outq, ms->outs);
|
||||||
ms->outs = stream_new(ms->max_msg_sz);
|
ms->outs = stream_new(MAX(ms->max_msg_sz, mlen));
|
||||||
} else {
|
} else {
|
||||||
MGMT_MSG_DBG(
|
MGMT_MSG_DBG(
|
||||||
dbgtag,
|
dbgtag,
|
||||||
|
@ -317,6 +342,16 @@ int mgmt_msg_send_msg(struct mgmt_msg_state *ms, uint8_t version, void *msg,
|
||||||
}
|
}
|
||||||
s = ms->outs;
|
s = ms->outs;
|
||||||
|
|
||||||
|
if (dbgtag && version == MGMT_MSG_VERSION_NATIVE) {
|
||||||
|
struct mgmt_msg_header *native_msg = msg;
|
||||||
|
|
||||||
|
MGMT_MSG_DBG(
|
||||||
|
dbgtag,
|
||||||
|
"Sending native msg sess/txn-id %"PRIu64" req-id %"PRIu64" code %u",
|
||||||
|
native_msg->session_id, native_msg->req_id, native_msg->code);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* We have a stream with space, pack the message into it. */
|
/* We have a stream with space, pack the message into it. */
|
||||||
mhdr = (struct mgmt_msg_hdr *)(STREAM_DATA(s) + s->endp);
|
mhdr = (struct mgmt_msg_hdr *)(STREAM_DATA(s) + s->endp);
|
||||||
mhdr->marker = MGMT_MSG_MARKER(version);
|
mhdr->marker = MGMT_MSG_MARKER(version);
|
||||||
|
@ -672,6 +707,9 @@ static int msg_client_connect_short_circuit(struct msg_client *client)
|
||||||
/* server side */
|
/* server side */
|
||||||
memset(&su, 0, sizeof(union sockunion));
|
memset(&su, 0, sizeof(union sockunion));
|
||||||
server_conn = server->create(sockets[1], &su);
|
server_conn = server->create(sockets[1], &su);
|
||||||
|
server_conn->debug = DEBUG_MODE_CHECK(server->debug, DEBUG_MODE_ALL)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
|
||||||
client->conn.remote_conn = server_conn;
|
client->conn.remote_conn = server_conn;
|
||||||
server_conn->remote_conn = &client->conn;
|
server_conn->remote_conn = &client->conn;
|
||||||
|
@ -765,8 +803,9 @@ void msg_client_cleanup(struct msg_client *client)
|
||||||
static void msg_server_accept(struct event *event)
|
static void msg_server_accept(struct event *event)
|
||||||
{
|
{
|
||||||
struct msg_server *server = EVENT_ARG(event);
|
struct msg_server *server = EVENT_ARG(event);
|
||||||
int fd;
|
struct msg_conn *conn;
|
||||||
union sockunion su;
|
union sockunion su;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (server->fd < 0)
|
if (server->fd < 0)
|
||||||
return;
|
return;
|
||||||
|
@ -789,7 +828,11 @@ static void msg_server_accept(struct event *event)
|
||||||
|
|
||||||
DEBUGD(server->debug, "Accepted new %s connection", server->idtag);
|
DEBUGD(server->debug, "Accepted new %s connection", server->idtag);
|
||||||
|
|
||||||
server->create(fd, &su);
|
conn = server->create(fd, &su);
|
||||||
|
if (conn)
|
||||||
|
conn->debug = DEBUG_MODE_CHECK(server->debug, DEBUG_MODE_ALL)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int msg_server_init(struct msg_server *server, const char *sopath,
|
int msg_server_init(struct msg_server *server, const char *sopath,
|
||||||
|
|
45
lib/mgmt_msg_native.c
Normal file
45
lib/mgmt_msg_native.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* June 29 2023, Christian Hopps <chopps@labn.net>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023, LabN Consulting, L.L.C.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "mgmt_msg_native.h"
|
||||||
|
|
||||||
|
DEFINE_MGROUP(MSG_NATIVE, "Native message allocations");
|
||||||
|
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_MSG, "native mgmt msg");
|
||||||
|
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_ERROR, "native mgmt error msg");
|
||||||
|
|
||||||
|
int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id,
|
||||||
|
uint64_t req_id, bool short_circuit_ok,
|
||||||
|
int16_t error, const char *errfmt, va_list ap)
|
||||||
|
{
|
||||||
|
struct mgmt_msg_error *msg;
|
||||||
|
ssize_t slen;
|
||||||
|
size_t mlen;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
msg = XCALLOC(MTYPE_MSG_NATIVE_ERROR, 1024);
|
||||||
|
msg->session_id = sess_or_txn_id;
|
||||||
|
msg->req_id = req_id;
|
||||||
|
msg->code = MGMT_MSG_CODE_ERROR;
|
||||||
|
msg->error = error;
|
||||||
|
|
||||||
|
slen = vsnprintfrr(msg->errstr, 1024 - sizeof(*msg), errfmt, ap);
|
||||||
|
mlen = MIN(slen + sizeof(*msg) + 1, 1024);
|
||||||
|
|
||||||
|
if (conn->debug)
|
||||||
|
zlog_debug("Sending error %d session-id %" PRIu64
|
||||||
|
" req-id %" PRIu64 " scok %d errstr: %s",
|
||||||
|
error, sess_or_txn_id, req_id, short_circuit_ok,
|
||||||
|
msg->errstr);
|
||||||
|
|
||||||
|
ret = msg_conn_send_msg(conn, MGMT_MSG_VERSION_NATIVE, msg, mlen, NULL,
|
||||||
|
short_circuit_ok);
|
||||||
|
|
||||||
|
XFREE(MTYPE_MSG_NATIVE_ERROR, msg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
121
lib/mgmt_msg_native.h
Normal file
121
lib/mgmt_msg_native.h
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* June 29 2023, Christian Hopps <chopps@labn.net>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023, LabN Consulting, L.L.C.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FRR_MGMT_MSG_NATIVE_H_
|
||||||
|
#define _FRR_MGMT_MSG_NATIVE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#elif 0
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "mgmt_msg.h"
|
||||||
|
#include "mgmt_defines.h"
|
||||||
|
|
||||||
|
#include <stdalign.h>
|
||||||
|
|
||||||
|
DECLARE_MTYPE(MSG_NATIVE_MSG);
|
||||||
|
DECLARE_MTYPE(MSG_NATIVE_ERROR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Native message codes
|
||||||
|
*/
|
||||||
|
#define MGMT_MSG_CODE_ERROR 0
|
||||||
|
#define MGMT_MSG_CODE_GET_TREE 1
|
||||||
|
#define MGMT_MSG_CODE_TREE_DATA 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A note on alignments: The zero length arrays fields are aligned such that
|
||||||
|
* this is so:
|
||||||
|
*
|
||||||
|
* sizeof(struct mgmt_msg_foo) == offsetof(struct mgmt_msg_foo, field)
|
||||||
|
*
|
||||||
|
* This allows things like `ptr = darr_append_n(A, sizeof(*ptr))`
|
||||||
|
* to work
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct mgmt_msg_header {
|
||||||
|
union {
|
||||||
|
uint64_t session_id;
|
||||||
|
uint64_t txn_id;
|
||||||
|
};
|
||||||
|
uint64_t req_id;
|
||||||
|
uint16_t code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mgmt_msg_error {
|
||||||
|
struct mgmt_msg_header;
|
||||||
|
int16_t error;
|
||||||
|
|
||||||
|
alignas(8) char errstr[];
|
||||||
|
};
|
||||||
|
_Static_assert(sizeof(struct mgmt_msg_error) ==
|
||||||
|
offsetof(struct mgmt_msg_error, errstr),
|
||||||
|
"Size mismatch");
|
||||||
|
|
||||||
|
struct mgmt_msg_get_tree {
|
||||||
|
struct mgmt_msg_header;
|
||||||
|
uint8_t result_type;
|
||||||
|
|
||||||
|
alignas(8) char xpath[];
|
||||||
|
};
|
||||||
|
_Static_assert(sizeof(struct mgmt_msg_get_tree) ==
|
||||||
|
offsetof(struct mgmt_msg_get_tree, xpath),
|
||||||
|
"Size mismatch");
|
||||||
|
|
||||||
|
struct mgmt_msg_tree_data {
|
||||||
|
struct mgmt_msg_header;
|
||||||
|
int8_t partial_error;
|
||||||
|
uint8_t result_type;
|
||||||
|
|
||||||
|
alignas(8) uint8_t result[];
|
||||||
|
};
|
||||||
|
_Static_assert(sizeof(struct mgmt_msg_tree_data) ==
|
||||||
|
offsetof(struct mgmt_msg_tree_data, result),
|
||||||
|
"Size mismatch");
|
||||||
|
|
||||||
|
#define MGMT_MSG_VALIDATE_NUL_TERM(msgp, len) \
|
||||||
|
((len) >= sizeof(*msg) + 1 && ((char *)msgp)[(len)-1] == 0)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a native message error to the other end of the connection.
|
||||||
|
*
|
||||||
|
* This function is normally used by the server-side to indicate a failure to
|
||||||
|
* process a client request. For this server side handling of client messages
|
||||||
|
* which expect a reply, either that reply or this error should be returned, as
|
||||||
|
* closing the connection is not allowed during message handling.
|
||||||
|
*
|
||||||
|
* Args:
|
||||||
|
* conn: the connection.
|
||||||
|
* sess_or_txn_id: Session ID (to FE client) or Txn ID (from BE client)
|
||||||
|
* req_id: which req_id this error is associated with.
|
||||||
|
* short_circuit_ok: if short circuit sending is OK.
|
||||||
|
* error: the error value
|
||||||
|
* errfmt: vprintfrr style format string
|
||||||
|
* ap: the variable args for errfmt.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* The return value of ``msg_conn_send_msg``.
|
||||||
|
*/
|
||||||
|
extern int vmgmt_msg_native_send_error(struct msg_conn *conn,
|
||||||
|
uint64_t sess_or_txn_id, uint64_t req_id,
|
||||||
|
bool short_circuit_ok, int16_t error,
|
||||||
|
const char *errfmt, va_list ap)
|
||||||
|
PRINTFRR(6, 0);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FRR_MGMT_MSG_NATIVE_H_ */
|
|
@ -68,6 +68,7 @@ lib_libfrr_la_SOURCES = \
|
||||||
lib/mgmt_be_client.c \
|
lib/mgmt_be_client.c \
|
||||||
lib/mgmt_fe_client.c \
|
lib/mgmt_fe_client.c \
|
||||||
lib/mgmt_msg.c \
|
lib/mgmt_msg.c \
|
||||||
|
lib/mgmt_msg_native.c \
|
||||||
lib/mlag.c \
|
lib/mlag.c \
|
||||||
lib/module.c \
|
lib/module.c \
|
||||||
lib/mpls.c \
|
lib/mpls.c \
|
||||||
|
@ -256,6 +257,7 @@ pkginclude_HEADERS += \
|
||||||
lib/mgmt_defines.h \
|
lib/mgmt_defines.h \
|
||||||
lib/mgmt_fe_client.h \
|
lib/mgmt_fe_client.h \
|
||||||
lib/mgmt_msg.h \
|
lib/mgmt_msg.h \
|
||||||
|
lib/mgmt_msg_native.h \
|
||||||
lib/mgmt_pb.h \
|
lib/mgmt_pb.h \
|
||||||
lib/module.h \
|
lib/module.h \
|
||||||
lib/monotime.h \
|
lib/monotime.h \
|
||||||
|
|
Loading…
Reference in a new issue