mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 05:27:47 +00:00
isisd: add support to import routes from other protocols
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
parent
6ac446878f
commit
f3ccedaa3e
@ -17,14 +17,15 @@ libisis_a_SOURCES = \
|
|||||||
isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \
|
isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \
|
||||||
isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \
|
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_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \
|
||||||
isis_spf.c isis_route.c isis_routemap.c
|
isis_spf.c isis_redist.c isis_route.c isis_routemap.c
|
||||||
|
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \
|
isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \
|
||||||
isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \
|
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 \
|
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_route.h \
|
iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_redist.h \
|
||||||
|
isis_route.h isis_routemap.h \
|
||||||
include-netbsd/clnp.h include-netbsd/esis.h include-netbsd/iso.h
|
include-netbsd/clnp.h include-netbsd/esis.h include-netbsd/iso.h
|
||||||
|
|
||||||
isisd_SOURCES = \
|
isisd_SOURCES = \
|
||||||
|
134
isisd/isis_lsp.c
134
isisd/isis_lsp.c
@ -5,9 +5,10 @@
|
|||||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
||||||
* Tampere University of Technology
|
* Tampere University of Technology
|
||||||
* Institute of Communications Engineering
|
* Institute of Communications Engineering
|
||||||
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public Licenseas published by the Free
|
* 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)
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
*
|
||||||
@ -35,6 +36,7 @@
|
|||||||
#include "if.h"
|
#include "if.h"
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
#include "table.h"
|
||||||
|
|
||||||
#include "isisd/dict.h"
|
#include "isisd/dict.h"
|
||||||
#include "isisd/isis_constants.h"
|
#include "isisd/isis_constants.h"
|
||||||
@ -1146,6 +1148,119 @@ lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area,
|
|||||||
return lsp;
|
return lsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, struct isis_area *area,
|
||||||
|
struct tlvs *tlv_data)
|
||||||
|
{
|
||||||
|
struct route_table *er_table;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct prefix_ipv4 *ipv4;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
struct ipv4_reachability *ipreach;
|
||||||
|
struct te_ipv4_reachability *te_ipreach;
|
||||||
|
|
||||||
|
er_table = get_ext_reach(area, AF_INET, lsp->level);
|
||||||
|
if (!er_table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (rn = route_top(er_table); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ipv4 = (struct prefix_ipv4*)&rn->p;
|
||||||
|
info = rn->info;
|
||||||
|
if (area->oldmetric)
|
||||||
|
{
|
||||||
|
if (tlv_data->ipv4_ext_reachs == NULL)
|
||||||
|
{
|
||||||
|
tlv_data->ipv4_ext_reachs = list_new();
|
||||||
|
tlv_data->ipv4_ext_reachs->del = free_tlv;
|
||||||
|
}
|
||||||
|
ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach));
|
||||||
|
|
||||||
|
ipreach->prefix.s_addr = ipv4->prefix.s_addr;
|
||||||
|
masklen2ip(ipv4->prefixlen, &ipreach->mask);
|
||||||
|
ipreach->prefix.s_addr &= ipreach->mask.s_addr;
|
||||||
|
|
||||||
|
if ((info->metric & 0x3f) != info->metric)
|
||||||
|
ipreach->metrics.metric_default = 0x3f;
|
||||||
|
else
|
||||||
|
ipreach->metrics.metric_default = info->metric;
|
||||||
|
ipreach->metrics.metric_expense = METRICS_UNSUPPORTED;
|
||||||
|
ipreach->metrics.metric_error = METRICS_UNSUPPORTED;
|
||||||
|
ipreach->metrics.metric_delay = METRICS_UNSUPPORTED;
|
||||||
|
listnode_add(tlv_data->ipv4_ext_reachs, ipreach);
|
||||||
|
}
|
||||||
|
if (area->newmetric)
|
||||||
|
{
|
||||||
|
if (tlv_data->te_ipv4_reachs == NULL)
|
||||||
|
{
|
||||||
|
tlv_data->te_ipv4_reachs = list_new();
|
||||||
|
tlv_data->te_ipv4_reachs->del = free_tlv;
|
||||||
|
}
|
||||||
|
te_ipreach =
|
||||||
|
XCALLOC(MTYPE_ISIS_TLV,
|
||||||
|
sizeof(*te_ipreach) - 1 + PSIZE(ipv4->prefixlen));
|
||||||
|
if (info->metric > MAX_WIDE_PATH_METRIC)
|
||||||
|
te_ipreach->te_metric = htonl(MAX_WIDE_PATH_METRIC);
|
||||||
|
else
|
||||||
|
te_ipreach->te_metric = htonl(info->metric);
|
||||||
|
te_ipreach->control = ipv4->prefixlen & 0x3f;
|
||||||
|
memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr,
|
||||||
|
PSIZE(ipv4->prefixlen));
|
||||||
|
listnode_add(tlv_data->te_ipv4_reachs, te_ipreach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, struct isis_area *area,
|
||||||
|
struct tlvs *tlv_data)
|
||||||
|
{
|
||||||
|
struct route_table *er_table;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct prefix_ipv6 *ipv6;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
struct ipv6_reachability *ip6reach;
|
||||||
|
|
||||||
|
er_table = get_ext_reach(area, AF_INET6, lsp->level);
|
||||||
|
if (!er_table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (rn = route_top(er_table); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ipv6 = (struct prefix_ipv6*)&rn->p;
|
||||||
|
info = rn->info;
|
||||||
|
|
||||||
|
if (tlv_data->ipv6_reachs == NULL)
|
||||||
|
{
|
||||||
|
tlv_data->ipv6_reachs = list_new();
|
||||||
|
tlv_data->ipv6_reachs->del = free_tlv;
|
||||||
|
}
|
||||||
|
ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach));
|
||||||
|
if (info->metric > MAX_WIDE_PATH_METRIC)
|
||||||
|
ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC);
|
||||||
|
else
|
||||||
|
ip6reach->metric = htonl(info->metric);
|
||||||
|
ip6reach->control_info = DISTRIBUTION_EXTERNAL;
|
||||||
|
ip6reach->prefix_len = ipv6->prefixlen;
|
||||||
|
memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, sizeof(ip6reach->prefix));
|
||||||
|
listnode_add(tlv_data->ipv6_reachs, ip6reach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lsp_build_ext_reach (struct isis_lsp *lsp, struct isis_area *area,
|
||||||
|
struct tlvs *tlv_data)
|
||||||
|
{
|
||||||
|
lsp_build_ext_reach_ipv4(lsp, area, tlv_data);
|
||||||
|
lsp_build_ext_reach_ipv6(lsp, area, tlv_data);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Builds the LSP data part. This func creates a new frag whenever
|
* Builds the LSP data part. This func creates a new frag whenever
|
||||||
* area->lsp_frag_threshold is exceeded.
|
* area->lsp_frag_threshold is exceeded.
|
||||||
@ -1561,6 +1676,8 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lsp_build_ext_reach(lsp, area, &tlv_data);
|
||||||
|
|
||||||
lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", area->area_tag);
|
lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", area->area_tag);
|
||||||
|
|
||||||
while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
|
while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
|
||||||
@ -1570,12 +1687,25 @@ lsp_build (struct isis_lsp *lsp, struct isis_area *area)
|
|||||||
lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
|
lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs,
|
||||||
&lsp->tlv_data.ipv4_int_reachs,
|
&lsp->tlv_data.ipv4_int_reachs,
|
||||||
IPV4_REACH_LEN, area->lsp_frag_threshold,
|
IPV4_REACH_LEN, area->lsp_frag_threshold,
|
||||||
tlv_add_ipv4_reachs);
|
tlv_add_ipv4_int_reachs);
|
||||||
if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
|
if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs))
|
||||||
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
|
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
|
||||||
lsp0, area, level);
|
lsp0, area, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs))
|
||||||
|
{
|
||||||
|
if (lsp->tlv_data.ipv4_ext_reachs == NULL)
|
||||||
|
lsp->tlv_data.ipv4_ext_reachs = list_new ();
|
||||||
|
lsp_tlv_fit (lsp, &tlv_data.ipv4_ext_reachs,
|
||||||
|
&lsp->tlv_data.ipv4_ext_reachs,
|
||||||
|
IPV4_REACH_LEN, area->lsp_frag_threshold,
|
||||||
|
tlv_add_ipv4_ext_reachs);
|
||||||
|
if (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs))
|
||||||
|
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1,
|
||||||
|
lsp0, area, level);
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit()
|
/* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit()
|
||||||
* for now. lsp_tlv_fit() needs to be fixed to deal with variable length
|
* for now. lsp_tlv_fit() needs to be fixed to deal with variable length
|
||||||
* TLVs (sub TLVs!). */
|
* TLVs (sub TLVs!). */
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "privs.h"
|
#include "privs.h"
|
||||||
#include "sigevent.h"
|
#include "sigevent.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "plist.h"
|
||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
#include "systemd.h"
|
#include "systemd.h"
|
||||||
@ -48,6 +49,7 @@
|
|||||||
#include "isisd/isis_dynhn.h"
|
#include "isisd/isis_dynhn.h"
|
||||||
#include "isisd/isis_spf.h"
|
#include "isisd/isis_spf.h"
|
||||||
#include "isisd/isis_route.h"
|
#include "isisd/isis_route.h"
|
||||||
|
#include "isisd/isis_routemap.h"
|
||||||
#include "isisd/isis_zebra.h"
|
#include "isisd/isis_zebra.h"
|
||||||
|
|
||||||
/* Default configuration file name */
|
/* Default configuration file name */
|
||||||
@ -339,9 +341,12 @@ main (int argc, char **argv, char **envp)
|
|||||||
memory_init ();
|
memory_init ();
|
||||||
access_list_init();
|
access_list_init();
|
||||||
vrf_init ();
|
vrf_init ();
|
||||||
|
prefix_list_init();
|
||||||
isis_init ();
|
isis_init ();
|
||||||
isis_circuit_init ();
|
isis_circuit_init ();
|
||||||
isis_spf_cmds_init ();
|
isis_spf_cmds_init ();
|
||||||
|
isis_redist_init ();
|
||||||
|
isis_route_map_init();
|
||||||
|
|
||||||
/* create the global 'isis' instance */
|
/* create the global 'isis' instance */
|
||||||
isis_new (1);
|
isis_new (1);
|
||||||
|
821
isisd/isis_redist.c
Normal file
821
isisd/isis_redist.c
Normal file
@ -0,0 +1,821 @@
|
|||||||
|
/*
|
||||||
|
* IS-IS Rout(e)ing protocol - isis_redist.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
||||||
|
*
|
||||||
|
* 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; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
|
||||||
|
#include "command.h"
|
||||||
|
#include "if.h"
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "memtypes.h"
|
||||||
|
#include "prefix.h"
|
||||||
|
#include "routemap.h"
|
||||||
|
#include "stream.h"
|
||||||
|
#include "table.h"
|
||||||
|
#include "vty.h"
|
||||||
|
|
||||||
|
#include "isisd/dict.h"
|
||||||
|
#include "isisd/isis_constants.h"
|
||||||
|
#include "isisd/isis_common.h"
|
||||||
|
#include "isisd/isis_flags.h"
|
||||||
|
#include "isisd/isis_misc.h"
|
||||||
|
#include "isisd/isis_circuit.h"
|
||||||
|
#include "isisd/isis_tlv.h"
|
||||||
|
#include "isisd/isisd.h"
|
||||||
|
#include "isisd/isis_lsp.h"
|
||||||
|
#include "isisd/isis_route.h"
|
||||||
|
#include "isisd/isis_zebra.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
redist_protocol(int family)
|
||||||
|
{
|
||||||
|
if (family == AF_INET)
|
||||||
|
return 0;
|
||||||
|
if (family == AF_INET6)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
assert(!"Unsupported address family!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_default(struct prefix *p)
|
||||||
|
{
|
||||||
|
if (p->family == AF_INET)
|
||||||
|
if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0)
|
||||||
|
return 1;
|
||||||
|
if (p->family == AF_INET6)
|
||||||
|
if (IN6_IS_ADDR_UNSPECIFIED(&p->u.prefix6) && p->prefixlen == 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct route_table*
|
||||||
|
get_ext_info(struct isis *i, int family)
|
||||||
|
{
|
||||||
|
int protocol = redist_protocol(family);
|
||||||
|
|
||||||
|
return i->ext_info[protocol];
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct isis_redist*
|
||||||
|
get_redist_settings(struct isis_area *area, int family, int type, int level)
|
||||||
|
{
|
||||||
|
int protocol = redist_protocol(family);
|
||||||
|
|
||||||
|
return &area->redist_settings[protocol][type][level-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct route_table*
|
||||||
|
get_ext_reach(struct isis_area *area, int family, int level)
|
||||||
|
{
|
||||||
|
int protocol = redist_protocol(family);
|
||||||
|
|
||||||
|
return area->ext_reach[protocol][level-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct route_node *
|
||||||
|
isis_redist_route_node_create(route_table_delegate_t *delegate,
|
||||||
|
struct route_table *table)
|
||||||
|
{
|
||||||
|
struct route_node *node;
|
||||||
|
node = XCALLOC(MTYPE_ROUTE_NODE, sizeof(*node));
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isis_redist_route_node_destroy(route_table_delegate_t *delegate,
|
||||||
|
struct route_table *table,
|
||||||
|
struct route_node *node)
|
||||||
|
{
|
||||||
|
if (node->info)
|
||||||
|
XFREE(MTYPE_ISIS, node->info);
|
||||||
|
XFREE (MTYPE_ROUTE_NODE, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static route_table_delegate_t isis_redist_rt_delegate = {
|
||||||
|
.create_node = isis_redist_route_node_create,
|
||||||
|
.destroy_node = isis_redist_route_node_destroy
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Install external reachability information into a
|
||||||
|
* specific area for a specific level.
|
||||||
|
* Schedule an lsp regenerate if necessary */
|
||||||
|
static void
|
||||||
|
isis_redist_install(struct isis_area *area, int level,
|
||||||
|
struct prefix *p, struct isis_ext_info *info)
|
||||||
|
{
|
||||||
|
int family = p->family;
|
||||||
|
struct route_table *er_table = get_ext_reach(area, family, level);
|
||||||
|
struct route_node *er_node;
|
||||||
|
|
||||||
|
if (!er_table)
|
||||||
|
{
|
||||||
|
zlog_warn("%s: External reachability table of area %s"
|
||||||
|
" is not initialized.", __func__, area->area_tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
er_node = route_node_get(er_table, p);
|
||||||
|
if (er_node->info)
|
||||||
|
{
|
||||||
|
route_unlock_node(er_node);
|
||||||
|
|
||||||
|
/* Don't update/reschedule lsp generation if nothing changed. */
|
||||||
|
if (!memcmp(er_node->info, info, sizeof(*info)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
er_node->info = XMALLOC(MTYPE_ISIS, sizeof(*info));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(er_node->info, info, sizeof(*info));
|
||||||
|
lsp_regenerate_schedule(area, level, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove external reachability information from a
|
||||||
|
* specific area for a specific level.
|
||||||
|
* Schedule an lsp regenerate if necessary. */
|
||||||
|
static void
|
||||||
|
isis_redist_uninstall(struct isis_area *area, int level, struct prefix *p)
|
||||||
|
{
|
||||||
|
int family = p->family;
|
||||||
|
struct route_table *er_table = get_ext_reach(area, family, level);
|
||||||
|
struct route_node *er_node;
|
||||||
|
|
||||||
|
if (!er_table)
|
||||||
|
{
|
||||||
|
zlog_warn("%s: External reachability table of area %s"
|
||||||
|
" is not initialized.", __func__, area->area_tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
er_node = route_node_lookup(er_table, p);
|
||||||
|
if (!er_node)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
route_unlock_node(er_node);
|
||||||
|
|
||||||
|
if (!er_node->info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
route_unlock_node(er_node);
|
||||||
|
lsp_regenerate_schedule(area, level, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update external reachability info of area for a given level
|
||||||
|
* and prefix, using the given redistribution settings. */
|
||||||
|
static void
|
||||||
|
isis_redist_update_ext_reach(struct isis_area *area, int level,
|
||||||
|
struct isis_redist *redist, struct prefix *p,
|
||||||
|
struct isis_ext_info *info)
|
||||||
|
{
|
||||||
|
struct isis_ext_info area_info;
|
||||||
|
route_map_result_t map_ret;
|
||||||
|
|
||||||
|
memcpy(&area_info, info, sizeof(area_info));
|
||||||
|
if (redist->metric != 0xffffffff)
|
||||||
|
area_info.metric = redist->metric;
|
||||||
|
|
||||||
|
if (redist->map_name)
|
||||||
|
{
|
||||||
|
map_ret = route_map_apply(redist->map, p, RMAP_ISIS, &area_info);
|
||||||
|
if (map_ret == RMAP_DENYMATCH)
|
||||||
|
area_info.distance = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow synthesized default routes only on always orignate */
|
||||||
|
if (area_info.origin == DEFAULT_ROUTE
|
||||||
|
&& redist->redist != DEFAULT_ORIGINATE_ALWAYS)
|
||||||
|
area_info.distance = 255;
|
||||||
|
|
||||||
|
if (area_info.distance < 255)
|
||||||
|
isis_redist_install(area, level, p, &area_info);
|
||||||
|
else
|
||||||
|
isis_redist_uninstall(area, level, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isis_redist_ensure_default(struct isis *isis, int family)
|
||||||
|
{
|
||||||
|
struct prefix p;
|
||||||
|
struct route_table *ei_table = get_ext_info(isis, family);
|
||||||
|
struct route_node *ei_node;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
|
||||||
|
if (family == AF_INET)
|
||||||
|
{
|
||||||
|
p.family = AF_INET;
|
||||||
|
p.prefixlen = 0;
|
||||||
|
memset(&p.u.prefix4, 0, sizeof(p.u.prefix4));
|
||||||
|
}
|
||||||
|
else if (family == AF_INET6)
|
||||||
|
{
|
||||||
|
p.family = AF_INET6;
|
||||||
|
p.prefixlen = 0;
|
||||||
|
memset(&p.u.prefix6, 0, sizeof(p.u.prefix6));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(!"Unknown family!");
|
||||||
|
|
||||||
|
ei_node = route_node_get(ei_table, &p);
|
||||||
|
if (ei_node->info)
|
||||||
|
{
|
||||||
|
route_unlock_node(ei_node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ei_node->info = XCALLOC(MTYPE_ISIS, sizeof(struct isis_ext_info));
|
||||||
|
|
||||||
|
info = ei_node->info;
|
||||||
|
info->origin = DEFAULT_ROUTE;
|
||||||
|
info->distance = 254;
|
||||||
|
info->metric = MAX_WIDE_PATH_METRIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle notification about route being added */
|
||||||
|
void
|
||||||
|
isis_redist_add(int type, struct prefix *p, u_char distance, uint32_t metric)
|
||||||
|
{
|
||||||
|
int family = p->family;
|
||||||
|
struct route_table *ei_table = get_ext_info(isis, family);
|
||||||
|
struct route_node *ei_node;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
struct listnode *node;
|
||||||
|
struct isis_area *area;
|
||||||
|
int level;
|
||||||
|
struct isis_redist *redist;
|
||||||
|
|
||||||
|
char debug_buf[BUFSIZ];
|
||||||
|
prefix2str(p, debug_buf, sizeof(debug_buf));
|
||||||
|
|
||||||
|
zlog_debug("%s: New route %s from %s.", __func__, debug_buf,
|
||||||
|
zebra_route_string(type));
|
||||||
|
|
||||||
|
if (!ei_table)
|
||||||
|
{
|
||||||
|
zlog_warn("%s: External information table not initialized.",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ei_node = route_node_get(ei_table, p);
|
||||||
|
if (ei_node->info)
|
||||||
|
route_unlock_node(ei_node);
|
||||||
|
else
|
||||||
|
ei_node->info = XCALLOC(MTYPE_ISIS, sizeof(struct isis_ext_info));
|
||||||
|
|
||||||
|
info = ei_node->info;
|
||||||
|
info->origin = type;
|
||||||
|
info->distance = distance;
|
||||||
|
info->metric = metric;
|
||||||
|
|
||||||
|
if (is_default(p))
|
||||||
|
type = DEFAULT_ROUTE;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
|
||||||
|
for (level = 1; level <= ISIS_LEVELS; level++)
|
||||||
|
{
|
||||||
|
redist = get_redist_settings(area, family, type, level);
|
||||||
|
if (!redist->redist)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
isis_redist_update_ext_reach(area, level, redist, p, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isis_redist_delete(int type, struct prefix *p)
|
||||||
|
{
|
||||||
|
int family = p->family;
|
||||||
|
struct route_table *ei_table = get_ext_info(isis, family);
|
||||||
|
struct route_node *ei_node;
|
||||||
|
struct listnode *node;
|
||||||
|
struct isis_area *area;
|
||||||
|
int level;
|
||||||
|
struct isis_redist *redist;
|
||||||
|
|
||||||
|
char debug_buf[BUFSIZ];
|
||||||
|
prefix2str(p, debug_buf, sizeof(debug_buf));
|
||||||
|
|
||||||
|
zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf,
|
||||||
|
zebra_route_string(type));
|
||||||
|
|
||||||
|
if (is_default(p))
|
||||||
|
{
|
||||||
|
/* Don't remove default route but add synthetic route for use
|
||||||
|
* by "default-information originate always". Areas without the
|
||||||
|
* "always" setting will ignore routes with origin DEFAULT_ROUTE. */
|
||||||
|
isis_redist_add(DEFAULT_ROUTE, p, 254, MAX_WIDE_PATH_METRIC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ei_table)
|
||||||
|
{
|
||||||
|
zlog_warn("%s: External information table not initialized.",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ei_node = route_node_lookup(ei_table, p);
|
||||||
|
if (!ei_node || !ei_node->info)
|
||||||
|
{
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
prefix2str(p, buf, sizeof(buf));
|
||||||
|
zlog_warn("%s: Got a delete for %s route %s, but that route"
|
||||||
|
" was never added.", __func__, zebra_route_string(type),
|
||||||
|
buf);
|
||||||
|
if (ei_node)
|
||||||
|
route_unlock_node(ei_node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
route_unlock_node(ei_node);
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
|
||||||
|
for (level = 1; level < ISIS_LEVELS; level++)
|
||||||
|
{
|
||||||
|
redist = get_redist_settings(area, family, type, level);
|
||||||
|
if (!redist->redist)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
isis_redist_uninstall(area, level, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
route_unlock_node(ei_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isis_redist_routemap_set(struct isis_redist *redist, const char *routemap)
|
||||||
|
{
|
||||||
|
if (redist->map_name) {
|
||||||
|
XFREE(MTYPE_ISIS, redist->map_name);
|
||||||
|
redist->map = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routemap && strlen(routemap)) {
|
||||||
|
redist->map_name = XSTRDUP(MTYPE_ISIS, routemap);
|
||||||
|
redist->map = route_map_lookup_by_name(routemap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isis_redist_update_zebra_subscriptions(struct isis *isis)
|
||||||
|
{
|
||||||
|
struct listnode *node;
|
||||||
|
struct isis_area *area;
|
||||||
|
int type;
|
||||||
|
int level;
|
||||||
|
int protocol;
|
||||||
|
|
||||||
|
char do_subscribe[ZEBRA_ROUTE_MAX + 1];
|
||||||
|
|
||||||
|
memset(do_subscribe, 0, sizeof(do_subscribe));
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
|
||||||
|
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
|
||||||
|
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
|
||||||
|
for (level = 0; level < ISIS_LEVELS; level++)
|
||||||
|
if (area->redist_settings[protocol][type][level].redist)
|
||||||
|
do_subscribe[type] = 1;
|
||||||
|
|
||||||
|
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
|
||||||
|
{
|
||||||
|
/* This field is actually controlling transmission of the IS-IS
|
||||||
|
* routes to Zebra and has nothing to do with redistribution,
|
||||||
|
* so skip it. */
|
||||||
|
if (type == ZEBRA_ROUTE_ISIS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (do_subscribe[type])
|
||||||
|
isis_zebra_redistribute_set(type);
|
||||||
|
else
|
||||||
|
isis_zebra_redistribute_unset(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isis_redist_set(struct isis_area *area, int level,
|
||||||
|
int family, int type, uint32_t metric,
|
||||||
|
const char *routemap, int originate_type)
|
||||||
|
{
|
||||||
|
int protocol = redist_protocol(family);
|
||||||
|
struct isis_redist *redist = get_redist_settings(area, family, type, level);
|
||||||
|
int i;
|
||||||
|
struct route_table *ei_table;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
|
||||||
|
redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1;
|
||||||
|
redist->metric = metric;
|
||||||
|
isis_redist_routemap_set(redist, routemap);
|
||||||
|
|
||||||
|
if (!area->ext_reach[protocol][level-1])
|
||||||
|
{
|
||||||
|
area->ext_reach[protocol][level-1] =
|
||||||
|
route_table_init_with_delegate(&isis_redist_rt_delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < REDIST_PROTOCOL_COUNT; i++)
|
||||||
|
if (!area->isis->ext_info[i])
|
||||||
|
{
|
||||||
|
area->isis->ext_info[i] =
|
||||||
|
route_table_init_with_delegate(&isis_redist_rt_delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
isis_redist_update_zebra_subscriptions(area->isis);
|
||||||
|
|
||||||
|
if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS)
|
||||||
|
isis_redist_ensure_default(area->isis, family);
|
||||||
|
|
||||||
|
ei_table = get_ext_info(area->isis, family);
|
||||||
|
for (rn = route_top(ei_table); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
info = rn->info;
|
||||||
|
|
||||||
|
if (type == DEFAULT_ROUTE)
|
||||||
|
{
|
||||||
|
if (!is_default(&rn->p))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (info->origin != type)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
isis_redist_update_ext_reach(area, level, redist, &rn->p, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
isis_redist_unset(struct isis_area *area, int level,
|
||||||
|
int family, int type)
|
||||||
|
{
|
||||||
|
struct isis_redist *redist = get_redist_settings(area, family, type, level);
|
||||||
|
struct route_table *er_table = get_ext_reach(area, family, level);
|
||||||
|
struct route_node *rn;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
|
||||||
|
if (!redist->redist)
|
||||||
|
return;
|
||||||
|
|
||||||
|
redist->redist = 0;
|
||||||
|
if (!er_table)
|
||||||
|
{
|
||||||
|
zlog_warn("%s: External reachability table uninitialized.", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rn = route_top(er_table); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
info = rn->info;
|
||||||
|
|
||||||
|
if (type == DEFAULT_ROUTE)
|
||||||
|
{
|
||||||
|
if (!is_default(&rn->p))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (info->origin != type)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
route_unlock_node(rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
lsp_regenerate_schedule(area, level, 0);
|
||||||
|
isis_redist_update_zebra_subscriptions(area->isis);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isis_redist_area_finish(struct isis_area *area)
|
||||||
|
{
|
||||||
|
int protocol;
|
||||||
|
int level;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
|
||||||
|
for (level = 0; level < ISIS_LEVELS; level++)
|
||||||
|
{
|
||||||
|
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
|
||||||
|
{
|
||||||
|
struct isis_redist *redist;
|
||||||
|
|
||||||
|
redist = &area->redist_settings[protocol][type][level];
|
||||||
|
redist->redist = 0;
|
||||||
|
if (redist->map_name)
|
||||||
|
XFREE(MTYPE_ISIS, redist->map_name);
|
||||||
|
}
|
||||||
|
route_table_finish(area->ext_reach[protocol][level]);
|
||||||
|
}
|
||||||
|
|
||||||
|
isis_redist_update_zebra_subscriptions(area->isis);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(isis_redistribute,
|
||||||
|
isis_redistribute_cmd,
|
||||||
|
"redistribute (ipv4|ipv6) " QUAGGA_REDIST_STR_ISISD
|
||||||
|
" (level-1|level-2) {metric <0-16777215>|route-map WORD}",
|
||||||
|
REDIST_STR
|
||||||
|
"Redistribute IPv4 routes\n"
|
||||||
|
"Redistribute IPv6 routes\n"
|
||||||
|
QUAGGA_REDIST_HELP_STR_ISISD
|
||||||
|
"Redistribute into level-1\n"
|
||||||
|
"Redistribute into level-2\n"
|
||||||
|
"Metric for redistributed routes\n"
|
||||||
|
"ISIS default metric\n"
|
||||||
|
"Route map reference\n"
|
||||||
|
"Pointer to route-map entries\n")
|
||||||
|
{
|
||||||
|
struct isis_area *area = vty->index;
|
||||||
|
int family;
|
||||||
|
int afi;
|
||||||
|
int type;
|
||||||
|
int level;
|
||||||
|
unsigned long metric;
|
||||||
|
const char *routemap;
|
||||||
|
|
||||||
|
if (argc < 5)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
family = str2family(argv[0]);
|
||||||
|
if (family < 0)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
afi = family2afi(family);
|
||||||
|
if (!afi)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
type = proto_redistnum(afi, argv[1]);
|
||||||
|
if (type < 0 || type == ZEBRA_ROUTE_ISIS)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if (!strcmp("level-1", argv[2]))
|
||||||
|
level = 1;
|
||||||
|
else if (!strcmp("level-2", argv[2]))
|
||||||
|
level = 2;
|
||||||
|
else
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if ((area->is_type & level) != level)
|
||||||
|
{
|
||||||
|
vty_out(vty, "Node is not a level-%d IS%s", level, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[3])
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
|
metric = strtoul(argv[3], &endp, 10);
|
||||||
|
if (argv[3][0] == '\0' || *endp != '\0')
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metric = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
routemap = argv[4];
|
||||||
|
|
||||||
|
isis_redist_set(area, level, family, type, metric, routemap, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_isis_redistribute,
|
||||||
|
no_isis_redistribute_cmd,
|
||||||
|
"no redistribute (ipv4|ipv6) " QUAGGA_REDIST_STR_ISISD
|
||||||
|
" (level-1|level-2)",
|
||||||
|
NO_STR
|
||||||
|
REDIST_STR
|
||||||
|
"Redistribute IPv4 routes\n"
|
||||||
|
"Redistribute IPv6 routes\n"
|
||||||
|
QUAGGA_REDIST_HELP_STR_ISISD
|
||||||
|
"Redistribute into level-1\n"
|
||||||
|
"Redistribute into level-2\n")
|
||||||
|
{
|
||||||
|
struct isis_area *area = vty->index;
|
||||||
|
int type;
|
||||||
|
int level;
|
||||||
|
int family;
|
||||||
|
int afi;
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
family = str2family(argv[0]);
|
||||||
|
if (family < 0)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
afi = family2afi(family);
|
||||||
|
if (!afi)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
type = proto_redistnum(afi, argv[1]);
|
||||||
|
if (type < 0 || type == ZEBRA_ROUTE_ISIS)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if (!strcmp("level-1", argv[2]))
|
||||||
|
level = 1;
|
||||||
|
else if (!strcmp("level-2", argv[2]))
|
||||||
|
level = 2;
|
||||||
|
else
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
isis_redist_unset(area, level, family, type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(isis_default_originate,
|
||||||
|
isis_default_originate_cmd,
|
||||||
|
"default-information originate (ipv4|ipv6) (level-1|level-2) "
|
||||||
|
"{always|metric <0-16777215>|route-map WORD}",
|
||||||
|
"Control distribution of default information\n"
|
||||||
|
"Distribute a default route\n"
|
||||||
|
"Distribute default route for IPv4\n"
|
||||||
|
"Distribute default route for IPv6\n"
|
||||||
|
"Distribute default route into level-1\n"
|
||||||
|
"Distribute default route into level-2\n"
|
||||||
|
"Always advertise default route\n"
|
||||||
|
"Metric for default route\n"
|
||||||
|
"ISIS default metric\n"
|
||||||
|
"Route map reference\n"
|
||||||
|
"Pointer to route-map entries\n")
|
||||||
|
{
|
||||||
|
struct isis_area *area = vty->index;
|
||||||
|
int family;
|
||||||
|
int originate_type;
|
||||||
|
int level;
|
||||||
|
unsigned long metric;
|
||||||
|
const char *routemap;
|
||||||
|
|
||||||
|
if (argc < 5)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
family = str2family(argv[0]);
|
||||||
|
if (family < 0)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if (!strcmp("level-1", argv[1]))
|
||||||
|
level = 1;
|
||||||
|
else if (!strcmp("level-2", argv[1]))
|
||||||
|
level = 2;
|
||||||
|
else
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if ((area->is_type & level) != level)
|
||||||
|
{
|
||||||
|
vty_out(vty, "Node is not a level-%d IS%s", level, VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[2] && *argv[2] != '\0')
|
||||||
|
originate_type = DEFAULT_ORIGINATE_ALWAYS;
|
||||||
|
else
|
||||||
|
originate_type = DEFAULT_ORIGINATE;
|
||||||
|
|
||||||
|
if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS)
|
||||||
|
{
|
||||||
|
vty_out(vty, "Zebra doesn't implement default-originate for IPv6 yet%s", VTY_NEWLINE);
|
||||||
|
vty_out(vty, "so use with care or use default-originate always.%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[3])
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
|
metric = strtoul(argv[3], &endp, 10);
|
||||||
|
if (argv[3][0] == '\0' || *endp != '\0')
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metric = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
routemap = argv[4];
|
||||||
|
|
||||||
|
isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, originate_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_isis_default_originate,
|
||||||
|
no_isis_default_originate_cmd,
|
||||||
|
"no default-information originate (ipv4|ipv6) (level-1|level-2)",
|
||||||
|
NO_STR
|
||||||
|
"Control distribution of default information\n"
|
||||||
|
"Distribute a default route\n"
|
||||||
|
"Distribute default route for IPv4\n"
|
||||||
|
"Distribute default route for IPv6\n"
|
||||||
|
"Distribute default route into level-1\n"
|
||||||
|
"Distribute default route into level-2\n")
|
||||||
|
{
|
||||||
|
struct isis_area *area = vty->index;
|
||||||
|
|
||||||
|
int family;
|
||||||
|
int level;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
family = str2family(argv[0]);
|
||||||
|
if (family < 0)
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
if (!strcmp("level-1", argv[1]))
|
||||||
|
level = 1;
|
||||||
|
else if (!strcmp("level-2", argv[1]))
|
||||||
|
level = 2;
|
||||||
|
else
|
||||||
|
return CMD_WARNING;
|
||||||
|
|
||||||
|
isis_redist_unset(area, level, family, DEFAULT_ROUTE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isis_redist_config_write(struct vty *vty, struct isis_area *area,
|
||||||
|
int family)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
int level;
|
||||||
|
int write = 0;
|
||||||
|
struct isis_redist *redist;
|
||||||
|
const char *family_str;
|
||||||
|
|
||||||
|
if (family == AF_INET)
|
||||||
|
family_str = "ipv4";
|
||||||
|
else if (family == AF_INET6)
|
||||||
|
family_str = "ipv6";
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
|
||||||
|
{
|
||||||
|
if (type == ZEBRA_ROUTE_ISIS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (level = 1; level <= ISIS_LEVELS; level++)
|
||||||
|
{
|
||||||
|
redist = get_redist_settings(area, family, type, level);
|
||||||
|
if (!redist->redist)
|
||||||
|
continue;
|
||||||
|
vty_out(vty, " redistribute %s %s level-%d",
|
||||||
|
family_str, zebra_route_string(type), level);
|
||||||
|
if (redist->metric != 0xffffffff)
|
||||||
|
vty_out(vty, " metric %u", redist->metric);
|
||||||
|
if (redist->map_name)
|
||||||
|
vty_out(vty, " route-map %s", redist->map_name);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (level = 1; level <= ISIS_LEVELS; level++)
|
||||||
|
{
|
||||||
|
redist = get_redist_settings(area, family, DEFAULT_ROUTE, level);
|
||||||
|
if (!redist->redist)
|
||||||
|
continue;
|
||||||
|
vty_out(vty, " default-information originate %s level-%d",
|
||||||
|
family_str, level);
|
||||||
|
if (redist->redist == DEFAULT_ORIGINATE_ALWAYS)
|
||||||
|
vty_out(vty, " always");
|
||||||
|
if (redist->metric != 0xffffffff)
|
||||||
|
vty_out(vty, " metric %u", redist->metric);
|
||||||
|
if (redist->map_name)
|
||||||
|
vty_out(vty, " route-map %s", redist->map_name);
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return write;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isis_redist_init(void)
|
||||||
|
{
|
||||||
|
install_element(ISIS_NODE, &isis_redistribute_cmd);
|
||||||
|
install_element(ISIS_NODE, &no_isis_redistribute_cmd);
|
||||||
|
install_element(ISIS_NODE, &isis_default_originate_cmd);
|
||||||
|
install_element(ISIS_NODE, &no_isis_default_originate_cmd);
|
||||||
|
}
|
58
isisd/isis_redist.h
Normal file
58
isisd/isis_redist.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* IS-IS Rout(e)ing protocol - isis_redist.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
||||||
|
*
|
||||||
|
* 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; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ISIS_REDIST_H
|
||||||
|
#define ISIS_REDIST_H
|
||||||
|
|
||||||
|
#define REDIST_PROTOCOL_COUNT 2
|
||||||
|
|
||||||
|
#define DEFAULT_ROUTE ZEBRA_ROUTE_MAX
|
||||||
|
#define DEFAULT_ORIGINATE 1
|
||||||
|
#define DEFAULT_ORIGINATE_ALWAYS 2
|
||||||
|
|
||||||
|
struct isis_ext_info
|
||||||
|
{
|
||||||
|
int origin;
|
||||||
|
uint32_t metric;
|
||||||
|
u_char distance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct isis_redist
|
||||||
|
{
|
||||||
|
int redist;
|
||||||
|
uint32_t metric;
|
||||||
|
char *map_name;
|
||||||
|
struct route_map *map;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct isis_area;
|
||||||
|
struct prefix;
|
||||||
|
|
||||||
|
struct route_table *get_ext_reach(struct isis_area *area,
|
||||||
|
int family, int level);
|
||||||
|
void isis_redist_add(int type, struct prefix *p,
|
||||||
|
u_char distance, uint32_t metric);
|
||||||
|
void isis_redist_delete(int type, struct prefix *p);
|
||||||
|
int isis_redist_config_write(struct vty *vty, struct isis_area *area,
|
||||||
|
int family);
|
||||||
|
void isis_redist_init(void);
|
||||||
|
void isis_redist_area_finish(struct isis_area *area);
|
||||||
|
|
||||||
|
#endif
|
@ -1,13 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* IS-IS Rout(e)ing protocol - isis_routemap.c
|
* IS-IS Rout(e)ing protocol - isis_routemap.c
|
||||||
*
|
|
||||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
|
||||||
* Tampere University of Technology
|
|
||||||
* Institute of Communications Engineering
|
|
||||||
*
|
*
|
||||||
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public Licenseas published by the Free
|
* 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)
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
*
|
||||||
@ -20,18 +17,22 @@
|
|||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
|
|
||||||
#include "thread.h"
|
#include "command.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "if.h"
|
||||||
#include "linklist.h"
|
#include "linklist.h"
|
||||||
#include "vty.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "hash.h"
|
#include "plist.h"
|
||||||
#include "if.h"
|
|
||||||
#include "table.h"
|
|
||||||
#include "routemap.h"
|
#include "routemap.h"
|
||||||
|
#include "table.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "vty.h"
|
||||||
|
|
||||||
#include "isis_constants.h"
|
#include "isis_constants.h"
|
||||||
#include "isis_common.h"
|
#include "isis_common.h"
|
||||||
@ -47,60 +48,518 @@
|
|||||||
#include "isis_spf.h"
|
#include "isis_spf.h"
|
||||||
#include "isis_route.h"
|
#include "isis_route.h"
|
||||||
#include "isis_zebra.h"
|
#include "isis_zebra.h"
|
||||||
|
#include "isis_routemap.h"
|
||||||
|
|
||||||
extern struct isis *isis;
|
static route_map_result_t
|
||||||
|
route_match_ip_address(void *rule, struct prefix *prefix,
|
||||||
/*
|
route_map_object_t type, void *object)
|
||||||
* Prototypes.
|
|
||||||
*/
|
|
||||||
void isis_route_map_upd(const char *);
|
|
||||||
void isis_route_map_event(route_map_event_t, const char *);
|
|
||||||
void isis_route_map_init(void);
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
isis_route_map_upd (const char *name)
|
|
||||||
{
|
{
|
||||||
int i = 0;
|
struct access_list *alist;
|
||||||
|
|
||||||
if (!isis)
|
if (type != RMAP_ISIS)
|
||||||
return;
|
return RMAP_NOMATCH;
|
||||||
|
|
||||||
for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
|
alist = access_list_lookup(AFI_IP, (char*)rule);
|
||||||
|
if (access_list_apply(alist, prefix) != FILTER_DENY)
|
||||||
|
return RMAP_MATCH;
|
||||||
|
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
route_match_ip_address_compile(const char *arg)
|
||||||
|
{
|
||||||
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_match_ip_address_free(void *rule)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct route_map_rule_cmd route_match_ip_address_cmd =
|
||||||
|
{
|
||||||
|
"ip address",
|
||||||
|
route_match_ip_address,
|
||||||
|
route_match_ip_address_compile,
|
||||||
|
route_match_ip_address_free
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static route_map_result_t
|
||||||
|
route_match_ip_address_prefix_list(void *rule, struct prefix *prefix,
|
||||||
|
route_map_object_t type, void *object)
|
||||||
|
{
|
||||||
|
struct prefix_list *plist;
|
||||||
|
|
||||||
|
if (type != RMAP_ISIS)
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
|
||||||
|
plist = prefix_list_lookup(AFI_IP, (char*)rule);
|
||||||
|
if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
|
||||||
|
return RMAP_MATCH;
|
||||||
|
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
route_match_ip_address_prefix_list_compile(const char *arg)
|
||||||
|
{
|
||||||
|
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_match_ip_address_prefix_list_free (void *rule)
|
||||||
|
{
|
||||||
|
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
|
||||||
|
{
|
||||||
|
"ip address prefix-list",
|
||||||
|
route_match_ip_address_prefix_list,
|
||||||
|
route_match_ip_address_prefix_list_compile,
|
||||||
|
route_match_ip_address_prefix_list_free
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static route_map_result_t
|
||||||
|
route_match_ipv6_address(void *rule, struct prefix *prefix,
|
||||||
|
route_map_object_t type, void *object)
|
||||||
|
{
|
||||||
|
struct access_list *alist;
|
||||||
|
|
||||||
|
if (type != RMAP_ISIS)
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
|
||||||
|
alist = access_list_lookup(AFI_IP6, (char*)rule);
|
||||||
|
if (access_list_apply(alist, prefix) != FILTER_DENY)
|
||||||
|
return RMAP_MATCH;
|
||||||
|
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
route_match_ipv6_address_compile(const char *arg)
|
||||||
|
{
|
||||||
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_match_ipv6_address_free(void *rule)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct route_map_rule_cmd route_match_ipv6_address_cmd =
|
||||||
|
{
|
||||||
|
"ipv6 address",
|
||||||
|
route_match_ipv6_address,
|
||||||
|
route_match_ipv6_address_compile,
|
||||||
|
route_match_ipv6_address_free
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static route_map_result_t
|
||||||
|
route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix,
|
||||||
|
route_map_object_t type, void *object)
|
||||||
|
{
|
||||||
|
struct prefix_list *plist;
|
||||||
|
|
||||||
|
if (type != RMAP_ISIS)
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
|
||||||
|
plist = prefix_list_lookup(AFI_IP6, (char*)rule);
|
||||||
|
if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
|
||||||
|
return RMAP_MATCH;
|
||||||
|
|
||||||
|
return RMAP_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
route_match_ipv6_address_prefix_list_compile(const char *arg)
|
||||||
|
{
|
||||||
|
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_match_ipv6_address_prefix_list_free (void *rule)
|
||||||
|
{
|
||||||
|
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
|
||||||
|
{
|
||||||
|
"ipv6 address prefix-list",
|
||||||
|
route_match_ipv6_address_prefix_list,
|
||||||
|
route_match_ipv6_address_prefix_list_compile,
|
||||||
|
route_match_ipv6_address_prefix_list_free
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static route_map_result_t
|
||||||
|
route_set_metric(void *rule, struct prefix *prefix,
|
||||||
|
route_map_object_t type, void *object)
|
||||||
|
{
|
||||||
|
uint32_t *metric;
|
||||||
|
struct isis_ext_info *info;
|
||||||
|
|
||||||
|
if (type == RMAP_ISIS)
|
||||||
{
|
{
|
||||||
if (isis->rmap[i].name)
|
metric = rule;
|
||||||
isis->rmap[i].map = route_map_lookup_by_name (isis->rmap[i].name);
|
info = object;
|
||||||
else
|
|
||||||
isis->rmap[i].map = NULL;
|
info->metric = *metric;
|
||||||
}
|
}
|
||||||
/* FIXME: do the address family sub-mode AF_INET6 here ? */
|
return RMAP_OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void *
|
||||||
isis_route_map_event (route_map_event_t event, const char *name)
|
route_set_metric_compile(const char *arg)
|
||||||
{
|
{
|
||||||
int type;
|
unsigned long metric;
|
||||||
|
char *endp;
|
||||||
|
uint32_t *ret;
|
||||||
|
|
||||||
if (!isis)
|
metric = strtoul(arg, &endp, 10);
|
||||||
return;
|
if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
|
ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(ret));
|
||||||
|
*ret = metric;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
route_set_metric_free(void *rule)
|
||||||
|
{
|
||||||
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct route_map_rule_cmd route_set_metric_cmd =
|
||||||
|
{
|
||||||
|
"metric",
|
||||||
|
route_set_metric,
|
||||||
|
route_set_metric_compile,
|
||||||
|
route_set_metric_free
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
isis_route_match_add(struct vty *vty, struct route_map_index *index,
|
||||||
|
const char *command, const char *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = route_map_add_match (index, command, arg);
|
||||||
|
if (ret)
|
||||||
{
|
{
|
||||||
if (isis->rmap[type].name && isis->rmap[type].map &&
|
switch (ret)
|
||||||
!strcmp (isis->rmap[type].name, name))
|
{
|
||||||
{
|
case RMAP_RULE_MISSING:
|
||||||
isis_distribute_list_update (type);
|
vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
|
||||||
}
|
return CMD_WARNING;
|
||||||
|
case RMAP_COMPILE_ERROR:
|
||||||
|
vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isis_route_match_delete(struct vty *vty, struct route_map_index *index,
|
||||||
|
const char *command, const char *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = route_map_delete_match (index, command, arg);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case RMAP_RULE_MISSING:
|
||||||
|
vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
case RMAP_COMPILE_ERROR:
|
||||||
|
vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isis_route_set_add(struct vty *vty, struct route_map_index *index,
|
||||||
|
const char *command, const char *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = route_map_add_set(index, command, arg);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case RMAP_RULE_MISSING:
|
||||||
|
vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
case RMAP_COMPILE_ERROR:
|
||||||
|
vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isis_route_set_delete (struct vty *vty, struct route_map_index *index,
|
||||||
|
const char *command, const char *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = route_map_delete_set (index, command, arg);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case RMAP_RULE_MISSING:
|
||||||
|
vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
case RMAP_COMPILE_ERROR:
|
||||||
|
vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DEFUN(match_ip_address,
|
||||||
|
match_ip_address_cmd,
|
||||||
|
"match ip address (<1-199>|<1300-2699>|WORD)",
|
||||||
|
MATCH_STR
|
||||||
|
IP_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"IP access-list number\n"
|
||||||
|
"IP access-list number (expanded range)\n"
|
||||||
|
"IP Access-list name\n")
|
||||||
|
{
|
||||||
|
return isis_route_match_add(vty, vty->index, "ip address", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_match_ip_address,
|
||||||
|
no_match_ip_address_val_cmd,
|
||||||
|
"no match ip address (<1-199>|<1300-2699>|WORD)",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IP_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"IP access-list number\n"
|
||||||
|
"IP access-list number (expanded range)\n"
|
||||||
|
"IP Access-list name\n")
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return isis_route_match_delete(vty, vty->index, "ip address", NULL);
|
||||||
|
return isis_route_match_delete(vty, vty->index, "ip address", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS(no_match_ip_address,
|
||||||
|
no_match_ip_address_cmd,
|
||||||
|
"no match ip address",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IP_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DEFUN(match_ip_address_prefix_list,
|
||||||
|
match_ip_address_prefix_list_cmd,
|
||||||
|
"match ip address prefix-list WORD",
|
||||||
|
MATCH_STR
|
||||||
|
IP_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"Match entries of prefix-lists\n"
|
||||||
|
"IP prefix-list name\n")
|
||||||
|
{
|
||||||
|
return isis_route_match_add(vty, vty->index, "ip address prefix-list", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_match_ip_address_prefix_list,
|
||||||
|
no_match_ip_address_prefix_list_cmd,
|
||||||
|
"no match ip address prefix-list",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IP_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"Match entries of prefix-lists\n")
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return isis_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
|
||||||
|
return isis_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS(no_match_ip_address_prefix_list,
|
||||||
|
no_match_ip_address_prefix_list_val_cmd,
|
||||||
|
"no match ip address prefix-list WORD",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IP_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"Match entries of prefix-lists\n"
|
||||||
|
"IP prefix-list name\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DEFUN(match_ipv6_address,
|
||||||
|
match_ipv6_address_cmd,
|
||||||
|
"match ipv6 address WORD",
|
||||||
|
MATCH_STR
|
||||||
|
IPV6_STR
|
||||||
|
"Match IPv6 address of route\n"
|
||||||
|
"IPv6 access-list name\n")
|
||||||
|
{
|
||||||
|
return isis_route_match_add(vty, vty->index, "ipv6 address", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_match_ipv6_address,
|
||||||
|
no_match_ipv6_address_val_cmd,
|
||||||
|
"no match ipv6 address WORD",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IPV6_STR
|
||||||
|
"Match IPv6 address of route\n"
|
||||||
|
"IPv6 access-list name\n")
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return isis_route_match_delete(vty, vty->index, "ipv6 address", NULL);
|
||||||
|
return isis_route_match_delete(vty, vty->index, "ipv6 address", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS(no_match_ipv6_address,
|
||||||
|
no_match_ipv6_address_cmd,
|
||||||
|
"no match ipv6 address",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IPV6_STR
|
||||||
|
"Match IPv6 address of route\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DEFUN(match_ipv6_address_prefix_list,
|
||||||
|
match_ipv6_address_prefix_list_cmd,
|
||||||
|
"match ipv6 address prefix-list WORD",
|
||||||
|
MATCH_STR
|
||||||
|
IPV6_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"Match entries of prefix-lists\n"
|
||||||
|
"IP prefix-list name\n")
|
||||||
|
{
|
||||||
|
return isis_route_match_add(vty, vty->index, "ipv6 address prefix-list", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_match_ipv6_address_prefix_list,
|
||||||
|
no_match_ipv6_address_prefix_list_cmd,
|
||||||
|
"no match ipv6 address prefix-list",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IPV6_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"Match entries of prefix-lists\n")
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", NULL);
|
||||||
|
return isis_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS(no_match_ipv6_address_prefix_list,
|
||||||
|
no_match_ipv6_address_prefix_list_val_cmd,
|
||||||
|
"no match ipv6 address prefix-list WORD",
|
||||||
|
NO_STR
|
||||||
|
MATCH_STR
|
||||||
|
IPV6_STR
|
||||||
|
"Match address of route\n"
|
||||||
|
"Match entries of prefix-lists\n"
|
||||||
|
"IP prefix-list name\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* set metric already exists e.g. in the ospf routemap. vtysh doesn't cope well with different
|
||||||
|
* commands at the same node, therefore add set metric with the same 32-bit range as ospf and
|
||||||
|
* verify that the input is a valid isis metric */
|
||||||
|
DEFUN(set_metric,
|
||||||
|
set_metric_cmd,
|
||||||
|
"set metric <0-4294967295>",
|
||||||
|
SET_STR
|
||||||
|
"Metric vale for destination routing protocol\n"
|
||||||
|
"Metric value\n")
|
||||||
|
{
|
||||||
|
return isis_route_set_add(vty, vty->index, "metric", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN(no_set_metric,
|
||||||
|
no_set_metric_val_cmd,
|
||||||
|
"no set metric <0-4294967295>",
|
||||||
|
NO_STR
|
||||||
|
SET_STR
|
||||||
|
"Metric value for destination routing protocol\n"
|
||||||
|
"Metric value\n")
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return isis_route_set_delete(vty, vty->index, "metric", NULL);
|
||||||
|
return isis_route_set_delete(vty, vty->index, "metric", argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALIAS(no_set_metric,
|
||||||
|
no_set_metric_cmd,
|
||||||
|
"no set metric",
|
||||||
|
NO_STR
|
||||||
|
SET_STR
|
||||||
|
"Metric vale for destination routing protocol\n"
|
||||||
|
);
|
||||||
|
|
||||||
void
|
void
|
||||||
isis_route_map_init (void)
|
isis_route_map_init(void)
|
||||||
{
|
{
|
||||||
route_map_init ();
|
route_map_init();
|
||||||
route_map_init_vty ();
|
route_map_init_vty();
|
||||||
|
|
||||||
route_map_add_hook (isis_route_map_upd);
|
route_map_install_match(&route_match_ip_address_cmd);
|
||||||
route_map_delete_hook (isis_route_map_upd);
|
install_element(RMAP_NODE, &match_ip_address_cmd);
|
||||||
route_map_event_hook (isis_route_map_event);
|
install_element(RMAP_NODE, &no_match_ip_address_val_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ip_address_cmd);
|
||||||
|
|
||||||
|
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
|
||||||
|
install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
|
||||||
|
|
||||||
|
route_map_install_match(&route_match_ipv6_address_cmd);
|
||||||
|
install_element(RMAP_NODE, &match_ipv6_address_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ipv6_address_val_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
|
||||||
|
|
||||||
|
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
|
||||||
|
install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_val_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
|
||||||
|
|
||||||
|
route_map_install_set(&route_set_metric_cmd);
|
||||||
|
install_element(RMAP_NODE, &set_metric_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_set_metric_val_cmd);
|
||||||
|
install_element(RMAP_NODE, &no_set_metric_cmd);
|
||||||
}
|
}
|
||||||
|
25
isisd/isis_routemap.h
Normal file
25
isisd/isis_routemap.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* IS-IS Rout(e)ing protocol - isis_routemap.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
||||||
|
*
|
||||||
|
* 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; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
#ifndef ISIS_ROUTEMAP_H
|
||||||
|
#define ISIS_ROUTEMAP_H
|
||||||
|
|
||||||
|
void isis_route_map_init(void);
|
||||||
|
|
||||||
|
#endif
|
@ -992,8 +992,8 @@ tlv_add_lsp_entries (struct list *lsps, struct stream *stream)
|
|||||||
return add_tlv (LSP_ENTRIES, pos - value, value, stream);
|
return add_tlv (LSP_ENTRIES, pos - value, value, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
|
tlv_add_ipv4_reachs (u_char tag, struct list *ipv4_reachs, struct stream *stream)
|
||||||
{
|
{
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct ipv4_reachability *reach;
|
struct ipv4_reachability *reach;
|
||||||
@ -1006,7 +1006,7 @@ tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
|
|||||||
if (pos - value + IPV4_REACH_LEN > 255)
|
if (pos - value + IPV4_REACH_LEN > 255)
|
||||||
{
|
{
|
||||||
retval =
|
retval =
|
||||||
add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
|
add_tlv (tag, pos - value, value, stream);
|
||||||
if (retval != ISIS_OK)
|
if (retval != ISIS_OK)
|
||||||
return retval;
|
return retval;
|
||||||
pos = value;
|
pos = value;
|
||||||
@ -1025,9 +1025,22 @@ tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream)
|
|||||||
pos += IPV4_MAX_BYTELEN;
|
pos += IPV4_MAX_BYTELEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return add_tlv (IPV4_INT_REACHABILITY, pos - value, value, stream);
|
return add_tlv (tag, pos - value, value, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tlv_add_ipv4_int_reachs (struct list *ipv4_reachs, struct stream *stream)
|
||||||
|
{
|
||||||
|
return tlv_add_ipv4_reachs(IPV4_INT_REACHABILITY, ipv4_reachs, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tlv_add_ipv4_ext_reachs (struct list *ipv4_reachs, struct stream *stream)
|
||||||
|
{
|
||||||
|
return tlv_add_ipv4_reachs(IPV4_EXT_REACHABILITY, ipv4_reachs, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
|
tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream)
|
||||||
{
|
{
|
||||||
|
@ -230,11 +230,13 @@ struct ipv6_reachability
|
|||||||
|
|
||||||
/* bits in control_info */
|
/* bits in control_info */
|
||||||
#define CTRL_INFO_DIRECTION 0x80
|
#define CTRL_INFO_DIRECTION 0x80
|
||||||
#define DIRECTION_UP 0
|
#define DIRECTION_UP 0x00
|
||||||
#define DIRECTION_DOWN 1
|
#define DIRECTION_DOWN 0x80
|
||||||
|
|
||||||
#define CTRL_INFO_DISTRIBUTION 0x40
|
#define CTRL_INFO_DISTRIBUTION 0x40
|
||||||
#define DISTRIBUTION_INTERNAL 0
|
#define DISTRIBUTION_INTERNAL 0x00
|
||||||
#define DISTRIBUTION_EXTERNAL 1
|
#define DISTRIBUTION_EXTERNAL 0x40
|
||||||
|
|
||||||
#define CTRL_INFO_SUBTLVS 0x20
|
#define CTRL_INFO_SUBTLVS 0x20
|
||||||
#endif /* HAVE_IPV6 */
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
@ -313,7 +315,8 @@ int tlv_add_in_addr (struct in_addr *, struct stream *stream, u_char tag);
|
|||||||
int tlv_add_dynamic_hostname (struct hostname *hostname,
|
int tlv_add_dynamic_hostname (struct hostname *hostname,
|
||||||
struct stream *stream);
|
struct stream *stream);
|
||||||
int tlv_add_lsp_entries (struct list *lsps, struct stream *stream);
|
int tlv_add_lsp_entries (struct list *lsps, struct stream *stream);
|
||||||
int tlv_add_ipv4_reachs (struct list *ipv4_reachs, struct stream *stream);
|
int tlv_add_ipv4_int_reachs (struct list *ipv4_reachs, struct stream *stream);
|
||||||
|
int tlv_add_ipv4_ext_reachs (struct list *ipv4_reachs, struct stream *stream);
|
||||||
int tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream);
|
int tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
int tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream);
|
int tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* Copyright (C) 2001,2002 Sampo Saaristo
|
* Copyright (C) 2001,2002 Sampo Saaristo
|
||||||
* Tampere University of Technology
|
* Tampere University of Technology
|
||||||
* Institute of Communications Engineering
|
* Institute of Communications Engineering
|
||||||
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public Licenseas published by the Free
|
* under the terms of the GNU General Public Licenseas published by the Free
|
||||||
@ -32,6 +33,7 @@
|
|||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "linklist.h"
|
#include "linklist.h"
|
||||||
|
#include "nexthop.h"
|
||||||
#include "vrf.h"
|
#include "vrf.h"
|
||||||
|
|
||||||
#include "isisd/dict.h"
|
#include "isisd/dict.h"
|
||||||
@ -531,8 +533,10 @@ isis_zebra_read_ipv4 (int command, struct zclient *zclient,
|
|||||||
struct stream *stream;
|
struct stream *stream;
|
||||||
struct zapi_ipv4 api;
|
struct zapi_ipv4 api;
|
||||||
struct prefix_ipv4 p;
|
struct prefix_ipv4 p;
|
||||||
|
struct prefix *p_generic = (struct prefix*)&p;
|
||||||
|
|
||||||
stream = zclient->ibuf;
|
stream = zclient->ibuf;
|
||||||
|
memset(&api, 0, sizeof(api));
|
||||||
memset (&p, 0, sizeof (struct prefix_ipv4));
|
memset (&p, 0, sizeof (struct prefix_ipv4));
|
||||||
|
|
||||||
api.type = stream_getc (stream);
|
api.type = stream_getc (stream);
|
||||||
@ -558,32 +562,80 @@ isis_zebra_read_ipv4 (int command, struct zclient *zclient,
|
|||||||
api.distance = stream_getc (stream);
|
api.distance = stream_getc (stream);
|
||||||
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
|
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
|
||||||
api.metric = stream_getl (stream);
|
api.metric = stream_getl (stream);
|
||||||
else
|
|
||||||
api.metric = 0;
|
/*
|
||||||
|
* Avoid advertising a false default reachability. (A default
|
||||||
|
* route installed by IS-IS gets redistributed from zebra back
|
||||||
|
* into IS-IS causing us to start advertising default reachabity
|
||||||
|
* without this check)
|
||||||
|
*/
|
||||||
|
if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
|
||||||
|
command = ZEBRA_IPV4_ROUTE_DELETE;
|
||||||
|
|
||||||
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
|
if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
|
||||||
{
|
isis_redist_add(api.type, p_generic, api.distance, api.metric);
|
||||||
if (isis->debugs & DEBUG_ZEBRA)
|
else
|
||||||
zlog_debug ("IPv4 Route add from Z");
|
isis_redist_delete(api.type, p_generic);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
static int
|
static int
|
||||||
isis_zebra_read_ipv6 (int command, struct zclient *zclient,
|
isis_zebra_read_ipv6 (int command, struct zclient *zclient,
|
||||||
zebra_size_t length, vrf_id_t vrf_id)
|
zebra_size_t length, vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
|
struct stream *stream;
|
||||||
|
struct zapi_ipv6 api;
|
||||||
|
struct prefix_ipv6 p;
|
||||||
|
struct prefix *p_generic = (struct prefix*)&p;
|
||||||
|
struct in6_addr nexthop;
|
||||||
|
unsigned long ifindex __attribute__((unused));
|
||||||
|
|
||||||
|
stream = zclient->ibuf;
|
||||||
|
memset(&api, 0, sizeof(api));
|
||||||
|
memset(&p, 0, sizeof(struct prefix_ipv6));
|
||||||
|
memset(&nexthop, 0, sizeof(nexthop));
|
||||||
|
ifindex = 0;
|
||||||
|
|
||||||
|
api.type = stream_getc(stream);
|
||||||
|
api.flags = stream_getc(stream);
|
||||||
|
api.message = stream_getc(stream);
|
||||||
|
|
||||||
|
p.family = AF_INET6;
|
||||||
|
p.prefixlen = stream_getc(stream);
|
||||||
|
stream_get(&p.prefix, stream, PSIZE(p.prefixlen));
|
||||||
|
|
||||||
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP))
|
||||||
|
{
|
||||||
|
api.nexthop_num = stream_getc(stream); /* this is always 1 */
|
||||||
|
stream_get(&nexthop, stream, sizeof(nexthop));
|
||||||
|
}
|
||||||
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX))
|
||||||
|
{
|
||||||
|
api.ifindex_num = stream_getc(stream);
|
||||||
|
ifindex = stream_getl(stream);
|
||||||
|
}
|
||||||
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
|
||||||
|
api.distance = stream_getc(stream);
|
||||||
|
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
|
||||||
|
api.metric = stream_getl(stream);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid advertising a false default reachability. (A default
|
||||||
|
* route installed by IS-IS gets redistributed from zebra back
|
||||||
|
* into IS-IS causing us to start advertising default reachabity
|
||||||
|
* without this check)
|
||||||
|
*/
|
||||||
|
if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS)
|
||||||
|
command = ZEBRA_IPV6_ROUTE_DELETE;
|
||||||
|
|
||||||
|
if (command == ZEBRA_IPV6_ROUTE_ADD)
|
||||||
|
isis_redist_add(api.type, p_generic, api.distance, api.metric);
|
||||||
|
else
|
||||||
|
isis_redist_delete(api.type, p_generic);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ISIS_TYPE_IS_REDISTRIBUTED(T) \
|
|
||||||
T == ZEBRA_ROUTE_MAX ? \
|
|
||||||
vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : \
|
|
||||||
(vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT) || \
|
|
||||||
vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT)
|
|
||||||
|
|
||||||
int
|
int
|
||||||
isis_distribute_list_update (int routetype)
|
isis_distribute_list_update (int routetype)
|
||||||
@ -591,14 +643,23 @@ isis_distribute_list_update (int routetype)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* Not yet. */
|
void
|
||||||
static int
|
isis_zebra_redistribute_set(int type)
|
||||||
isis_redistribute_default_set (int routetype, int metric_type,
|
|
||||||
int metric_value)
|
|
||||||
{
|
{
|
||||||
return 0;
|
if (type == DEFAULT_ROUTE)
|
||||||
|
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, VRF_DEFAULT);
|
||||||
|
else
|
||||||
|
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0, VRF_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isis_zebra_redistribute_unset(int type)
|
||||||
|
{
|
||||||
|
if (type == DEFAULT_ROUTE)
|
||||||
|
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, VRF_DEFAULT);
|
||||||
|
else
|
||||||
|
zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, 0, VRF_DEFAULT);
|
||||||
}
|
}
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
isis_zebra_connected (struct zclient *zclient)
|
isis_zebra_connected (struct zclient *zclient)
|
||||||
|
@ -28,5 +28,7 @@ void isis_zebra_init(struct thread_master *);
|
|||||||
void isis_zebra_route_update (struct prefix *prefix,
|
void isis_zebra_route_update (struct prefix *prefix,
|
||||||
struct isis_route_info *route_info);
|
struct isis_route_info *route_info);
|
||||||
int isis_distribute_list_update (int routetype);
|
int isis_distribute_list_update (int routetype);
|
||||||
|
void isis_zebra_redistribute_set(int type);
|
||||||
|
void isis_zebra_redistribute_unset(int type);
|
||||||
|
|
||||||
#endif /* _ZEBRA_ISIS_ZEBRA_H */
|
#endif /* _ZEBRA_ISIS_ZEBRA_H */
|
||||||
|
@ -280,6 +280,8 @@ isis_area_destroy (struct vty *vty, const char *area_tag)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_IPV6 */
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
|
isis_redist_area_finish(area);
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS (area->area_addrs, node, nnode, addr))
|
for (ALL_LIST_ELEMENTS (area->area_addrs, node, nnode, addr))
|
||||||
{
|
{
|
||||||
list_delete_node (area->area_addrs, node);
|
list_delete_node (area->area_addrs, node);
|
||||||
@ -3050,6 +3052,8 @@ isis_config_write (struct vty *vty)
|
|||||||
vty_out (vty, " is-type level-2-only%s", VTY_NEWLINE);
|
vty_out (vty, " is-type level-2-only%s", VTY_NEWLINE);
|
||||||
write++;
|
write++;
|
||||||
}
|
}
|
||||||
|
write += isis_redist_config_write(vty, area, AF_INET);
|
||||||
|
write += isis_redist_config_write(vty, area, AF_INET6);
|
||||||
/* ISIS - Lsp generation interval */
|
/* ISIS - Lsp generation interval */
|
||||||
if (area->lsp_gen_interval[0] == area->lsp_gen_interval[1])
|
if (area->lsp_gen_interval[0] == area->lsp_gen_interval[1])
|
||||||
{
|
{
|
||||||
|
@ -27,16 +27,12 @@
|
|||||||
|
|
||||||
#define ISISD_VERSION "0.0.7"
|
#define ISISD_VERSION "0.0.7"
|
||||||
|
|
||||||
|
#include "isisd/isis_redist.h"
|
||||||
|
|
||||||
/* uncomment if you are a developer in bug hunt */
|
/* uncomment if you are a developer in bug hunt */
|
||||||
/* #define EXTREME_DEBUG */
|
/* #define EXTREME_DEBUG */
|
||||||
/* #define EXTREME_TLV_DEBUG */
|
/* #define EXTREME_TLV_DEBUG */
|
||||||
|
|
||||||
struct rmap
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
struct route_map *map;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct isis
|
struct isis
|
||||||
{
|
{
|
||||||
u_long process_id;
|
u_long process_id;
|
||||||
@ -55,30 +51,7 @@ struct isis
|
|||||||
time_t uptime; /* when did we start */
|
time_t uptime; /* when did we start */
|
||||||
struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */
|
struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */
|
||||||
|
|
||||||
/* Redistributed external information. */
|
struct route_table *ext_info[REDIST_PROTOCOL_COUNT];
|
||||||
struct route_table *external_info[ZEBRA_ROUTE_MAX + 1];
|
|
||||||
/* Redistribute metric info. */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int type; /* Internal or External */
|
|
||||||
int value; /* metric value */
|
|
||||||
} dmetric[ZEBRA_ROUTE_MAX + 1];
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
struct route_map *map;
|
|
||||||
} rmap[ZEBRA_ROUTE_MAX + 1];
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
struct route_map *map;
|
|
||||||
} rmap[ZEBRA_ROUTE_MAX + 1];
|
|
||||||
} inet6_afmode;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct isis *isis;
|
extern struct isis *isis;
|
||||||
@ -147,6 +120,9 @@ struct isis_area
|
|||||||
#endif /* HAVE_IPV6 */
|
#endif /* HAVE_IPV6 */
|
||||||
/* Counters */
|
/* Counters */
|
||||||
u_int32_t circuit_state_changes;
|
u_int32_t circuit_state_changes;
|
||||||
|
struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]
|
||||||
|
[ZEBRA_ROUTE_MAX + 1][ISIS_LEVELS];
|
||||||
|
struct route_table *ext_reach[REDIST_PROTOCOL_COUNT][ISIS_LEVELS];
|
||||||
|
|
||||||
#ifdef TOPOLOGY_GENERATE
|
#ifdef TOPOLOGY_GENERATE
|
||||||
struct list *topology;
|
struct list *topology;
|
||||||
|
11
lib/prefix.c
11
lib/prefix.c
@ -187,6 +187,17 @@ prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen)
|
|||||||
return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
|
return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
str2family(const char *string)
|
||||||
|
{
|
||||||
|
if (!strcmp("ipv4", string))
|
||||||
|
return AF_INET;
|
||||||
|
else if (!strcmp("ipv6", string))
|
||||||
|
return AF_INET6;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Address Famiy Identifier to Address Family converter. */
|
/* Address Famiy Identifier to Address Family converter. */
|
||||||
int
|
int
|
||||||
afi2family (afi_t afi)
|
afi2family (afi_t afi)
|
||||||
|
@ -167,6 +167,7 @@ union prefix46constptr
|
|||||||
#endif /*s6_addr32*/
|
#endif /*s6_addr32*/
|
||||||
|
|
||||||
/* Prototypes. */
|
/* Prototypes. */
|
||||||
|
extern int str2family(const char *);
|
||||||
extern int afi2family (afi_t);
|
extern int afi2family (afi_t);
|
||||||
extern afi_t family2afi (int);
|
extern afi_t family2afi (int);
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@ typedef enum
|
|||||||
RMAP_OSPF,
|
RMAP_OSPF,
|
||||||
RMAP_OSPF6,
|
RMAP_OSPF6,
|
||||||
RMAP_BGP,
|
RMAP_BGP,
|
||||||
RMAP_ZEBRA
|
RMAP_ZEBRA,
|
||||||
|
RMAP_ISIS,
|
||||||
} route_map_object_t;
|
} route_map_object_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
Loading…
Reference in New Issue
Block a user