0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

cbor_cmds.c, ospf_for_cbor.c: ospf show topology looks working

This commit is contained in:
Katerina Kubecova 2023-12-01 14:43:24 +01:00
parent c27d43bf4c
commit 5a079e8eae
11 changed files with 817 additions and 57 deletions

View File

@ -81,6 +81,15 @@ void cbor_add_string(struct cbor_writer *writer, const char *string)
writer->pt+=length; writer->pt+=length;
} }
void cbor_nonterminated_string(struct cbor_writer *writer, const char *string, uint length)
{
int length = strlen(string);
write_item(writer, 3, length); // 3 is major, then goes length of string and string
check_memory(writer, length);
memcpy(writer->cbor+writer->pt, string, length);
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, int num)
{ {
major = major<<5; major = major<<5;

View File

@ -1,4 +1,4 @@
#include "nest/cbor_shortcuts.c"
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/route.h" #include "nest/route.h"
@ -6,15 +6,11 @@
#include "conf/conf.h" #include "conf/conf.h"
#include "lib/string.h" #include "lib/string.h"
#include "filter/filter.h" #include "filter/filter.h"
#include "nest/cbor_cmds.h"
#include "proto/ospf/ospf_for_cbor.c"
struct cbor_show_data { uint compare_str(byte *str1, uint length, const char *str2) {
int type; /* Symbols type to show */
int name_length;
char *name;
};
uint compare_str(byte *str1, uint length, char *str2) {
if (length != strlen(str2)) { if (length != strlen(str2)) {
return 0; return 0;
} }
@ -32,10 +28,10 @@ extern pool *rta_pool;
extern uint *pages_kept; extern uint *pages_kept;
uint uint
cmd_show_memory_cbor(byte *tbuf, uint capacity) cmd_show_memory_cbor(byte *tbuf, uint capacity, struct linpool *lp)
{ {
log("in cmd_show_memory_cbor"); log("in cmd_show_memory_cbor");
struct cbor_writer *w = cbor_init(tbuf, capacity, lp_new(proto_pool)); struct cbor_writer *w = cbor_init(tbuf, capacity, lp);
cbor_open_block_with_length(w, 1); cbor_open_block_with_length(w, 1);
cbor_add_string(w, "show_memory:message"); cbor_add_string(w, "show_memory:message");
@ -75,9 +71,9 @@ extern int shutting_down;
extern int configuring; extern int configuring;
uint uint
cmd_show_status_cbor(byte *tbuf, uint capacity) cmd_show_status_cbor(byte *tbuf, uint capacity, struct linpool *lp)
{ {
struct cbor_writer *w = cbor_init(tbuf, capacity, lp_new(proto_pool)); struct cbor_writer *w = cbor_init(tbuf, capacity, lp);
cbor_open_block_with_length(w, 1); cbor_open_block_with_length(w, 1);
cbor_add_string(w, "show_status:message"); cbor_add_string(w, "show_status:message");
@ -112,15 +108,35 @@ cmd_show_status_cbor(byte *tbuf, uint capacity)
return w->pt; return w->pt;
} }
int int parse_show_symbols_arg(struct argument *argument)
cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct cbor_show_data show)
{ {
struct cbor_writer *w = cbor_init(tbuf, capacity, lp_new(proto_pool)); char *params[] = {"table", "filter", "function", "protocol", "template"};
int param_vals[] = {SYM_TABLE, SYM_FILTER, SYM_FUNCTION, SYM_PROTO, SYM_TEMPLATE}; // defined in conf.h
for (size_t j = 0; j < sizeof(params)/sizeof(char*); j++)
{
if (compare_str(argument->arg, argument->len, params[j]))
{
return param_vals[j];
}
}
return -1;
}
uint
cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct arg_list *args, struct linpool *lp)
{
struct cbor_writer *w = cbor_init(tbuf, capacity, lp);
cbor_open_block_with_length(w, 1); cbor_open_block_with_length(w, 1);
cbor_add_string(w, "show_symbols:message"); cbor_add_string(w, "show_symbols:message");
cbor_open_block_with_length(w, 1); cbor_open_block_with_length(w, 1);
if (show.type == -1) int show_type = SYM_VOID;
if (args->pt > 0)
{
show_type = parse_show_symbols_arg(&args->args[args->pt - 1]); // Takes just the last one argument. Current bird cli answers only last argument too, but can fail on previous.
}
if (show_type == -1)
{ {
cbor_add_string(w, "table"); cbor_add_string(w, "table");
cbor_open_list_with_length(w, 1); cbor_open_list_with_length(w, 1);
@ -130,16 +146,16 @@ cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct cbor_show_data show)
{ {
HASH_WALK(scope->hash, next, sym) HASH_WALK(scope->hash, next, sym)
{ {
if (compare_str(show.name, show.name_length, sym->name)) if (compare_str(args->args[args->pt - 1].arg, args->args[args->pt - 1].len, sym->name))
{ {
cbor_string_string(w, "name", show.name); cbor_string_string(w, "name", args->args[args->pt - 1].arg);
cbor_string_string(w, "type", cf_symbol_class_name(sym)); cbor_string_string(w, "type", cf_symbol_class_name(sym));
return w->pt; return w->pt;
} }
} }
HASH_WALK_END; HASH_WALK_END;
} }
cbor_string_string(w, "name", show.name); cbor_string_string(w, "name", args->args[args->pt - 1].arg);
cbor_string_string(w, "type", "symbol not known"); cbor_string_string(w, "type", "symbol not known");
return w->pt; return w->pt;
} }
@ -154,7 +170,7 @@ cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct cbor_show_data show)
if (!sym->scope->active) if (!sym->scope->active)
continue; continue;
if (show.type != SYM_VOID && (sym->class != show.type)) if (show_type != SYM_VOID && (sym->class != show_type))
continue; continue;
cbor_open_block_with_length(w, 2); cbor_open_block_with_length(w, 2);
@ -169,5 +185,91 @@ cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct cbor_show_data show)
} }
struct proto *
cbor_get_proto_type(enum protocol_class proto_type, struct cbor_writer *w)
{
log("in type");
struct proto *p, *q;
p = NULL;
WALK_LIST(q, proto_list)
if ((q->proto->class == proto_type) && (q->proto_state != PS_DOWN))
{
if (p)
{
cbor_string_string(w, "error", "multiple protocols running");
return NULL;
}
p = q;
}
if (!p)
{
cbor_string_string(w, "error", "no such protocols running");
return NULL;
}
return p;
}
struct proto *
cbor_get_proto_name(struct argument *arg, enum protocol_class proto_type, struct cbor_writer *w)
{
log("in name");
struct proto *q;
WALK_LIST(q, proto_list)
{
log("%s %s %i %i %i", arg->arg, q->name, compare_str(arg->arg, arg->len, q->name) , (q->proto_state != PS_DOWN) , (q->proto->class == proto_type));
if (compare_str(arg->arg, arg->len, q->name) && (q->proto_state != PS_DOWN) && (q->proto->class == proto_type))
{
return q;
}
}
cbor_add_string(w, "not found");
cbor_nonterminated_string(w, arg->arg, arg->len);
return NULL;
}
uint
cmd_show_ospf_cbor(byte *tbuf, uint capacity, struct arg_list *args, struct linpool *lp)
{
log("in ospf args %i, pt %i", args, args->pt);
struct cbor_writer *w = cbor_init(tbuf, capacity, lp);
cbor_open_block_with_length(w, 1);
cbor_add_string(w, "show_ospf:message");
if (args->pt == 0)
{
cbor_open_block_with_length(w, 1);
cbor_string_string(w, "not implemented", "show everything about ospf");
return w->pt;
}
if (compare_str(args->args[0].arg, args->args[0].len, "topology"))
{
cbor_open_block(w);
struct proto *proto;
int all_ospf = (args->pt > 1) && compare_str(args->args[1].arg, args->args[1].len, "all");
if (args->pt - all_ospf > 1) // if there is protocol name
{
proto = cbor_get_proto_name(&args->args[args->pt -1], PROTOCOL_OSPF, w);
}
else {
proto = cbor_get_proto_type(PROTOCOL_OSPF, w);
}
if (proto == NULL)
{
cbor_close_block_or_list(w);
return w->pt;
}
ospf_sh_state_cbor(w, proto, 0, all_ospf);
cbor_close_block_or_list(w);
return w->pt;
} else {
cbor_open_block_with_length(w, 1);
cbor_add_string(w, "not implemented");
cbor_nonterminated_string(w, args->args[0].arg, args->args[0].len);
return w->pt;
}
}

18
nest/cbor_cmds.h Normal file
View File

@ -0,0 +1,18 @@
struct argument {
char *arg;
uint len;
};
struct arg_list {
struct argument *args;
int capacity;
int pt;
struct linpool *lp;
};
uint cmd_show_memory_cbor(byte *tbuf, uint capacity, struct linpool *lp);
uint cmd_show_status_cbor(byte *tbuf, uint capacity, struct linpool *lp);
uint cmd_show_symbols_cbor(byte *tbuf, uint capacity, struct arg_list *args, struct linpool *lp);

View File

@ -4,6 +4,7 @@ enum functions {
SHOW_STATUS = 0, SHOW_STATUS = 0,
SHOW_MEMORY = 1, SHOW_MEMORY = 1,
SHOW_SYMBOLS = 2, SHOW_SYMBOLS = 2,
SHOW_OSPF = 3,
}; };
enum cbor_majors { enum cbor_majors {
@ -29,6 +30,7 @@ struct buff_reader {
uint size; uint size;
}; };
uint compare_buff_str(struct buff_reader *buf_read, uint length, char *string) { uint compare_buff_str(struct buff_reader *buf_read, uint length, char *string) {
if (length != strlen(string)) { if (length != strlen(string)) {
return 0; return 0;
@ -39,7 +41,7 @@ uint compare_buff_str(struct buff_reader *buf_read, uint length, char *string) {
} }
} }
return 1; return 1;
} };
struct value struct value
get_value(struct buff_reader *reader) get_value(struct buff_reader *reader)
@ -105,16 +107,15 @@ void skip_optional_args(struct buff_reader *rbuf_read, int items_in_block)
} }
} }
void parse_show_symbols_args(struct buff_reader *rbuf_read, int items_in_block, struct cbor_show_data *arg) struct arg_list *parse_args(struct buff_reader *rbuf_read, int items_in_block, struct linpool *lp)
{ {
log("parse symbols args"); // We are in opened block, which could be empty or contain arguments <"args":[{"arg":"string"}]>
char *params[] = {"table", "filter", "function", "protocol", "template"}; struct arg_list *arguments = (struct arg_list*)lp_alloc(lp, sizeof(struct arg_list));
int param_vals[] = {SYM_TABLE, SYM_FILTER, SYM_FUNCTION, SYM_PROTO, SYM_TEMPLATE}; // defined in conf.h arguments->capacity = 0;
arg->type = SYM_VOID; // default option arguments->pt = 0;
arg->name = NULL;
if (items_in_block == 0) if (items_in_block == 0)
{ // there should not be arg array { // there should not be arg array
return; return arguments;
} }
struct value val = get_value(rbuf_read); struct value val = get_value(rbuf_read);
if (val.major == TEXT) if (val.major == TEXT)
@ -127,13 +128,24 @@ void parse_show_symbols_args(struct buff_reader *rbuf_read, int items_in_block,
ASSERT(val.major == ARRAY); ASSERT(val.major == ARRAY);
int num_array_items = val.val; int num_array_items = val.val;
log("num arr items %i", num_array_items); log("num arr items %i", num_array_items);
for (int i = 0; i<num_array_items || (num_array_items == -1 && !val_is_break(val)); i++) if (num_array_items > 0)
{
arguments->args = (struct argument*)lp_alloc(lp, sizeof(struct argument) * num_array_items);
arguments->capacity = num_array_items;
}
else if (num_array_items == -1)
{
arguments->args = (struct argument*)lp_alloc(lp, sizeof(struct argument) * 4);
arguments->capacity = 4;
}
for (int i = 0; i < num_array_items || num_array_items == -1; i++)
{ {
// There will be only one argument in struct cbor_show_data arg after parsing the array of args. Current bird cli is behaving this way too. // There will be only one argument in struct cbor_show_data arg after parsing the array of args. Current bird cli is behaving this way too.
val = get_value(rbuf_read); val = get_value(rbuf_read);
if (val_is_break(val)) if (val_is_break(val))
{ {
rbuf_read->pt--; rbuf_read->pt--;
return arguments;
} }
else if (val.major == BLOCK) else if (val.major == BLOCK)
{ {
@ -145,24 +157,20 @@ void parse_show_symbols_args(struct buff_reader *rbuf_read, int items_in_block,
val = get_value(rbuf_read); val = get_value(rbuf_read);
ASSERT(compare_buff_str(rbuf_read, val.val, "arg")); ASSERT(compare_buff_str(rbuf_read, val.val, "arg"));
rbuf_read->pt+=val.val; rbuf_read->pt+=val.val;
val = get_value(rbuf_read); val = get_value(rbuf_read);
ASSERT(val.major == TEXT); ASSERT(val.major == TEXT); // Now we have an argument in val
int found = 0; if (num_array_items == -1 && arguments->capacity == arguments->pt)
for (size_t j = 0; j < sizeof(params)/sizeof(char*) && found == 0; j++)
{ {
if (compare_buff_str(rbuf_read, val.val, params[j])) struct argument *a = arguments->args;
{ arguments->args = (struct argument*)lp_alloc(lp, sizeof(struct argument) * 2 * arguments->capacity);
arg->type = param_vals[j]; arguments->capacity = 2 * arguments->capacity;
found = 1; memcpy(arguments->args, a, sizeof(struct argument) * arguments->pt);
log("found %s, on %i val %i", params[j], j, param_vals[j]);
}
}
if (found == 0)
{
arg->type = -1;
arg->name = rbuf_read->buff + rbuf_read->pt;
arg->name_length = val.val;
} }
arguments->args[arguments->pt].arg = rbuf_read->buff + rbuf_read->pt; // pointer to actual position in rbuf_read buffer
arguments->args[arguments->pt].len = val.val;
arguments->pt++;
rbuf_read->pt+=val.val; rbuf_read->pt+=val.val;
if (wait_close) if (wait_close)
{ {
@ -177,28 +185,34 @@ void parse_show_symbols_args(struct buff_reader *rbuf_read, int items_in_block,
} }
} else } else
{ {
ASSERT(items_in_block == -1); // assert the block was not open to exact num of items, because it cant be just for command (we would returned) and we did not find more items. ASSERT(items_in_block == -1); // assert the block was not open to exact num of items, because it cant be just for command (we would returned) and we did not found more items.
rbuf_read->pt--; // we read one byte from future, we need to shift pointer back rbuf_read->pt--; // we read one byte from future, we need to shift pointer back
} }
return arguments;
} }
uint uint
do_command(struct buff_reader *rbuf_read, struct buff_reader *tbuf_read, int items_in_block) do_command(struct buff_reader *rbuf_read, struct buff_reader *tbuf_read, int items_in_block, struct linpool *lp)
{ {
struct value val = get_value(rbuf_read); struct value val = get_value(rbuf_read);
ASSERT(val.major == UINT); ASSERT(val.major == UINT);
struct arg_list * args;
switch (val.val) switch (val.val)
{ {
case SHOW_MEMORY: case SHOW_MEMORY:
skip_optional_args(rbuf_read, items_in_block); skip_optional_args(rbuf_read, items_in_block);
return cmd_show_memory_cbor(tbuf_read->buff, tbuf_read->size); return cmd_show_memory_cbor(tbuf_read->buff, tbuf_read->size, lp);
case SHOW_STATUS: case SHOW_STATUS:
skip_optional_args(rbuf_read, items_in_block); skip_optional_args(rbuf_read, items_in_block);
return cmd_show_status_cbor(tbuf_read->buff, tbuf_read->size); return cmd_show_status_cbor(tbuf_read->buff, tbuf_read->size, lp);
case SHOW_SYMBOLS: case SHOW_SYMBOLS:
struct cbor_show_data arg; args = parse_args(rbuf_read, items_in_block, lp);
parse_show_symbols_args(rbuf_read, items_in_block, &arg); return cmd_show_symbols_cbor(tbuf_read->buff, tbuf_read->size, args, lp);
return cmd_show_symbols_cbor(tbuf_read->buff, tbuf_read->size, arg); case SHOW_OSPF:
args = parse_args(rbuf_read, items_in_block, lp);
log("args %i, pt %i", args, args->pt);
return cmd_show_ospf_cbor(tbuf_read->buff, tbuf_read->size, args, lp);
return 0;
default: default:
return 0; return 0;
} }
@ -206,7 +220,7 @@ do_command(struct buff_reader *rbuf_read, struct buff_reader *tbuf_read, int ite
uint uint
parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize) parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize, struct linpool* lp)
{ {
log("cbor parse"); log("cbor parse");
struct buff_reader rbuf_read; struct buff_reader rbuf_read;
@ -246,7 +260,7 @@ parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize)
ASSERT(compare_buff_str(&rbuf_read, val.val, "command")); ASSERT(compare_buff_str(&rbuf_read, val.val, "command"));
rbuf_read.pt+=val.val; rbuf_read.pt+=val.val;
tbuf_read.pt = do_command(&rbuf_read, &tbuf_read, items_in_block); tbuf_read.pt = do_command(&rbuf_read, &tbuf_read, items_in_block, lp);
if (items_in_block == -1) if (items_in_block == -1)
{ {
val = get_value(&rbuf_read); val = get_value(&rbuf_read);

View File

@ -338,7 +338,7 @@ cli_kick(cli *c)
uint uint
yi_process(uint size, byte *rbuf, byte *tbuf, uint tbsize) { yi_process(uint size, byte *rbuf, byte *tbuf, uint tbsize) {
return parse_cbor(size, rbuf, tbuf, tbsize); return parse_cbor(size, rbuf, tbuf, tbsize, lp_new(yi_pool));
} }
static list cli_log_hooks; static list cli_log_hooks;

View File

@ -2382,6 +2382,12 @@ proto_get_named(struct symbol *sym, struct protocol *pr)
return p; return p;
} }
list
get_protolist_for_cbor(void)
{
return proto_list;
}
struct proto * struct proto *
proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old) proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old)
{ {

View File

@ -300,6 +300,7 @@ void proto_cmd_mrtdump(struct proto *, uintptr_t, int);
void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), int restricted, uintptr_t arg); void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), int restricted, uintptr_t arg);
struct proto *proto_get_named(struct symbol *, struct protocol *); struct proto *proto_get_named(struct symbol *, struct protocol *);
list get_protolist_for_cbor(void);
struct proto *proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old); struct proto *proto_iterate_named(struct symbol *sym, struct protocol *proto, struct proto *old);
#define PROTO_WALK_CMD(sym,pr,p) for(struct proto *p = NULL; p = proto_iterate_named(sym, pr, p); ) #define PROTO_WALK_CMD(sym,pr,p) for(struct proto *p = NULL; p = proto_iterate_named(sym, pr, p); )

610
proto/ospf/ospf_for_cbor.c Normal file
View File

@ -0,0 +1,610 @@
/**
* There are cli functions from ospf.c adapted for cbor.
*/
#include <stdlib.h>
#include "ospf.h"
#include "nest/cbor_shortcuts.c"
static inline void
show_lsa_distance_cbor(struct cbor_writer *w, struct top_hash_entry *he)
{
if (he->color == INSPF)
cbor_string_int(w, "distance", he->dist);
else
cbor_string_string(w, "distance", "unreachable");
}
static inline void
show_lsa_router_cbor(struct cbor_writer *w, struct ospf_proto *p, struct top_hash_entry *he, int verbose)
{
struct ospf_lsa_rt_walk rtl;
cbor_add_string(w, "lsa_router");
cbor_open_block(w);
cbor_string_int(w, "router", he->lsa.rt);
show_lsa_distance_cbor(w, he);
cbor_add_string(w, "vlink");
cbor_open_list(w);
lsa_walk_rt_init(p, he, &rtl);
while (lsa_walk_rt(&rtl))
{
if (rtl.type == LSART_VLNK)
{
cbor_open_block_with_length(w, 2);
cbor_string_int(w, "vlink", rtl.id);
cbor_string_int(w, "metric", rtl.metric);
}
}
cbor_close_block_or_list(w);
cbor_add_string(w, "router_metric");
cbor_open_list(w);
lsa_walk_rt_init(p, he, &rtl);
while (lsa_walk_rt(&rtl))
{
if (rtl.type == LSART_PTP)
{
cbor_open_block_with_length(w, 2);
cbor_string_int(w, "router", rtl.id);
cbor_string_int(w, "metric", rtl.metric);
}
}
cbor_close_block_or_list(w);
cbor_add_string(w, "network");
cbor_open_list(w);
lsa_walk_rt_init(p, he, &rtl);
while (lsa_walk_rt(&rtl))
{
if (rtl.type == LSART_NET)
{
if (ospf_is_v2(p))
{
/* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
struct top_hash_entry *net_he = ospf_hash_find_net2(p->gr, he->domain, rtl.id);
if (net_he && (net_he->lsa.age < LSA_MAXAGE))
{
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_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_string_int(w, "network", rtl.id);
cbor_string_int(w, "metric", rtl.metric);
}
}
else
{
cbor_open_block_with_length(w, 3);
cbor_string_int(w, "network", rtl.id);
cbor_string_int(w, "nif", rtl.nif);
cbor_string_int(w, "metric", rtl.metric);
}
}
}
cbor_close_block_or_list(w);
if (ospf_is_v2(p) && verbose)
{
cbor_add_string(w, "stubnet");
cbor_open_list(w);
lsa_walk_rt_init(p, he, &rtl);
while (lsa_walk_rt(&rtl))
{
if (rtl.type == LSART_STUB)
{
cbor_open_block_with_length(w, 3);
cbor_string_int(w, "stubnet", rtl.id);
cbor_string_int(w, "len", u32_masklen(rtl.data));
cbor_string_int(w, "metric", rtl.metric);
}
}
cbor_close_block_or_list(w);
}
cbor_close_block_or_list(w);
}
static inline void
show_lsa_network_cbor(struct cbor_writer *w, struct top_hash_entry *he, int ospf2)
{
cbor_add_string(w, "lsa_network");
cbor_open_block_with_length(w, 3);
struct ospf_lsa_header *lsa = &(he->lsa);
struct ospf_lsa_net *ln = he->lsa_body;
u32 i;
if (ospf2)
{
cbor_add_string(w, "ospf2");
cbor_open_block_with_length(w, 3);
cbor_string_int(w, "network", lsa->id & ln->optx);
cbor_string_int(w, "optx", u32_masklen(ln->optx));
cbor_string_int(w, "dr", lsa->rt);
}
else
{
cbor_add_string(w, "ospf");
cbor_open_block_with_length(w, 2);
cbor_string_int(w, "network", lsa->rt);
cbor_string_int(w, "lsa_id", lsa->id);
}
show_lsa_distance_cbor(w, he);
cbor_add_string(w, "routers");
cbor_open_list(w);
for (i = 0; i < lsa_net_count(lsa); i++)
cbor_string_int(w, "router", ln->routers[i]);
cbor_close_block_or_list(w);
}
static inline void
show_lsa_sum_net_cbor(struct cbor_writer *w, struct top_hash_entry *he, int ospf2, int af)
{
char str[IPA_MAX_TEXT_LENGTH + 8] = "";
net_addr net;
u8 pxopts;
u32 metric;
lsa_parse_sum_net(he, ospf2, af, &net, &pxopts, &metric);
cbor_add_string(w, "lsa_sum_net");
cbor_open_block_with_length(w, 2);
bsprintf(str, "%N", &net);
cbor_string_string(w, "net", str);
cbor_string_int(w, "metric", metric);
}
static inline void
show_lsa_sum_rt_cbor(struct cbor_writer *w, struct top_hash_entry *he, int ospf2)
{
u32 metric;
u32 dst_rid;
u32 options;
lsa_parse_sum_rt(he, ospf2, &dst_rid, &metric, &options);
cbor_add_string(w, "lsa_sum_rt");
cbor_open_block_with_length(w, 2);
cbor_string_int(w, "router", dst_rid);
cbor_string_int(w, "metric", metric);
}
static inline void
show_lsa_external_cbor(struct cbor_writer *w, struct top_hash_entry *he, int ospf2, int af)
{
struct ospf_lsa_ext_local rt;
char str[IPA_MAX_TEXT_LENGTH + 8] = "";
cbor_add_string(w, "lsa_external");
cbor_open_block(w);
if (he->lsa_type == LSA_T_EXT)
he->domain = 0; /* Unmark the LSA */
lsa_parse_ext(he, ospf2, af, &rt);
if (rt.fbit)
{
bsprintf(str, "%N", rt.fwaddr);
cbor_string_string(w, "via", str);
}
if (rt.tag)
cbor_string_int(w, "tag", rt.tag);
if (he->lsa_type == LSA_T_NSSA)
{
cbor_string_string(w, "lsa_type", "nssa-ext");
} else {
cbor_string_string(w, "lsa_type", "external");
}
bsprintf(str, "%N", rt.net);
cbor_string_string(w, "rt_net", str);
if(rt.ebit)
{
cbor_string_int(w, "lsa_type", 2);
}
cbor_string_int(w, "metric", rt.metric);
cbor_close_block_or_list(w);
}
static inline void
show_lsa_prefix_cbor(struct cbor_writer *w, struct top_hash_entry *he, struct top_hash_entry *cnode, int af)
{
struct ospf_lsa_prefix *px = he->lsa_body;
u32 *buf;
int i;
cbor_add_string(w, "lsa_prefix");
cbor_open_block(w);
/* We check whether given prefix-LSA is related to the current node */
if ((px->ref_type != cnode->lsa.type_raw) || (px->ref_rt != cnode->lsa.rt))
{
cbor_close_block_or_list(w);
return;
}
if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
{
cbor_close_block_or_list(w);
return;
}
if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->lsa.id))
{
cbor_close_block_or_list(w);
return;
}
buf = px->rest;
cbor_add_string(w, "prexixes");
cbor_open_list(w);
char str[IPA_MAX_TEXT_LENGTH + 8] = "";
for (i = 0; i < px->pxcount; i++)
{
net_addr net;
u8 pxopts;
u16 metric;
cbor_open_block(w);
buf = ospf3_get_prefix(buf, af, &net, &pxopts, &metric);
if (px->ref_type == LSA_T_RT)
{
bsprintf(str, "%N", &net);
cbor_string_string(w, "stubnet", str);
cbor_string_int(w, "metric", metric);
}
else{
bsprintf(str, "%N", &net);
cbor_string_string(w, "stubnet", str);
}
cbor_close_block_or_list(w);
}
cbor_close_block_or_list(w);
cbor_close_block_or_list(w);
}
static struct ospf_lsa_header *
fake_lsa_from_prefix_lsa_cbor(struct ospf_lsa_header *dst, struct ospf_lsa_header *src,
struct ospf_lsa_prefix *px)
{
dst->age = src->age;
dst->type_raw = px->ref_type;
dst->id = px->ref_id;
dst->rt = px->ref_rt;
dst->sn = src->sn;
return dst;
}
static int lsa_compare_ospf3_cbor;
static int
lsa_compare_for_state_cbor(const void *p1, const void *p2)
{
struct top_hash_entry *he1 = * (struct top_hash_entry **) p1;
struct top_hash_entry *he2 = * (struct top_hash_entry **) p2;
struct ospf_lsa_header *lsa1 = &(he1->lsa);
struct ospf_lsa_header *lsa2 = &(he2->lsa);
struct ospf_lsa_header lsatmp1, lsatmp2;
u16 lsa1_type = he1->lsa_type;
u16 lsa2_type = he2->lsa_type;
if (he1->domain < he2->domain)
return -1;
if (he1->domain > he2->domain)
return 1;
/* px1 or px2 assumes OSPFv3 */
int px1 = (lsa1_type == LSA_T_PREFIX);
int px2 = (lsa2_type == LSA_T_PREFIX);
if (px1)
{
lsa1 = fake_lsa_from_prefix_lsa_cbor(&lsatmp1, lsa1, he1->lsa_body);
lsa1_type = lsa1->type_raw; /* FIXME: handle unknown ref_type */
}
if (px2)
{
lsa2 = fake_lsa_from_prefix_lsa_cbor(&lsatmp2, lsa2, he2->lsa_body);
lsa2_type = lsa2->type_raw;
}
int nt1 = (lsa1_type == LSA_T_NET);
int nt2 = (lsa2_type == LSA_T_NET);
if (nt1 != nt2)
return nt1 - nt2;
if (nt1)
{
/* In OSPFv3, networks are named based on ID of DR */
if (lsa_compare_ospf3_cbor)
{
if (lsa1->rt < lsa2->rt)
return -1;
if (lsa1->rt > lsa2->rt)
return 1;
}
/* For OSPFv2, this is IP of the network,
for OSPFv3, this is interface ID */
if (lsa1->id < lsa2->id)
return -1;
if (lsa1->id > lsa2->id)
return 1;
if (px1 != px2)
return px1 - px2;
return lsa1->sn - lsa2->sn;
}
else
{
if (lsa1->rt < lsa2->rt)
return -1;
if (lsa1->rt > lsa2->rt)
return 1;
if (lsa1_type < lsa2_type)
return -1;
if (lsa1_type > lsa2_type)
return 1;
if (lsa1->id < lsa2->id)
return -1;
if (lsa1->id > lsa2->id)
return 1;
if (px1 != px2)
return px1 - px2;
return lsa1->sn - lsa2->sn;
}
}
static int
ext_compare_for_state_cbor(const void *p1, const void *p2)
{
struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
struct ospf_lsa_header *lsa1 = &(he1->lsa);
struct ospf_lsa_header *lsa2 = &(he2->lsa);
if (lsa1->rt < lsa2->rt)
return -1;
if (lsa1->rt > lsa2->rt)
return 1;
if (lsa1->id < lsa2->id)
return -1;
if (lsa1->id > lsa2->id)
return 1;
return lsa1->sn - lsa2->sn;
}
void
ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reachable)
{
log("in ospf_state");
struct ospf_proto *p = (struct ospf_proto *) P;
int ospf2 = ospf_is_v2(p);
int af = ospf_get_af(p);
uint i, ix, j1, jx;
u32 last_area = 0xFFFFFFFF;
if (p->p.proto_state != PS_UP)
{
cbor_string_string(w, "error", "protocol is not up");
return;
}
/* We store interesting area-scoped LSAs in array hea and
global-scoped (LSA_T_EXT) LSAs in array hex */
uint num = p->gr->hash_entries;
struct top_hash_entry *hea[num];
struct top_hash_entry **hex = verbose ? alloca(num * sizeof(struct top_hash_entry *)) : NULL;
struct top_hash_entry *he;
struct top_hash_entry *cnode = NULL;
j1 = jx = 0;
WALK_SLIST(he, p->lsal)
{
int accept;
if (he->lsa.age == LSA_MAXAGE)
continue;
switch (he->lsa_type)
{
case LSA_T_RT:
case LSA_T_NET:
accept = 1;
break;
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_NSSA:
case LSA_T_PREFIX:
accept = verbose;
break;
case LSA_T_EXT:
if (verbose)
{
he->domain = 1; /* Abuse domain field to mark the LSA */
hex[jx++] = he;
}
/* fallthrough */
default:
accept = 0;
}
if (accept)
hea[j1++] = he;
}
ASSERT(j1 <= num && jx <= num);
lsa_compare_ospf3_cbor = !ospf2;
qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state_cbor);
if (verbose)
qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state_cbor);
/*
* This code is a bit tricky, we have a primary LSAs (router and
* network) that are presented as a node, and secondary LSAs that
* are presented as a part of a primary node. cnode represents an
* currently opened node (whose header was presented). The LSAs are
* sorted to get secondary LSAs just after related primary LSA (if
* available). We present secondary LSAs only when related primary
* LSA is opened.
*
* AS-external LSAs are stored separately as they might be presented
* several times (for each area when related ASBR is opened). When
* the node is closed, related external routes are presented. We
* also have to take into account that in OSPFv3, there might be
* more router-LSAs and only the first should be considered as a
* primary. This is handled by not closing old router-LSA when next
* one is processed (which is not opened because there is already
* one opened).
*/
cbor_add_string(w, "areas");
cbor_open_list_with_length(w, j1);
ix = 0;
for (i = 0; i < j1; i++)
{
cbor_open_block(w);
he = hea[i];
/* If there is no opened node, we open the LSA (if appropriate) or skip to the next one */
if (!cnode)
{
if (((he->lsa_type == LSA_T_RT) || (he->lsa_type == LSA_T_NET))
&& ((he->color == INSPF) || !reachable))
{
cnode = he;
if (he->domain != last_area)
{
cbor_string_int(w, "area", he->domain);
last_area = he->domain;
ix = 0;
}
}
else
continue;
}
ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->lsa.rt));
switch (he->lsa_type)
{
case LSA_T_RT:
if (he->lsa.id == cnode->lsa.id)
show_lsa_router_cbor(w, p, he, verbose);
break;
case LSA_T_NET:
show_lsa_network_cbor(w, he, ospf2);
break;
case LSA_T_SUM_NET:
if (cnode->lsa_type == LSA_T_RT)
show_lsa_sum_net_cbor(w, he, ospf2, af);
break;
case LSA_T_SUM_RT:
if (cnode->lsa_type == LSA_T_RT)
show_lsa_sum_rt_cbor(w, he, ospf2);
break;
case LSA_T_EXT:
case LSA_T_NSSA:
show_lsa_external_cbor(w, he, ospf2, af);
break;
case LSA_T_PREFIX:
show_lsa_prefix_cbor(w, he, cnode, af);
break;
}
/* In these cases, we close the current node */
if ((i+1 == j1)
|| (hea[i+1]->domain != last_area)
|| (hea[i+1]->lsa.rt != cnode->lsa.rt)
|| (hea[i+1]->lsa_type == LSA_T_NET))
{
while ((ix < jx) && (hex[ix]->lsa.rt < cnode->lsa.rt))
ix++;
while ((ix < jx) && (hex[ix]->lsa.rt == cnode->lsa.rt))
show_lsa_external_cbor(w, hex[ix++], ospf2, af);
cnode = NULL;
}
cbor_close_block_or_list(w);
}
int hdr = 0;
u32 last_rt = 0xFFFFFFFF;
cbor_add_string(w, "asbrs");
cbor_open_list(w);
for (ix = 0; ix < jx; ix++)
{
he = hex[ix];
/* If it is still marked, we show it now. */
if (he->domain)
{
cbor_add_string(w, "asbr");
cbor_open_block(w);
he->domain = 0;
if ((he->color != INSPF) && reachable)
continue;
if (!hdr)
{
cbor_add_string(w, "other_ASBRs");
cbor_open_list_with_length(w, 0);
hdr = 1;
}
if (he->lsa.rt != last_rt)
{
cbor_string_int(w, "router", he->lsa.rt);
last_rt = he->lsa.rt;
}
show_lsa_external_cbor(w, he, ospf2, af);
cbor_close_block_or_list(w);
}
}
cbor_close_block_or_list(w);
}

