summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/route_opaque.h8
-rw-r--r--ospf6d/ospf6_top.c39
-rw-r--r--ospf6d/ospf6_top.h6
-rw-r--r--ospf6d/ospf6_zebra.c37
-rw-r--r--ospfd/ospf_route.c16
-rw-r--r--ospfd/ospf_route.h1
-rw-r--r--ospfd/ospf_vty.c54
-rw-r--r--ospfd/ospf_zebra.c36
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--ospfd/ospfd.h1
-rw-r--r--zebra/zebra_vty.c29
11 files changed, 224 insertions, 5 deletions
diff --git a/lib/route_opaque.h b/lib/route_opaque.h
index 678a171e48..bf6081c054 100644
--- a/lib/route_opaque.h
+++ b/lib/route_opaque.h
@@ -47,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_top.c b/ospf6d/ospf6_top.c
index 6c79dcfb71..b50f32059e 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -437,6 +437,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();
@@ -887,6 +888,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)",
@@ -2198,6 +2232,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)) {
@@ -2283,6 +2321,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 55cab72307..fae5569168 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 84469160d3..ac1b2b807c 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2220,6 +2220,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)
{
@@ -11837,6 +11884,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",
@@ -12273,6 +12324,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 05433ccb95..d051151601 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -409,6 +409,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/zebra/zebra_vty.c b/zebra/zebra_vty.c
index a3faa3d3e2..39695a148c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -428,6 +428,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;
@@ -441,7 +442,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) {
@@ -466,7 +467,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;
}