cbor_string_ipv4(w, "router", he->lsa.rt);
show_lsa_distance_cbor(w, he);
- cbor_add_string(w, "vlink");
+ cbor_add_string(w, "rt");
cbor_open_list(w);
lsa_walk_rt_init(p, he, &rtl);
+
+ int dummy_id = 0;
while (lsa_walk_rt(&rtl))
{
- if (rtl.type == LSART_VLNK)
+ cbor_open_block(w);
+ cbor_string_int(spitw, "dummy_id", i);
+ dummy_id++;
+ cbor_string_int(w, "metric", rtl.metric);
+ switch (rtl.type)
+ case (LSART_VLNK)
{
- cbor_open_block_with_length(w, 2);
+ cbor_add_string(w, "vlink");
+ cbor_open_block_with_length(w, 1);
cbor_string_ipv4(w, "vlink", rtl.id);
- cbor_string_int(w, "metric", rtl.metric);
+ break;
}
- }
- 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)
+
+ case (LSART_PTP)
{
- cbor_open_block_with_length(w, 2);
+ cbor_add_string(w, "router_metric");
+ cbor_open_block_with_length(w, 1);
cbor_string_ipv4(w, "router", rtl.id);
- cbor_string_int(w, "metric", rtl.metric);
+ break;
}
- }
- cbor_close_block_or_list(w);
- 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)
+ case (LSART_NET)
{
+ cbor_add_string(w, "network");
if (ospf_is_v2(p))
{
/* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
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, 4);
- cbor_string_int(w, "dummy_yang_id", dummy_id);
+ cbor_open_block_with_length(w, 2);
cbor_string_ipv4(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, 3);
- cbor_string_int(w, "dummy_yang_id", dummy_id);
+ cbor_open_block_with_length(w, 1);
cbor_string_ipv4(w, "network", rtl.id);
- cbor_string_int(w, "metric", rtl.metric);
}
}
else
{
- cbor_open_block_with_length(w, 4);
- cbor_string_int(w, "dummy_yang_id", dummy_id);
+ cbor_open_block_with_length(w, 2);
cbor_string_ipv4(w, "network", rtl.id);
cbor_string_int(w, "nif", rtl.nif);
- cbor_string_int(w, "metric", rtl.metric);
}
+ break;
}
- dummy_id++;
- }
- 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))
+ case (LSART_STUB)
{
- if (rtl.type == LSART_STUB)
+ if (ospf_is_v2(p) && verbose)
{
- cbor_open_block_with_length(w, 3);
+ cbor_add_string(w, "stubnet");
+ cbor_open_block_with_length(w, 2);
cbor_string_ipv4(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);
+ cbor_close_block_or_list(w);
}
static inline void
return lsa1->sn - lsa2->sn;
}
-
void
ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reachable)
{
struct top_hash_entry *he;
struct top_hash_entry *cnode = NULL;
- j1 = jx = 0;
+ int i = 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_add_string(w, "areas");
+ cbor_open_list_with_length(w, j1);
+
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 */
- 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_ipv4(w, "area", he->domain);
- last_area = he->domain;
- ix = 0;
- }
- }
- else
- continue;
- }
-
- ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->lsa.rt));
+ i++;
+ cbor_string_ipv4(w, "area", he->domain);
switch (he->lsa_type)
{
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. */
+ u32 last_rt = 0xFFFFFFFF;
if (he->domain)
{
- 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;
- }
+ cbor_add_string(w, "other_ASBR");
+ cbor_open_block(w);
if (he->lsa.rt != last_rt)
{
UYTC_CONTAINER(message, msg) {
UYTC_LEAF(header, "BIRD memory usage");
- UYTC_CONTAINER(body, body) {
- UYTC_LEAF(routing_tables, rmemsize(rt_table_pool));
- UYTC_LEAF(route_attributes, rmemsize(rta_pool));
- ...;
+ UYTC_CONTAINER(body) {
+ UYTC_USE(memory, routing_tables, rmemsize(rt_table_pool));
+ UYTC_USE(memory, route_attributes, rmemsize(rta_pool));
+ UYTC_USE(memory, protocols, rmemsize(proto_pool));
+ UYTC_USE(memory, current_config, rmemsize(config_pool));
#ifdef HAVE_MMAP
- UYTC_LEAF(standby_memory, (struct resmem) { .overhead = page_size * *pages_kept });
+ UYTC_USE(memory, standby_memory, (struct resmem) { .overhead = page_size * *pages_kept });
#endif
- UYTC_LEAF(total, rmemsize(&root_pool));
+ UYTC_LEAF(total, (struct resmem) { .overhead = &root_pool.overhead + page_size * *pages_kept, .effective = &root_pool.effective });
}
}
}
leaf dummy_yang_id {
type int32;
}
- leaf metric {
- type int32;
- }
+ uses metric;
choice rt_type {
case vlink {
- grouping vlink {
- leaf vlink {
- type int32;
- }
+ container vlink {
+ leaf vlink {
+ type int32;
+ }
}
}
case router {
- grouping router_metric {
+ container router {
uses router;
}
}
case network {
- grouping network {
+ container network {
leaf network {
type ipv4;
}
}
case stubnet {
- grouping stubnet {
+ container stubnet {
leaf stubnet {
type ipv4;
}
}
}
}
- list asbrs {
- key "router";
-
- leaf other_ABSRs {
- type empty;
- }
+ container other_ABSR {
uses router;
uses lsa_external;
+static inline void
+show_lsa_distance_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he)
+{
+ if (he->color == INSPF)
+ UYTC_LEAF(distance, he->dist);
+ else
+ UYTC_LEAF(distance, unreachable);
+}
+
static inline void
show_lsa_router_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he, int verbose)
{
- UYTC_GROUPING(lsa_router) {
- UYTC_ITEM(router, he->lsa.rt);
-
- ...;
+ //FIXME: This is not accurate - in yang this corresponds to DEFINITION, not USAGE of the grouping. That means, from yang point of view, we are calling definition of grouping. From cbor perspective this is correct.
+ UYTC_DEF_GROUPING(lsa_router) {
+ UYTC_LEAF(router, he->lsa.rt);
+ show_lsa_distance_cbor(UYTC_CONTEXT, he);
lsa_walk_rt_init(p, he, &rtl);
+ int dummy_id_ = 0;
+ UYTC_LIST_WHILE (rt, lsa_walk_rt(&rtl)) // The while corresponds to list and they need to be tight together.
+ {
+ UITC_LEAF(dummy_id, dummy_id_);
+ dummy_id_++;
+ UYTC_LEAF(metric, rtl.metric);
+ switch (rtl.type)
+ {
+ case (LSART_VLNK)
+ {
+ UYTC_CONTAINER(vlink)
+ {
+ UYTC_LEAF(vlink, rtl.id);
+ }
+ break;
+ }
+
+ case (LSART_PTP)
+ {
+ UYTC_CONTAINER(router_metric)
+ {
+ UYTC_LEAF(router, rtl.id);
+ }
+ break;
+ }
+
+ case (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;
+
+ UYTC_CONTAINER(network)
+ {
+ UYTC_LEAF(network, net_lsa->id & net_ln->optx);
+ UYTC_LEAF(len, u32_masklen(net_ln->optx));
+ }
+ }
+ else
+ {
+ UYTC_CONTAINER(network)
+ {
+ UYTC_LEAF(network, rtl.id);
+ }
+ }
+ }
+ else
+ {
+ UYTC_CONTAINER(network)
+ {
+ UYTC_LEAF(network, rtl.id);
+ UITC_LEAF(nif, rtl.nif);
+ }
+ break;
+ }
+ case (LSART_STUB)
+ {
+ if (ospf_is_v2(p) && verbose)
+ {
+ UYTC_CONTAINER(stubnet)
+ {
+ UYTC_LEAF(stubnet, rtl.id);
+ UYTC_LEAF(len, u32_masklen(rtl.data));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static inline void
+show_lsa_network_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he, int ospf2)
+{
+ UYTC_DEF_GROUPING(lsa_network)
+ {
+ struct ospf_lsa_header *lsa = &(he->lsa);
+ struct ospf_lsa_net *ln = he->lsa_body;
+ u32 i;
+
+ if (ospf2)
+ {
+ UYTC_CONTAINER(ospf2)
+ {
+ UYTC_LEAF(network, lsa->id & ln->optx);
+ UYTC_LEAF(optx, u32_masklen(ln->optx));
+ UYTC_LEAF(dr, lsa->rt);
+ }
+ }
+ else
+ {
+ UYTC_CONTAINER(ospf)
+ {
+ UYTC_LEAF(network, lsa->rt);
+ UYTC_LEAF(lsa_id, lsa->id);
+ }
+ }
+
+ show_lsa_distance_cbor(UYTC_CONTEXT, he);
+
+ int i = 0;
+ UITC_LIST_FOR (routers, i; i < lsa_net_count(lsa); i++) // Not sure if this syntax is ok, but, again, we need to squash cbor list and for()
+ {
+ UYTC_LEAF(router, ln->routers[i]);
+ }
+ }
+}
+
+static inline void
+show_lsa_sum_net_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he, int ospf2, int af)
+{
+ net_addr net;
+ u8 pxopts;
+ u32 metric_;
+
+ lsa_parse_sum_net(he, ospf2, af, &net, &pxopts, &metric_);
+ UYTC_DEF_GROUPING(lsa_sum_net)
+ {
+ UYTC_LEAF(net, &net);
+ UYTC_LEAF(metric_, metric);
+ }
+}
+
+static inline void
+show_lsa_sum_rt_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he, int ospf2)
+{
+ u32 metric;
+ u32 dst_rid;
+ u32 options;
+
+ lsa_parse_sum_rt(he, ospf2, &dst_rid, &metric, &options);
+
+ UYTC_DEF_GROUPING(lsa_sum_rt);
+ UYTC_LEAF(router, dst_rid);
+ UYTC_LEAF(metric, metric);
+}
+
+static inline void
+show_lsa_external_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he, int ospf2, int af)
+{
+ struct ospf_lsa_ext_local rt;
+
+ UYTC_DEF_GROUPING(lsa_external)
+ {
+ if (he->lsa_type == LSA_T_EXT)
+ he->domain = 0; /* Unmark the LSA */
+
+ lsa_parse_ext(he, ospf2, af, &rt);
+
+ if (rt.fbit)
+ {
+ UYTC_LEAF(via, rt.fwaddr.addr[0]);
+ }
+
+ if (rt.tag)
+ UYTC_LEAF(tag, rt.tag);
+
+ if (he->lsa_type == LSA_T_NSSA)
+ {
+ UYTC_LEAF(lsa_type, "nssa-ext");
+ } else {
+ UYTC_LEAF(lsa_type, "external");
+ }
+ UYTC_LEAF(rt_net, &rt.net);
+
+ if(rt.ebit)
+ {
+ UYTC_LEAF(lsa_type_num, 2);
+ }
+ UYTC_LEAF(metric, rt.metric);
+ }
+}
+
+static inline void
+show_lsa_prefix_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct top_hash_entry *he, struct top_hash_entry *cnode, int af)
+{
+ struct ospf_lsa_prefix *px = he->lsa_body;
+ u32 *buf;
+ int i;
+
+ /* 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))
+ return;
+
+ if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
+ return;
+
+ if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->lsa.id))
+ return;
+
+ UYTC_DEF_GROUPING(lsa_prefix)
+ {
+ buf = px->rest;
+
int i = 0;
- while (lsa_walk_rt(&rtl))
- {
- i++;
- UYTC_LIST_ITEM(rt) {
- UYTC_LEAF(dummy_yang_id, i);
- UYTC_LEAF(metric, rtl.metric);
- switch (rtl.type) {
- case LSART_VLNK:
- UYTC_CHOICE_ITEM(rt_type, vlink) {
- UYTC_GROUPING(vlink) {
- UYTC_LEAF(vlink, rtl.id);
- UYTC_LEAF(name, rtl.name);
- }
- }
- break;
-
- case LSART_PTP:
- ...;
- }
+ UYTC_LIST_FOR (prefixes, i; i < px->pxcount; i++)
+ {
+ net_addr net;
+ u8 pxopts;
+ u16 metric_;
+
+ buf = ospf3_get_prefix(buf, af, &net, &pxopts, &metric_);
+
+ if (px->ref_type == LSA_T_RT)
+ {
+ UYTC_LEAF(stubnet, &net);
+ UYTC_LEAF(metric_, metric);
+ }
+ else
+ {
+ UYTC_LEAF(address, &net);
}
}
}
}
+void
+ospf_sh_state_cbor(UYTC_CONTEXT_TYPE UYTC_CONTEXT, struct proto *P, int verbose, int reachable)
+{
+ 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;
-for (i = 0; i < j1; i++) {
- UYTC_LIST_ITEM(areas) {
- struct top_hash_entry *he = hea[i];
+ if (p->p.proto_state != PS_UP)
+ {
+ UYTC_LEAF(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;
+
+ int i = 0;
+ UYTC_LIST_WALK_SLIST(areas, he, p->lsal)
+ {
UYTC_LEAF(dummy_yang_id, i);
+ i++;
UYTC_LEAF(area, he->domain);
-
switch (he->lsa_type)
{
- case LSA_T_RT:
- UYTC_CHOICE_ITEM(lsa_type, rt, show_lsa_router_cbor(UYTC_CONTEXT, he));
- break;
+ case LSA_T_RT:
+ if (he->lsa.id == cnode->lsa.id)
+ show_lsa_router_cbor(UYTC_CONTEXT, p, he, verbose);
+ break;
+
+ case LSA_T_NET:
+ show_lsa_network_cbor(UYTC_CONTEXT, he, ospf2);
+ break;
+
+ case LSA_T_SUM_NET:
+ if (cnode->lsa_type == LSA_T_RT)
+ show_lsa_sum_net_cbor(UYTC_CONTEXT, he, ospf2, af);
+ break;
+
+ case LSA_T_SUM_RT:
+ if (cnode->lsa_type == LSA_T_RT)
+ show_lsa_sum_rt_cbor(UYTC_CONTEXT, he, ospf2);
+ break;
+
+ case LSA_T_EXT:
+ case LSA_T_NSSA:
+ show_lsa_external_cbor(UYTC_CONTEXT, he, ospf2, af);
+ break;
+
+ case LSA_T_PREFIX:
+ show_lsa_prefix_cbor(UYTC_CONTEXT, he, cnode, af);
+ break;
+ }
+
+ u32 last_rt = 0xFFFFFFFF;
+ if (he->domain)
+ {
+ he->domain = 0;
+
+ if ((he->color != INSPF) && reachable)
+ continue;
+
+ UITC_CONTAINER(other_ASBR)
+ {
+ if (he->lsa.rt != last_rt)
+ {
+ UYTC_LEAF(router, he->lsa.rt);
+ last_rt = he->lsa.rt;
+ }
- case LSA_T_NET:
- UYTC_CHOICE_ITEM(lsa_type, net, show_lsa_network_cbor(UYTC_CONTEXT, he, ospf2));
- break;
+ show_lsa_external_cbor(UYTC_CONTEXT, he, ospf2, af);
+ }
}
}
}
+