0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

birdc.py: first complete cbor to cbor commands, cbor saving int64 fix

This commit is contained in:
Katerina Kubecova 2023-12-06 08:40:40 +01:00
parent 0dccbc81d6
commit 78750e197f
14 changed files with 309 additions and 54 deletions

View File

@ -310,6 +310,14 @@ tm_format_time(char *x, struct timeformat *fmt, btime t)
strcpy(x, "<error>");
}
btime
tm_get_real_time(btime t)
{
btime dt = current_time() - t;
btime rt = current_real_time() - dt;
return rt;
}
/* Replace %f in format string with usec scaled to requested precision */
static int
strfusec(char *buf, int size, const char *fmt, uint usec)

View File

@ -125,6 +125,7 @@ struct timeformat {
btime tm_parse_time(const char *x);
void tm_format_time(char *x, struct timeformat *fmt, btime t);
btime tm_get_real_time(btime t);
int tm_format_real_time(char *x, size_t max, const char *fmt, btime t);
#endif

View File

@ -9,7 +9,7 @@ struct cbor_writer {
struct linpool *lp;
};
void write_item(struct cbor_writer *writer, int8_t major, int num);
void write_item(struct cbor_writer *writer, int8_t major, u64 num);
void check_memory(struct cbor_writer *writer, int add_size);
@ -55,7 +55,7 @@ void cbor_open_list_with_length(struct cbor_writer *writer, int length)
}
void cbor_add_int(struct cbor_writer *writer, int item)
void cbor_add_int(struct cbor_writer *writer, int64_t item)
{
if (item >= 0)
{
@ -63,10 +63,15 @@ void cbor_add_int(struct cbor_writer *writer, int item)
}
else
{
write_item(writer, 1, item);
write_item(writer, 1, -item);
}
}
void cbor_add_uint(struct cbor_writer *writer, u64 item)
{
write_item(writer, 0, item);
}
void cbor_add_tag(struct cbor_writer *writer, int item)
{
write_item(writer, 6, item);
@ -89,10 +94,26 @@ void cbor_nonterminated_string(struct cbor_writer *writer, const char *string, u
writer->pt+=length;
}
void write_item(struct cbor_writer *writer, int8_t major, int num)
void write_item(struct cbor_writer *writer, int8_t major, u64 num)
{
major = major<<5;
check_memory(writer, 10);
log("writing %li %lx max for lower %lx ", num, num, ((u64)1<<(4*8))-1);
if (num > ((u64)1<<(4*8))-1)
{ // We need 8 bytes to encode the num
log("loong num");
major += 0x1b; // reserving those bytes
writer->cbor[writer->pt] = major;
writer->pt++;
for (int i = 7; i>=0; i--)
{ // write n-th byte of num
uint8_t to_write = (num>>(i*8)) & 0xff;
log("%x", to_write);
writer->cbor[writer->pt] = to_write;
writer->pt++;
}
return;
}
if (num > (1<<(2*8))-1)
{ // We need 4 bytes to encode the num
major += 0x1a; // reserving those bytes
@ -101,6 +122,7 @@ void write_item(struct cbor_writer *writer, int8_t major, int num)
for (int i = 3; i>=0; i--)
{ // write n-th byte of num
uint8_t to_write = (num>>(i*8)) & 0xff;
log("%x", to_write);
writer->cbor[writer->pt] = to_write;
writer->pt++;
}

View File

@ -22,6 +22,9 @@ uint compare_str(byte *str1, uint length, const char *str2) {
return 1;
}
int64_t preprocess_time(btime t) {
return tm_get_real_time(t) TO_S ;
}
extern pool *rt_table_pool;
extern pool *rta_pool;
@ -73,6 +76,7 @@ extern int configuring;
uint
cmd_show_status_cbor(byte *tbuf, uint capacity, struct linpool *lp)
{
log("show status");
struct cbor_writer *w = cbor_init(tbuf, capacity, lp);
cbor_open_block_with_length(w, 1);
cbor_add_string(w, "show_status:message");
@ -83,11 +87,12 @@ cmd_show_status_cbor(byte *tbuf, uint capacity, struct linpool *lp)
cbor_open_block(w);
cbor_string_int(w, "router_id", config->router_id);
cbor_string_string(w, "hostname", config->hostname);
cbor_string_int(w, "server_time", current_time());
cbor_string_int(w, "last_reboot", boot_time);
cbor_string_int(w, "last_reconfiguration", config->load_time);
cbor_string_int(w, "server_time", preprocess_time(current_time()));
cbor_string_int(w, "last_reboot", preprocess_time(boot_time));
cbor_string_int(w, "last_reconfiguration", preprocess_time(config->load_time));
if (is_gr_active())
{
log("graceful restart");
cbor_add_string(w, "gr_restart");
cbor_open_block_with_length(w, 2);
cbor_string_int(w, "waiting_for_n_channels_to_recover", get_graceful_restart_locks_num());
@ -105,6 +110,7 @@ cmd_show_status_cbor(byte *tbuf, uint capacity, struct linpool *lp)
else
cbor_add_string(w, "Daemon is up and running");
cbor_write_to_file(w, "test.cbor");
log("leaving show status");
return w->pt;
}
@ -148,14 +154,16 @@ cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct arg_list *args, struct l
{
if (compare_str(args->args[args->pt - 1].arg, args->args[args->pt - 1].len, sym->name))
{
cbor_string_string(w, "name", args->args[args->pt - 1].arg);
cbor_add_string(w, "name");
cbor_nonterminated_string(w, args->args[args->pt - 1].arg, args->args[args->pt - 1].len);
cbor_string_string(w, "type", cf_symbol_class_name(sym));
return w->pt;
}
}
HASH_WALK_END;
}
cbor_string_string(w, "name", args->args[args->pt - 1].arg);
cbor_add_string(w, "name");
cbor_nonterminated_string(w, args->args[args->pt - 1].arg, args->args[args->pt - 1].len);
cbor_string_string(w, "type", "symbol not known");
return w->pt;
}

View File

@ -21,7 +21,7 @@ enum cbor_majors {
struct value {
int major;
int val;
int64_t val;
};
struct buff_reader {
@ -49,7 +49,8 @@ get_value(struct buff_reader *reader)
struct value val;
byte *buff = reader->buff;
val.major = buff[reader->pt]>>5;
log("in get value");
log("in get value are zou here?");
log("major is %x", val.major);
int first_byte_val = buff[reader->pt] - (val.major<<5);
if (first_byte_val <=23) {
val.val = first_byte_val;
@ -66,6 +67,12 @@ get_value(struct buff_reader *reader)
{
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 == 0x1b)
{
for(int i = 1; i<=8; i++) {
val.val += buff[reader->pt+i]>>(64-(i*8));
}
reader->pt+=9;
} else if (first_byte_val == 0xff)
{
val.val = -1;

View File

@ -9,11 +9,16 @@ void cbor_string_string(struct cbor_writer *writer, char *key, const char *value
cbor_add_string(writer, value);
}
void cbor_string_int(struct cbor_writer *writer, char *key, int value) {
void cbor_string_int(struct cbor_writer *writer, char *key, int64_t value) {
cbor_add_string(writer, key);
cbor_add_int(writer, value);
}
void cbor_string_uint(struct cbor_writer *writer, char *key, u64 value) {
cbor_add_string(writer, key);
cbor_add_uint(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);

View File

@ -26,7 +26,7 @@ cmd_show_status(void)
cli_msg(-1000, "BIRD " BIRD_VERSION);
tm_format_time(tim, &config->tf_base, current_time());
cli_msg(-1011, "Router ID is %R %i %x", config->router_id, config->router_id, config->router_id);
cli_msg(-1011, "Router ID is %R", config->router_id);
cli_msg(-1011, "Hostname is %s", config->hostname);
cli_msg(-1011, "Current server time is %s", tim);
tm_format_time(tim, &config->tf_base, boot_time);

View File

@ -58,6 +58,7 @@ show_lsa_router_cbor(struct cbor_writer *w, struct ospf_proto *p, struct top_has
cbor_add_string(w, "network");
cbor_open_list(w);
lsa_walk_rt_init(p, he, &rtl);
int dummy_id = 0;
while (lsa_walk_rt(&rtl))
{
if (rtl.type == LSART_NET)
@ -72,26 +73,30 @@ show_lsa_router_cbor(struct cbor_writer *w, struct ospf_proto *p, struct top_has
struct ospf_lsa_header *net_lsa = &(net_he->lsa);
struct ospf_lsa_net *net_ln = net_he->lsa_body;
cbor_open_block_with_length(w, 3);
cbor_open_block_with_length(w, 4);
cbor_string_int(w, "dummy_yang_id", dummy_id);
cbor_string_int(w, "network", net_lsa->id & net_ln->optx);
cbor_string_int(w, "len", u32_masklen(net_ln->optx));
cbor_string_int(w, "metric", rtl.metric);
}
else
{
cbor_open_block_with_length(w, 2);
cbor_open_block_with_length(w, 3);
cbor_string_int(w, "dummy_yang_id", dummy_id);
cbor_string_int(w, "network", rtl.id);
cbor_string_int(w, "metric", rtl.metric);
}
}
else
{
cbor_open_block_with_length(w, 3);
cbor_open_block_with_length(w, 4);
cbor_string_int(w, "dummy_yang_id", dummy_id);
cbor_string_int(w, "network", rtl.id);
cbor_string_int(w, "nif", rtl.nif);
cbor_string_int(w, "metric", rtl.metric);
}
}
dummy_id++;
}
cbor_close_block_or_list(w);
@ -145,7 +150,10 @@ show_lsa_network_cbor(struct cbor_writer *w, struct top_hash_entry *he, int ospf
cbor_add_string(w, "routers");
cbor_open_list(w);
for (i = 0; i < lsa_net_count(lsa); i++)
{
cbor_open_block_with_length(w, 1);
cbor_string_int(w, "router", ln->routers[i]);
}
cbor_close_block_or_list(w);
}
@ -215,7 +223,7 @@ show_lsa_external_cbor(struct cbor_writer *w, struct top_hash_entry *he, int osp
if(rt.ebit)
{
cbor_string_int(w, "lsa_type", 2);
cbor_string_int(w, "lsa_type_num", 2);
}
cbor_string_int(w, "metric", rt.metric);
cbor_close_block_or_list(w);
@ -252,7 +260,7 @@ show_lsa_prefix_cbor(struct cbor_writer *w, struct top_hash_entry *he, struct to
buf = px->rest;
cbor_add_string(w, "prexixes");
cbor_add_string(w, "prefixes");
cbor_open_list(w);
char str[IPA_MAX_TEXT_LENGTH + 8] = "";
for (i = 0; i < px->pxcount; i++)
@ -500,6 +508,7 @@ ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reac
for (i = 0; i < j1; i++)
{
cbor_open_block(w);
cbor_string_int(w, "dummy_yang_id", i);
he = hea[i];
/* If there is no opened node, we open the LSA (if appropriate) or skip to the next one */
@ -580,7 +589,6 @@ ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reac
/* If it is still marked, we show it now. */
if (he->domain)
{
cbor_add_string(w, "asbr");
cbor_open_block(w);
he->domain = 0;

200
yang/birdc.py Normal file
View File

@ -0,0 +1,200 @@
import cbor
import json
import sys
import os
import socket, struct
import datetime
class Command:
num = -1
def addr_to_str(self, addr):
return socket.inet_ntoa(struct.pack('!L', addr))
def print_answer(self, answer):
print(answer)
class Memory(Command):
num = 1
def nums_to_str(self, answer, key):
e = answer["show_memory:message"]["body"][key]["effective"]
o = answer["show_memory:message"]["body"][key]["overhead"]
j_e = " B"
j_o = " B"
if e > 9999:
e = e/1000
j_e = "kB"
if o > 9999:
o = o/1000
j_o = "kB"
return f"{e:>7} {j_e} {o:>7} {j_o}"
def print_answer(self, answer):
print()
print("BIRD memory usage")
keys = answer["show_memory:message"]["body"].keys()
first_column_width = len("route attributes ")
print(" " * (first_column_width+4), "Effective ", "Overhead")
for key in keys:
name = key.replace("_", " ")
print(name,":", " "*(first_column_width - len(name)), self.nums_to_str(answer, key))
class Status(Command):
num = 0
def print_answer(self, answer):
print(answer)
print()
print("BIRD", answer["show_status:message"]["version"])
for key in answer["show_status:message"]["body"].keys():
name = key.replace("_", " ")
if key == "router_id":
print(name, self.addr_to_str( answer["show_status:message"]["body"][key]))
elif key in "server_time last_reboot last_reconfiguration":
print(name, datetime.datetime.fromtimestamp(answer["show_status:message"]["body"][key]))
else:
print(name, answer["show_status:message"]["body"][key])
print(answer["show_status:message"]["state"])
class Symbols(Command):
num = 2
def print_answer(self, answer):
print()
for item in answer["show_symbols:message"]["table"]:
print(f"{item['name']:<15} {item['type']}")
class Ospf(Command):
num = 3
def print_lsa_router(self, area):
print ("\trouter", self.addr_to_str(area['router']))
print("\t\tdistance", area['distance'])
if ('vlink' in area.keys()):
for vlink in area['vlink']:
print(f"\t\tvlink {self.addr_to_str( vlink['vlink'])} metric {vlink['metric']}")
if ('router_metric' in area.keys()):
for router in area['router_metric']:
print(f"\t\trouter {self.addr_to_str( router['router'])} metric {router['metric']}")
for network in area['network']:
addr = self.addr_to_str(network['network'])
if('nif' in network):
print(f"\t\tnetwork [{addr}-{network['nif']}] metric {network['metric']}")
elif('len' in area.keys()):
print(f"\t\tnetwork {addr}/{network['len']} metric {network['metric']}")
else:
print(f"\t\tnetwork [{addr}] metric {network['metric']}")
if ('stubnet' in area.keys()):
for stubnet in area['stubnet']:
print(f"\t\tstubnet {self.addr_to_str(stubnet['stubnet'])}/{stubnet['len']} metric {stubnet['metric']}")
def print_lsa_network(self, area):
if ('ospf2' in area.keys()):
print(f"\tnetwork {self.addr_to_str(area['ospf2']['network'])}/{area['ospf2']['optx']}")
print(f"\t\tdr {self.addr_to_str(area['ospf2']['dr'])}")
elif ('ospf' in area.keys()):
print(f"\tnetwork [{self.addr_to_str(area['ospf']['network'])}-{area['ospf']['lsa_id']}]")
print("\t\tdistance", area['distance'])
for router in area['routers']:
print(f"\t\trouter {self.addr_to_str(router['router'])}")
def print_lsa_sum_net(self, area):
print(f"\t\txnetwork {area['net']} metric {area['metric']}")
def print_lsa_sum_rt(self, area):
print(f"\t\txrouter {self.addr_to_str(area['router'])} metric {area['metric']}")
def print_lsa_external(self, area):
if('lsa_type_num' in area.keys()):
print(f"\t\t{area['lsa_type']} {self.addr_to_str(area['rt_net'])} metric{area[lsa_type_num]} {area['metric']}%s%s")
else:
print(f"\t\t{area['lsa_type']} {self.addr_to_str(area['rt_net'])} metric {area['metric']}{area['via']}{area['tag']}")
def print_lsa_prefix(self, area):
for prefix in area['prefixes']:
if 'metric' in prefix.keys():
print(f"\t\tstubnet {self.addr_to_str(prefix['stubnet'])} metric {prefix['metric']}")
def print_answer(self, answer):
print()
if ("error" in answer["show_ospf:message"].keys()):
print("error: ", answer["show_ospf:message"]["error"])
return
if ("not implemented" in answer["show_ospf:message"].keys()):
print("not implemented: ", answer["show_ospf:message"]["not implemented"])
return
for area in answer["show_ospf:message"]["areas"]:
if 'area' in area.keys():
print ("area", self.addr_to_str(area['area']))
print()
if 'lsa_router' in area.keys():
self.print_lsa_router(area['lsa_router'])
elif 'lsa_network' in area.keys():
self.print_lsa_network(area['lsa_network'])
elif 'lsa_sum_net' in area.keys():
self.print_lsa_sum_net(area['lsa_sum_net'])
elif 'lsa_sum_rt' in area.keys():
self.print_lsa_sum_rt(area['lsa_sum_rt'])
elif 'lsa_external' in area.keys():
self.print_lsa_external(area['lsa_external'])
elif 'lsa_prefix' in area.keys():
self.print_lsa_prefix(area['lsa_prefix'])
if('asbrs' in area.keys()):
for asbr in area['asbrs']:
if('other_ABSRs' in asbr.keys()):
print("other ASBRs")
print("other ASBRs")
print(f"\trouter {self.addr_to_str(asbr['router'])}")
command_dictionary = {"status":0, "memory":1, "symbols":2, "ospf":3}
def get_command_class(string):
if string == "status":
return Status()
if string == "memory":
return Memory()
if string == "symbols":
return Symbols()
if string == "ospf":
return Ospf()
raise Exception(f"Command {string} not known. Expected status, memory, symbols or ospf")
def run_on_machine(dev, cmd):
ws = os.system(f"ip netns exec {dev} {cmd}")
if os.WIFEXITED(ws):
ec = os.WEXITSTATUS(ws)
else:
ec = False
if ec != 0:
raise Exception(f"Command {cmd} exited with exit code {ws}")
arguments = sys.argv
if (len(sys.argv) <= 2):
raise Exception("Expected command, no argunents given.")
if (len(sys.argv) == 3):
raise Exception(f"only one ({sys.argv[2]}) command given, that is not implemented")
if(sys.argv[2] != "show"):
raise Exception(f"Expected 'dev show status/memory/symbols/ospf', unknown {sys.argv[2]}.")
comm = get_command_class(sys.argv[3])
command = {"command:do":{"command":comm.num, "args":[]}}
for i in range (4, len(sys.argv)):
command["command:do"]["args"].append({"arg": sys.argv[i]})
print(command)
with open(os.getcwd()+"/command.cbor", "wb") as of:
cbor.dump(command, of)
run_on_machine(sys.argv[1], f"cat command.cbor | sudo socat UNIX-CONNECT:{os.getcwd()}/bird-yang.ctl STDIO > answer.cbor")
with open("answer.cbor", "br") as cbor_file:
answer = cbor.load(cbor_file)
comm.print_answer(answer)

View File

@ -1 +1 @@
¡jcommand:do¢gcommanddargs¡carghtopology¡cargeospf6
¡jcommand:do¢gcommanddargs„¡cargculg¡cargbui¡cargb76¡cargbkl

View File

@ -1,2 +1,2 @@
{"command:do":{"command": 3, "args":[{"arg":"topology"}, {"arg":"ospf6"}]}}
{"command:do":{"command": 3, "args":[{"arg":"topology"}, {"arg":"ospf4"}]}}

View File

@ -37,9 +37,7 @@ module show_ospf {
leaf vlink {
type int32;
}
leaf metric {
type int32;
}
uses metric;
}
list router_metric {
@ -49,7 +47,10 @@ module show_ospf {
}
list network {
key "network";
key "dummy_yang_id";
leaf dummy_yang_id {
type int32;
}
leaf network {
type int32;
}
@ -148,7 +149,7 @@ module show_ospf {
leaf rt_net {
type string;
}
leaf lsa_type {
leaf lsa_type_num {
type int32;
}
uses metric;
@ -158,20 +159,25 @@ module show_ospf {
grouping lsa_prefix {
container lsa_prefix {
list prefixes {
key "stubnet";
leaf stubnet {
type string;
type int32;
}
uses metric;
}
}
}
container ospf {
container message {
leaf error {
mandatory false;
type string;
}
list areas {
key "dummy_yang_id";
leaf dummy_yang_id {
type int32;
}
leaf area {
type int32;
}
@ -197,31 +203,15 @@ module show_ospf {
}
}
list asbrs {
container asbr {
leaf other_ABSRs {
type none;
}
uses router;
uses lsa_external;
key "router";
leaf other_ABSRs {
type empty;
}
uses router;
uses lsa_external;
}
}
}

View File

@ -35,13 +35,13 @@ module show_status {
type string;
}
leaf server_time {
type int32;
type int64;
}
leaf last_reboot {
type int32;
type int64;
}
leaf last_reconfiguration {
type int32;
type int64;
}
container gr_restart {
leaf waiting_for_n_channels_to_recover {

View File

@ -20,6 +20,12 @@
"revision": "",
"conformance-type": "implement"
},
{
"name": "show_ospf",
"namespace": "https://bird.nic.cz/yang/v2.15/cli-debug",
"revision": "",
"conformance-type": "implement"
},
{
"name": "show_protocols",
"namespace": "https://bird.nic.cz/yang/v2.15/cli-debug",