diff options
author | Olivier Dugeon <olivier.dugeon@orange.com> | 2021-03-11 16:25:37 +0100 |
---|---|---|
committer | Olivier Dugeon <olivier.dugeon@orange.com> | 2021-03-23 15:39:30 +0100 |
commit | 1888e24382ba024e89d9ad582899607af20aea11 (patch) | |
tree | 9c6cc893ae222e062cd3643a9ce315126b32061e /sharpd | |
parent | topotest: Add new OSPF TE topotest (diff) | |
download | frr-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.h | 3 | ||||
-rw-r--r-- | sharpd/sharp_main.c | 2 | ||||
-rw-r--r-- | sharpd/sharp_vty.c | 139 | ||||
-rw-r--r-- | sharpd/sharp_zebra.c | 27 | ||||
-rw-r--r-- | sharpd/sharp_zebra.h | 3 |
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 |