forked from Mirror/frr
isisd: add support for segment routing
This is an implementation of the IS-IS SR draft [1] for FRR. The following features are supported: * IPv4 and IPv6 Prefix-SIDs; * IPv4 and IPv6 Adj-SIDs and LAN-Adj-SIDs; * Index and absolute labels; * The no-php and explicit-null Prefix-SID flags; * Full integration with the Label Manager. Known limitations: * No support for Anycast-SIDs; * No support for the SID/Label Binding TLV (required for LDP interop). * No support for persistent Adj-SIDs; * No support for multiple SRGBs. [1] draft-ietf-isis-segment-routing-extensions-25 Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com> Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
8f6c893629
commit
26f6acafc3
|
@ -93,6 +93,7 @@ struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
|
|||
.last_dis_change = time(NULL);
|
||||
}
|
||||
}
|
||||
adj->adj_sids = list_new();
|
||||
|
||||
return adj;
|
||||
}
|
||||
|
@ -122,6 +123,44 @@ struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool isis_adj_exists(const struct isis_area *area, int level,
|
||||
const uint8_t *sysid)
|
||||
{
|
||||
struct isis_circuit *circuit;
|
||||
struct listnode *node;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
|
||||
struct isis_adjacency *adj;
|
||||
struct listnode *anode;
|
||||
struct list *adjdb;
|
||||
|
||||
switch (circuit->circ_type) {
|
||||
case CIRCUIT_T_BROADCAST:
|
||||
adjdb = circuit->u.bc.adjdb[level - 1];
|
||||
if (!adjdb)
|
||||
continue;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(adjdb, anode, adj)) {
|
||||
if (!memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case CIRCUIT_T_P2P:
|
||||
adj = circuit->u.p2p.neighbor;
|
||||
if (!adj)
|
||||
break;
|
||||
|
||||
if (!memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN))
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj))
|
||||
|
||||
void isis_delete_adj(void *arg)
|
||||
|
@ -145,6 +184,7 @@ void isis_delete_adj(void *arg)
|
|||
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
|
||||
|
||||
adj_mt_finish(adj);
|
||||
list_delete(&adj->adj_sids);
|
||||
|
||||
XFREE(MTYPE_ISIS_ADJACENCY, adj);
|
||||
return;
|
||||
|
@ -441,6 +481,9 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
|
|||
}
|
||||
|
||||
if (detail == ISIS_UI_LEVEL_DETAIL) {
|
||||
struct sr_adjacency *sra;
|
||||
struct listnode *anode;
|
||||
|
||||
level = adj->level;
|
||||
vty_out(vty, "\n");
|
||||
if (adj->circuit)
|
||||
|
@ -529,6 +572,31 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
|
|||
vty_out(vty, " %s\n", buf);
|
||||
}
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(adj->adj_sids, anode, sra)) {
|
||||
const char *adj_type;
|
||||
const char *backup;
|
||||
uint32_t sid;
|
||||
|
||||
switch (sra->adj->circuit->circ_type) {
|
||||
case CIRCUIT_T_BROADCAST:
|
||||
adj_type = "LAN Adjacency-SID";
|
||||
sid = sra->u.ladj_sid->sid;
|
||||
break;
|
||||
case CIRCUIT_T_P2P:
|
||||
adj_type = "Adjacency-SID";
|
||||
sid = sra->u.adj_sid->sid;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
|
||||
: "";
|
||||
|
||||
vty_out(vty, " %s %s%s: %u\n",
|
||||
(sra->nexthop.family == AF_INET) ? "IPv4"
|
||||
: "IPv6",
|
||||
adj_type, backup, sid);
|
||||
}
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -69,6 +69,7 @@ struct isis_dis_record {
|
|||
};
|
||||
|
||||
struct bfd_session;
|
||||
struct isis_area;
|
||||
|
||||
struct isis_adjacency {
|
||||
uint8_t snpa[ETH_ALEN]; /* NeighbourSNPAAddress */
|
||||
|
@ -103,6 +104,7 @@ struct isis_adjacency {
|
|||
uint16_t *mt_set; /* Topologies this adjacency is valid for */
|
||||
unsigned int mt_count; /* Number of entries in mt_set */
|
||||
struct bfd_session *bfd_session;
|
||||
struct list *adj_sids; /* Segment Routing Adj-SIDs. */
|
||||
};
|
||||
|
||||
struct isis_threeway_adj;
|
||||
|
@ -111,6 +113,8 @@ struct isis_adjacency *isis_adj_lookup(const uint8_t *sysid,
|
|||
struct list *adjdb);
|
||||
struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa,
|
||||
struct list *adjdb);
|
||||
bool isis_adj_exists(const struct isis_area *area, int level,
|
||||
const uint8_t *sysid);
|
||||
struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
|
||||
int level, struct isis_circuit *circuit);
|
||||
void isis_delete_adj(void *adj);
|
||||
|
|
|
@ -1480,7 +1480,7 @@ DEFPY (isis_sr_prefix_sid,
|
|||
isis_sr_prefix_sid_cmd,
|
||||
"segment-routing prefix\
|
||||
<A.B.C.D/M|X:X::X:X/M>$prefix\
|
||||
<absolute$sid_type (16000-1048575)$sid_value|index$sid_type (0-65535)$sid_value>\
|
||||
<absolute$sid_type (16-1048575)$sid_value|index$sid_type (0-65535)$sid_value>\
|
||||
[<no-php-flag|explicit-null>$lh_behavior]",
|
||||
SR_STR
|
||||
"Prefix SID\n"
|
||||
|
@ -1518,7 +1518,7 @@ DEFPY (isis_sr_prefix_sid,
|
|||
DEFPY (no_isis_sr_prefix_sid,
|
||||
no_isis_sr_prefix_sid_cmd,
|
||||
"no segment-routing prefix <A.B.C.D/M|X:X::X:X/M>$prefix\
|
||||
[<absolute$sid_type (16000-1048575)|index (0-65535)> [<no-php-flag|explicit-null>]]",
|
||||
[<absolute$sid_type (16-1048575)|index (0-65535)> [<no-php-flag|explicit-null>]]",
|
||||
NO_STR
|
||||
SR_STR
|
||||
"Prefix SID\n"
|
||||
|
|
|
@ -37,6 +37,12 @@ static struct log_ref ferr_isis_err[] = {
|
|||
.description = "Isis has detected an error within configuration for the router",
|
||||
.suggestion = "Ensure configuration is correct"
|
||||
},
|
||||
{
|
||||
.code = EC_ISIS_SID_OVERFLOW,
|
||||
.title = "SID index overflow",
|
||||
.description = "Isis has detected that a SID index falls outside of its associated SRGB range",
|
||||
.suggestion = "Configure a larger SRGB"
|
||||
},
|
||||
{
|
||||
.code = END_FERR,
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
enum isis_log_refs {
|
||||
EC_ISIS_PACKET = ISIS_FERR_START,
|
||||
EC_ISIS_CONFIG,
|
||||
EC_ISIS_SID_OVERFLOW,
|
||||
};
|
||||
|
||||
extern void isis_error_init(void);
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_tlvs.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isis_tx_queue.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
|
@ -763,9 +764,15 @@ static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp,
|
|||
if (area->oldmetric)
|
||||
isis_tlvs_add_oldstyle_ip_reach(lsp->tlvs, ipv4,
|
||||
metric);
|
||||
if (area->newmetric)
|
||||
isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4,
|
||||
metric);
|
||||
if (area->newmetric) {
|
||||
struct sr_prefix_cfg *pcfg = NULL;
|
||||
|
||||
if (area->srdb.enabled)
|
||||
pcfg = isis_sr_cfg_prefix_find(area, ipv4);
|
||||
|
||||
isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, metric,
|
||||
true, pcfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,9 +799,14 @@ static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp,
|
|||
metric = MAX_WIDE_PATH_METRIC;
|
||||
|
||||
if (!src_p || !src_p->prefixlen) {
|
||||
struct sr_prefix_cfg *pcfg = NULL;
|
||||
|
||||
if (area->srdb.enabled)
|
||||
pcfg = isis_sr_cfg_prefix_find(area, p);
|
||||
|
||||
isis_tlvs_add_ipv6_reach(lsp->tlvs,
|
||||
isis_area_ipv6_topology(area),
|
||||
p, metric);
|
||||
p, metric, true, pcfg);
|
||||
} else if (isis_area_ipv6_dstsrc_enabled(area)) {
|
||||
isis_tlvs_add_ipv6_dstsrc_reach(lsp->tlvs,
|
||||
ISIS_MT_IPV6_DSTSRC,
|
||||
|
@ -910,6 +922,33 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
|
|||
area->area_tag);
|
||||
}
|
||||
|
||||
/* Add Router Capability TLV. */
|
||||
if (isis->router_id != 0) {
|
||||
struct isis_router_cap cap = {};
|
||||
|
||||
cap.router_id.s_addr = isis->router_id;
|
||||
|
||||
/* Add SR Sub-TLVs if SR is enabled. */
|
||||
if (area->srdb.enabled) {
|
||||
struct isis_sr_db *srdb = &area->srdb;
|
||||
uint32_t range_size;
|
||||
|
||||
range_size = srdb->config.srgb_upper_bound
|
||||
- srdb->config.srgb_lower_bound + 1;
|
||||
cap.srgb.flags = ISIS_SUBTLV_SRGB_FLAG_I
|
||||
| ISIS_SUBTLV_SRGB_FLAG_V;
|
||||
cap.srgb.range_size = range_size;
|
||||
cap.srgb.lower_bound = srdb->config.srgb_lower_bound;
|
||||
cap.algo[0] = SR_ALGORITHM_SPF;
|
||||
cap.algo[1] = SR_ALGORITHM_UNSET;
|
||||
cap.msd = srdb->config.msd;
|
||||
}
|
||||
|
||||
isis_tlvs_set_router_capability(lsp->tlvs, &cap);
|
||||
lsp_debug("ISIS (%s): Adding Router Capabilities information",
|
||||
area->area_tag);
|
||||
}
|
||||
|
||||
/* IPv4 address and TE router ID TLVs.
|
||||
* In case of the first one we don't follow "C" vendor,
|
||||
* but "J" vendor behavior - one IPv4 address is put
|
||||
|
@ -996,13 +1035,21 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
|
|||
}
|
||||
|
||||
if (area->newmetric) {
|
||||
struct sr_prefix_cfg *pcfg = NULL;
|
||||
|
||||
lsp_debug(
|
||||
"ISIS (%s): Adding te-style IP reachability for %s",
|
||||
area->area_tag,
|
||||
prefix2str(ipv4, buf,
|
||||
sizeof(buf)));
|
||||
|
||||
if (area->srdb.enabled)
|
||||
pcfg = isis_sr_cfg_prefix_find(
|
||||
area, ipv4);
|
||||
|
||||
isis_tlvs_add_extended_ip_reach(
|
||||
lsp->tlvs, ipv4, metric);
|
||||
lsp->tlvs, ipv4, metric, false,
|
||||
pcfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1014,14 +1061,21 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
|
|||
|
||||
for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link,
|
||||
ipnode, ipv6)) {
|
||||
struct sr_prefix_cfg *pcfg = NULL;
|
||||
|
||||
lsp_debug(
|
||||
"ISIS (%s): Adding IPv6 reachability for %s",
|
||||
area->area_tag,
|
||||
prefix2str(ipv6, buf, sizeof(buf)));
|
||||
|
||||
if (area->srdb.enabled)
|
||||
pcfg = isis_sr_cfg_prefix_find(area,
|
||||
ipv6);
|
||||
|
||||
isis_tlvs_add_ipv6_reach(
|
||||
lsp->tlvs,
|
||||
isis_area_ipv6_topology(area), ipv6,
|
||||
metric);
|
||||
metric, false, pcfg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,9 @@ struct zebra_privs_t isisd_privs = {
|
|||
.cap_num_i = 0};
|
||||
|
||||
/* isisd options */
|
||||
struct option longopts[] = {{0}};
|
||||
static const struct option longopts[] = {
|
||||
{"int_num", required_argument, NULL, 'I'},
|
||||
{0}};
|
||||
|
||||
/* Master of threads. */
|
||||
struct thread_master *master;
|
||||
|
@ -99,6 +101,7 @@ void sigusr1(void);
|
|||
|
||||
static __attribute__((__noreturn__)) void terminate(int i)
|
||||
{
|
||||
isis_sr_term();
|
||||
isis_zebra_stop();
|
||||
exit(i);
|
||||
}
|
||||
|
@ -196,13 +199,16 @@ FRR_DAEMON_INFO(isisd, ISIS, .vty_port = ISISD_VTY_PORT,
|
|||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
int opt;
|
||||
int instance = 1;
|
||||
|
||||
#ifdef FABRICD
|
||||
frr_preinit(&fabricd_di, argc, argv);
|
||||
#else
|
||||
frr_preinit(&isisd_di, argc, argv);
|
||||
#endif
|
||||
frr_opt_add("", longopts, "");
|
||||
frr_opt_add(
|
||||
"I:", longopts,
|
||||
" -I, --int_num Set instance number (label-manager)\n");
|
||||
|
||||
/* Command line argument treatment. */
|
||||
while (1) {
|
||||
|
@ -214,6 +220,12 @@ int main(int argc, char **argv, char **envp)
|
|||
switch (opt) {
|
||||
case 0:
|
||||
break;
|
||||
case 'I':
|
||||
instance = atoi(optarg);
|
||||
if (instance < 1 || instance > (unsigned short)-1)
|
||||
zlog_err("Instance %i out of range (1..%u)",
|
||||
instance, (unsigned short)-1);
|
||||
break;
|
||||
default:
|
||||
frr_help_exit(1);
|
||||
break;
|
||||
|
@ -242,13 +254,14 @@ int main(int argc, char **argv, char **envp)
|
|||
isis_redist_init();
|
||||
isis_route_map_init();
|
||||
isis_mpls_te_init();
|
||||
isis_sr_init();
|
||||
lsp_init();
|
||||
mt_init();
|
||||
|
||||
/* create the global 'isis' instance */
|
||||
isis_new(1, VRF_DEFAULT);
|
||||
|
||||
isis_zebra_init(master);
|
||||
isis_zebra_init(master, instance);
|
||||
isis_bfd_init();
|
||||
fabricd_init();
|
||||
|
||||
|
|
|
@ -464,6 +464,7 @@ const struct frr_yang_module_info frr_isisd_info = {
|
|||
{
|
||||
.xpath = "/frr-isisd:isis/instance/segment-routing/srgb",
|
||||
.cbs = {
|
||||
.apply_finish = isis_instance_segment_routing_srgb_apply_finish,
|
||||
.cli_show = cli_show_isis_srgb,
|
||||
},
|
||||
},
|
||||
|
@ -492,6 +493,8 @@ const struct frr_yang_module_info frr_isisd_info = {
|
|||
.cbs = {
|
||||
.create = isis_instance_segment_routing_prefix_sid_map_prefix_sid_create,
|
||||
.destroy = isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy,
|
||||
.pre_validate = isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate,
|
||||
.apply_finish = isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish,
|
||||
.cli_show = cli_show_isis_prefix_sid,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -183,11 +183,11 @@ int isis_instance_segment_routing_srgb_upper_bound_modify(
|
|||
int isis_instance_segment_routing_msd_node_msd_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int isis_instance_segment_routing_msd_node_msd_destroy(
|
||||
struct nb_cb_modify_args *args);
|
||||
struct nb_cb_destroy_args *args);
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_create(
|
||||
struct nb_cb_modify_args *args);
|
||||
struct nb_cb_create_args *args);
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
|
||||
struct nb_cb_modify_args *args);
|
||||
struct nb_cb_destroy_args *args);
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
|
||||
|
@ -279,6 +279,10 @@ struct yang_data *
|
|||
lib_interface_isis_event_counters_authentication_fails_get_elem(
|
||||
struct nb_cb_get_elem_args *args);
|
||||
|
||||
/* Optional 'pre_validate' callbacks. */
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate(
|
||||
struct nb_cb_pre_validate_args *args);
|
||||
|
||||
/* Optional 'apply_finish' callbacks. */
|
||||
void ietf_backoff_delay_apply_finish(struct nb_cb_apply_finish_args *args);
|
||||
void area_password_apply_finish(struct nb_cb_apply_finish_args *args);
|
||||
|
@ -291,6 +295,10 @@ void default_info_origin_ipv6_apply_finish(
|
|||
void redistribute_apply_finish(const struct lyd_node *dnode, int family);
|
||||
void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args);
|
||||
void redistribute_ipv6_apply_finish(struct nb_cb_apply_finish_args *args);
|
||||
void isis_instance_segment_routing_srgb_apply_finish(
|
||||
struct nb_cb_apply_finish_args *args);
|
||||
void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish(
|
||||
struct nb_cb_apply_finish_args *args);
|
||||
|
||||
/* Optional 'cli_show' callbacks. */
|
||||
void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
|
||||
|
|
|
@ -1405,35 +1405,78 @@ int isis_instance_mpls_te_router_address_destroy(
|
|||
/*
|
||||
* XPath: /frr-isisd:isis/instance/segment-routing/enabled
|
||||
*/
|
||||
int isis_instance_segment_routing_enabled_modify(enum nb_event event,
|
||||
const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
int isis_instance_segment_routing_enabled_modify(
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
struct isis_area *area;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
area->srdb.config.enabled = yang_dnode_get_bool(args->dnode, NULL);
|
||||
|
||||
if (area->srdb.config.enabled) {
|
||||
if (IS_DEBUG_ISIS(DEBUG_EVENTS))
|
||||
zlog_debug("SR: Segment Routing: OFF -> ON");
|
||||
|
||||
if (isis_sr_start(area) == 0)
|
||||
area->srdb.enabled = true;
|
||||
} else {
|
||||
if (IS_DEBUG_ISIS(DEBUG_EVENTS))
|
||||
zlog_debug("SR: Segment Routing: ON -> OFF");
|
||||
|
||||
isis_sr_stop(area);
|
||||
area->srdb.enabled = false;
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/segment-routing/srgb
|
||||
*/
|
||||
void isis_instance_segment_routing_srgb_apply_finish(
|
||||
struct nb_cb_apply_finish_args *args)
|
||||
{
|
||||
struct isis_area *area;
|
||||
uint32_t lower_bound, upper_bound;
|
||||
int ret;
|
||||
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
|
||||
upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
|
||||
|
||||
ret = isis_sr_cfg_srgb_update(area, lower_bound, upper_bound);
|
||||
if (area->srdb.config.enabled) {
|
||||
if (ret == 0)
|
||||
area->srdb.enabled = true;
|
||||
else {
|
||||
isis_sr_stop(area);
|
||||
area->srdb.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/segment-routing/srgb/lower-bound
|
||||
*/
|
||||
int isis_instance_segment_routing_srgb_lower_bound_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) {
|
||||
zlog_warn("Invalid SRGB lower bound: %" PRIu32,
|
||||
lower_bound);
|
||||
return NB_ERR_VALIDATION;
|
||||
}
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1444,15 +1487,21 @@ int isis_instance_segment_routing_srgb_lower_bound_modify(
|
|||
* XPath: /frr-isisd:isis/instance/segment-routing/srgb/upper-bound
|
||||
*/
|
||||
int isis_instance_segment_routing_srgb_upper_bound_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL);
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) {
|
||||
zlog_warn("Invalid SRGB upper bound: %" PRIu32,
|
||||
upper_bound);
|
||||
return NB_ERR_VALIDATION;
|
||||
}
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1463,32 +1512,31 @@ int isis_instance_segment_routing_srgb_upper_bound_modify(
|
|||
* XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd
|
||||
*/
|
||||
int isis_instance_segment_routing_msd_node_msd_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
struct isis_area *area;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
area->srdb.config.msd = yang_dnode_get_uint8(args->dnode, NULL);
|
||||
isis_sr_cfg_msd_update(area);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int isis_instance_segment_routing_msd_node_msd_destroy(
|
||||
enum nb_event event, const struct lyd_node *dnode)
|
||||
struct nb_cb_destroy_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
struct isis_area *area;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
area->srdb.config.msd = 0;
|
||||
isis_sr_cfg_msd_update(area);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
@ -1497,34 +1545,86 @@ int isis_instance_segment_routing_msd_node_msd_destroy(
|
|||
* XPath: /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid
|
||||
*/
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_create(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_create_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
struct isis_area *area;
|
||||
struct prefix prefix;
|
||||
struct sr_prefix_cfg *pcfg;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
|
||||
|
||||
pcfg = isis_sr_cfg_prefix_add(area, &prefix);
|
||||
nb_running_set_entry(args->dnode, pcfg);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
|
||||
struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct sr_prefix_cfg *pcfg;
|
||||
struct isis_area *area;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
pcfg = nb_running_unset_entry(args->dnode);
|
||||
area = pcfg->area;
|
||||
isis_sr_cfg_prefix_del(pcfg);
|
||||
lsp_regenerate_schedule(area, area->is_type, 0);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate(
|
||||
struct nb_cb_pre_validate_args *args)
|
||||
{
|
||||
uint32_t srgb_lbound;
|
||||
uint32_t srgb_ubound;
|
||||
uint32_t srgb_range;
|
||||
uint32_t sid;
|
||||
enum sr_sid_value_type sid_type;
|
||||
|
||||
srgb_lbound = yang_dnode_get_uint32(args->dnode,
|
||||
"../../srgb/lower-bound");
|
||||
srgb_ubound = yang_dnode_get_uint32(args->dnode,
|
||||
"../../srgb/upper-bound");
|
||||
sid = yang_dnode_get_uint32(args->dnode, "./sid-value");
|
||||
sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type");
|
||||
|
||||
srgb_range = srgb_ubound - srgb_lbound + 1;
|
||||
switch (sid_type) {
|
||||
case SR_SID_VALUE_TYPE_INDEX:
|
||||
if (sid >= srgb_range) {
|
||||
zlog_warn("SID index %u falls outside local SRGB range",
|
||||
sid);
|
||||
return NB_ERR_VALIDATION;
|
||||
}
|
||||
break;
|
||||
case SR_SID_VALUE_TYPE_ABSOLUTE:
|
||||
if (!IS_MPLS_UNRESERVED_LABEL(sid)) {
|
||||
zlog_warn("Invalid absolute SID %u", sid);
|
||||
return NB_ERR_VALIDATION;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
|
||||
enum nb_event event, const struct lyd_node *dnode)
|
||||
void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish(
|
||||
struct nb_cb_apply_finish_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
struct sr_prefix_cfg *pcfg;
|
||||
struct isis_area *area;
|
||||
|
||||
return NB_OK;
|
||||
pcfg = nb_running_get_entry(args->dnode, NULL, true);
|
||||
area = pcfg->area;
|
||||
lsp_regenerate_schedule(area, area->is_type, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1532,17 +1632,15 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_destroy(
|
|||
* /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value-type
|
||||
*/
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
struct sr_prefix_cfg *pcfg;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
pcfg = nb_running_get_entry(args->dnode, NULL, true);
|
||||
pcfg->sid_type = yang_dnode_get_enum(args->dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
@ -1552,17 +1650,15 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_type_modif
|
|||
* /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/sid-value
|
||||
*/
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
struct sr_prefix_cfg *pcfg;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
pcfg = nb_running_get_entry(args->dnode, NULL, true);
|
||||
pcfg->sid = yang_dnode_get_uint32(args->dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
@ -1572,17 +1668,15 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_sid_value_modify(
|
|||
* /frr-isisd:isis/instance/segment-routing/prefix-sid-map/prefix-sid/last-hop-behavior
|
||||
*/
|
||||
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_last_hop_behavior_modify(
|
||||
enum nb_event event, const struct lyd_node *dnode,
|
||||
union nb_resource *resource)
|
||||
struct nb_cb_modify_args *args)
|
||||
{
|
||||
switch (event) {
|
||||
case NB_EV_VALIDATE:
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
struct sr_prefix_cfg *pcfg;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
pcfg = nb_running_get_entry(args->dnode, NULL, true);
|
||||
pcfg->last_hop_behavior = yang_dnode_get_enum(args->dnode, NULL);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
|
|||
nexthop->family = family;
|
||||
nexthop->ifindex = ifindex;
|
||||
nexthop->ip = *ip;
|
||||
isis_sr_nexthop_reset(&nexthop->sr);
|
||||
|
||||
return nexthop;
|
||||
}
|
||||
|
@ -129,6 +130,7 @@ static void adjinfo2nexthop(int family, struct list *nexthops,
|
|||
nh = isis_nexthop_create(
|
||||
AF_INET, &ip,
|
||||
adj->circuit->interface->ifindex);
|
||||
memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid));
|
||||
listnode_add(nexthops, nh);
|
||||
break;
|
||||
}
|
||||
|
@ -143,6 +145,7 @@ static void adjinfo2nexthop(int family, struct list *nexthops,
|
|||
nh = isis_nexthop_create(
|
||||
AF_INET6, &ip,
|
||||
adj->circuit->interface->ifindex);
|
||||
memcpy(nh->sysid, adj->sysid, sizeof(nh->sysid));
|
||||
listnode_add(nexthops, nh);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ struct isis_nexthop {
|
|||
ifindex_t ifindex;
|
||||
int family;
|
||||
union g_addr ip;
|
||||
uint8_t sysid[ISIS_SYS_ID_LEN];
|
||||
struct sr_nexthop_info sr;
|
||||
};
|
||||
|
||||
struct isis_route_info {
|
||||
|
|
|
@ -1214,6 +1214,8 @@ static int isis_run_spf_cb(struct thread *thread)
|
|||
|
||||
isis_area_verify_routes(area);
|
||||
|
||||
isis_area_verify_sr(area);
|
||||
|
||||
/* walk all circuits and reset any spf specific flags */
|
||||
struct listnode *node;
|
||||
struct isis_circuit *circuit;
|
||||
|
|
1525
isisd/isis_sr.c
Normal file
1525
isisd/isis_sr.c
Normal file
File diff suppressed because it is too large
Load diff
259
isisd/isis_sr.h
Normal file
259
isisd/isis_sr.h
Normal file
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* This is an implementation of Segment Routing for IS-IS
|
||||
* as per draft draft-ietf-isis-segment-routing-extensions-25
|
||||
*
|
||||
* Copyright (C) 2019 Orange Labs http://www.orange.com
|
||||
*
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
* Contributor: Renato Westphal <renato@opensourcerouting.org> for NetDEF
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _FRR_ISIS_SR_H
|
||||
#define _FRR_ISIS_SR_H
|
||||
|
||||
#include "lib/linklist.h"
|
||||
#include "lib/mpls.h"
|
||||
#include "lib/nexthop.h"
|
||||
#include "lib/typesafe.h"
|
||||
|
||||
#include "isisd/isis_tlvs.h"
|
||||
|
||||
/*
|
||||
* Segment Routing information is transported through the following Sub-TLVs:
|
||||
*
|
||||
* Sub-TLV Name Value TLVs
|
||||
* ---------------------------------------------------------------------
|
||||
* SID Label 1
|
||||
*
|
||||
* Prefix Segment Identifier 3 135, 235, 236 and 237
|
||||
*
|
||||
* Adjacency Segment Identifier 31 22, 23, 141, 222 and 223
|
||||
* LAN Adjacency Segment Identifier 32 22, 23, 141, 222 and 223
|
||||
*
|
||||
* Segment Routing Capability 2 242
|
||||
* Segment Routing Algorithm 19 242
|
||||
* Node Maximum Stack Depth (MSD) 23 242
|
||||
*
|
||||
* Sub-TLV definitions, serialization and de-serialization are defined
|
||||
* in isis_tlvs.[c,h].
|
||||
*/
|
||||
|
||||
#define SRGB_LOWER_BOUND 16000
|
||||
#define SRGB_UPPER_BOUND 23999
|
||||
|
||||
PREDECL_RBTREE_UNIQ(tree_sr_node)
|
||||
PREDECL_RBTREE_UNIQ(tree_sr_node_prefix)
|
||||
PREDECL_RBTREE_UNIQ(tree_sr_area_prefix)
|
||||
PREDECL_RBTREE_UNIQ(tree_sr_prefix_cfg)
|
||||
|
||||
/* SR Adj-SID type. */
|
||||
enum sr_adj_type {
|
||||
ISIS_SR_ADJ_NORMAL = 0,
|
||||
ISIS_SR_LAN_BACKUP,
|
||||
};
|
||||
|
||||
/* SR Adjacency. */
|
||||
struct sr_adjacency {
|
||||
/* Adjacency type. */
|
||||
enum sr_adj_type type;
|
||||
|
||||
/* Adj-SID nexthop information. */
|
||||
struct {
|
||||
int family;
|
||||
union g_addr address;
|
||||
mpls_label_t label;
|
||||
} nexthop;
|
||||
|
||||
/* (LAN-)Adj-SID Sub-TLV. */
|
||||
union {
|
||||
struct isis_adj_sid *adj_sid;
|
||||
struct isis_lan_adj_sid *ladj_sid;
|
||||
} u;
|
||||
|
||||
/* Back pointer to IS-IS adjacency. */
|
||||
struct isis_adjacency *adj;
|
||||
};
|
||||
|
||||
/* SR Prefix-SID type. */
|
||||
enum sr_prefix_type {
|
||||
ISIS_SR_PREFIX_LOCAL = 0,
|
||||
ISIS_SR_PREFIX_REMOTE,
|
||||
};
|
||||
|
||||
/* SR Nexthop Information. */
|
||||
struct sr_nexthop_info {
|
||||
mpls_label_t label;
|
||||
time_t uptime;
|
||||
};
|
||||
|
||||
/* SR Prefix-SID. */
|
||||
struct sr_prefix {
|
||||
/* RB-tree entries. */
|
||||
struct tree_sr_node_prefix_item node_entry;
|
||||
struct tree_sr_area_prefix_item area_entry;
|
||||
|
||||
/* IP prefix. */
|
||||
struct prefix prefix;
|
||||
|
||||
/* SID value, algorithm and flags. */
|
||||
struct isis_prefix_sid sid;
|
||||
|
||||
/* Local label value. */
|
||||
mpls_label_t local_label;
|
||||
|
||||
/* Prefix-SID type. */
|
||||
enum sr_prefix_type type;
|
||||
union {
|
||||
struct {
|
||||
/* Information about this local Prefix-SID. */
|
||||
struct sr_nexthop_info info;
|
||||
} local;
|
||||
struct {
|
||||
/* Route associated to this remote Prefix-SID. */
|
||||
struct isis_route_info *rinfo;
|
||||
} remote;
|
||||
} u;
|
||||
|
||||
/* Backpointer to SR node. */
|
||||
struct sr_node *srn;
|
||||
|
||||
/* Flags used while the LSPDB is being parsed. */
|
||||
uint8_t parse_flags;
|
||||
#define F_ISIS_SR_PREFIX_SID_NEW 0x01
|
||||
#define F_ISIS_SR_PREFIX_SID_MODIFIED 0x02
|
||||
#define F_ISIS_SR_PREFIX_SID_UNCHANGED 0x04
|
||||
};
|
||||
|
||||
/* SR node. */
|
||||
struct sr_node {
|
||||
/* RB-tree entry. */
|
||||
struct tree_sr_node_item entry;
|
||||
|
||||
/* IS-IS level: ISIS_LEVEL1 or ISIS_LEVEL2. */
|
||||
int level;
|
||||
|
||||
/* IS-IS node identifier. */
|
||||
uint8_t sysid[ISIS_SYS_ID_LEN];
|
||||
|
||||
/* IS-IS node capabilities (SRGB, SR Algorithms, etc). */
|
||||
struct isis_router_cap cap;
|
||||
|
||||
/* List of Prefix-SIDs advertised by this node. */
|
||||
struct tree_sr_node_prefix_head prefix_sids;
|
||||
|
||||
/* Backpointer to IS-IS area. */
|
||||
struct isis_area *area;
|
||||
|
||||
/* Flags used while the LSPDB is being parsed. */
|
||||
uint8_t parse_flags;
|
||||
#define F_ISIS_SR_NODE_NEW 0x01
|
||||
#define F_ISIS_SR_NODE_MODIFIED 0x02
|
||||
#define F_ISIS_SR_NODE_UNCHANGED 0x04
|
||||
};
|
||||
|
||||
/* NOTE: these values must be in sync with the YANG module. */
|
||||
enum sr_sid_value_type {
|
||||
SR_SID_VALUE_TYPE_INDEX = 0,
|
||||
SR_SID_VALUE_TYPE_ABSOLUTE = 1,
|
||||
};
|
||||
|
||||
/* NOTE: these values must be in sync with the YANG module. */
|
||||
enum sr_last_hop_behavior {
|
||||
SR_LAST_HOP_BEHAVIOR_EXP_NULL = 0,
|
||||
SR_LAST_HOP_BEHAVIOR_NO_PHP = 1,
|
||||
SR_LAST_HOP_BEHAVIOR_PHP = 2,
|
||||
};
|
||||
|
||||
/* SR Prefix-SID configuration. */
|
||||
struct sr_prefix_cfg {
|
||||
/* RB-tree entry. */
|
||||
struct tree_sr_prefix_cfg_item entry;
|
||||
|
||||
/* IP prefix. */
|
||||
struct prefix prefix;
|
||||
|
||||
/* SID value. */
|
||||
uint32_t sid;
|
||||
|
||||
/* SID value type. */
|
||||
enum sr_sid_value_type sid_type;
|
||||
|
||||
/* SID last hop behavior. */
|
||||
enum sr_last_hop_behavior last_hop_behavior;
|
||||
|
||||
/* Does this Prefix-SID refer to a loopback address (Node-SID)? */
|
||||
bool node_sid;
|
||||
|
||||
/* Backpointer to IS-IS area. */
|
||||
struct isis_area *area;
|
||||
};
|
||||
|
||||
/* Per-area IS-IS Segment Routing information. */
|
||||
struct isis_sr_db {
|
||||
/* Operational status of Segment Routing. */
|
||||
bool enabled;
|
||||
|
||||
/* Adj-SIDs. */
|
||||
struct list *adj_sids;
|
||||
|
||||
/* SR information from all nodes. */
|
||||
struct tree_sr_node_head sr_nodes[ISIS_LEVELS];
|
||||
|
||||
/* Prefix-SIDs. */
|
||||
struct tree_sr_area_prefix_head prefix_sids[ISIS_LEVELS];
|
||||
|
||||
/* Area SR configuration. */
|
||||
struct {
|
||||
/* Administrative status of Segment Routing. */
|
||||
bool enabled;
|
||||
|
||||
/* Segment Routing Global Block lower & upper bound. */
|
||||
uint32_t srgb_lower_bound;
|
||||
uint32_t srgb_upper_bound;
|
||||
|
||||
/* Maximum SID Depth supported by the node. */
|
||||
uint8_t msd;
|
||||
|
||||
/* Prefix-SID mappings. */
|
||||
struct tree_sr_prefix_cfg_head prefix_sids;
|
||||
} config;
|
||||
};
|
||||
|
||||
/* Prototypes. */
|
||||
extern int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound,
|
||||
uint32_t upper_bound);
|
||||
extern void isis_sr_cfg_msd_update(struct isis_area *area);
|
||||
extern struct sr_prefix_cfg *
|
||||
isis_sr_cfg_prefix_add(struct isis_area *area, const struct prefix *prefix);
|
||||
extern void isis_sr_cfg_prefix_del(struct sr_prefix_cfg *pcfg);
|
||||
extern struct sr_prefix_cfg *
|
||||
isis_sr_cfg_prefix_find(struct isis_area *area, union prefixconstptr prefix);
|
||||
extern void isis_sr_prefix_cfg2subtlv(const struct sr_prefix_cfg *pcfg,
|
||||
bool external,
|
||||
struct isis_prefix_sid *psid);
|
||||
extern void isis_sr_nexthop_update(struct sr_nexthop_info *srnh,
|
||||
mpls_label_t label);
|
||||
extern void isis_sr_nexthop_reset(struct sr_nexthop_info *srnh);
|
||||
extern void isis_area_verify_sr(struct isis_area *area);
|
||||
extern int isis_sr_start(struct isis_area *area);
|
||||
extern void isis_sr_stop(struct isis_area *area);
|
||||
extern void isis_sr_area_init(struct isis_area *area);
|
||||
extern void isis_sr_area_term(struct isis_area *area);
|
||||
extern void isis_sr_init(void);
|
||||
extern void isis_sr_term(void);
|
||||
|
||||
#endif /* _FRR_ISIS_SR_H */
|
|
@ -43,9 +43,10 @@
|
|||
#include "isisd/isis_pdu.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_TLV, "ISIS TLVs")
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_SUBTLV, "ISIS Sub-TLVs")
|
||||
DEFINE_MTYPE(ISISD, ISIS_SUBTLV, "ISIS Sub-TLVs")
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_MT_ITEM_LIST, "ISIS MT Item Lists")
|
||||
|
||||
typedef int (*unpack_tlv_func)(enum isis_tlv_context context, uint8_t tlv_type,
|
||||
|
@ -887,7 +888,11 @@ static int unpack_item_prefix_sid(uint16_t mtid, uint8_t len, struct stream *s,
|
|||
|
||||
if (sid.flags & ISIS_PREFIX_SID_VALUE) {
|
||||
sid.value = stream_get3(s);
|
||||
sid.value &= MPLS_LABEL_VALUE_MASK;
|
||||
if (!IS_MPLS_UNRESERVED_LABEL(sid.value)) {
|
||||
sbuf_push(log, indent, "Invalid absolute SID %u\n",
|
||||
sid.value);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
sid.value = stream_getl(s);
|
||||
}
|
||||
|
@ -2623,7 +2628,7 @@ static void format_tlv_router_cap(const struct isis_router_cap *router_cap,
|
|||
sbuf_push(buf, indent, " Algorithm: %s",
|
||||
router_cap->algo[0] == 0 ? "0: SPF"
|
||||
: "0: Strict SPF");
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
|
||||
for (int i = 1; i < SR_ALGORITHM_COUNT; i++)
|
||||
if (router_cap->algo[i] != SR_ALGORITHM_UNSET)
|
||||
sbuf_push(buf, indent, " %s",
|
||||
router_cap->algo[1] == 0
|
||||
|
@ -4630,24 +4635,42 @@ void isis_tlvs_del_lan_adj_sid(struct isis_ext_subtlvs *exts,
|
|||
}
|
||||
|
||||
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
|
||||
struct prefix_ipv4 *dest, uint32_t metric)
|
||||
struct prefix_ipv4 *dest, uint32_t metric,
|
||||
bool external, struct sr_prefix_cfg *pcfg)
|
||||
{
|
||||
struct isis_extended_ip_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
|
||||
|
||||
r->metric = metric;
|
||||
memcpy(&r->prefix, dest, sizeof(*dest));
|
||||
apply_mask_ipv4(&r->prefix);
|
||||
if (pcfg) {
|
||||
struct isis_prefix_sid *psid =
|
||||
XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*psid));
|
||||
|
||||
isis_sr_prefix_cfg2subtlv(pcfg, external, psid);
|
||||
r->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH);
|
||||
append_item(&r->subtlvs->prefix_sids, (struct isis_item *)psid);
|
||||
}
|
||||
append_item(&tlvs->extended_ip_reach, (struct isis_item *)r);
|
||||
}
|
||||
|
||||
void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||
struct prefix_ipv6 *dest, uint32_t metric)
|
||||
struct prefix_ipv6 *dest, uint32_t metric,
|
||||
bool external, struct sr_prefix_cfg *pcfg)
|
||||
{
|
||||
struct isis_ipv6_reach *r = XCALLOC(MTYPE_ISIS_TLV, sizeof(*r));
|
||||
|
||||
r->metric = metric;
|
||||
memcpy(&r->prefix, dest, sizeof(*dest));
|
||||
apply_mask_ipv6(&r->prefix);
|
||||
if (pcfg) {
|
||||
struct isis_prefix_sid *psid =
|
||||
XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*psid));
|
||||
|
||||
isis_sr_prefix_cfg2subtlv(pcfg, external, psid);
|
||||
r->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH);
|
||||
append_item(&r->subtlvs->prefix_sids, (struct isis_item *)psid);
|
||||
}
|
||||
|
||||
struct isis_item_list *l;
|
||||
l = (mtid == ISIS_MT_IPV4_UNICAST)
|
||||
|
@ -4661,7 +4684,7 @@ void isis_tlvs_add_ipv6_dstsrc_reach(struct isis_tlvs *tlvs, uint16_t mtid,
|
|||
struct prefix_ipv6 *src,
|
||||
uint32_t metric)
|
||||
{
|
||||
isis_tlvs_add_ipv6_reach(tlvs, mtid, dest, metric);
|
||||
isis_tlvs_add_ipv6_reach(tlvs, mtid, dest, metric, false, NULL);
|
||||
struct isis_item_list *l = isis_get_mt_items(&tlvs->mt_ipv6_reach,
|
||||
mtid);
|
||||
|
||||
|
|
|
@ -28,8 +28,11 @@
|
|||
#include "openbsd-tree.h"
|
||||
#include "prefix.h"
|
||||
|
||||
DECLARE_MTYPE(ISIS_SUBTLV)
|
||||
|
||||
struct lspdb_head;
|
||||
struct isis_subtlvs;
|
||||
struct sr_prefix_cfg;
|
||||
|
||||
struct isis_area_address;
|
||||
struct isis_area_address {
|
||||
|
@ -580,9 +583,11 @@ void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
|
|||
void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
|
||||
struct prefix_ipv4 *dest, uint8_t metric);
|
||||
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
|
||||
struct prefix_ipv4 *dest, uint32_t metric);
|
||||
struct prefix_ipv4 *dest, uint32_t metric,
|
||||
bool external, struct sr_prefix_cfg *pcfg);
|
||||
void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||
struct prefix_ipv6 *dest, uint32_t metric);
|
||||
struct prefix_ipv6 *dest, uint32_t metric,
|
||||
bool external, struct sr_prefix_cfg *pcfg);
|
||||
void isis_tlvs_add_ipv6_dstsrc_reach(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||
struct prefix_ipv6 *dest,
|
||||
struct prefix_ipv6 *src,
|
||||
|
|
|
@ -50,8 +50,16 @@
|
|||
#include "isisd/isis_route.h"
|
||||
#include "isisd/isis_zebra.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
|
||||
struct zclient *zclient = NULL;
|
||||
struct zclient *zclient;
|
||||
static struct zclient *zclient_sync;
|
||||
|
||||
/* List of chunks of labels externally assigned by zebra. */
|
||||
static struct list *label_chunk_list;
|
||||
static struct listnode *current_label_chunk;
|
||||
|
||||
static void isis_zebra_label_manager_connect(void);
|
||||
|
||||
/* Router-id update message from zebra. */
|
||||
static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
|
||||
|
@ -245,6 +253,88 @@ void isis_zebra_route_del_route(struct prefix *prefix,
|
|||
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
|
||||
}
|
||||
|
||||
/* Install Prefix-SID in the forwarding plane. */
|
||||
void isis_zebra_install_prefix_sid(const struct sr_prefix *srp)
|
||||
{
|
||||
struct zapi_labels zl;
|
||||
struct zapi_nexthop_label *znh;
|
||||
struct listnode *node;
|
||||
struct isis_nexthop *nexthop;
|
||||
struct interface *ifp;
|
||||
|
||||
/* Prepare message. */
|
||||
memset(&zl, 0, sizeof(zl));
|
||||
zl.type = ZEBRA_LSP_ISIS_SR;
|
||||
zl.local_label = srp->local_label;
|
||||
|
||||
switch (srp->type) {
|
||||
case ISIS_SR_PREFIX_LOCAL:
|
||||
ifp = if_lookup_by_name("lo", VRF_DEFAULT);
|
||||
if (!ifp) {
|
||||
zlog_warn(
|
||||
"%s: couldn't install Prefix-SID %pFX: loopback interface not found",
|
||||
__func__, &srp->prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
znh = &zl.nexthops[zl.nexthop_num++];
|
||||
znh->type = NEXTHOP_TYPE_IFINDEX;
|
||||
znh->ifindex = ifp->ifindex;
|
||||
znh->label = MPLS_LABEL_IMPLICIT_NULL;
|
||||
break;
|
||||
case ISIS_SR_PREFIX_REMOTE:
|
||||
/* Update route in the RIB too. */
|
||||
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
|
||||
zl.route.prefix = srp->prefix;
|
||||
zl.route.type = ZEBRA_ROUTE_ISIS;
|
||||
zl.route.instance = 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(srp->u.remote.rinfo->nexthops, node,
|
||||
nexthop)) {
|
||||
if (nexthop->sr.label == MPLS_INVALID_LABEL)
|
||||
continue;
|
||||
|
||||
if (zl.nexthop_num >= MULTIPATH_NUM)
|
||||
break;
|
||||
|
||||
znh = &zl.nexthops[zl.nexthop_num++];
|
||||
znh->type = (srp->prefix.family == AF_INET)
|
||||
? NEXTHOP_TYPE_IPV4_IFINDEX
|
||||
: NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
znh->family = nexthop->family;
|
||||
znh->address = nexthop->ip;
|
||||
znh->ifindex = nexthop->ifindex;
|
||||
znh->label = nexthop->sr.label;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Send message to zebra. */
|
||||
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);
|
||||
}
|
||||
|
||||
/* Uninstall Prefix-SID from the forwarding plane. */
|
||||
void isis_zebra_uninstall_prefix_sid(const struct sr_prefix *srp)
|
||||
{
|
||||
struct zapi_labels zl;
|
||||
|
||||
/* Prepare message. */
|
||||
memset(&zl, 0, sizeof(zl));
|
||||
zl.type = ZEBRA_LSP_ISIS_SR;
|
||||
zl.local_label = srp->local_label;
|
||||
|
||||
if (srp->type == ISIS_SR_PREFIX_REMOTE) {
|
||||
/* Update route in the RIB too. */
|
||||
SET_FLAG(zl.message, ZAPI_LABELS_FTN);
|
||||
zl.route.prefix = srp->prefix;
|
||||
zl.route.type = ZEBRA_ROUTE_ISIS;
|
||||
zl.route.instance = 0;
|
||||
}
|
||||
|
||||
/* Send message to zebra. */
|
||||
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
|
||||
}
|
||||
|
||||
static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
|
||||
{
|
||||
struct zapi_route api;
|
||||
|
@ -302,13 +392,192 @@ void isis_zebra_redistribute_unset(afi_t afi, int type)
|
|||
type, 0, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
/* Label Manager Requests. */
|
||||
int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t start, end;
|
||||
|
||||
if (zclient_sync->sock == -1)
|
||||
isis_zebra_label_manager_connect();
|
||||
|
||||
ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
|
||||
&end);
|
||||
if (ret < 0) {
|
||||
zlog_warn("%s: error getting label range!", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isis_zebra_release_label_range(uint32_t start, uint32_t end)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (zclient_sync->sock == -1)
|
||||
isis_zebra_label_manager_connect();
|
||||
|
||||
ret = lm_release_label_chunk(zclient_sync, start, end);
|
||||
if (ret < 0)
|
||||
zlog_warn("%s: error releasing label range!", __func__);
|
||||
}
|
||||
|
||||
static int isis_zebra_get_label_chunk(void)
|
||||
{
|
||||
int ret;
|
||||
uint32_t start, end;
|
||||
struct label_chunk *new_label_chunk;
|
||||
|
||||
if (zclient_sync->sock == -1)
|
||||
isis_zebra_label_manager_connect();
|
||||
|
||||
ret = lm_get_label_chunk(zclient_sync, 0, MPLS_LABEL_BASE_ANY,
|
||||
CHUNK_SIZE, &start, &end);
|
||||
if (ret < 0) {
|
||||
zlog_warn("%s: error getting label chunk!", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_label_chunk = calloc(1, sizeof(struct label_chunk));
|
||||
if (!new_label_chunk) {
|
||||
zlog_warn("%s: error trying to allocate label chunk %u - %u",
|
||||
__func__, start, end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_label_chunk->start = start;
|
||||
new_label_chunk->end = end;
|
||||
new_label_chunk->used_mask = 0;
|
||||
|
||||
listnode_add(label_chunk_list, (void *)new_label_chunk);
|
||||
|
||||
/* let's update current if needed */
|
||||
if (!current_label_chunk)
|
||||
current_label_chunk = listtail(label_chunk_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpls_label_t isis_zebra_request_dynamic_label(void)
|
||||
{
|
||||
struct label_chunk *label_chunk;
|
||||
uint32_t i, size;
|
||||
uint64_t pos;
|
||||
uint32_t label = MPLS_INVALID_LABEL;
|
||||
|
||||
while (current_label_chunk) {
|
||||
label_chunk = listgetdata(current_label_chunk);
|
||||
if (!label_chunk)
|
||||
goto end;
|
||||
|
||||
/* try to get next free label in currently used label chunk */
|
||||
size = label_chunk->end - label_chunk->start + 1;
|
||||
for (i = 0, pos = 1; i < size; i++, pos <<= 1) {
|
||||
if (!(pos & label_chunk->used_mask)) {
|
||||
label_chunk->used_mask |= pos;
|
||||
label = label_chunk->start + i;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
current_label_chunk = listnextnode(current_label_chunk);
|
||||
}
|
||||
|
||||
end:
|
||||
/*
|
||||
* we moved till the last chunk, or were not able to find a label, so
|
||||
* let's ask for another one.
|
||||
*/
|
||||
if (!current_label_chunk
|
||||
|| current_label_chunk == listtail(label_chunk_list)
|
||||
|| label == MPLS_INVALID_LABEL) {
|
||||
if (isis_zebra_get_label_chunk() != 0)
|
||||
zlog_warn("%s: error getting label chunk!", __func__);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static void isis_zebra_del_label_chunk(void *val)
|
||||
{
|
||||
free(val);
|
||||
}
|
||||
|
||||
static int isis_zebra_release_label_chunk(uint32_t start, uint32_t end)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lm_release_label_chunk(zclient_sync, start, end);
|
||||
if (ret < 0) {
|
||||
zlog_warn("%s: error releasing label chunk!", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isis_zebra_release_dynamic_label(mpls_label_t label)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct label_chunk *label_chunk;
|
||||
uint64_t pos;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(label_chunk_list, node, label_chunk)) {
|
||||
if (!(label <= label_chunk->end && label >= label_chunk->start))
|
||||
continue;
|
||||
|
||||
pos = 1ULL << (label - label_chunk->start);
|
||||
label_chunk->used_mask &= ~pos;
|
||||
|
||||
/*
|
||||
* If nobody is using this chunk and it's not
|
||||
* current_label_chunk, then free it.
|
||||
*/
|
||||
if (!label_chunk->used_mask && (current_label_chunk != node)) {
|
||||
if (isis_zebra_release_label_chunk(label_chunk->start,
|
||||
label_chunk->end)
|
||||
!= 0)
|
||||
zlog_warn("%s: error releasing label chunk!",
|
||||
__func__);
|
||||
else {
|
||||
listnode_delete(label_chunk_list, label_chunk);
|
||||
isis_zebra_del_label_chunk(label_chunk);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void isis_zebra_label_manager_connect(void)
|
||||
{
|
||||
/* Connect to label manager. */
|
||||
while (zclient_socket_connect(zclient_sync) < 0) {
|
||||
zlog_warn("%s: error connecting synchronous zclient!",
|
||||
__func__);
|
||||
sleep(1);
|
||||
}
|
||||
set_nonblocking(zclient_sync->sock);
|
||||
while (lm_label_manager_connect(zclient_sync, 0) != 0) {
|
||||
zlog_warn("%s: error connecting to label manager!", __func__);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
label_chunk_list = list_new();
|
||||
label_chunk_list->del = isis_zebra_del_label_chunk;
|
||||
while (isis_zebra_get_label_chunk() != 0) {
|
||||
zlog_warn("%s: error getting first label chunk!", __func__);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void isis_zebra_connected(struct zclient *zclient)
|
||||
{
|
||||
zclient_send_reg_requests(zclient, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
void isis_zebra_init(struct thread_master *master)
|
||||
void isis_zebra_init(struct thread_master *master, int instance)
|
||||
{
|
||||
/* Initialize asynchronous zclient. */
|
||||
zclient = zclient_new(master, &zclient_options_default);
|
||||
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
|
||||
zclient->zebra_connected = isis_zebra_connected;
|
||||
|
@ -319,7 +588,12 @@ void isis_zebra_init(struct thread_master *master)
|
|||
zclient->redistribute_route_add = isis_zebra_read;
|
||||
zclient->redistribute_route_del = isis_zebra_read;
|
||||
|
||||
return;
|
||||
/* Initialize special zclient for synchronous message exchanges. */
|
||||
zclient_sync = zclient_new(master, &zclient_options_default);
|
||||
zclient_sync->sock = -1;
|
||||
zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
|
||||
zclient_sync->instance = instance;
|
||||
zclient_sync->privs = &isisd_privs;
|
||||
}
|
||||
|
||||
void isis_zebra_stop(void)
|
||||
|
|
|
@ -24,10 +24,18 @@
|
|||
|
||||
extern struct zclient *zclient;
|
||||
|
||||
void isis_zebra_init(struct thread_master *);
|
||||
struct label_chunk {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint64_t used_mask;
|
||||
};
|
||||
#define CHUNK_SIZE 64
|
||||
|
||||
void isis_zebra_init(struct thread_master *master, int instance);
|
||||
void isis_zebra_stop(void);
|
||||
|
||||
struct isis_route_info;
|
||||
struct sr_prefix;
|
||||
|
||||
void isis_zebra_route_add_route(struct prefix *prefix,
|
||||
struct prefix_ipv6 *src_p,
|
||||
|
@ -35,8 +43,14 @@ void isis_zebra_route_add_route(struct prefix *prefix,
|
|||
void isis_zebra_route_del_route(struct prefix *prefix,
|
||||
struct prefix_ipv6 *src_p,
|
||||
struct isis_route_info *route_info);
|
||||
void isis_zebra_install_prefix_sid(const struct sr_prefix *srp);
|
||||
void isis_zebra_uninstall_prefix_sid(const struct sr_prefix *srp);
|
||||
int isis_distribute_list_update(int routetype);
|
||||
void isis_zebra_redistribute_set(afi_t afi, int type);
|
||||
void isis_zebra_redistribute_unset(afi_t afi, int type);
|
||||
int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size);
|
||||
void isis_zebra_release_label_range(uint32_t start, uint32_t end);
|
||||
mpls_label_t isis_zebra_request_dynamic_label(void);
|
||||
void isis_zebra_release_dynamic_label(mpls_label_t label);
|
||||
|
||||
#endif /* _ZEBRA_ISIS_ZEBRA_H */
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "isisd/isis_events.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
|
||||
|
@ -128,6 +129,8 @@ struct isis_area *isis_area_create(const char *area_tag)
|
|||
thread_add_timer(master, lsp_tick, area, 1, &area->t_tick);
|
||||
flags_initialize(&area->flags);
|
||||
|
||||
isis_sr_area_init(area);
|
||||
|
||||
/*
|
||||
* Default values
|
||||
*/
|
||||
|
@ -271,6 +274,8 @@ int isis_area_destroy(const char *area_tag)
|
|||
isis_area_invalidate_routes(area, area->is_type);
|
||||
isis_area_verify_routes(area);
|
||||
|
||||
isis_sr_area_term(area);
|
||||
|
||||
spftree_area_del(area);
|
||||
|
||||
THREAD_TIMER_OFF(area->spf_timer[0]);
|
||||
|
@ -748,6 +753,9 @@ void print_debug(struct vty *vty, int flags, int onoff)
|
|||
onoffs);
|
||||
if (flags & DEBUG_SPF_EVENTS)
|
||||
vty_out(vty, "IS-IS SPF events debugging is %s\n", onoffs);
|
||||
if (flags & DEBUG_SR)
|
||||
vty_out(vty, "IS-IS Segment Routing events debugging is %s\n",
|
||||
onoffs);
|
||||
if (flags & DEBUG_UPDATE_PACKETS)
|
||||
vty_out(vty, "IS-IS Update related packet debugging is %s\n",
|
||||
onoffs);
|
||||
|
@ -812,6 +820,10 @@ static int config_write_debug(struct vty *vty)
|
|||
vty_out(vty, "debug " PROTO_NAME " spf-events\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_SR) {
|
||||
vty_out(vty, "debug " PROTO_NAME " sr-events\n");
|
||||
write++;
|
||||
}
|
||||
if (flags & DEBUG_UPDATE_PACKETS) {
|
||||
vty_out(vty, "debug " PROTO_NAME " update-packets\n");
|
||||
write++;
|
||||
|
@ -1011,6 +1023,33 @@ DEFUN (no_debug_isis_spfevents,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_isis_srevents,
|
||||
debug_isis_srevents_cmd,
|
||||
"debug " PROTO_NAME " sr-events",
|
||||
DEBUG_STR
|
||||
PROTO_HELP
|
||||
"IS-IS Segment Routing Events\n")
|
||||
{
|
||||
isis->debugs |= DEBUG_SR;
|
||||
print_debug(vty, DEBUG_SR, 1);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_isis_srevents,
|
||||
no_debug_isis_srevents_cmd,
|
||||
"no debug " PROTO_NAME " sr-events",
|
||||
NO_STR
|
||||
UNDEBUG_STR
|
||||
PROTO_HELP
|
||||
"IS-IS Segment Routing Events\n")
|
||||
{
|
||||
isis->debugs &= ~DEBUG_SR;
|
||||
print_debug(vty, DEBUG_SR, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_isis_rtevents,
|
||||
debug_isis_rtevents_cmd,
|
||||
"debug " PROTO_NAME " route-events",
|
||||
|
@ -2198,6 +2237,8 @@ void isis_init(void)
|
|||
install_element(ENABLE_NODE, &no_debug_isis_upd_cmd);
|
||||
install_element(ENABLE_NODE, &debug_isis_spfevents_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_isis_spfevents_cmd);
|
||||
install_element(ENABLE_NODE, &debug_isis_srevents_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_isis_srevents_cmd);
|
||||
install_element(ENABLE_NODE, &debug_isis_rtevents_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_isis_rtevents_cmd);
|
||||
install_element(ENABLE_NODE, &debug_isis_events_cmd);
|
||||
|
@ -2223,6 +2264,8 @@ void isis_init(void)
|
|||
install_element(CONFIG_NODE, &no_debug_isis_upd_cmd);
|
||||
install_element(CONFIG_NODE, &debug_isis_spfevents_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_isis_spfevents_cmd);
|
||||
install_element(CONFIG_NODE, &debug_isis_srevents_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_isis_srevents_cmd);
|
||||
install_element(CONFIG_NODE, &debug_isis_rtevents_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_isis_rtevents_cmd);
|
||||
install_element(CONFIG_NODE, &debug_isis_events_cmd);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "isisd/isis_redist.h"
|
||||
#include "isisd/isis_pdu_counter.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
#include "isis_flags.h"
|
||||
#include "isis_lsp.h"
|
||||
#include "isis_memory.h"
|
||||
|
@ -165,6 +166,8 @@ struct isis_area {
|
|||
struct list *mt_settings;
|
||||
/* MPLS-TE settings */
|
||||
struct mpls_te_area *mta;
|
||||
/* Segment Routing information */
|
||||
struct isis_sr_db srdb;
|
||||
int ipv6_circuits;
|
||||
bool purge_originator;
|
||||
/* Counters */
|
||||
|
@ -218,6 +221,10 @@ int isis_area_passwd_cleartext_set(struct isis_area *area, int level,
|
|||
int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level,
|
||||
const char *passwd, uint8_t snp_auth);
|
||||
|
||||
/* YANG paths */
|
||||
#define ISIS_INSTANCE "/frr-isisd:isis/instance"
|
||||
#define ISIS_SR "/frr-isisd:isis/instance/segment-routing"
|
||||
|
||||
/* Master of threads. */
|
||||
extern struct thread_master *master;
|
||||
|
||||
|
@ -233,6 +240,7 @@ extern struct thread_master *master;
|
|||
#define DEBUG_FLOODING (1<<9)
|
||||
#define DEBUG_BFD (1<<10)
|
||||
#define DEBUG_TX_QUEUE (1<<11)
|
||||
#define DEBUG_SR (1<<12)
|
||||
|
||||
#define lsp_debug(...) \
|
||||
do { \
|
||||
|
|
|
@ -11,6 +11,7 @@ vtysh_scan += \
|
|||
isisd/isis_redist.c \
|
||||
isisd/isis_spf.c \
|
||||
isisd/isis_te.c \
|
||||
isisd/isis_sr.c \
|
||||
isisd/isis_vty_fabricd.c \
|
||||
isisd/isisd.c \
|
||||
# end
|
||||
|
@ -48,6 +49,7 @@ noinst_HEADERS += \
|
|||
isisd/isis_routemap.h \
|
||||
isisd/isis_spf.h \
|
||||
isisd/isis_spf_private.h \
|
||||
isisd/isis_sr.h \
|
||||
isisd/isis_te.h \
|
||||
isisd/isis_tlvs.h \
|
||||
isisd/isis_tx_queue.h \
|
||||
|
@ -77,6 +79,7 @@ LIBISIS_SOURCES = \
|
|||
isisd/isis_route.c \
|
||||
isisd/isis_routemap.c \
|
||||
isisd/isis_spf.c \
|
||||
isisd/isis_sr.c \
|
||||
isisd/isis_te.c \
|
||||
isisd/isis_tlvs.c \
|
||||
isisd/isis_tx_queue.c \
|
||||
|
|
|
@ -127,7 +127,8 @@ enum lsp_types_t {
|
|||
ZEBRA_LSP_LDP = 2, /* LDP LSP. */
|
||||
ZEBRA_LSP_BGP = 3, /* BGP LSP. */
|
||||
ZEBRA_LSP_OSPF_SR = 4,/* OSPF Segment Routing LSP. */
|
||||
ZEBRA_LSP_SHARP = 5, /* Identifier for test protocol */
|
||||
ZEBRA_LSP_ISIS_SR = 5,/* IS-IS Segment Routing LSP. */
|
||||
ZEBRA_LSP_SHARP = 6, /* Identifier for test protocol */
|
||||
};
|
||||
|
||||
/* Functions for basic label operations. */
|
||||
|
|
|
@ -430,6 +430,7 @@ static inline uint8_t lsp_distance(enum lsp_types_t type)
|
|||
case ZEBRA_LSP_NONE:
|
||||
case ZEBRA_LSP_SHARP:
|
||||
case ZEBRA_LSP_OSPF_SR:
|
||||
case ZEBRA_LSP_ISIS_SR:
|
||||
return 150;
|
||||
}
|
||||
|
||||
|
@ -457,6 +458,8 @@ static inline enum lsp_types_t lsp_type_from_re_type(int re_type)
|
|||
return ZEBRA_LSP_BGP;
|
||||
case ZEBRA_ROUTE_OSPF:
|
||||
return ZEBRA_LSP_OSPF_SR;
|
||||
case ZEBRA_ROUTE_ISIS:
|
||||
return ZEBRA_LSP_ISIS_SR;
|
||||
case ZEBRA_ROUTE_SHARP:
|
||||
return ZEBRA_LSP_SHARP;
|
||||
default:
|
||||
|
@ -478,6 +481,8 @@ static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
|
|||
return ZEBRA_ROUTE_BGP;
|
||||
case ZEBRA_LSP_OSPF_SR:
|
||||
return ZEBRA_ROUTE_OSPF;
|
||||
case ZEBRA_LSP_ISIS_SR:
|
||||
return ZEBRA_ROUTE_ISIS;
|
||||
case ZEBRA_LSP_NONE:
|
||||
return ZEBRA_ROUTE_KERNEL;
|
||||
case ZEBRA_LSP_SHARP:
|
||||
|
@ -505,6 +510,8 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
|
|||
return "BGP";
|
||||
case ZEBRA_LSP_OSPF_SR:
|
||||
return "SR (OSPF)";
|
||||
case ZEBRA_LSP_ISIS_SR:
|
||||
return "SR (IS-IS)";
|
||||
case ZEBRA_LSP_SHARP:
|
||||
return "SHARP";
|
||||
case ZEBRA_LSP_NONE:
|
||||
|
|
Loading…
Reference in a new issue