mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
cbor_parse: parsing command, can show memory
This commit is contained in:
parent
10afb161bd
commit
d91390e2d2
@ -58,6 +58,11 @@ void cbor_add_int(struct cbor_writer *writer, int item) {
|
||||
write_item(writer, 1, item);
|
||||
}
|
||||
}
|
||||
|
||||
void cbor_add_tag(struct cbor_writer *writer, int item) {
|
||||
write_item(writer, 6, item);
|
||||
}
|
||||
|
||||
void cbor_add_string(struct cbor_writer *writer, char *string) {
|
||||
int length = strlen(string);
|
||||
write_item(writer, 3, length); // 3 is major, then goes length of string and string
|
||||
@ -92,7 +97,7 @@ void write_item(struct cbor_writer *writer, int8_t major, int num) {
|
||||
return;
|
||||
}
|
||||
if (num > 23) { // byte is enough, but aditional value would be too big
|
||||
major += 0x18; // reserving those bytes
|
||||
major += 0x18; // reserving that byte
|
||||
writer->cbor[writer->pt] = major;
|
||||
writer->pt++;
|
||||
uint8_t to_write = num & 0xff;
|
||||
|
53
nest/cbor_cmds.c
Normal file
53
nest/cbor_cmds.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include "nest/cbor_shortcuts.c"
|
||||
#include "nest/bird.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/route.h"
|
||||
#include "nest/cli.h"
|
||||
#include "conf/conf.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/resource.h"
|
||||
#include "filter/filter.h"
|
||||
|
||||
|
||||
extern pool *rt_table_pool;
|
||||
extern pool *rta_pool;
|
||||
extern uint *pages_kept;
|
||||
|
||||
uint
|
||||
cmd_show_memory_cbor(byte *tbuf, uint capacity) {
|
||||
log("in cmd_show_memory_cbor");
|
||||
struct cbor_writer *w = cbor_init(tbuf, capacity, lp_new(proto_pool));
|
||||
cbor_open_block_with_length(w, 1);
|
||||
|
||||
cbor_add_string(w, "show_memory:message");
|
||||
cbor_open_block_with_length(w, 2);
|
||||
|
||||
cbor_string_string(w, "header", "BIRD memory usage");
|
||||
|
||||
cbor_add_string(w, "body");
|
||||
cbor_open_block(w);
|
||||
|
||||
struct resmem memory = rmemsize(rt_table_pool);
|
||||
cbor_named_block_two_ints(w, "routing_tables", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(rta_pool);
|
||||
cbor_named_block_two_ints(w, "route_attributes", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(proto_pool);
|
||||
cbor_named_block_two_ints(w, "protocols", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(config_pool);
|
||||
cbor_named_block_two_ints(w, "current_config", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(&root_pool);
|
||||
#ifdef HAVE_MMAP
|
||||
cbor_named_block_two_ints(w, "standby_memory", "effective", 0, "overhead", page_size * *pages_kept);
|
||||
#endif
|
||||
memory.overhead += page_size * *pages_kept;
|
||||
cbor_named_block_two_ints(w, "total", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
cbor_close_block_or_list(w); // we do not know for sure, that standby memory will be printed, so we do not know number of block items. If we know that, we open the block for 6 (or 5) items and we do not close anything
|
||||
|
||||
cbor_write_to_file(w, "show_memory.cbor");
|
||||
return w->pt;
|
||||
}
|
154
nest/cbor_parse.c
Normal file
154
nest/cbor_parse.c
Normal file
@ -0,0 +1,154 @@
|
||||
#include "nest/cbor_cmds.c"
|
||||
|
||||
enum functions {
|
||||
SHOW_STATUS=0,
|
||||
SHOW_MEMORY=1,
|
||||
};
|
||||
|
||||
enum cbor_majors {
|
||||
UINT = 0,
|
||||
NEG_INT = 1,
|
||||
BYTE_STR = 2,
|
||||
TEXT = 3,
|
||||
ARRAY = 4,
|
||||
BLOCK = 5,
|
||||
TAG = 6,
|
||||
FLOAT = 7,
|
||||
};
|
||||
|
||||
|
||||
struct value {
|
||||
int major;
|
||||
int val;
|
||||
};
|
||||
|
||||
struct buff_reader {
|
||||
byte *buff;
|
||||
uint pt;
|
||||
uint size;
|
||||
};
|
||||
|
||||
|
||||
struct value
|
||||
get_value(struct buff_reader *reader) {
|
||||
struct value val;
|
||||
byte *buff = reader->buff;
|
||||
val.major = buff[reader->pt]>>5;
|
||||
log("in get value");
|
||||
int first_byte_val = buff[reader->pt] - (val.major<<5);
|
||||
if (first_byte_val <=23) {
|
||||
val.val = first_byte_val;
|
||||
reader->pt++;
|
||||
} else if (first_byte_val == 0x18) {
|
||||
val.val = buff[reader->pt+1];
|
||||
reader->pt+=2;
|
||||
} else if (first_byte_val == 0x19) {
|
||||
val.val = buff[reader->pt+1]>>8 + buff[reader->pt+2];
|
||||
reader->pt+=3;
|
||||
} else if (first_byte_val == 0x1a) {
|
||||
val.val = buff[reader->pt+1]>>24 + buff[reader->pt+2]>>16 + buff[reader->pt+3]>>8 + buff[reader->pt+4];
|
||||
reader->pt+=5;
|
||||
} else if (first_byte_val == 0xff) {
|
||||
val.val = -1;
|
||||
reader->pt++;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint compare_str(struct buff_reader *buf_read, uint length, char *string) {
|
||||
if (length != strlen(string)) {
|
||||
return 0;
|
||||
}
|
||||
for (size_t i = 0; i < strlen(string); i++) {
|
||||
if (buf_read->buff[i+buf_read->pt]!=string[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int val_is_break(struct value val) {
|
||||
return val.major == FLOAT && val.val == -1; // break code is 0xff, so the major is same for float and break
|
||||
}
|
||||
|
||||
uint
|
||||
do_command(struct buff_reader *rbuf_read, struct buff_reader *tbuf_read, int items_in_block) {
|
||||
struct value val= get_value(rbuf_read);
|
||||
ASSERT(val.major == UINT);
|
||||
switch (val.val)
|
||||
{
|
||||
case SHOW_MEMORY:
|
||||
if (items_in_block != 0) {
|
||||
val = get_value(rbuf_read);
|
||||
if (val.major == TEXT) { //Since the list args is optional, we need to know if it is here and check if it is empty.
|
||||
ASSERT(compare_str(rbuf_read, val.val, "args"));
|
||||
rbuf_read->pt+=val.val;
|
||||
val = get_value(rbuf_read);
|
||||
ASSERT(val.major == ARRAY);
|
||||
ASSERT(val.val <=0);
|
||||
if (val.val ==-1) { // list open with unspecified size, but we know there should be none for show memory (but, of course, we know it because of the show memory function, not because of yang)
|
||||
val = get_value(rbuf_read);
|
||||
ASSERT(val_is_break(val));
|
||||
}
|
||||
} else {
|
||||
ASSERT(items_in_block == -1); // assert the block was not open to exactly two items (we do not have args list and there is no chance to have another item in the block)
|
||||
rbuf_read->pt--; // we read one byte from future, we need to shift pointer back
|
||||
}
|
||||
}
|
||||
return cmd_show_memory_cbor(tbuf_read->buff, tbuf_read->size);
|
||||
case SHOW_STATUS:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint
|
||||
parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize) {
|
||||
log("cbor parse");
|
||||
struct buff_reader rbuf_read;
|
||||
struct buff_reader tbuf_read;
|
||||
rbuf_read.buff = rbuf;
|
||||
tbuf_read.buff = tbuf;
|
||||
rbuf_read.size = size;
|
||||
tbuf_read.size = tbsize;
|
||||
rbuf_read.pt = 0;
|
||||
tbuf_read.pt = 0;
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
struct value val = get_value(&rbuf_read);
|
||||
ASSERT(val.major == BLOCK);
|
||||
ASSERT(val.val <=1);
|
||||
int wait_for_end_main_block = val.val == -1;
|
||||
if (val.val != 0) {
|
||||
val = get_value(&rbuf_read);
|
||||
if ( !( wait_for_end_main_block == -1 && val_is_break(val) )) {
|
||||
ASSERT(val.major == TEXT);
|
||||
ASSERT(compare_str(&rbuf_read, val.val, "command:do"));
|
||||
rbuf_read.pt+=val.val;
|
||||
|
||||
val = get_value(&rbuf_read);
|
||||
ASSERT(val.major == BLOCK);
|
||||
ASSERT(val.val == 1 || val.val == 2 || val.val == -1);
|
||||
int items_in_block = val.val;
|
||||
|
||||
val = get_value(&rbuf_read);
|
||||
ASSERT(val.major == TEXT);
|
||||
items_in_block--;
|
||||
ASSERT(compare_str(&rbuf_read, val.val, "command"));
|
||||
rbuf_read.pt+=val.val;
|
||||
|
||||
tbuf_read.pt = do_command(&rbuf_read, &tbuf_read, items_in_block);
|
||||
if (items_in_block == -1) {
|
||||
val = get_value(&rbuf_read);
|
||||
ASSERT(val.major == FLOAT && val.val == -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tbuf_read.pt;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,11 @@ void cbor_string_string(struct cbor_writer *writer, char *key, char *value) {
|
||||
cbor_add_string(writer, value);
|
||||
}
|
||||
|
||||
void cbor_string_int(struct cbor_writer *writer, char *key, int value) {
|
||||
cbor_add_string(writer, key);
|
||||
cbor_add_int(writer, value);
|
||||
}
|
||||
|
||||
void cbor_named_block_two_ints(struct cbor_writer *writer, char *key, char *name1, int val1, char *name2, int val2) {
|
||||
cbor_add_string(writer, key);
|
||||
cbor_open_block_with_length(writer, 2);
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "nest/cli.h"
|
||||
#include "conf/conf.h"
|
||||
#include "lib/string.h"
|
||||
#include "nest/cbor_parse.c"
|
||||
|
||||
pool *cli_pool;
|
||||
pool *yi_pool;
|
||||
@ -337,7 +338,7 @@ cli_kick(cli *c)
|
||||
|
||||
uint
|
||||
yi_process(uint size, byte *rbuf, byte *tbuf, uint tbsize) {
|
||||
return cmd_show_memory_cbor(tbuf, tbsize);
|
||||
return parse_cbor(size, rbuf, tbuf, tbsize);
|
||||
}
|
||||
|
||||
static list cli_log_hooks;
|
||||
|
54
nest/cmds.c
54
nest/cmds.c
@ -15,7 +15,6 @@
|
||||
#include "lib/string.h"
|
||||
#include "lib/resource.h"
|
||||
#include "filter/filter.h"
|
||||
#include "nest/cbor_shortcuts.c"
|
||||
|
||||
extern int shutting_down;
|
||||
extern int configuring;
|
||||
@ -45,9 +44,7 @@ cmd_show_status(void)
|
||||
cli_msg(13, "Daemon is up and running");
|
||||
|
||||
|
||||
/*byte time[TM_DATETIME_BUFFER_SIZE];
|
||||
tm_format_time(time, &config->tf_base, current_time());
|
||||
struct cbor_writer *w = cbor_init(lp_new(proto_pool), 1000);
|
||||
/*struct cbor_writer *w = cbor_init(lp_new(proto_pool), 1000);
|
||||
cbor_open_block_with_length(w, 1);
|
||||
cbor_add_string(w, "show_status:message");
|
||||
|
||||
@ -55,14 +52,12 @@ cmd_show_status(void)
|
||||
cbor_string_string(w, "BIRD", BIRD_VERSION);
|
||||
cbor_add_string(w, "body");
|
||||
cbor_open_block(w);
|
||||
cbor_add_string(w, "router_id");
|
||||
cbor_add_int(w, config->router_id);
|
||||
cbor_string_int(w, "router_id", config->router_id);
|
||||
cbor_string_string(w, "hostname", config->hostname);
|
||||
cbor_string_string(w, "server_time", time);
|
||||
cbor_string_string(w, "server_time", current_time());
|
||||
tm_format_time(time, &config->tf_base, boot_time);
|
||||
cbor_string_string(w, "last_reboot", time);
|
||||
tm_format_time(time, &config->tf_base, config->load_time);
|
||||
cbor_string_string(w, "last_reconfiguration", time);
|
||||
cbor_string_int(w, "last_reboot", boot_time);
|
||||
cbor_string_string(w, "last_reconfiguration", config->load_time);
|
||||
|
||||
// TODO graceful restart
|
||||
cbor_close_block_or_list(w);
|
||||
@ -161,45 +156,6 @@ cmd_show_memory(void)
|
||||
cli_msg(0, "");
|
||||
}
|
||||
|
||||
uint
|
||||
cmd_show_memory_cbor(byte *tbuf, uint capacity) {
|
||||
bug("in cmd_show_memory_cbor");
|
||||
struct cbor_writer *w = cbor_init(tbuf, capacity, lp_new(proto_pool));
|
||||
cbor_open_block_with_length(w, 1);
|
||||
|
||||
cbor_add_string(w, "show_memory:message");
|
||||
cbor_open_block_with_length(w, 2);
|
||||
|
||||
cbor_string_string(w, "header", "BIRD memory usage");
|
||||
|
||||
cbor_add_string(w, "body");
|
||||
cbor_open_block(w);
|
||||
|
||||
struct resmem memory = rmemsize(rt_table_pool);
|
||||
cbor_named_block_two_ints(w, "routing_tables", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(rta_pool);
|
||||
cbor_named_block_two_ints(w, "route_attributes", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(proto_pool);
|
||||
cbor_named_block_two_ints(w, "protocols", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(config_pool);
|
||||
cbor_named_block_two_ints(w, "current_config", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
memory = rmemsize(&root_pool);
|
||||
#ifdef HAVE_MMAP
|
||||
cbor_named_block_two_ints(w, "standby_memory", "effective", 0, "overhead", page_size * *pages_kept);
|
||||
#endif
|
||||
memory.overhead += page_size * *pages_kept;
|
||||
cbor_named_block_two_ints(w, "total", "effective", memory.effective, "overhead", memory.overhead);
|
||||
|
||||
cbor_close_block_or_list(w); // we do not know for sure, that standby memory will be printed, so we do not know number of block items. If we know that, we open the block for 6 (or 5) items and we do not close anything
|
||||
|
||||
cbor_write_to_file(w, "show_memory.cbor");
|
||||
return w->pt;
|
||||
}
|
||||
|
||||
void
|
||||
cmd_eval(const struct f_line *expr)
|
||||
{
|
||||
|
@ -1810,7 +1810,6 @@ sk_send_full(sock *s, unsigned len, struct iface *ifa,
|
||||
static void
|
||||
call_rx_hook(sock *s, int size)
|
||||
{
|
||||
log(L_WARN "soc rx_hook");
|
||||
if (s->rx_hook(s, size))
|
||||
{
|
||||
/* We need to be careful since the socket could have been deleted by the hook */
|
||||
|
@ -566,7 +566,6 @@ static void
|
||||
yi_init_unix(uid_t use_uid, gid_t use_gid)
|
||||
{
|
||||
sock *s;
|
||||
log("yi_init_unix before");
|
||||
yi_init();
|
||||
s = yi_sk = sk_new(yi_pool);
|
||||
s->type = SK_UNIX_PASSIVE;
|
||||
@ -575,7 +574,6 @@ yi_init_unix(uid_t use_uid, gid_t use_gid)
|
||||
s->rbsize = 1024;
|
||||
s->tbsize = 16384;
|
||||
s->fast_rx = 1;
|
||||
log("yi_init_unix after set");
|
||||
/* Return value intentionally ignored */
|
||||
unlink(path_control_socket_yi);
|
||||
|
||||
@ -588,7 +586,14 @@ yi_init_unix(uid_t use_uid, gid_t use_gid)
|
||||
|
||||
if (chmod(path_control_socket_yi, 0660) < 0)
|
||||
die("chmod: %m");
|
||||
log("yi_init_unix after fc");
|
||||
|
||||
FILE *write_ptr; // this block is for testing purposes and should be deleted
|
||||
write_ptr = fopen("in.cbor", "wb");
|
||||
fwrite("mem", 3, 1, write_ptr);
|
||||
fclose(write_ptr);
|
||||
write_ptr = fopen("out.cbor", "wb");
|
||||
fwrite("", 0, 1, write_ptr);
|
||||
fclose(write_ptr);
|
||||
}
|
||||
|
||||
|
||||
|
1
yang/command.cbor
Normal file
1
yang/command.cbor
Normal file
@ -0,0 +1 @@
|
||||
¡jcommand:do¢gcommanddargs€
|
2
yang/command.json
Normal file
2
yang/command.json
Normal file
@ -0,0 +1,2 @@
|
||||
{"command:do":{"command": 1, "args":[]}}
|
||||
|
19
yang/command.yang
Normal file
19
yang/command.yang
Normal file
@ -0,0 +1,19 @@
|
||||
module command {
|
||||
|
||||
namespace ".";
|
||||
|
||||
prefix "command";
|
||||
|
||||
container do {
|
||||
leaf command {
|
||||
mandatory true;
|
||||
type uint32;
|
||||
}
|
||||
list args {
|
||||
key "arg";
|
||||
leaf arg {
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,12 @@
|
||||
"namespace": "https://bird.nic.cz/yang/v2.15/cli-debug",
|
||||
"revision": "",
|
||||
"conformance-type": "implement"
|
||||
},
|
||||
{
|
||||
"name": "command",
|
||||
"namespace": "https://bird.nic.cz/yang/v2.15/cli-debug",
|
||||
"revision": "",
|
||||
"conformance-type": "implement"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user