From: Christian Franke Date: Thu, 27 Apr 2017 11:56:35 +0000 (+0200) Subject: isisd: add MT configuration X-Git-Tag: reindent-master-before~209^2~5 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=064f48967b1d352511702dd4e999a0e790835d2a;p=mirror_frr.git isisd: add MT configuration Signed-off-by: Christian Franke --- diff --git a/isisd/Makefile.am b/isisd/Makefile.am index c97385f87..2973820ee 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -16,7 +16,7 @@ libisis_a_SOURCES = \ isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \ isis_spf.c isis_redist.c isis_route.c isis_routemap.c isis_te.c \ - isis_vty.c + isis_vty.c isis_mt.c noinst_HEADERS = \ @@ -25,7 +25,7 @@ noinst_HEADERS = \ isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \ isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \ iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_redist.h \ - isis_route.h isis_routemap.h isis_te.h + isis_route.h isis_routemap.h isis_te.h isis_mt.h isisd_SOURCES = \ isis_main.c $(libisis_a_SOURCES) \ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 6207ae189..6caf8200e 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -60,6 +60,7 @@ #include "isisd/isis_csm.h" #include "isisd/isis_events.h" #include "isisd/isis_te.h" +#include "isisd/isis_mt.h" DEFINE_QOBJ_TYPE(isis_circuit) @@ -102,6 +103,8 @@ isis_circuit_new () circuit->mtc = mpls_te_circuit_new(); + circuit_mt_init(circuit); + QOBJ_REG (circuit, isis_circuit); return circuit; @@ -117,6 +120,8 @@ isis_circuit_del (struct isis_circuit *circuit) isis_circuit_if_unbind (circuit, circuit->interface); + circuit_mt_finish(circuit); + /* and lastly the circuit itself */ XFREE (MTYPE_ISIS_CIRCUIT, circuit); @@ -1215,6 +1220,7 @@ isis_interface_config_write (struct vty *vty) VTY_NEWLINE); write++; } + write += circuit_write_mt_settings(circuit, vty); } vty_out (vty, "!%s", VTY_NEWLINE); } @@ -1382,6 +1388,22 @@ isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type) return 0; } +int +isis_circuit_mt_enabled_set (struct isis_circuit *circuit, uint16_t mtid, + bool enabled) +{ + struct isis_circuit_mt_setting *setting; + + setting = circuit_get_mt_setting(circuit, mtid); + if (setting->enabled != enabled) + { + setting->enabled = enabled; + lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); + } + + return CMD_SUCCESS; +} + int isis_if_new_hook (struct interface *ifp) { diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index bb0dc0f98..16dfa6304 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -123,6 +123,7 @@ struct isis_circuit struct mpls_te_circuit *mtc; /* Support for MPLS-TE parameters - see isis_te.[c,h] */ int ip_router; /* Route IP ? */ int is_passive; /* Is Passive ? */ + struct list *mt_settings; /* IS-IS MT Settings */ struct list *ip_addrs; /* our IP addresses */ int ipv6_router; /* Route IPv6 ? */ struct list *ipv6_link; /* our link local IPv6 addresses */ @@ -187,4 +188,6 @@ int isis_circuit_passwd_unset (struct isis_circuit *circuit); int isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd); int isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd); +int isis_circuit_mt_enabled_set (struct isis_circuit *circuit, uint16_t mtid, bool enabled); + #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c new file mode 100644 index 000000000..7908fd4bb --- /dev/null +++ b/isisd/isis_mt.c @@ -0,0 +1,262 @@ +/* + * IS-IS Rout(e)ing protocol - Multi Topology Support + * + * Copyright (C) 2017 Christian Franke + * + * This file is part of FreeRangeRouting (FRR) + * + * FRR 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, or (at your option) any + * later version. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include +#include "isisd/isisd.h" +#include "isisd/isis_memory.h" +#include "isisd/isis_circuit.h" +#include "isisd/isis_mt.h" + +DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting") +DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting") + +/* MT naming api */ +const char *isis_mtid2str(uint16_t mtid) +{ + switch(mtid) + { + case ISIS_MT_IPV4_UNICAST: + return "ipv4-unicast"; + case ISIS_MT_IPV4_MGMT: + return "ipv4-mgmt"; + case ISIS_MT_IPV6_UNICAST: + return "ipv6-unicast"; + case ISIS_MT_IPV4_MULTICAST: + return "ipv4-multicast"; + case ISIS_MT_IPV6_MULTICAST: + return "ipv6-multicast"; + case ISIS_MT_IPV6_MGMT: + return "ipv6-mgmt"; + default: + return NULL; + } +} + +uint16_t isis_str2mtid(const char *name) +{ + if (!strcmp(name,"ipv4-unicast")) + return ISIS_MT_IPV4_UNICAST; + if (!strcmp(name,"ipv4-mgmt")) + return ISIS_MT_IPV4_MGMT; + if (!strcmp(name,"ipv6-unicast")) + return ISIS_MT_IPV6_UNICAST; + if (!strcmp(name,"ipv4-multicast")) + return ISIS_MT_IPV4_MULTICAST; + if (!strcmp(name,"ipv6-multicast")) + return ISIS_MT_IPV6_MULTICAST; + if (!strcmp(name,"ipv6-mgmt")) + return ISIS_MT_IPV6_MGMT; + return -1; +} + +/* General MT settings api */ + +struct mt_setting { + ISIS_MT_INFO_FIELDS; +}; + +static void * +lookup_mt_setting(struct list *mt_list, uint16_t mtid) +{ + struct listnode *node; + struct mt_setting *setting; + + for (ALL_LIST_ELEMENTS_RO(mt_list, node, setting)) + { + if (setting->mtid == mtid) + return setting; + } + return NULL; +} + +static void +add_mt_setting(struct list **mt_list, void *setting) +{ + if (!*mt_list) + *mt_list = list_new(); + listnode_add(*mt_list, setting); +} + +/* Area specific MT settings api */ + +struct isis_area_mt_setting* +area_lookup_mt_setting(struct isis_area *area, uint16_t mtid) +{ + return lookup_mt_setting(area->mt_settings, mtid); +} + +struct isis_area_mt_setting* +area_new_mt_setting(struct isis_area *area, uint16_t mtid) +{ + struct isis_area_mt_setting *setting; + + setting = XCALLOC(MTYPE_MT_AREA_SETTING, sizeof(*setting)); + setting->mtid = mtid; + return setting; +} + +static void +area_free_mt_setting(void *setting) +{ + XFREE(MTYPE_MT_AREA_SETTING, setting); +} + +void +area_add_mt_setting(struct isis_area *area, struct isis_area_mt_setting *setting) +{ + add_mt_setting(&area->mt_settings, setting); +} + +void +area_mt_init(struct isis_area *area) +{ + struct isis_area_mt_setting *v4_unicast_setting; + + /* MTID 0 is always enabled */ + v4_unicast_setting = area_new_mt_setting(area, ISIS_MT_IPV4_UNICAST); + v4_unicast_setting->enabled = true; + add_mt_setting(&area->mt_settings, v4_unicast_setting); + area->mt_settings->del = area_free_mt_setting; +} + +void +area_mt_finish(struct isis_area *area) +{ + list_delete(area->mt_settings); + area->mt_settings = NULL; +} + +struct isis_area_mt_setting * +area_get_mt_setting(struct isis_area *area, uint16_t mtid) +{ + struct isis_area_mt_setting *setting; + + setting = area_lookup_mt_setting(area, mtid); + if (!setting) + { + setting = area_new_mt_setting(area, mtid); + area_add_mt_setting(area, setting); + } + return setting; +} + +int +area_write_mt_settings(struct isis_area *area, struct vty *vty) +{ + int written = 0; + struct listnode *node; + struct isis_area_mt_setting *setting; + + for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) + { + const char *name = isis_mtid2str(setting->mtid); + if (name && setting->enabled) + { + if (setting->mtid == ISIS_MT_IPV4_UNICAST) + continue; /* always enabled, no need to write out config */ + vty_out (vty, " topology %s%s%s", name, + setting->overload ? " overload" : "", + VTY_NEWLINE); + written++; + } + } + return written; +} + +/* Circuit specific MT settings api */ + +struct isis_circuit_mt_setting* +circuit_lookup_mt_setting(struct isis_circuit *circuit, uint16_t mtid) +{ + return lookup_mt_setting(circuit->mt_settings, mtid); +} + +struct isis_circuit_mt_setting* +circuit_new_mt_setting(struct isis_circuit *circuit, uint16_t mtid) +{ + struct isis_circuit_mt_setting *setting; + + setting = XCALLOC(MTYPE_MT_CIRCUIT_SETTING, sizeof(*setting)); + setting->mtid = mtid; + setting->enabled = true; /* Enabled is default for circuit */ + return setting; +} + +static void +circuit_free_mt_setting(void *setting) +{ + XFREE(MTYPE_MT_CIRCUIT_SETTING, setting); +} + +void +circuit_add_mt_setting(struct isis_circuit *circuit, + struct isis_circuit_mt_setting *setting) +{ + add_mt_setting(&circuit->mt_settings, setting); +} + +void +circuit_mt_init(struct isis_circuit *circuit) +{ + circuit->mt_settings = list_new(); + circuit->mt_settings->del = circuit_free_mt_setting; +} + +void +circuit_mt_finish(struct isis_circuit *circuit) +{ + list_delete(circuit->mt_settings); + circuit->mt_settings = NULL; +} + +struct isis_circuit_mt_setting* +circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid) +{ + struct isis_circuit_mt_setting *setting; + + setting = circuit_lookup_mt_setting(circuit, mtid); + if (!setting) + { + setting = circuit_new_mt_setting(circuit, mtid); + circuit_add_mt_setting(circuit, setting); + } + return setting; +} + +int +circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty) +{ + int written = 0; + struct listnode *node; + struct isis_circuit_mt_setting *setting; + + for (ALL_LIST_ELEMENTS_RO (circuit->mt_settings, node, setting)) + { + const char *name = isis_mtid2str(setting->mtid); + if (name && !setting->enabled) + { + vty_out (vty, " no isis topology %s%s", name, VTY_NEWLINE); + written++; + } + } + return written; +} diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h new file mode 100644 index 000000000..a6f401357 --- /dev/null +++ b/isisd/isis_mt.h @@ -0,0 +1,97 @@ +/* + * IS-IS Rout(e)ing protocol - Multi Topology Support + * + * Copyright (C) 2017 Christian Franke + * + * This file is part of FreeRangeRouting (FRR) + * + * FRR 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, or (at your option) any + * later version. + * + * FRR 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 FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef ISIS_MT_H +#define ISIS_MT_H + +#define ISIS_MT_IPV4_UNICAST 0 +#define ISIS_MT_IPV4_MGMT 1 +#define ISIS_MT_IPV6_UNICAST 2 +#define ISIS_MT_IPV4_MULTICAST 3 +#define ISIS_MT_IPV6_MULTICAST 4 +#define ISIS_MT_IPV6_MGMT 5 + +#define ISIS_MT_NAMES \ + "" + +#define ISIS_MT_DESCRIPTIONS \ + "IPv4 unicast topology\n" \ + "IPv4 management topology\n" \ + "IPv6 unicast topology\n" \ + "IPv4 multicast topology\n" \ + "IPv6 multicast topology\n" \ + "IPv6 management topology\n" + +#define ISIS_MT_INFO_FIELDS \ + uint16_t mtid; + +struct isis_area_mt_setting { + ISIS_MT_INFO_FIELDS + bool enabled; + bool overload; +}; + +struct isis_circuit_mt_setting { + ISIS_MT_INFO_FIELDS + bool enabled; +}; + +const char *isis_mtid2str(uint16_t mtid); +uint16_t isis_str2mtid(const char *name); + +struct isis_area; +struct isis_circuit; + +struct isis_area_mt_setting* area_lookup_mt_setting(struct isis_area *area, + uint16_t mtid); +struct isis_area_mt_setting* area_new_mt_setting(struct isis_area *area, + uint16_t mtid); +void area_add_mt_setting(struct isis_area *area, + struct isis_area_mt_setting *setting); + +void area_mt_init(struct isis_area *area); +void area_mt_finish(struct isis_area *area); +struct isis_area_mt_setting* area_get_mt_setting(struct isis_area *area, + uint16_t mtid); +int area_write_mt_settings(struct isis_area *area, struct vty *vty); + +struct isis_circuit_mt_setting* circuit_lookup_mt_setting( + struct isis_circuit *circuit, + uint16_t mtid); +struct isis_circuit_mt_setting* circuit_new_mt_setting( + struct isis_circuit *circuit, + uint16_t mtid); +void circuit_add_mt_setting(struct isis_circuit *circuit, + struct isis_circuit_mt_setting *setting); +void circuit_mt_init(struct isis_circuit *circuit); +void circuit_mt_finish(struct isis_circuit *circuit); +struct isis_circuit_mt_setting* circuit_get_mt_setting( + struct isis_circuit *circuit, + uint16_t mtid); +int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty); +#endif diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 721959859..1658ca373 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -29,6 +29,7 @@ #include "isis_circuit.h" #include "isis_csm.h" #include "isis_misc.h" +#include "isis_mt.h" #include "isisd.h" static struct isis_circuit * @@ -1271,6 +1272,48 @@ DEFUN (no_psnp_interval_l2, return CMD_SUCCESS; } +DEFUN (circuit_topology, + circuit_topology_cmd, + "isis topology " ISIS_MT_NAMES, + "IS-IS commands\n" + "Configure interface IS-IS topologies\n" + ISIS_MT_DESCRIPTIONS) +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + const char *arg = argv[2]->arg; + uint16_t mtid = isis_str2mtid(arg); + if (mtid == (uint16_t)-1) + { + vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + return isis_circuit_mt_enabled_set(circuit, mtid, true); +} + +DEFUN (no_circuit_topology, + no_circuit_topology_cmd, + "no isis topology " ISIS_MT_NAMES, + NO_STR + "IS-IS commands\n" + "Configure interface IS-IS topologies\n" + ISIS_MT_DESCRIPTIONS) +{ + struct isis_circuit *circuit = isis_circuit_lookup (vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + const char *arg = argv[3]->arg; + uint16_t mtid = isis_str2mtid(arg); + if (mtid == (uint16_t)-1) + { + vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + return isis_circuit_mt_enabled_set(circuit, mtid, false); +} static int validate_metric_style_narrow (struct vty *vty, struct isis_area *area) @@ -2116,6 +2159,9 @@ isis_vty_init (void) install_element (INTERFACE_NODE, &psnp_interval_l2_cmd); install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd); + install_element (INTERFACE_NODE, &circuit_topology_cmd); + install_element (INTERFACE_NODE, &no_circuit_topology_cmd); + install_element (ISIS_NODE, &metric_style_cmd); install_element (ISIS_NODE, &no_metric_style_cmd); diff --git a/isisd/isisd.c b/isisd/isisd.c index f226c4a1f..179e43098 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -56,6 +56,7 @@ #include "isisd/isis_zebra.h" #include "isisd/isis_events.h" #include "isisd/isis_te.h" +#include "isisd/isis_mt.h" struct isis *isis = NULL; @@ -156,6 +157,8 @@ isis_area_create (const char *area_tag) area->lsp_frag_threshold = 90; area->lsp_mtu = DEFAULT_LSP_MTU; + area_mt_init(area); + area->area_tag = strdup (area_tag); listnode_add (isis->area_list, area); area->isis = isis; @@ -296,6 +299,8 @@ isis_area_destroy (struct vty *vty, const char *area_tag) free (area->area_tag); + area_mt_finish(area); + XFREE (MTYPE_ISIS_AREA, area); if (listcount (isis->area_list) == 0) @@ -307,6 +312,33 @@ isis_area_destroy (struct vty *vty, const char *area_tag) return CMD_SUCCESS; } +static void +area_set_mt_enabled(struct isis_area *area, uint16_t mtid, bool enabled) +{ + struct isis_area_mt_setting *setting; + + setting = area_get_mt_setting(area, mtid); + if (setting->enabled != enabled) + { + setting->enabled = enabled; + lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); + } +} + +static void +area_set_mt_overload(struct isis_area *area, uint16_t mtid, bool overload) +{ + struct isis_area_mt_setting *setting; + + setting = area_get_mt_setting(area, mtid); + if (setting->overload != overload) + { + setting->overload = overload; + if (setting->enabled) + lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); + } +} + int area_net_title (struct vty *vty, const char *net_title) { @@ -1626,6 +1658,61 @@ DEFUN (no_net, return area_clear_net_title (vty, argv[idx_word]->arg); } +DEFUN (isis_topology, + isis_topology_cmd, + "topology " ISIS_MT_NAMES " [overload]", + "Configure IS-IS topologies\n" + ISIS_MT_DESCRIPTIONS + "Set overload bit for topology\n") +{ + VTY_DECLVAR_CONTEXT (isis_area, area); + + const char *arg = argv[1]->arg; + uint16_t mtid = isis_str2mtid(arg); + if (mtid == (uint16_t)-1) + { + vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == ISIS_MT_IPV4_UNICAST) + { + vty_out (vty, "Cannot configure IPv4 unicast topology%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + area_set_mt_enabled(area, mtid, true); + area_set_mt_overload(area, mtid, (argc == 3)); + return CMD_SUCCESS; +} + +DEFUN (no_isis_topology, + no_isis_topology_cmd, + "no topology " ISIS_MT_NAMES " [overload]", + NO_STR + "Configure IS-IS topologies\n" + ISIS_MT_DESCRIPTIONS + "Set overload bit for topology\n") +{ + VTY_DECLVAR_CONTEXT (isis_area, area); + + const char *arg = argv[2]->arg; + uint16_t mtid = isis_str2mtid(arg); + if (mtid == (uint16_t)-1) + { + vty_out (vty, "Don't know topology '%s'%s", arg, VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == ISIS_MT_IPV4_UNICAST) + { + vty_out (vty, "Cannot configure IPv4 unicast topology%s", VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + + area_set_mt_enabled(area, mtid, false); + area_set_mt_overload(area, mtid, false); + return CMD_SUCCESS; +} + void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu) { area->lsp_mtu = lsp_mtu; @@ -2148,6 +2235,7 @@ isis_config_write (struct vty *vty) write++; } + write += area_write_mt_settings(area, vty); } isis_mpls_te_config_write_router(vty); } @@ -2254,6 +2342,9 @@ isis_init () install_element (ISIS_NODE, &net_cmd); install_element (ISIS_NODE, &no_net_cmd); + install_element (ISIS_NODE, &isis_topology_cmd); + install_element (ISIS_NODE, &no_isis_topology_cmd); + install_element (ISIS_NODE, &log_adj_changes_cmd); install_element (ISIS_NODE, &no_log_adj_changes_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index e1d3a69f8..a8cf3673f 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -120,6 +120,8 @@ struct isis_area int ip_circuits; /* logging adjacency changes? */ u_char log_adj_changes; + /* multi topology settings */ + struct list *mt_settings; int ipv6_circuits; /* Counters */ u_int32_t circuit_state_changes;