diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index de25aa30d9..21912d143e 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -65,6 +65,8 @@ #include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_mac.h" #include "bgpd/bgp_trace.h" +#include "bgpd/bgp_community.h" +#include "bgpd/bgp_lcommunity.h" /* All information about zebra. */ struct zclient *zclient = NULL; diff --git a/lib/route_opaque.h b/lib/route_opaque.h index c5e7d6a327..bf6081c054 100644 --- a/lib/route_opaque.h +++ b/lib/route_opaque.h @@ -24,9 +24,12 @@ #include "assert.h" #include "zclient.h" -#include "bgpd/bgp_aspath.h" -#include "bgpd/bgp_community.h" -#include "bgpd/bgp_lcommunity.h" +/* copied from bgpd/bgp_community.h */ +#define COMMUNITY_SIZE 4 +/* copied from bgpd/bgp_lcommunity.h */ +#define LCOMMUNITY_SIZE 12 +/* copied from bgpd/bgp_route.h */ +#define BGP_MAX_SELECTION_REASON_STR_BUF 32 struct bgp_zebra_opaque { char aspath[256]; @@ -44,7 +47,15 @@ struct bgp_zebra_opaque { char selection_reason[BGP_MAX_SELECTION_REASON_STR_BUF]; }; +struct ospf_zebra_opaque { + char path_type[32]; + char area_id[INET_ADDRSTRLEN]; + char tag[16]; +}; + static_assert(sizeof(struct bgp_zebra_opaque) <= ZAPI_MESSAGE_OPAQUE_LENGTH, "BGP opaque data shouldn't be larger than zebra's buffer"); +static_assert(sizeof(struct ospf_zebra_opaque) <= ZAPI_MESSAGE_OPAQUE_LENGTH, + "OSPF opaque data shouldn't be larger than zebra's buffer"); #endif /* FRR_ROUTE_OPAQUE_H */ diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 905fbac949..1c8c5dfd3e 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -124,7 +124,6 @@ struct ospf6_area { #define OSPF6_NSSA_TRANSLATE_ENABLED 1 }; -#define OSPF6_AREA_DEFAULT 0x00 #define OSPF6_AREA_ENABLE 0x01 #define OSPF6_AREA_ACTIVE 0x02 #define OSPF6_AREA_TRANSIT 0x04 /* TransitCapability */ diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 633b8d77cd..bb5827a176 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -148,8 +148,7 @@ struct ospf6_path { #define OSPF6_PATH_TYPE_INTER 2 #define OSPF6_PATH_TYPE_EXTERNAL1 3 #define OSPF6_PATH_TYPE_EXTERNAL2 4 -#define OSPF6_PATH_TYPE_REDISTRIBUTE 5 -#define OSPF6_PATH_TYPE_MAX 6 +#define OSPF6_PATH_TYPE_MAX 5 #define OSPF6_PATH_SUBTYPE_DEFAULT_RT 1 diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 54f6c85cea..e2db77d44b 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -436,6 +436,7 @@ static struct ospf6 *ospf6_create(const char *name) o->fd = -1; o->max_multipath = MULTIPATH_NUM; + SET_FLAG(o->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA); o->oi_write_q = list_new(); @@ -885,6 +886,39 @@ DEFUN (no_ospf6_log_adjacency_changes_detail, return CMD_SUCCESS; } +static void ospf6_reinstall_routes(struct ospf6 *ospf6) +{ + struct ospf6_route *route; + + for (route = ospf6_route_head(ospf6->route_table); route; + route = ospf6_route_next(route)) + ospf6_zebra_route_update_add(route, ospf6); +} + +DEFPY (ospf6_send_extra_data, + ospf6_send_extra_data_cmd, + "[no] ospf6 send-extra-data zebra", + NO_STR + OSPF6_STR + "Extra data to Zebra for display/use\n" + "To zebra\n") +{ + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + + if (no + && CHECK_FLAG(ospf6->config_flags, + OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) { + UNSET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA); + ospf6_reinstall_routes(ospf6); + } else if (!CHECK_FLAG(ospf6->config_flags, + OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) { + SET_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA); + ospf6_reinstall_routes(ospf6); + } + + return CMD_SUCCESS; +} + DEFUN (ospf6_timers_lsa, ospf6_timers_lsa_cmd, "timers lsa min-arrival (0-600000)", @@ -2202,6 +2236,10 @@ static int config_write_ospf6(struct vty *vty) vty_out(vty, " ospf6 router-id %pI4\n", &ospf6->router_id_static); + if (!CHECK_FLAG(ospf6->config_flags, + OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) + vty_out(vty, " no ospf6 send-extra-data zebra\n"); + /* log-adjacency-changes flag print. */ if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) { @@ -2287,6 +2325,7 @@ void ospf6_top_init(void) install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd); install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd); install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd); + install_element(OSPF6_NODE, &ospf6_send_extra_data_cmd); /* LSA timers commands */ install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd); diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 4cc0923e93..77156f961d 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -32,9 +32,9 @@ struct ospf6_master { }; /* ospf6->config_flags */ -enum { - OSPF6_LOG_ADJACENCY_CHANGES = (1 << 0), - OSPF6_LOG_ADJACENCY_DETAIL = (1 << 1), +enum { OSPF6_LOG_ADJACENCY_CHANGES = (1 << 0), + OSPF6_LOG_ADJACENCY_DETAIL = (1 << 1), + OSPF6_SEND_EXTRA_DATA_TO_ZEBRA = (1 << 2), }; /* For processing route-map change update in the callback */ diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 5e50a6cc55..b818633518 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -27,6 +27,7 @@ #include "stream.h" #include "zclient.h" #include "memory.h" +#include "route_opaque.h" #include "lib/bfd.h" #include "lib_errors.h" @@ -371,6 +372,38 @@ DEFUN(show_zebra, return CMD_SUCCESS; } +static void ospf6_zebra_append_opaque_attr(struct ospf6_route *request, + struct zapi_route *api) +{ + struct ospf_zebra_opaque ospf_opaque = {}; + + /* OSPF path type */ + snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s", + OSPF6_PATH_TYPE_NAME(request->path.type)); + + switch (request->path.type) { + case OSPF6_PATH_TYPE_INTRA: + case OSPF6_PATH_TYPE_INTER: + /* OSPF area ID */ + (void)inet_ntop(AF_INET, &request->path.area_id, + ospf_opaque.area_id, + sizeof(ospf_opaque.area_id)); + break; + case OSPF6_PATH_TYPE_EXTERNAL1: + case OSPF6_PATH_TYPE_EXTERNAL2: + /* OSPF route tag */ + snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u", + request->path.tag); + break; + default: + break; + } + + SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE); + api->opaque.length = sizeof(struct ospf_zebra_opaque); + memcpy(api->opaque.data, &ospf_opaque, api->opaque.length); +} + #define ADD 0 #define REM 1 static void ospf6_zebra_route_update(int type, struct ospf6_route *request, @@ -455,6 +488,10 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request, api.distance = ospf6_distance_apply((struct prefix_ipv6 *)dest, request, ospf6); + if (type == ADD + && CHECK_FLAG(ospf6->config_flags, OSPF6_SEND_EXTRA_DATA_TO_ZEBRA)) + ospf6_zebra_append_opaque_attr(request, &api); + if (type == REM) ret = zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); else diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 502a4a08c1..ec0c5524c9 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -39,6 +39,22 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" +const char *ospf_path_type_name(int path_type) +{ + switch (path_type) { + case OSPF_PATH_INTRA_AREA: + return "Intra-Area"; + case OSPF_PATH_INTER_AREA: + return "Inter-Area"; + case OSPF_PATH_TYPE1_EXTERNAL: + return "External-1"; + case OSPF_PATH_TYPE2_EXTERNAL: + return "External-2"; + default: + return "Unknown"; + } +} + struct ospf_route *ospf_route_new(void) { struct ospf_route *new; diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index c2ce0569db..5463e70ffb 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -128,6 +128,7 @@ struct ospf_route { bool changed; }; +extern const char *ospf_path_type_name(int path_type); extern struct ospf_path *ospf_path_new(void); extern void ospf_path_free(struct ospf_path *); extern struct ospf_path *ospf_path_lookup(struct list *, struct ospf_path *); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 1a20eb515f..3d0804b018 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2218,6 +2218,53 @@ ALIAS(no_ospf_compatible_rfc1583, no_ospf_rfc1583_flag_cmd, "OSPF specific commands\n" "Disable the RFC1583Compatibility flag\n") +static void ospf_table_reinstall_routes(struct ospf *ospf, + struct route_table *rt) +{ + struct route_node *rn; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct ospf_route *or; + + or = rn->info; + if (!or) + continue; + + if (or->type == OSPF_DESTINATION_NETWORK) + ospf_zebra_add(ospf, (struct prefix_ipv4 *)&rn->p, or); + else if (or->type == OSPF_DESTINATION_DISCARD) + ospf_zebra_add_discard(ospf, + (struct prefix_ipv4 *)&rn->p); + } +} + +static void ospf_reinstall_routes(struct ospf *ospf) +{ + ospf_table_reinstall_routes(ospf, ospf->new_table); + ospf_table_reinstall_routes(ospf, ospf->new_external_route); +} + +DEFPY (ospf_send_extra_data, + ospf_send_extra_data_cmd, + "[no] ospf send-extra-data zebra", + NO_STR + OSPF_STR + "Extra data to Zebra for display/use\n" + "To zebra\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (no && CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) { + UNSET_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA); + ospf_reinstall_routes(ospf); + } else if (!CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) { + SET_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA); + ospf_reinstall_routes(ospf); + } + + return CMD_SUCCESS; +} + static int ospf_timers_spf_set(struct vty *vty, unsigned int delay, unsigned int hold, unsigned int max) { @@ -12212,6 +12259,10 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) vty_out(vty, " ospf router-id %pI4\n", &ospf->router_id_static); + /* zebra opaque attributes configuration. */ + if (!CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) + vty_out(vty, " no ospf send-extra-data zebra\n"); + /* ABR type print. */ if (ospf->abr_type != OSPF_ABR_DEFAULT) vty_out(vty, " ospf abr-type %s\n", @@ -12663,6 +12714,9 @@ void ospf_vty_init(void) install_element(OSPF_NODE, &ospf_rfc1583_flag_cmd); install_element(OSPF_NODE, &no_ospf_rfc1583_flag_cmd); + /* "ospf send-extra-data zebra" commands. */ + install_element(OSPF_NODE, &ospf_send_extra_data_cmd); + /* "network area" commands. */ install_element(OSPF_NODE, &ospf_network_area_cmd); install_element(OSPF_NODE, &no_ospf_network_area_cmd); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index b0ed66da5f..7834b7d934 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -33,6 +33,7 @@ #include "filter.h" #include "plist.h" #include "log.h" +#include "route_opaque.h" #include "lib/bfd.h" #include "nexthop.h" @@ -255,6 +256,38 @@ static void ospf_zebra_add_nexthop(struct ospf *ospf, struct ospf_path *path, api->nexthop_num++; } +static void ospf_zebra_append_opaque_attr(struct ospf_route *or, + struct zapi_route *api) +{ + struct ospf_zebra_opaque ospf_opaque = {}; + + /* OSPF path type */ + snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s", + ospf_path_type_name(or->path_type)); + + switch (or->path_type) { + case OSPF_PATH_INTRA_AREA: + case OSPF_PATH_INTER_AREA: + /* OSPF area ID */ + (void)inet_ntop(AF_INET, &or->u.std.area_id, + ospf_opaque.area_id, + sizeof(ospf_opaque.area_id)); + break; + case OSPF_PATH_TYPE1_EXTERNAL: + case OSPF_PATH_TYPE2_EXTERNAL: + /* OSPF route tag */ + snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u", + or->u.ext.tag); + break; + default: + break; + } + + SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE); + api->opaque.length = sizeof(struct ospf_zebra_opaque); + memcpy(api->opaque.data, &ospf_opaque, api->opaque.length); +} + void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p, struct ospf_route * or) { @@ -322,6 +355,9 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p, } } + if (CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) + ospf_zebra_append_opaque_attr(or, &api); + zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index e5f3eec603..726ce329e3 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -406,6 +406,8 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name) ospf_opaque_type11_lsa_init(new); + SET_FLAG(new->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA); + QOBJ_REG(new, ospf); new->fd = -1; diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index d64a044e14..3369429eba 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -125,6 +125,7 @@ enum { OSPF_OPAQUE_CAPABLE = (1 << 2), OSPF_LOG_ADJACENCY_CHANGES = (1 << 3), OSPF_LOG_ADJACENCY_DETAIL = (1 << 4), + OSPF_SEND_EXTRA_DATA_TO_ZEBRA = (1 << 5), }; /* TI-LFA */ diff --git a/tests/topotests/zebra_opaque/r3/ospf6d.conf b/tests/topotests/zebra_opaque/r3/ospf6d.conf new file mode 100644 index 0000000000..bf3d18c6dd --- /dev/null +++ b/tests/topotests/zebra_opaque/r3/ospf6d.conf @@ -0,0 +1,8 @@ +! +interface r3-eth0 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +router ospf6 +! diff --git a/tests/topotests/zebra_opaque/r3/ospfd.conf b/tests/topotests/zebra_opaque/r3/ospfd.conf new file mode 100644 index 0000000000..fdc7a97866 --- /dev/null +++ b/tests/topotests/zebra_opaque/r3/ospfd.conf @@ -0,0 +1,8 @@ +! +interface r3-eth0 + ip ospf area 0 + ip ospf hello-interval 2 + ip ospf dead-interval 10 +! +router ospf +! diff --git a/tests/topotests/zebra_opaque/r3/zebra.conf b/tests/topotests/zebra_opaque/r3/zebra.conf new file mode 100644 index 0000000000..744f2f1f78 --- /dev/null +++ b/tests/topotests/zebra_opaque/r3/zebra.conf @@ -0,0 +1,5 @@ +! +int r3-eth0 + ip address 192.168.1.1/24 + ipv6 address 2001:db8:1::1/64 +! diff --git a/tests/topotests/zebra_opaque/r4/ospf6d.conf b/tests/topotests/zebra_opaque/r4/ospf6d.conf new file mode 100644 index 0000000000..3b6846ff13 --- /dev/null +++ b/tests/topotests/zebra_opaque/r4/ospf6d.conf @@ -0,0 +1,8 @@ +! +interface r4-eth0 + ipv6 ospf6 area 0 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 10 +! +router ospf6 +! diff --git a/tests/topotests/zebra_opaque/r4/ospfd.conf b/tests/topotests/zebra_opaque/r4/ospfd.conf new file mode 100644 index 0000000000..6e08beebca --- /dev/null +++ b/tests/topotests/zebra_opaque/r4/ospfd.conf @@ -0,0 +1,8 @@ +! +interface r4-eth0 + ip ospf area 0 + ip ospf hello-interval 2 + ip ospf dead-interval 10 +! +router ospf +! diff --git a/tests/topotests/zebra_opaque/r4/zebra.conf b/tests/topotests/zebra_opaque/r4/zebra.conf new file mode 100644 index 0000000000..5916f5f882 --- /dev/null +++ b/tests/topotests/zebra_opaque/r4/zebra.conf @@ -0,0 +1,5 @@ +! +int r4-eth0 + ip address 192.168.1.2/24 + ipv6 address 2001:db8:1::2/64 +! diff --git a/tests/topotests/zebra_opaque/test_zebra_opaque.py b/tests/topotests/zebra_opaque/test_zebra_opaque.py index 2983df3ed6..202e28a178 100644 --- a/tests/topotests/zebra_opaque/test_zebra_opaque.py +++ b/tests/topotests/zebra_opaque/test_zebra_opaque.py @@ -35,11 +35,11 @@ sys.path.append(os.path.join(CWD, "../")) from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -pytestmark = [pytest.mark.bgpd] +pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.ospf6d] def setup_module(mod): - topodef = {"s1": ("r1", "r2")} + topodef = {"s1": ("r1", "r2"), "s2": ("r3", "r4")} tgen = Topogen(topodef, mod.__name__) tgen.start_topology() @@ -52,6 +52,12 @@ def setup_module(mod): router.load_config( TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) ) + router.load_config( + TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_OSPF6, os.path.join(CWD, "{}/ospf6d.conf".format(rname)) + ) tgen.start_router() @@ -67,8 +73,6 @@ def test_zebra_opaque(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) - router = tgen.gears["r1"] - def _bgp_converge(router): output = json.loads(router.vtysh_cmd("show ip route 192.168.1.0/24 json")) expected = { @@ -81,11 +85,45 @@ def test_zebra_opaque(): } return topotest.json_cmp(output, expected) + def _ospf_converge(router): + output = json.loads(router.vtysh_cmd("show ip route 192.168.1.0/24 json")) + expected = { + "192.168.1.0/24": [ + { + "ospfPathType": "Intra-Area", + "ospfAreaId": "0.0.0.0", + } + ] + } + return topotest.json_cmp(output, expected) + + def _ospf6_converge(router): + output = json.loads(router.vtysh_cmd("show ipv6 route 2001:db8:1::/64 json")) + expected = { + "2001:db8:1::/64": [ + { + "ospfPathType": "Intra-Area", + "ospfAreaId": "0.0.0.0", + } + ] + } + return topotest.json_cmp(output, expected) + + router = tgen.gears["r1"] test_func = functools.partial(_bgp_converge, router) success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) - assert result is None, 'Cannot see BGP community aliases "{}"'.format(router) + router = tgen.gears["r3"] + test_func = functools.partial(_ospf_converge, router) + success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, 'Cannot see OSPFv2 opaque attributes "{}"'.format(router) + + router = tgen.gears["r3"] + test_func = functools.partial(_ospf6_converge, router) + success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, 'Cannot see OSPFv3 opaque attributes "{}"'.format(router) + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 04f2e91e69..f35c9f65fb 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -429,6 +429,7 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re, struct json_object *json) { struct bgp_zebra_opaque bzo = {}; + struct ospf_zebra_opaque ozo = {}; if (!re->opaque) return; @@ -442,7 +443,7 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re, vty_out(vty, " Opaque Data: %s", (char *)re->opaque->data); break; - case ZEBRA_ROUTE_BGP: { + case ZEBRA_ROUTE_BGP: memcpy(&bzo, re->opaque->data, re->opaque->length); if (json) { @@ -467,7 +468,31 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re, vty_out(vty, " Selection reason : %s\n", bzo.selection_reason); } - } + break; + case ZEBRA_ROUTE_OSPF: + case ZEBRA_ROUTE_OSPF6: + memcpy(&ozo, re->opaque->data, re->opaque->length); + + if (json) { + json_object_string_add(json, "ospfPathType", + ozo.path_type); + if (ozo.area_id[0] != '\0') + json_object_string_add(json, "ospfAreaId", + ozo.area_id); + if (ozo.tag[0] != '\0') + json_object_string_add(json, "ospfTag", + ozo.tag); + } else { + vty_out(vty, " OSPF path type : %s\n", + ozo.path_type); + if (ozo.area_id[0] != '\0') + vty_out(vty, " OSPF area ID : %s\n", + ozo.area_id); + if (ozo.tag[0] != '\0') + vty_out(vty, " OSPF tag : %s\n", + ozo.tag); + } + break; default: break; }