View File

@ -1 +1 @@
¡jcommand:do¢gcommanddargs<67>¡carghprotocol ¡jcommand:do¢gcommanddargs¡carghtopology¡cargeospf6

View File

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

View File

@ -1 +1 @@
ˇtshow_symbols:messageˇetableź˘dnamegebgp4_1dtypehprotocol˘dnamegebgp6_1dtypehprotocol˘dnamegebgp4_2dtypehprotocol˘dnamegebgp6_2dtypehprotocol˘dnamegstatic6dtypehprotocol˘dnamegstatic4dtypehprotocol˘dnamegkernel6dtypehprotocol˘dnamegkernel4dtypehprotocol˘dnamegdevice1dtypehprotocol˙ ¡tshow_symbols:message¡etableŸ¢dnamehips_sitedtypehconstant¢dnamejipt_unspecdtypehconstant¢dnamehipp_xorpdtypehconstant¢dnamehipp_dhcpdtypehconstant¢dnamehipp_birddtypehconstant¢dnamegmaster5dtypemrouting table¢dnamegmaster4dtypemrouting table¢dnamegmaster6dtypemrouting table¢dnamehipp_bootdtypehconstant¢dnamehipt_maindtypehconstant¢dnamehips_linkdtypehconstant¢dnamehipp_isisdtypehconstant¢dnameeospf6dtypehprotocol¢dnameeospf5dtypehprotocol¢dnameeospf4dtypehprotocol¢dnamejips_globaldtypehconstant¢dnamegstatic6dtypehprotocol¢dnamegstatic5dtypehprotocol¢dnamegstatic4dtypehprotocol¢dnamejipp_kerneldtypehconstant¢dnamehips_hostdtypehconstant¢dnamekips_nowheredtypehconstant¢dnamelipp_dnrouteddtypehconstant¢dnamegkernel6dtypehprotocol¢dnamegkernel5dtypehprotocol¢dnamegkernel4dtypehprotocol¢dnamegipp_ntkdtypehconstant¢dnamegipp_mrtdtypehconstant¢dnamejipr_cosmosdtypehconstant¢dnameiipp_babeldtypehconstant¢dnamelipp_redirectdtypehconstant¢dnamenipp_keepaliveddtypehconstant¢dnameiipt_localdtypehconstant¢dnamegipp_bgpdtypehconstant¢dnameiipp_zebradtypehconstant¢dnameiipp_gateddtypehconstant¢dnameiipp_openrdtypehconstant¢dnameiipp_eigrpdtypehconstant¢dnamegipp_ripdtypehconstant¢dnamegdevice1dtypehprotocol¢dnamekipt_defaultdtypehconstant¢dnamejipp_staticdtypehconstant¢dnamefipp_radtypehconstant¢dnamehipp_ospfdtypehconstant¢dnamejipp_unspecdtypehconstantÿ