]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib, ospfd, ospf6d, zebra: add OSPF opaque route attributes
authorRenato Westphal <renato@opensourcerouting.org>
Tue, 21 Sep 2021 01:15:55 +0000 (22:15 -0300)
committerDavid Lamparter <equinox@opensourcerouting.org>
Sat, 15 Jan 2022 16:22:27 +0000 (17:22 +0100)
Update ospfd and ospf6d to send opaque route attributes to
zebra. Those attributes are stored in the RIB and can be viewed
using the "show ip[v6] route" commands (other than that, they are
completely ignored by zebra).

Example:
```
debian# show ip route 192.168.1.0/24
Routing entry for 192.168.1.0/24
  Known via "ospf", distance 110, metric 20, best
  Last update 01:57:08 ago
  * 10.0.1.2, via eth-rt2, weight 1
    OSPF path type        : External-2
    OSPF tag              : 0

debian#
debian# show ip route 192.168.1.0/24 json
{
  "192.168.1.0\/24":[
    {
      "prefix":"192.168.1.0\/24",
      "prefixLen":24,
      "protocol":"ospf",
      "vrfId":0,
      "vrfName":"default",
      "selected":true,
      [snip]
      "ospfPathType":"External-2",
      "ospfTag":"0"
    }
  ]
}
```

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
lib/route_opaque.h
ospf6d/ospf6_top.c
ospf6d/ospf6_top.h
ospf6d/ospf6_zebra.c
ospfd/ospf_route.c
ospfd/ospf_route.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
ospfd/ospfd.c
ospfd/ospfd.h
zebra/zebra_vty.c

index 678a171e48099927843f54be163c7779f0658971..bf6081c0547c1b9c1d8a06f1f37e67dfa134793c 100644 (file)
@@ -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 */
index 6c79dcfb711279d5e35c56a55226d083784b49d3..b50f32059e1f1f872d5462b2d703456d5f5af771 100644 (file)
@@ -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);
index 55cab72307e042e678ecbd4fa66bf3d96d08b976..fae5569168188f85b493ddcabc8b21fd84687f50 100644 (file)
@@ -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 */
index 5e50a6cc5524b69d4769ae8b4a777019b8a74960..b8186335183e64a97655ff743dccdc1bcce92972 100644 (file)
@@ -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
index 502a4a08c160cf83f04c706689a78302c192fd57..ec0c5524c93678aa2114ee281fdd2cff6e0637b7 100644 (file)
 #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;
index c2ce0569dbc48d1420941f4d88aa5078c236c3f5..5463e70ffba574897dc981387b4da91ecea5f655 100644 (file)
@@ -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 *);
index 84469160d3aa7eba45d58e0cb34ea1f0216ad78f..ac1b2b807cec3ff4e266ce56f9a9862e58214962 100644 (file)
@@ -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);
index b0ed66da5f818c98bf03aef91da98b39d9466628..7834b7d9344cbf319e4fe6eba9e6ce3a6c9ae676 100644 (file)
@@ -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);
 }
 
index 05433ccb95dbcfcf0de86dbe3b7a91ec37b741e0..d051151601bfa1845d1bef39f5caa5e371a23aa1 100644 (file)
@@ -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;
index d64a044e14aff769e1466bc973269b44484cc0aa..3369429ebaff33c47ed1fa750d4d685a40387a72 100644 (file)
@@ -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 */
index a3faa3d3e26208d1d0caa92d7d013525a013f77f..39695a148ce90e14a0bef7648d56ce57da5515ef 100644 (file)
@@ -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;
        }