diff --git a/proto/ospf/ospf_for_cbor.c b/proto/ospf/ospf_for_cbor.c index feed5606..462af013 100644 --- a/proto/ospf/ospf_for_cbor.c +++ b/proto/ospf/ospf_for_cbor.c @@ -27,42 +27,37 @@ show_lsa_router_cbor(struct cbor_writer *w, struct ospf_proto *p, struct top_has cbor_string_ipv4(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_ipv4(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_ipv4(w, "router", rtl.id); - cbor_string_int(w, "metric", rtl.metric); - } - } - cbor_close_block_or_list(w); - - cbor_add_string(w, "network"); + 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_NET) + 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_add_string(w, "vlink"); + cbor_open_block_with_length(w, 1); + cbor_string_ipv4(w, "vlink", rtl.id); + break; + } + + case (LSART_PTP) + { + cbor_add_string(w, "router_metric"); + cbor_open_block_with_length(w, 1); + cbor_string_ipv4(w, "router", rtl.id); + break; + } + + 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 */ @@ -73,51 +68,38 @@ 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, 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 @@ -407,7 +389,6 @@ ext_compare_for_state_cbor(const void *p1, const void *p2) return lsa1->sn - lsa2->sn; } - void ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reachable) { @@ -433,99 +414,16 @@ ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reac 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) { @@ -558,45 +456,16 @@ ospf_sh_state_cbor(struct cbor_writer *w, struct proto *P, int verbose, int reac 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) { diff --git a/yang/show_memory_meta.c b/yang/show_memory_meta.c index 8d2b6a3b..c07f628c 100644 --- a/yang/show_memory_meta.c +++ b/yang/show_memory_meta.c @@ -7,14 +7,15 @@ UYTC_MODULE(show_memory) { 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 }); } } } diff --git a/yang/show_ospf.yang b/yang/show_ospf.yang index b8b32889..985bbdfd 100644 --- a/yang/show_ospf.yang +++ b/yang/show_ospf.yang @@ -37,26 +37,24 @@ module show_ospf { 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; } @@ -72,7 +70,7 @@ module show_ospf { } case stubnet { - grouping stubnet { + container stubnet { leaf stubnet { type ipv4; } @@ -204,12 +202,7 @@ module show_ospf { } } } - list asbrs { - key "router"; - - leaf other_ABSRs { - type empty; - } + container other_ABSR { uses router; uses lsa_external; diff --git a/yang/show_ospf_meta.c b/yang/show_ospf_meta.c index acf3c5b0..abde6724 100644 --- a/yang/show_ospf_meta.c +++ b/yang/show_ospf_meta.c @@ -1,53 +1,324 @@ +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 i = 0; - while (lsa_walk_rt(&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. { - 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; + 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_PTP: - ...; - } + 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; -for (i = 0; i < j1; i++) { - UYTC_LIST_ITEM(areas) { - struct top_hash_entry *he = hea[i]; - UYTC_LEAF(dummy_yang_id, i); - UYTC_LEAF(area, he->domain); - - switch (he->lsa_type) + if (ospf2) { - case LSA_T_RT: - UYTC_CHOICE_ITEM(lsa_type, rt, show_lsa_router_cbor(UYTC_CONTEXT, he)); - break; + 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); + } + } - case LSA_T_NET: - UYTC_CHOICE_ITEM(lsa_type, net, show_lsa_network_cbor(UYTC_CONTEXT, he, ospf2)); - break; + 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; + 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; + + 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: + 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; + } + + show_lsa_external_cbor(UYTC_CONTEXT, he, ospf2, af); + } + } + } +} +