diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 9f82d85810..2650c5bcb7 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -43,8 +43,273 @@ #ifndef FABRICD +/* + * XPath: /frr-isisd:isis/instance + */ +DEFPY_NOSH(router_isis, router_isis_cmd, "router isis WORD$tag", + ROUTER_STR + "ISO IS-IS\n" + "ISO Routing area tag\n") +{ + int ret; + char base_xpath[XPATH_MAXLEN]; + + snprintf(base_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s']", tag); + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + /* default value in yang for is-type is level-1, but in FRR + * the first instance is assigned is-type level-1-2. We + * need to make sure to set it in the yang model so that it + * is consistent with what FRR sees. + */ + if (listcount(isis->area_list) == 0) + nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, + "level-1-2"); + ret = nb_cli_apply_changes(vty, base_xpath); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(ISIS_NODE, base_xpath); + + return ret; +} + +DEFPY(no_router_isis, no_router_isis_cmd, "no router isis WORD$tag", + NO_STR ROUTER_STR + "ISO IS-IS\n" + "ISO Routing area tag\n") +{ + char temp_xpath[XPATH_MAXLEN]; + struct listnode *node, *nnode; + struct isis_circuit *circuit = NULL; + struct isis_area *area = NULL; + + area = isis_area_lookup(tag); + if (!area) { + vty_out(vty, "ISIS area %s not found.\n", tag); + return CMD_ERR_NOTHING_TODO; + } + + nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL); + if (area->circuit_list && listcount(area->circuit_list)) { + for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode, + circuit)) { + /* add callbacks to delete each of the circuits listed + */ + const char *vrf_name = + vrf_lookup_by_id(circuit->interface->vrf_id) + ->name; + snprintf( + temp_xpath, XPATH_MAXLEN, + "/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis", + circuit->interface->name, vrf_name); + nb_cli_enqueue_change(vty, temp_xpath, NB_OP_DELETE, + NULL); + } + } + + return nb_cli_apply_changes( + vty, "/frr-isisd:isis/instance[area-tag='%s']", tag); +} + +void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, "!\n"); + vty_out(vty, "router isis %s\n", + yang_dnode_get_string(dnode, "./area-tag")); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing + * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv6-routing + * XPath: /frr-isisd:isis/instance + */ +DEFPY(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n") +{ + char temp_xpath[XPATH_MAXLEN]; + const char *circ_type; + struct isis_area *area; + + /* area will be created if it is not present. make sure the yang model + * is synced with FRR and call the appropriate NB cb. + */ + area = isis_area_lookup(tag); + if (!area) { + snprintf(temp_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s']", tag); + nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag); + snprintf(temp_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s']/is-type", + tag); + nb_cli_enqueue_change( + vty, temp_xpath, NB_OP_MODIFY, + listcount(isis->area_list) == 0 ? "level-1-2" : NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, + NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", + NB_OP_MODIFY, tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing", + NB_OP_CREATE, NULL); + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, + listcount(isis->area_list) == 0 ? "level-1-2" + : "level-1"); + } else { + /* area exists, circuit type defaults to its area's is_type */ + switch (area->is_type) { + case IS_LEVEL_1: + circ_type = "level-1"; + break; + case IS_LEVEL_2: + circ_type = "level-2"; + break; + case IS_LEVEL_1_AND_2: + circ_type = "level-1-2"; + break; + } + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, + NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", + NB_OP_MODIFY, tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing", + NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", + NB_OP_MODIFY, circ_type); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n") +{ + char temp_xpath[XPATH_MAXLEN]; + const char *circ_type; + struct isis_area *area; + + /* area will be created if it is not present. make sure the yang model + * is synced with FRR and call the appropriate NB cb. + */ + area = isis_area_lookup(tag); + if (!area) { + snprintf(temp_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s']", tag); + nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag); + snprintf(temp_xpath, XPATH_MAXLEN, + "/frr-isisd:isis/instance[area-tag='%s']/is-type", + tag); + nb_cli_enqueue_change( + vty, temp_xpath, NB_OP_MODIFY, + listcount(isis->area_list) == 0 ? "level-1-2" : NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, + NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", + NB_OP_MODIFY, tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing", + NB_OP_CREATE, NULL); + nb_cli_enqueue_change( + vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY, + listcount(isis->area_list) == 0 ? "level-1-2" + : "level-1"); + } else { + /* area exists, circuit type defaults to its area's is_type */ + switch (area->is_type) { + case IS_LEVEL_1: + circ_type = "level-1"; + break; + case IS_LEVEL_2: + circ_type = "level-2"; + break; + case IS_LEVEL_1_AND_2: + circ_type = "level-1-2"; + break; + } + nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, + NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", + NB_OP_MODIFY, tag); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing", + NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type", + NB_OP_MODIFY, circ_type); + } + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY(no_ip_router_isis, no_ip_router_isis_cmd, + "no $ip router isis [WORD]$tag", + NO_STR + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IP router interface commands\n" + "IS-IS routing protocol\n" + "Routing process tag\n") +{ + const struct lyd_node *dnode = + yang_dnode_get(running_config->dnode, VTY_CURR_XPATH); + struct interface *ifp; + struct isis_circuit *circuit = NULL; + + /* check for the existance of a circuit */ + if (dnode) { + ifp = yang_dnode_get_entry(dnode, false); + if (ifp) + circuit = circuit_scan_by_ifp(ifp); + } + + /* if both ipv4 and ipv6 are off delete the interface isis container too + */ + if (!strncmp(ip, "ipv6", strlen("ipv6"))) { + if (circuit && !circuit->ip_router) + nb_cli_enqueue_change(vty, "./frr-isisd:isis", + NB_OP_DELETE, NULL); + else + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/ipv6-routing", + NB_OP_DELETE, NULL); + } else { /* no ipv4 */ + if (circuit && !circuit->ipv6_router) + nb_cli_enqueue_change(vty, "./frr-isisd:isis", + NB_OP_DELETE, NULL); + else + nb_cli_enqueue_change(vty, + "./frr-isisd:isis/ipv4-routing", + NB_OP_DELETE, NULL); + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " ip router isis %s\n", + yang_dnode_get_string(dnode, "../area-tag")); +} + +void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " ipv6 router isis %s\n", + yang_dnode_get_string(dnode, "../area-tag")); +} + void isis_cli_init(void) { + install_element(CONFIG_NODE, &router_isis_cmd); + install_element(CONFIG_NODE, &no_router_isis_cmd); + + 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); } #endif /* ifndef FABRICD */ diff --git a/isisd/isis_cli.h b/isisd/isis_cli.h index 952bd9d744..e986087595 100644 --- a/isisd/isis_cli.h +++ b/isisd/isis_cli.h @@ -21,5 +21,11 @@ #define ISISD_ISIS_CLI_H_ /* add cli_show declarations here as externs */ +void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +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); #endif /* ISISD_ISIS_CLI_H_ */ diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index 23c4fec4ff..7114512345 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -54,14 +54,35 @@ static int isis_instance_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct isis_area *area; + const char *area_tag; + + if (event != NB_EV_APPLY) + return NB_OK; + + area_tag = yang_dnode_get_string(dnode, "./area-tag"); + area = isis_area_lookup(area_tag); + if (area) + return NB_ERR_INCONSISTENCY; + + area = isis_area_create(area_tag); + /* save area in dnode to avoid looking it up all the time */ + yang_dnode_set_entry(dnode, area); + return NB_OK; } static int isis_instance_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + const char *area_tag; + + if (event != NB_EV_APPLY) + return NB_OK; + + area_tag = yang_dnode_get_string(dnode, "./area-tag"); + isis_area_destroy(area_tag); + return NB_OK; } @@ -72,7 +93,16 @@ static int isis_instance_is_type_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct isis_area *area; + int type; + + if (event != NB_EV_APPLY) + return NB_OK; + + area = yang_dnode_get_entry(dnode, true); + type = yang_dnode_get_enum(dnode, NULL); + isis_area_is_type_set(area, type); + return NB_OK; } @@ -1003,14 +1033,63 @@ static int lib_interface_isis_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct isis_area *area; + struct interface *ifp; + struct isis_circuit *circuit; + const char *area_tag = yang_dnode_get_string(dnode, "./area-tag"); + + if (event != NB_EV_APPLY) + return NB_OK; + + area = isis_area_lookup(area_tag); + /* The area should have already be created. We are + * setting the priority of the global isis area creation + * slightly lower, so it should be executed first, but I + * cannot rely on that so here I have to check. + */ + if (!area) { + flog_err( + EC_LIB_NB_CB_CONFIG_APPLY, + "%s: attempt to create circuit for area %s before the area has been created", + __func__, area_tag); + abort(); + } + + ifp = yang_dnode_get_entry(dnode, true); + circuit = isis_circuit_create(area, ifp); + assert(circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP); + yang_dnode_set_entry(dnode, circuit); + return NB_OK; } static int lib_interface_isis_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = yang_dnode_get_entry(dnode, true); + if (!circuit) + return NB_ERR_INCONSISTENCY; + /* delete circuit through csm changes */ + switch (circuit->state) { + case C_STATE_UP: + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, + circuit->interface); + isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area); + break; + case C_STATE_CONF: + isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area); + break; + case C_STATE_INIT: + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, + circuit->interface); + break; + } + return NB_OK; } @@ -1021,7 +1100,32 @@ static int lib_interface_isis_area_tag_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + struct isis_circuit *circuit; + struct interface *ifp; + struct vrf *vrf; + const char *area_tag, *ifname, *vrfname; + + if (event == NB_EV_VALIDATE) { + /* libyang doesn't like relative paths across module boundaries + */ + ifname = yang_dnode_get_string(dnode->parent->parent, "./name"); + vrfname = yang_dnode_get_string(dnode->parent->parent, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + assert(vrf); + ifp = if_lookup_by_name(ifname, vrf->vrf_id); + if (!ifp) + return NB_OK; + circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); + area_tag = yang_dnode_get_string(dnode, NULL); + if (circuit && circuit->area && circuit->area->area_tag + && strcmp(circuit->area->area_tag, area_tag)) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "ISIS circuit is already defined on %s", + circuit->area->area_tag); + return NB_ERR_VALIDATION; + } + } + return NB_OK; } @@ -1032,7 +1136,42 @@ static int lib_interface_isis_circuit_type_modify(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + int circ_type = yang_dnode_get_enum(dnode, NULL); + struct isis_circuit *circuit; + struct interface *ifp; + struct vrf *vrf; + const char *ifname, *vrfname; + + switch (event) { + case NB_EV_VALIDATE: + /* libyang doesn't like relative paths across module boundaries + */ + ifname = yang_dnode_get_string(dnode->parent->parent, "./name"); + vrfname = yang_dnode_get_string(dnode->parent->parent, "./vrf"); + vrf = vrf_lookup_by_name(vrfname); + assert(vrf); + ifp = if_lookup_by_name(ifname, vrf->vrf_id); + if (!ifp) + break; + circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list); + if (circuit && circuit->state == C_STATE_UP + && circuit->area->is_type != IS_LEVEL_1_AND_2 + && circuit->area->is_type != circ_type) { + flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE, + "Invalid circuit level for area %s", + circuit->area->area_tag); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + circuit = yang_dnode_get_entry(dnode, true); + isis_circuit_is_type_set(circuit, circ_type); + break; + } + return NB_OK; } @@ -1043,14 +1182,34 @@ static int lib_interface_isis_ipv4_routing_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + bool ipv6; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = yang_dnode_get_entry(dnode, true); + ipv6 = yang_dnode_exists(dnode, "../ipv6-routing"); + isis_circuit_af_set(circuit, true, ipv6); + return NB_OK; } static int lib_interface_isis_ipv4_routing_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + bool ipv6; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = yang_dnode_get_entry(dnode, true); + if (circuit && circuit->area) { + ipv6 = yang_dnode_exists(dnode, "../ipv6-routing"); + isis_circuit_af_set(circuit, false, ipv6); + } + return NB_OK; } @@ -1061,14 +1220,34 @@ static int lib_interface_isis_ipv6_routing_create(enum nb_event event, const struct lyd_node *dnode, union nb_resource *resource) { - /* TODO: implement me. */ + bool ipv4; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = yang_dnode_get_entry(dnode, true); + ipv4 = yang_dnode_exists(dnode, "../ipv6-routing"); + isis_circuit_af_set(circuit, ipv4, true); + return NB_OK; } static int lib_interface_isis_ipv6_routing_delete(enum nb_event event, const struct lyd_node *dnode) { - /* TODO: implement me. */ + bool ipv4; + struct isis_circuit *circuit; + + if (event != NB_EV_APPLY) + return NB_OK; + + circuit = yang_dnode_get_entry(dnode, true); + if (circuit->area) { + ipv4 = yang_dnode_exists(dnode, "../ipv4-routing"); + isis_circuit_af_set(circuit, ipv4, false); + } + return NB_OK; } @@ -1415,6 +1594,8 @@ const struct frr_yang_module_info frr_isisd_info = { .xpath = "/frr-isisd:isis/instance", .cbs.create = isis_instance_create, .cbs.delete = isis_instance_delete, + .cbs.cli_show = cli_show_router_isis, + .priority = NB_DFLT_PRIORITY - 1, }, { .xpath = "/frr-isisd:isis/instance/is-type", @@ -1705,11 +1886,13 @@ const struct frr_yang_module_info frr_isisd_info = { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/ipv4-routing", .cbs.create = lib_interface_isis_ipv4_routing_create, .cbs.delete = lib_interface_isis_ipv4_routing_delete, + .cbs.cli_show = cli_show_ip_isis_ipv4, }, { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/ipv6-routing", .cbs.create = lib_interface_isis_ipv6_routing_create, .cbs.delete = lib_interface_isis_ipv6_routing_delete, + .cbs.cli_show = cli_show_ip_isis_ipv6, }, { .xpath = "/frr-interface:lib/interface/frr-isisd:isis/csnp-interval/level-1", diff --git a/isisd/isis_vty_common.c b/isisd/isis_vty_common.c index c211763042..f5ca9c1dd3 100644 --- a/isisd/isis_vty_common.c +++ b/isisd/isis_vty_common.c @@ -57,109 +57,6 @@ struct isis_circuit *isis_circuit_lookup(struct vty *vty) return circuit; } -DEFUN (ip_router_isis, - ip_router_isis_cmd, - "ip router " PROTO_NAME " WORD", - "Interface Internet Protocol config commands\n" - "IP router interface commands\n" - PROTO_HELP - "Routing process tag\n") -{ - int idx_afi = 0; - int idx_word = 3; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct isis_circuit *circuit; - struct isis_area *area; - const char *af = argv[idx_afi]->arg; - const char *area_tag = argv[idx_word]->arg; - - /* Prevent more than one area per circuit */ - circuit = circuit_scan_by_ifp(ifp); - if (circuit && circuit->area) { - if (strcmp(circuit->area->area_tag, area_tag)) { - vty_out(vty, "ISIS circuit is already defined on %s\n", - circuit->area->area_tag); - return CMD_ERR_NOTHING_TODO; - } - } - - area = isis_area_lookup(area_tag); - if (!area) - area = isis_area_create(area_tag); - - if (!circuit || !circuit->area) { - circuit = isis_circuit_create(area, ifp); - - if (circuit->state != C_STATE_CONF - && circuit->state != C_STATE_UP) { - vty_out(vty, - "Couldn't bring up interface, please check log.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; - if (af[2] != '\0') - ipv6 = true; - else - ip = true; - - isis_circuit_af_set(circuit, ip, ipv6); - return CMD_SUCCESS; -} - -DEFUN (ip6_router_isis, - ip6_router_isis_cmd, - "ipv6 router " PROTO_NAME " WORD", - "Interface Internet Protocol config commands\n" - "IP router interface commands\n" - PROTO_HELP - "Routing process tag\n") -{ - return ip_router_isis(self, vty, argc, argv); -} - -DEFUN (no_ip_router_isis, - no_ip_router_isis_cmd, - "no router " PROTO_NAME " WORD", - NO_STR - "Interface Internet Protocol config commands\n" - "IP router interface commands\n" - "IP router interface commands\n" - PROTO_HELP - "Routing process tag\n") -{ - int idx_afi = 1; - int idx_word = 4; - VTY_DECLVAR_CONTEXT(interface, ifp); - struct isis_area *area; - struct isis_circuit *circuit; - const char *af = argv[idx_afi]->arg; - const char *area_tag = argv[idx_word]->arg; - - area = isis_area_lookup(area_tag); - if (!area) { - vty_out(vty, "Can't find ISIS instance %s\n", - area_tag); - return CMD_ERR_NO_MATCH; - } - - circuit = circuit_lookup_by_ifp(ifp, area->circuit_list); - if (!circuit) { - vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name); - return CMD_ERR_NO_MATCH; - } - - bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; - if (af[2] != '\0') - ipv6 = false; - else - ip = false; - - isis_circuit_af_set(circuit, ip, ipv6); - return CMD_SUCCESS; -} - DEFUN (isis_passive, isis_passive_cmd, PROTO_NAME " passive", @@ -947,10 +844,6 @@ DEFUN (no_domain_passwd, void isis_vty_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(INTERFACE_NODE, &isis_passive_cmd); install_element(INTERFACE_NODE, &no_isis_passive_cmd); diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index aa48fe1d3a..819b61dc7e 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -29,6 +29,7 @@ #include "isisd/isis_tlvs.h" #include "isisd/isis_misc.h" #include "isisd/isis_lsp.h" +#include "isisd/isis_csm.h" DEFUN (fabric_tier, fabric_tier_cmd, @@ -181,6 +182,109 @@ DEFUN (show_lsp_flooding, return CMD_SUCCESS; } +DEFUN (ip_router_isis, + ip_router_isis_cmd, + "ip router " PROTO_NAME " WORD", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + PROTO_HELP + "Routing process tag\n") +{ + int idx_afi = 0; + int idx_word = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct isis_circuit *circuit; + struct isis_area *area; + const char *af = argv[idx_afi]->arg; + const char *area_tag = argv[idx_word]->arg; + + /* Prevent more than one area per circuit */ + circuit = circuit_scan_by_ifp(ifp); + if (circuit && circuit->area) { + if (strcmp(circuit->area->area_tag, area_tag)) { + vty_out(vty, "ISIS circuit is already defined on %s\n", + circuit->area->area_tag); + return CMD_ERR_NOTHING_TODO; + } + } + + area = isis_area_lookup(area_tag); + if (!area) + area = isis_area_create(area_tag); + + if (!circuit || !circuit->area) { + circuit = isis_circuit_create(area, ifp); + + if (circuit->state != C_STATE_CONF + && circuit->state != C_STATE_UP) { + vty_out(vty, + "Couldn't bring up interface, please check log.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; + if (af[2] != '\0') + ipv6 = true; + else + ip = true; + + isis_circuit_af_set(circuit, ip, ipv6); + return CMD_SUCCESS; +} + +DEFUN (ip6_router_isis, + ip6_router_isis_cmd, + "ipv6 router " PROTO_NAME " WORD", + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + PROTO_HELP + "Routing process tag\n") +{ + return ip_router_isis(self, vty, argc, argv); +} + +DEFUN (no_ip_router_isis, + no_ip_router_isis_cmd, + "no router " PROTO_NAME " WORD", + NO_STR + "Interface Internet Protocol config commands\n" + "IP router interface commands\n" + "IP router interface commands\n" + PROTO_HELP + "Routing process tag\n") +{ + int idx_afi = 1; + int idx_word = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct isis_area *area; + struct isis_circuit *circuit; + const char *af = argv[idx_afi]->arg; + const char *area_tag = argv[idx_word]->arg; + + area = isis_area_lookup(area_tag); + if (!area) { + vty_out(vty, "Can't find ISIS instance %s\n", + area_tag); + return CMD_ERR_NO_MATCH; + } + + circuit = circuit_lookup_by_ifp(ifp, area->circuit_list); + if (!circuit) { + vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name); + return CMD_ERR_NO_MATCH; + } + + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; + if (af[2] != '\0') + ipv6 = false; + else + ip = false; + + isis_circuit_af_set(circuit, ip, ipv6); + return CMD_SUCCESS; +} + void isis_vty_daemon_init(void) { install_element(ROUTER_NODE, &fabric_tier_cmd); @@ -189,4 +293,8 @@ void isis_vty_daemon_init(void) install_element(ROUTER_NODE, &no_triggered_csnp_cmd); install_element(ENABLE_NODE, &show_lsp_flooding_cmd); + + 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); } diff --git a/isisd/isisd.c b/isisd/isisd.c index 0e496193a3..3721dff3b4 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -36,6 +36,7 @@ #include "table.h" #include "qobj.h" #include "spf_backoff.h" +#include "lib/northbound_cli.h" #include "isisd/dict.h" #include "isisd/isis_constants.h" @@ -67,7 +68,6 @@ DEFINE_QOBJ_TYPE(isis_area) * Prototypes. */ int isis_area_get(struct vty *, const char *); -int isis_area_destroy(struct vty *, const char *); int area_net_title(struct vty *, const char *); int area_clear_net_title(struct vty *, const char *); int show_isis_interface_common(struct vty *, const char *ifname, char); @@ -207,7 +207,7 @@ int isis_area_get(struct vty *vty, const char *area_tag) return CMD_SUCCESS; } -int isis_area_destroy(struct vty *vty, const char *area_tag) +int isis_area_destroy(const char *area_tag) { struct isis_area *area; struct listnode *node, *nnode; @@ -217,7 +217,8 @@ int isis_area_destroy(struct vty *vty, const char *area_tag) area = isis_area_lookup(area_tag); if (area == NULL) { - vty_out(vty, "Can't find ISIS instance \n"); + zlog_warn("%s: could not find area with area-tag %s", + __func__, area_tag); return CMD_ERR_NO_MATCH; } @@ -1452,12 +1453,13 @@ DEFUN (show_database, return show_isis_database(vty, id, uilevel); } +#ifdef FABRICD /* - * 'router isis' command + * 'router openfabric' command */ -DEFUN_NOSH (router_isis, - router_isis_cmd, - "router " PROTO_NAME " WORD", +DEFUN_NOSH (router_openfabric, + router_openfabric_cmd, + "router openfabric WORD", ROUTER_STR PROTO_HELP "ISO Routing area tag\n") @@ -1467,20 +1469,20 @@ DEFUN_NOSH (router_isis, } /* - *'no router isis' command + *'no router openfabric' command */ -DEFUN (no_router_isis, - no_router_isis_cmd, - "no router " PROTO_NAME " WORD", +DEFUN (no_router_openfabric, + no_router_openfabric_cmd, + "no router openfabric WORD", NO_STR ROUTER_STR PROTO_HELP "ISO Routing area tag\n") { int idx_word = 3; - return isis_area_destroy(vty, argv[idx_word]->arg); + return isis_area_destroy(argv[idx_word]->arg); } - +#endif /* ifdef FABRICD */ /* * 'net' command */ @@ -2179,11 +2181,12 @@ void isis_init() install_element(CONFIG_NODE, &debug_isis_bfd_cmd); install_element(CONFIG_NODE, &no_debug_isis_bfd_cmd); - install_element(CONFIG_NODE, &router_isis_cmd); - install_element(CONFIG_NODE, &no_router_isis_cmd); - install_default(ROUTER_NODE); +#ifdef FABRICD + install_element(CONFIG_NODE, &router_openfabric_cmd); + install_element(CONFIG_NODE, &no_router_openfabric_cmd); +#endif /* ifdef FABRICD */ install_element(ROUTER_NODE, &net_cmd); install_element(ROUTER_NODE, &no_net_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index 14677ac7a5..8447a309b2 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -29,6 +29,7 @@ #include "isisd/isis_common.h" #include "isisd/isis_redist.h" #include "isisd/isis_pdu_counter.h" +#include "isisd/isis_circuit.h" #include "isis_flags.h" #include "dict.h" #include "isis_memory.h" @@ -185,6 +186,7 @@ void isis_new(unsigned long); struct isis_area *isis_area_create(const char *); struct isis_area *isis_area_lookup(const char *); int isis_area_get(struct vty *vty, const char *area_tag); +int isis_area_destroy(const char *area_tag); void print_debug(struct vty *, int, int); struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb);