isisd: add MT configuration

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
Christian Franke 2017-04-27 13:56:35 +02:00
parent 316a98ecd1
commit 064f48967b
8 changed files with 525 additions and 2 deletions

View File

@ -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) \

View File

@ -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)
{

View File

@ -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 */

262
isisd/isis_mt.c Normal file
View File

@ -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 <zebra.h>
#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;
}

97
isisd/isis_mt.h Normal file
View File

@ -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 \
"<ipv4-unicast" \
"|ipv4-mgmt" \
"|ipv6-unicast" \
"|ipv4-multicast" \
"|ipv6-multicast" \
"|ipv6-mgmt" \
">"
#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

View File

@ -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);

View File

@ -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);

View File

@ -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;