diff options
author | Emanuele Di Pascale <emanuele@voltanet.io> | 2018-11-13 17:33:49 +0100 |
---|---|---|
committer | Emanuele Di Pascale <emanuele@voltanet.io> | 2018-12-18 15:21:15 +0100 |
commit | f084ea552361c94d008ed0bfe5c87224ff06a55d (patch) | |
tree | c0a342ca75d92c870b0541f818dccdaf68900c84 | |
parent | isisd: retrofit 'router isis' and 'ip router isis' cmds (diff) | |
download | frr-f084ea552361c94d008ed0bfe5c87224ff06a55d.tar.xz frr-f084ea552361c94d008ed0bfe5c87224ff06a55d.zip |
isisd: retrofit the 'net' command
This is a simple command but with a complex callback, the only
one in isisd which uses the resource allocation API implemented
in the northbound (i.e. the PREPARE phase).
Signed-off-by: Emanuele Di Pascale <emanuele@voltanet.io>
Diffstat (limited to '')
-rw-r--r-- | isisd/isis_cli.c | 22 | ||||
-rw-r--r-- | isisd/isis_cli.h | 2 | ||||
-rw-r--r-- | isisd/isis_northbound.c | 113 | ||||
-rw-r--r-- | isisd/isis_vty_fabricd.c | 1 | ||||
-rw-r--r-- | isisd/isisd.c | 6 |
5 files changed, 140 insertions, 4 deletions
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 2650c5bcb..41632b0a7 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -302,6 +302,26 @@ void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "../area-tag")); } +/* + * XPath: /frr-isisd:isis/instance/area-address + */ +DEFPY(net, net_cmd, "[no] net WORD", + "Remove an existing Network Entity Title for this process\n" + "A Network Entity Title for this process (OSI only)\n" + "XX.XXXX. ... .XXX.XX Network entity title (NET)\n") +{ + nb_cli_enqueue_change(vty, "./area-address", + no ? NB_OP_DELETE : NB_OP_CREATE, net); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " net %s\n", yang_dnode_get_string(dnode, NULL)); +} + void isis_cli_init(void) { install_element(CONFIG_NODE, &router_isis_cmd); @@ -310,6 +330,8 @@ void isis_cli_init(void) install_element(INTERFACE_NODE, &ip_router_isis_cmd); install_element(INTERFACE_NODE, &ip6_router_isis_cmd); install_element(INTERFACE_NODE, &no_ip_router_isis_cmd); + + install_element(ISIS_NODE, &net_cmd); } #endif /* ifndef FABRICD */ diff --git a/isisd/isis_cli.h b/isisd/isis_cli.h index e98608759..b052f75c2 100644 --- a/isisd/isis_cli.h +++ b/isisd/isis_cli.h @@ -27,5 +27,7 @@ void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_isis_area_address(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); #endif /* ISISD_ISIS_CLI_H_ */ diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index 711451234..10f8f1e75 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -113,14 +113,122 @@ static int isis_instance_area_address_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct isis_area *area; + struct area_addr addr, *addrr = NULL, *addrp = NULL; + struct listnode *node; + uint8_t buff[255]; + const char *net_title = yang_dnode_get_string(dnode, NULL); + + switch (event) { + case NB_EV_VALIDATE: + addr.addr_len = dotformat2buff(buff, net_title); + memcpy(addr.area_addr, buff, addr.addr_len); + if (addr.area_addr[addr.addr_len - 1] != 0) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "nsel byte (last byte) in area address must be 0"); + return NB_ERR_VALIDATION; + } + if (isis->sysid_set) { + /* Check that the SystemID portions match */ + if (memcmp(isis->sysid, GETSYSID((&addr)), + ISIS_SYS_ID_LEN)) { + flog_warn( + EC_LIB_NB_CB_CONFIG_VALIDATE, + "System ID must not change when defining additional area addresses"); + return NB_ERR_VALIDATION; + } + } + break; + case NB_EV_PREPARE: + addrr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr)); + addrr->addr_len = dotformat2buff(buff, net_title); + memcpy(addrr->area_addr, buff, addrr->addr_len); + resource->ptr = addrr; + break; + case NB_EV_ABORT: + XFREE(MTYPE_ISIS_AREA_ADDR, resource->ptr); + break; + case NB_EV_APPLY: + area = yang_dnode_get_entry(dnode, true); + addrr = resource->ptr; + + if (isis->sysid_set == 0) { + /* + * First area address - get the SystemID for this router + */ + memcpy(isis->sysid, GETSYSID(addrr), ISIS_SYS_ID_LEN); + isis->sysid_set = 1; + } else { + /* check that we don't already have this address */ + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, + addrp)) { + if ((addrp->addr_len + ISIS_SYS_ID_LEN + + ISIS_NSEL_LEN) + != (addrr->addr_len)) + continue; + if (!memcmp(addrp->area_addr, addrr->area_addr, + addrr->addr_len)) { + XFREE(MTYPE_ISIS_AREA_ADDR, addrr); + return NB_OK; /* silent fail */ + } + } + } + + /*Forget the systemID part of the address */ + addrr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN); + assert(area->area_addrs); /* to silence scan-build sillyness */ + listnode_add(area->area_addrs, addrr); + + /* only now we can safely generate our LSPs for this area */ + if (listcount(area->area_addrs) > 0) { + if (area->is_type & IS_LEVEL_1) + lsp_generate(area, IS_LEVEL_1); + if (area->is_type & IS_LEVEL_2) + lsp_generate(area, IS_LEVEL_2); + } + break; + } + return NB_OK; } static int isis_instance_area_address_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + struct area_addr addr, *addrp = NULL; + struct listnode *node; + uint8_t buff[255]; + struct isis_area *area; + const char *net_title; + + if (event != NB_EV_APPLY) + return NB_OK; + + net_title = yang_dnode_get_string(dnode, NULL); + addr.addr_len = dotformat2buff(buff, net_title); + memcpy(addr.area_addr, buff, (int)addr.addr_len); + area = yang_dnode_get_entry(dnode, true); + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) { + if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len + && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len)) + break; + } + if (!addrp) + return NB_ERR_INCONSISTENCY; + + listnode_delete(area->area_addrs, addrp); + XFREE(MTYPE_ISIS_AREA_ADDR, addrp); + /* + * Last area address - reset the SystemID for this router + */ + if (listcount(area->area_addrs) == 0) { + memset(isis->sysid, 0, ISIS_SYS_ID_LEN); + isis->sysid_set = 0; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("Router has no SystemID"); + } + return NB_OK; } @@ -1605,6 +1713,7 @@ const struct frr_yang_module_info frr_isisd_info = { .xpath = "/frr-isisd:isis/instance/area-address", .cbs.create = isis_instance_area_address_create, .cbs.delete = isis_instance_area_address_delete, + .cbs.cli_show = cli_show_isis_area_address, }, { .xpath = "/frr-isisd:isis/instance/dynamic-hostname", diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index 819b61dc7..e420988f1 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -30,6 +30,7 @@ #include "isisd/isis_misc.h" #include "isisd/isis_lsp.h" #include "isisd/isis_csm.h" +#include "isisd/isis_circuit.h" DEFUN (fabric_tier, fabric_tier_cmd, diff --git a/isisd/isisd.c b/isisd/isisd.c index 3721dff3b..084cbf16c 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1483,6 +1483,7 @@ DEFUN (no_router_openfabric, return isis_area_destroy(argv[idx_word]->arg); } #endif /* ifdef FABRICD */ +#ifdef FABRICD /* * 'net' command */ @@ -1509,7 +1510,7 @@ DEFUN (no_net, int idx_word = 2; return area_clear_net_title(vty, argv[idx_word]->arg); } - +#endif /* ifdef FABRICD */ DEFUN (isis_topology, isis_topology_cmd, "topology " ISIS_MT_NAMES " [overload]", @@ -2187,9 +2188,10 @@ void isis_init() install_element(CONFIG_NODE, &router_openfabric_cmd); install_element(CONFIG_NODE, &no_router_openfabric_cmd); #endif /* ifdef FABRICD */ +#ifdef FABRICD install_element(ROUTER_NODE, &net_cmd); install_element(ROUTER_NODE, &no_net_cmd); - +#endif /* ifdef FABRICD */ install_element(ROUTER_NODE, &isis_topology_cmd); install_element(ROUTER_NODE, &no_isis_topology_cmd); |