mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 03:47:47 +00:00
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>
This commit is contained in:
parent
927b08024e
commit
1888e24382
@ -131,3 +131,15 @@ keyword. At present, no sharp commands will be preserved in the config.
|
|||||||
|
|
||||||
Send an ARP/NDP request to trigger the addition of a neighbor in the ARP
|
Send an ARP/NDP request to trigger the addition of a neighbor in the ARP
|
||||||
table.
|
table.
|
||||||
|
|
||||||
|
.. clicmd:: sharp import-te
|
||||||
|
|
||||||
|
Import Traffic Engineering Database produce by OSPF or IS-IS.
|
||||||
|
|
||||||
|
.. clicmd:: show sharp ted [verbose|json]
|
||||||
|
|
||||||
|
.. clicmd:: show sharp ted [<vertex [A.B.C.D]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]
|
||||||
|
|
||||||
|
Show imported Traffic Engineering Data Base
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,6 +55,9 @@ struct sharp_global {
|
|||||||
|
|
||||||
/* The list of nexthops that we are watching and data about them */
|
/* The list of nexthops that we are watching and data about them */
|
||||||
struct list *nhs;
|
struct list *nhs;
|
||||||
|
|
||||||
|
/* Traffic Engineering Database */
|
||||||
|
struct ls_ted *ted;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct sharp_global sg;
|
extern struct sharp_global sg;
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "libfrr.h"
|
#include "libfrr.h"
|
||||||
#include "routemap.h"
|
#include "routemap.h"
|
||||||
#include "nexthop_group.h"
|
#include "nexthop_group.h"
|
||||||
|
#include "link_state.h"
|
||||||
|
|
||||||
#include "sharp_zebra.h"
|
#include "sharp_zebra.h"
|
||||||
#include "sharp_vty.h"
|
#include "sharp_vty.h"
|
||||||
@ -138,6 +139,7 @@ static void sharp_global_init(void)
|
|||||||
{
|
{
|
||||||
memset(&sg, 0, sizeof(sg));
|
memset(&sg, 0, sizeof(sg));
|
||||||
sg.nhs = list_new();
|
sg.nhs = list_new();
|
||||||
|
sg.ted = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sharp_start_configuration(void)
|
static void sharp_start_configuration(void)
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
#include "nexthop_group.h"
|
#include "nexthop_group.h"
|
||||||
|
#include "link_state.h"
|
||||||
|
|
||||||
#include "sharpd/sharp_globals.h"
|
#include "sharpd/sharp_globals.h"
|
||||||
#include "sharpd/sharp_zebra.h"
|
#include "sharpd/sharp_zebra.h"
|
||||||
@ -700,6 +701,142 @@ DEFPY (neigh_discover,
|
|||||||
return CMD_SUCCESS;
|
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)
|
void sharp_vty_init(void)
|
||||||
{
|
{
|
||||||
install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
|
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_unicast_cmd);
|
||||||
install_element(ENABLE_NODE, &send_opaque_reg_cmd);
|
install_element(ENABLE_NODE, &send_opaque_reg_cmd);
|
||||||
install_element(ENABLE_NODE, &neigh_discover_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_debugging_sharpd_cmd);
|
||||||
|
install_element(ENABLE_NODE, &show_sharp_ted_cmd);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
#include "nexthop.h"
|
#include "nexthop.h"
|
||||||
#include "nexthop_group.h"
|
#include "nexthop_group.h"
|
||||||
|
#include "link_state.h"
|
||||||
|
|
||||||
#include "sharp_globals.h"
|
#include "sharp_globals.h"
|
||||||
#include "sharp_nht.h"
|
#include "sharp_nht.h"
|
||||||
@ -769,11 +770,15 @@ int sharp_zclient_delete(uint32_t session_id)
|
|||||||
return 0;
|
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 */
|
/* Handler for opaque messages */
|
||||||
static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
|
static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
|
||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
struct zapi_opaque_msg info;
|
struct zapi_opaque_msg info;
|
||||||
|
struct ls_element *lse;
|
||||||
|
|
||||||
s = zclient->ibuf;
|
s = zclient->ibuf;
|
||||||
|
|
||||||
@ -783,6 +788,18 @@ static int sharp_opaque_handler(ZAPI_CALLBACK_ARGS)
|
|||||||
zlog_debug("%s: [%u] received opaque type %u", __func__,
|
zlog_debug("%s: [%u] received opaque type %u", __func__,
|
||||||
zclient->session_id, info.type);
|
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;
|
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)
|
void sharp_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
|
||||||
{
|
{
|
||||||
zclient_send_neigh_discovery_req(zclient, ifp, p);
|
zclient_send_neigh_discovery_req(zclient, ifp, p);
|
||||||
|
@ -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,
|
extern void sharp_zebra_send_arp(const struct interface *ifp,
|
||||||
const struct prefix *p);
|
const struct prefix *p);
|
||||||
|
|
||||||
|
/* Register Link State Opaque messages */
|
||||||
|
extern void sharp_zebra_register_te(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user