Skip to content

Commit

Permalink
isisd: add isis flex-algo base interface
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
slankdev authored and louis-6wind committed Apr 18, 2023
1 parent 72eae2c commit 7f198e0
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 0 deletions.
240 changes: 240 additions & 0 deletions isisd/isis_flex_algo.c
Original file line number Diff line number Diff line change
@@ -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 changes: 51 additions & 0 deletions isisd/isis_flex_algo.h
Original file line number Diff line number Diff line change
@@ -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 */
15 changes: 15 additions & 0 deletions isisd/isis_tlvs.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "segment_routing.h"
#include "openbsd-tree.h"
#include "prefix.h"
#include "flex_algo.h"

DECLARE_MTYPE(ISIS_SUBTLV);

Expand Down Expand Up @@ -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;
Expand All @@ -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 {
Expand Down
8 changes: 8 additions & 0 deletions isisd/isisd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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"

Expand Down Expand Up @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions isisd/isisd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 2 additions & 0 deletions isisd/subdir.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 \
Expand Down

0 comments on commit 7f198e0

Please sign in to comment.