summaryrefslogtreecommitdiffstats
path: root/sharpd
diff options
context:
space:
mode:
authorOlivier Dugeon <olivier.dugeon@orange.com>2021-03-11 16:25:37 +0100
committerOlivier Dugeon <olivier.dugeon@orange.com>2021-03-23 15:39:30 +0100
commit1888e24382ba024e89d9ad582899607af20aea11 (patch)
tree9c6cc893ae222e062cd3643a9ce315126b32061e /sharpd
parenttopotest: Add new OSPF TE topotest (diff)
downloadfrr-1888e24382ba024e89d9ad582899607af20aea11.tar.xz
frr-1888e24382ba024e89d9ad582899607af20aea11.zip
sharpd: Add Traffic Engineering Database (TED)
Add new feature and commands to sharpd in order to collect Traffic Engineering Database information from an IGP (OSPF or IS-IS) though the ZAPI Opaque Message and the support of the Link State Library. This feature serves as an example of how to code a Traffic Engineering Database consumer and tests the mechanism. Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Diffstat (limited to 'sharpd')
-rw-r--r--sharpd/sharp_globals.h3
-rw-r--r--sharpd/sharp_main.c2
-rw-r--r--sharpd/sharp_vty.c139
-rw-r--r--sharpd/sharp_zebra.c27
-rw-r--r--sharpd/sharp_zebra.h3
5 files changed, 174 insertions, 0 deletions
diff --git a/sharpd/sharp_globals.h b/sharpd/sharp_globals.h
index ecb7053fd..0b3776cd9 100644
--- a/sharpd/sharp_globals.h
+++ b/sharpd/sharp_globals.h
@@ -55,6 +55,9 @@ struct sharp_global {
/* The list of nexthops that we are watching and data about them */
struct list *nhs;
+
+ /* Traffic Engineering Database */
+ struct ls_ted *ted;
};
extern struct sharp_global sg;
diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c
index a1216247c..e93db34ff 100644
--- a/sharpd/sharp_main.c
+++ b/sharpd/sharp_main.c
@@ -43,6 +43,7 @@
#include "libfrr.h"
#include "routemap.h"
#include "nexthop_group.h"
+#include "link_state.h"
#include "sharp_zebra.h"
#include "sharp_vty.h"
@@ -138,6 +139,7 @@ static void sharp_global_init(void)
{
memset(&sg, 0, sizeof(sg));
sg.nhs = list_new();
+ sg.ted = NULL;
}
static void sharp_start_configuration(void)
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 940415b06..002336616 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -29,6 +29,7 @@
#include "vrf.h"
#include "zclient.h"
#include "nexthop_group.h"
+#include "link_state.h"
#include "sharpd/sharp_globals.h"
#include "sharpd/sharp_zebra.h"
@@ -700,6 +701,142 @@ DEFPY (neigh_discover,
return CMD_SUCCESS;
}
+DEFPY (import_te,
+ import_te_cmd,
+ "sharp import-te",
+ SHARP_STR
+ "Import Traffic Engineering\n")
+{
+ sg.ted = ls_ted_new(1, "Sharp", 0);
+ sharp_zebra_register_te();
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_sharp_ted,
+ show_sharp_ted_cmd,
+ "show sharp ted [<vertex [A.B.C.D]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
+ SHOW_STR
+ SHARP_STR
+ "Traffic Engineering Database\n"
+ "MPLS-TE Vertex\n"
+ "MPLS-TE router ID (as an IP address)\n"
+ "MPLS-TE Edge\n"
+ "MPLS-TE Edge ID (as an IP address)\n"
+ "MPLS-TE Subnet\n"
+ "MPLS-TE Subnet ID (as an IP prefix)\n"
+ "Verbose output\n"
+ JSON_STR)
+{
+ int idx = 0;
+ struct in_addr ip_addr;
+ struct prefix pref;
+ struct ls_vertex *vertex;
+ struct ls_edge *edge;
+ struct ls_subnet *subnet;
+ uint64_t key;
+ bool verbose = false;
+ bool uj = use_json(argc, argv);
+ json_object *json = NULL;
+
+ if (sg.ted == NULL) {
+ vty_out(vty, "MPLS-TE import is not enabled\n");
+ return CMD_WARNING;
+ }
+
+ if (uj)
+ json = json_object_new_object();
+
+ if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
+ verbose = true;
+
+ if (argv_find(argv, argc, "vertex", &idx)) {
+ /* Show Vertex */
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
+ vty_out(vty,
+ "Specified Router ID %s is invalid\n",
+ argv[idx + 1]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Vertex from the Link State Database */
+ key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
+ vertex = ls_find_vertex_by_key(sg.ted, key);
+ if (!vertex) {
+ vty_out(vty, "No vertex found for ID %pI4\n",
+ &ip_addr);
+ return CMD_WARNING;
+ }
+ } else
+ vertex = NULL;
+
+ if (vertex)
+ ls_show_vertex(vertex, vty, json, verbose);
+ else
+ ls_show_vertices(sg.ted, vty, json, verbose);
+
+ } else if (argv_find(argv, argc, "edge", &idx)) {
+ /* Show Edge */
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ if (!inet_aton(argv[idx]->arg, &ip_addr)) {
+ vty_out(vty,
+ "Specified Edge ID %s is invalid\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Edge from the Link State Database */
+ key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
+ edge = ls_find_edge_by_key(sg.ted, key);
+ if (!edge) {
+ vty_out(vty, "No edge found for ID %pI4\n",
+ &ip_addr);
+ return CMD_WARNING;
+ }
+ } else
+ edge = NULL;
+
+ if (edge)
+ ls_show_edge(edge, vty, json, verbose);
+ else
+ ls_show_edges(sg.ted, vty, json, verbose);
+
+ } else if (argv_find(argv, argc, "subnet", &idx)) {
+ /* Show Subnet */
+ if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
+ if (!str2prefix(argv[idx]->arg, &pref)) {
+ vty_out(vty, "Invalid prefix format %s\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Get the Subnet from the Link State Database */
+ subnet = ls_find_subnet(sg.ted, pref);
+ if (!subnet) {
+ vty_out(vty, "No subnet found for ID %pFX\n",
+ &pref);
+ return CMD_WARNING;
+ }
+ } else
+ subnet = NULL;
+
+ if (subnet)
+ ls_show_subnet(subnet, vty, json, verbose);
+ else
+ ls_show_subnets(sg.ted, vty, json, verbose);
+
+ } else {
+ /* Show the complete TED */
+ ls_show_ted(sg.ted, vty, json, verbose);
+ }
+
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+ return CMD_SUCCESS;
+}
+
void sharp_vty_init(void)
{
install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
@@ -718,8 +855,10 @@ void sharp_vty_init(void)
install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
install_element(ENABLE_NODE, &send_opaque_reg_cmd);
install_element(ENABLE_NODE, &neigh_discover_cmd);
+ install_element(ENABLE_NODE, &import_te_cmd);
install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
+ install_element(ENABLE_NODE, &show_sharp_ted_cmd);
return;
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 73bbaf0bc..0f2c63404 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -30,6 +30,7 @@
#include "zclient.h"
#include "nexthop.h"
#include "nexthop_group.h"
+#include "link_state.h"
#include "sharp_globals.h"
#include "sharp_nht.h"
@@ -769,11 +770,15 @@ int sharp_zclient_delete(uint32_t session_id)
return 0;
}
+static const char *const type2txt[] = { "Generic", "Vertex", "Edge", "Subnet" };
+static const char *const status2txt[] = { "Unknown", "New", "Update",
+ "Delete", "Sync", "Orphan"};
/* Handler for opaque messages */
static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
{
struct stream *s;
struct zapi_opaque_msg info;
+ struct ls_element *lse;
s = zclient->ibuf;
@@ -783,6 +788,18 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
zlog_debug("%s: [%u] received opaque type %u", __func__,
zclient->session_id, info.type);
+ if (info.type == LINK_STATE_UPDATE) {
+ lse = ls_stream2ted(sg.ted, s, false);
+ if (lse)
+ zlog_debug(" |- Got %s %s from Link State Database",
+ status2txt[lse->status],
+ type2txt[lse->type]);
+ else
+ zlog_debug(
+ "%s: Error to convert Stream into Link State",
+ __func__);
+ }
+
return 0;
}
@@ -853,6 +870,16 @@ void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,
}
+/* Link State registration */
+void sharp_zebra_register_te(void)
+{
+ /* First register to received Link State Update messages */
+ zclient_register_opaque(zclient, LINK_STATE_UPDATE);
+
+ /* Then, request initial TED with SYNC message */
+ ls_request_sync(zclient);
+}
+
void sharp_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
{
zclient_send_neigh_discovery_req(zclient, ifp, p);
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index e7247f537..ffddb9e78 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -60,4 +60,7 @@ void sharp_opaque_reg_send(bool is_reg, uint32_t proto, uint32_t instance,
extern void sharp_zebra_send_arp(const struct interface *ifp,
const struct prefix *p);
+/* Register Link State Opaque messages */
+extern void sharp_zebra_register_te(void);
+
#endif