forked from Mirror/frr
isisd: add isis flex-algo base interface
Adds basic functionality to Flex-Algo for IS-IS wrapping lib/flex_algo. The configuration interface will be added in the next commit. Signed-off-by: Hiroki Shirokura <hiroki.shirokura@linecorp.com> Signed-off-by: Eric Kinzie <ekinzie@labn.net> Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
parent
72eae2c3cb
commit
7f198e063c
240
isisd/isis_flex_algo.c
Normal file
240
isisd/isis_flex_algo.c
Normal file
|
@ -0,0 +1,240 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*********************************************************************
|
||||
* Copyright 2022 Hiroki Shirokura, LINE Corporation
|
||||
* Copyright 2022 Masakazu Asama
|
||||
* Copyright 2022 6WIND S.A.
|
||||
*
|
||||
* isis_flex_algo.c: IS-IS Flexible Algorithm
|
||||
*
|
||||
* Authors
|
||||
* -------
|
||||
* Hiroki Shirokura
|
||||
* Masakazu Asama
|
||||
* Louis Scalbert
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "stream.h"
|
||||
#include "sbuf.h"
|
||||
#include "network.h"
|
||||
#include "command.h"
|
||||
#include "bitfield.h"
|
||||
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_tlvs.h"
|
||||
#include "isisd/isis_common.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_circuit.h"
|
||||
#include "isisd/isis_pdu.h"
|
||||
#include "isisd/isis_lsp.h"
|
||||
#include "isisd/isis_spf.h"
|
||||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
#include "isisd/isis_spf_private.h"
|
||||
#include "isisd/isis_flex_algo.h"
|
||||
|
||||
#ifndef FABRICD
|
||||
DEFINE_MTYPE_STATIC(ISISD, FLEX_ALGO, "ISIS Flex Algo");
|
||||
|
||||
void *isis_flex_algo_data_alloc(void *voidarg)
|
||||
{
|
||||
struct isis_flex_algo_alloc_arg *arg = voidarg;
|
||||
struct isis_flex_algo_data *data;
|
||||
|
||||
data = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*data));
|
||||
|
||||
for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++) {
|
||||
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
||||
if (!(arg->area->is_type & level))
|
||||
continue;
|
||||
data->spftree[tree][level - 1] = isis_spftree_new(
|
||||
arg->area, &arg->area->lspdb[level - 1],
|
||||
arg->area->isis->sysid, level, tree,
|
||||
SPF_TYPE_FORWARD, 0, arg->algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void isis_flex_algo_data_free(void *voiddata)
|
||||
{
|
||||
struct isis_flex_algo_data *data = voiddata;
|
||||
|
||||
for (int tree = SPFTREE_IPV4; tree < SPFTREE_COUNT; tree++)
|
||||
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++)
|
||||
if (data->spftree[tree][level - 1])
|
||||
isis_spftree_del(
|
||||
data->spftree[tree][level - 1]);
|
||||
}
|
||||
|
||||
static struct isis_router_cap_fad *
|
||||
isis_flex_algo_definition_cmp(struct isis_router_cap_fad *elected,
|
||||
struct isis_router_cap_fad *fa)
|
||||
{
|
||||
if (!elected || fa->fad.priority > elected->fad.priority ||
|
||||
(fa->fad.priority == elected->fad.priority &&
|
||||
lsp_id_cmp(fa->sysid, elected->sysid) > 0))
|
||||
return fa;
|
||||
|
||||
return elected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Look up the flex-algo definition with the highest priority in the LSP
|
||||
* Database (LSDB). If the value of priority is the same, the flex-algo
|
||||
* definition with the highest sysid will be selected.
|
||||
* @param algorithm flex-algo algorithm number
|
||||
* @param area pointer
|
||||
* @param local router capability Flex-Algo Definition (FAD) double pointer.
|
||||
* - fad is NULL: use the local router capability FAD from LSDB for the
|
||||
* election.
|
||||
* - fad is not NULL and *fad is NULL: use no local router capability FAD for
|
||||
* the election.
|
||||
* - fad and *fad are not NULL: uses the *fad local definition instead of the
|
||||
* local definition from LSDB for the election.
|
||||
* @return elected flex-algo-definition object if exist, else NULL
|
||||
*/
|
||||
static struct isis_router_cap_fad *
|
||||
_isis_flex_algo_elected(int algorithm, const struct isis_area *area,
|
||||
struct isis_router_cap_fad **fad)
|
||||
{
|
||||
struct flex_algo *flex_ago;
|
||||
const struct isis_lsp *lsp;
|
||||
struct isis_router_cap_fad *fa, *elected = NULL;
|
||||
|
||||
if (!flex_algo_id_valid(algorithm))
|
||||
return NULL;
|
||||
|
||||
/* No elected FAD if the algorithm is not locally configured */
|
||||
flex_ago = flex_algo_lookup(area->flex_algos, algorithm);
|
||||
if (!flex_ago)
|
||||
return NULL;
|
||||
|
||||
/* No elected FAD if no data-plane is enabled
|
||||
* Currently, only Segment-Routing MPLS is supported.
|
||||
* Segment-Routing SRv6 and IP will be configured in the future.
|
||||
*/
|
||||
if (!CHECK_FLAG(flex_ago->dataplanes, FLEX_ALGO_SR_MPLS))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Perform FAD comparison. First, compare the priority, and if they are
|
||||
* the same, compare the sys-id.
|
||||
*/
|
||||
/* clang-format off */
|
||||
frr_each_const(lspdb, &area->lspdb[ISIS_LEVEL1 - 1], lsp) {
|
||||
/* clang-format on */
|
||||
|
||||
if (!lsp->tlvs || !lsp->tlvs->router_cap)
|
||||
continue;
|
||||
|
||||
if (lsp->own_lsp && fad)
|
||||
continue;
|
||||
|
||||
fa = lsp->tlvs->router_cap->fads[algorithm];
|
||||
|
||||
if (!fa)
|
||||
continue;
|
||||
|
||||
assert(algorithm == fa->fad.algorithm);
|
||||
|
||||
memcpy(fa->sysid, lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 2);
|
||||
|
||||
elected = isis_flex_algo_definition_cmp(elected, fa);
|
||||
}
|
||||
|
||||
if (fad && *fad)
|
||||
elected = isis_flex_algo_definition_cmp(elected, *fad);
|
||||
|
||||
return elected;
|
||||
}
|
||||
|
||||
struct isis_router_cap_fad *isis_flex_algo_elected(int algorithm,
|
||||
const struct isis_area *area)
|
||||
{
|
||||
return _isis_flex_algo_elected(algorithm, area, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check the Flex-Algo Definition is supported by the current FRR version
|
||||
* @param flex-algo
|
||||
* @return true if supported else false
|
||||
*/
|
||||
bool isis_flex_algo_supported(struct flex_algo *fad)
|
||||
{
|
||||
if (fad->calc_type != CALC_TYPE_SPF)
|
||||
return false;
|
||||
if (fad->metric_type != MT_IGP)
|
||||
return false;
|
||||
if (fad->flags != 0)
|
||||
return false;
|
||||
if (fad->exclude_srlg)
|
||||
return false;
|
||||
if (fad->unsupported_subtlv)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Look for the elected Flex-Algo Definition and check that it is
|
||||
* supported by the current FRR version
|
||||
* @param algorithm flex-algo algorithm number
|
||||
* @param area pointer
|
||||
* @param local router capability Flex-Algo Definition (FAD) double pointer.
|
||||
* @return elected flex-algo-definition object if exist and supported, else NULL
|
||||
*/
|
||||
static struct isis_router_cap_fad *
|
||||
_isis_flex_algo_elected_supported(int algorithm, const struct isis_area *area,
|
||||
struct isis_router_cap_fad **fad)
|
||||
{
|
||||
struct isis_router_cap_fad *elected_fad;
|
||||
|
||||
elected_fad = _isis_flex_algo_elected(algorithm, area, fad);
|
||||
if (!elected_fad)
|
||||
return NULL;
|
||||
|
||||
if (isis_flex_algo_supported(&elected_fad->fad))
|
||||
return elected_fad;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct isis_router_cap_fad *
|
||||
isis_flex_algo_elected_supported(int algorithm, const struct isis_area *area)
|
||||
{
|
||||
return _isis_flex_algo_elected_supported(algorithm, area, NULL);
|
||||
}
|
||||
|
||||
struct isis_router_cap_fad *
|
||||
isis_flex_algo_elected_supported_local_fad(int algorithm,
|
||||
const struct isis_area *area,
|
||||
struct isis_router_cap_fad **fad)
|
||||
{
|
||||
return _isis_flex_algo_elected_supported(algorithm, area, fad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check LSP is participating specified SR Algorithm
|
||||
*
|
||||
* @param lsp IS-IS lsp
|
||||
* @param algorithm SR Algorithm
|
||||
* @return Return true if sr-algorithm tlv includes specified
|
||||
* algorithm in router capability tlv
|
||||
*/
|
||||
bool sr_algorithm_participated(const struct isis_lsp *lsp, uint8_t algorithm)
|
||||
{
|
||||
if (!lsp || !lsp->tlvs || !lsp->tlvs->router_cap)
|
||||
return false;
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
|
||||
if (lsp->tlvs->router_cap->algo[i] == algorithm)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* ifndef FABRICD */
|
51
isisd/isis_flex_algo.h
Normal file
51
isisd/isis_flex_algo.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*********************************************************************
|
||||
* Copyright 2022 Hiroki Shirokura, LINE Corporation
|
||||
* Copyright 2022 Masakazu Asama
|
||||
* Copyright 2022 6WIND S.A.
|
||||
*
|
||||
* isis_flex_algo.h: IS-IS Flexible Algorithm
|
||||
*
|
||||
* Authors
|
||||
* -------
|
||||
* Hiroki Shirokura
|
||||
* Masakazu Asama
|
||||
* Louis Scalbert
|
||||
*/
|
||||
|
||||
#ifndef ISIS_FLEX_ALGO_H
|
||||
#define ISIS_FLEX_ALGO_H
|
||||
|
||||
#include "flex_algo.h"
|
||||
#include "isisd/isis_constants.h"
|
||||
|
||||
#ifndef FABRICD
|
||||
|
||||
struct isis_flex_algo_data {
|
||||
struct isis_spftree *spftree[SPFTREE_COUNT][ISIS_LEVELS];
|
||||
struct isis_area *area;
|
||||
};
|
||||
|
||||
struct isis_flex_algo_alloc_arg {
|
||||
uint8_t algorithm;
|
||||
struct isis_area *area;
|
||||
};
|
||||
|
||||
void *isis_flex_algo_data_alloc(void *arg);
|
||||
void isis_flex_algo_data_free(void *data);
|
||||
|
||||
struct isis_router_cap_fad *
|
||||
isis_flex_algo_elected(int algorithm, const struct isis_area *area);
|
||||
bool isis_flex_algo_supported(struct flex_algo *fad);
|
||||
struct isis_router_cap_fad *
|
||||
isis_flex_algo_elected_supported(int algorithm, const struct isis_area *area);
|
||||
struct isis_router_cap_fad *
|
||||
isis_flex_algo_elected_supported_local_fad(int algorithm,
|
||||
const struct isis_area *area,
|
||||
struct isis_router_cap_fad **fad);
|
||||
struct isis_lsp;
|
||||
bool sr_algorithm_participated(const struct isis_lsp *lsp, uint8_t algorithm);
|
||||
|
||||
#endif /* ifndef FABRICD */
|
||||
|
||||
#endif /* ISIS_FLEX_ALGO_H */
|
|
@ -12,6 +12,7 @@
|
|||
#include "segment_routing.h"
|
||||
#include "openbsd-tree.h"
|
||||
#include "prefix.h"
|
||||
#include "flex_algo.h"
|
||||
|
||||
DECLARE_MTYPE(ISIS_SUBTLV);
|
||||
|
||||
|
@ -181,6 +182,15 @@ struct isis_lan_adj_sid {
|
|||
#define MSD_TYPE_BASE_MPLS_IMPOSITION 0x01
|
||||
#define MSD_TLV_SIZE 2
|
||||
|
||||
#ifndef FABRICD
|
||||
struct isis_router_cap_fad;
|
||||
struct isis_router_cap_fad {
|
||||
uint8_t sysid[ISIS_SYS_ID_LEN + 2];
|
||||
|
||||
struct flex_algo fad;
|
||||
};
|
||||
#endif /* ifndef FABRICD */
|
||||
|
||||
struct isis_router_cap {
|
||||
struct in_addr router_id;
|
||||
uint8_t flags;
|
||||
|
@ -191,6 +201,11 @@ struct isis_router_cap {
|
|||
uint8_t algo[SR_ALGORITHM_COUNT];
|
||||
/* RFC 8491 */
|
||||
uint8_t msd;
|
||||
|
||||
#ifndef FABRICD
|
||||
/* RFC9350 Flex-Algorithm */
|
||||
struct isis_router_cap_fad *fads[SR_ALGORITHM_COUNT];
|
||||
#endif /* ifndef FABRICD */
|
||||
};
|
||||
|
||||
struct isis_item {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "zclient.h"
|
||||
#include "vrf.h"
|
||||
#include "spf_backoff.h"
|
||||
#include "flex_algo.h"
|
||||
#include "lib/northbound_cli.h"
|
||||
#include "bfd.h"
|
||||
|
||||
|
@ -49,6 +50,7 @@
|
|||
#include "isisd/isis_te.h"
|
||||
#include "isisd/isis_mt.h"
|
||||
#include "isisd/isis_sr.h"
|
||||
#include "isisd/isis_flex_algo.h"
|
||||
#include "isisd/fabricd.h"
|
||||
#include "isisd/isis_nb.h"
|
||||
|
||||
|
@ -317,6 +319,12 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
|
|||
if (area->is_type & IS_LEVEL_2)
|
||||
lsp_db_init(&area->lspdb[1]);
|
||||
|
||||
#ifndef FABRICD
|
||||
/* Flex-Algo */
|
||||
area->flex_algos = flex_algos_alloc(isis_flex_algo_data_alloc,
|
||||
isis_flex_algo_data_free);
|
||||
#endif /* ifndef FABRICD */
|
||||
|
||||
spftree_area_init(area);
|
||||
|
||||
area->circuit_list = list_new();
|
||||
|
|
|
@ -220,6 +220,10 @@ struct isis_area {
|
|||
size_t tilfa_protected_links[ISIS_LEVELS];
|
||||
/* MPLS LDP-IGP Sync */
|
||||
struct ldp_sync_info_cmd ldp_sync_cmd;
|
||||
#ifndef FABRICD
|
||||
/* Flex-Algo */
|
||||
struct flex_algos *flex_algos;
|
||||
#endif /* ifndef FABRICD */
|
||||
/* Counters */
|
||||
uint32_t circuit_state_changes;
|
||||
struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]
|
||||
|
|
|
@ -45,6 +45,7 @@ noinst_HEADERS += \
|
|||
isisd/isis_spf.h \
|
||||
isisd/isis_spf_private.h \
|
||||
isisd/isis_sr.h \
|
||||
isisd/isis_flex_algo.h \
|
||||
isisd/isis_te.h \
|
||||
isisd/isis_tlvs.h \
|
||||
isisd/isis_tx_queue.h \
|
||||
|
@ -76,6 +77,7 @@ LIBISIS_SOURCES = \
|
|||
isisd/isis_routemap.c \
|
||||
isisd/isis_spf.c \
|
||||
isisd/isis_sr.c \
|
||||
isisd/isis_flex_algo.c \
|
||||
isisd/isis_te.c \
|
||||
isisd/isis_tlvs.c \
|
||||
isisd/isis_tx_queue.c \
|
||||
|
|
Loading…
Reference in a new issue