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:
Hiroki Shirokura 2021-12-12 09:43:37 +00:00 committed by Louis Scalbert
parent 72eae2c3cb
commit 7f198e063c
6 changed files with 320 additions and 0 deletions

240
isisd/isis_flex_algo.c Normal file
View 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
View 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 */

View file

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

View file

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

View file

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

View file

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