From 735fb37db1897f6393680c62d369e339146f004b Mon Sep 17 00:00:00 2001 From: Hiroki Shirokura Date: Sat, 22 Jan 2022 11:08:05 +0000 Subject: [PATCH] lib: add library for igp flexible-algorithm Add a library to deal with Flexible Algorithm that will be common to IS-IS and OSPF. The functions enables to deal with: - Affinity-maps - Extended Admin Group (RFC7308) - Flex-Algo structures that contains the flex-algo configurations Signed-off-by: Hiroki Shirokura Signed-off-by: Louis Scalbert --- lib/flex_algo.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/flex_algo.h | 121 +++++++++++++++++++++++++++++++++++++++++ lib/subdir.am | 2 + 3 files changed, 265 insertions(+) create mode 100644 lib/flex_algo.c create mode 100644 lib/flex_algo.h diff --git a/lib/flex_algo.c b/lib/flex_algo.c new file mode 100644 index 0000000000..bafbf8b779 --- /dev/null +++ b/lib/flex_algo.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/********************************************************************* + * Copyright 2022 Hiroki Shirokura, LINE Corporation + * Copyright 2022 Masakazu Asama + * Copyright 2022 6WIND S.A. + * + * flex_algo.c: Flexible Algorithm library + * + * Authors + * ------- + * Hiroki Shirokura + * Masakazu Asama + * Louis Scalbert + */ + +#include "zebra.h" + +#include "flex_algo.h" + +DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo Definition"); + +struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator, + flex_algo_releaser_t releaser) +{ + struct flex_algos *flex_algos; + + flex_algos = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*flex_algos)); + flex_algos->flex_algos = list_new(); + flex_algos->allocator = allocator; + flex_algos->releaser = releaser; + return flex_algos; +} + +struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos, + uint8_t algorithm, void *arg) +{ + struct flex_algo *fa; + + fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(*fa)); + fa->algorithm = algorithm; + if (flex_algos->allocator) + fa->data = flex_algos->allocator(arg); + admin_group_init(&fa->admin_group_exclude_any); + admin_group_init(&fa->admin_group_include_any); + admin_group_init(&fa->admin_group_include_all); + listnode_add(flex_algos->flex_algos, fa); + return fa; +} + +/** + * @brief Look up the local flex-algo object by its algorithm number. + * @param algorithm flex-algo algorithm number + * @param area area pointer of flex-algo + * @return local flex-algo object if exist, else NULL + */ +struct flex_algo *flex_algo_lookup(struct flex_algos *flex_algos, + uint8_t algorithm) +{ + struct listnode *node; + struct flex_algo *fa; + + for (ALL_LIST_ELEMENTS_RO(flex_algos->flex_algos, node, fa)) + if (fa->algorithm == algorithm) + return fa; + return NULL; +} + +/** + * @brief Compare two Flex-Algo Definitions (FAD) + * @param Flex algo 1 + * @param Flex algo 2 + * @return true if the definition is equal, else false + */ +bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2) +{ + if (fa1->algorithm != fa2->algorithm) + return false; + if (fa1->calc_type != fa2->calc_type) + return false; + if (fa1->metric_type != fa2->metric_type) + return false; + + if (!admin_group_cmp(&fa1->admin_group_exclude_any, + &fa2->admin_group_exclude_any)) + return false; + if (!admin_group_cmp(&fa1->admin_group_include_all, + &fa2->admin_group_include_all)) + return false; + if (!admin_group_cmp(&fa1->admin_group_include_any, + &fa2->admin_group_include_any)) + return false; + + return true; +} + +void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm) +{ + struct listnode *node, *nnode; + struct flex_algo *fa; + + for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) { + if (fa->algorithm != algorithm) + continue; + if (flex_algos->releaser) + flex_algos->releaser(fa->data); + admin_group_term(&fa->admin_group_exclude_any); + admin_group_term(&fa->admin_group_include_any); + admin_group_term(&fa->admin_group_include_all); + listnode_delete(flex_algos->flex_algos, fa); + XFREE(MTYPE_FLEX_ALGO, fa); + return; + } +} + +/** + * Check SR Algorithm is Flex-Algo + * according to RFC9350 section 4 + * + * @param algorithm SR Algorithm + */ +bool flex_algo_id_valid(uint16_t algorithm) +{ + return algorithm >= SR_ALGORITHM_FLEX_MIN && + algorithm <= SR_ALGORITHM_FLEX_MAX; +} + +char *flex_algo_metric_type_print(char *type_str, size_t sz, + enum flex_algo_metric_type metric_type) +{ + switch (metric_type) { + case MT_IGP: + snprintf(type_str, sz, "igp"); + break; + case MT_MIN_UNI_LINK_DELAY: + snprintf(type_str, sz, "delay"); + break; + case MT_TE_DEFAULT: + snprintf(type_str, sz, "te"); + break; + } + return type_str; +} diff --git a/lib/flex_algo.h b/lib/flex_algo.h new file mode 100644 index 0000000000..e012f46862 --- /dev/null +++ b/lib/flex_algo.h @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/********************************************************************* + * Copyright 2022 Hiroki Shirokura, LINE Corporation + * Copyright 2022 Masakazu Asama + * Copyright 2022 6WIND S.A. + * + * flex_algo.h: Flexible Algorithm library + * + * Authors + * ------- + * Hiroki Shirokura + * Masakazu Asama + * Louis Scalbert + */ + +#ifndef _FRR_FLEX_ALGO_H +#define _FRR_FLEX_ALGO_H + +#include "admin_group.h" +#include "linklist.h" +#include "prefix.h" +#include "segment_routing.h" + +#define FLEX_ALGO_PRIO_DEFAULT 128 + +#define CALC_TYPE_SPF 0 + +/* flex-algo definition flags */ + +/* M-flag (aka. prefix-metric) + * Flex-Algorithm specific prefix and ASBR metric MUST be used + */ +#define FAD_FLAG_M 0x80 + +/* + * Metric Type values from RFC9350 section 5.1 + */ +enum flex_algo_metric_type { + MT_IGP = 0, + MT_MIN_UNI_LINK_DELAY = 1, + MT_TE_DEFAULT = 2, +}; + + +/* Flex-Algo data about a given algorithm. + * It includes the definition and some local data. + */ +struct flex_algo { + /* Flex-Algo definition */ + uint8_t algorithm; + enum flex_algo_metric_type metric_type; + uint8_t calc_type; + uint8_t priority; + uint8_t flags; + + /* extended admin-groups */ + struct admin_group admin_group_exclude_any; + struct admin_group admin_group_include_any; + struct admin_group admin_group_include_all; + + /* Exclude SRLG Sub-TLV is not yet supported by IS-IS + * True if a Exclude SRLG Sub-TLV has been found + */ + bool exclude_srlg; + + /* True if an unsupported sub-TLV other Exclude SRLG + * has been received. + * A router that receives an unsupported definition + * that is elected must not participate in the algorithm. + * This boolean prevents future sub-TLV from being considered + * as supported. + */ + bool unsupported_subtlv; + + /* Flex-Algo local data */ + + /* True if the local definition must be advertised */ + bool advertise_definition; + + /* which dataplane must be used for the algorithm */ +#define FLEX_ALGO_SR_MPLS 0x01 +#define FLEX_ALGO_SRV6 0x02 +#define FLEX_ALGO_IP 0x04 + uint8_t dataplanes; + + /* + * This property can be freely extended among different routing + * protocols. Since Flex-Algo is an IGP protocol agnostic, both IS-IS + * and OSPF can implement Flex-Algo. The struct flex_algo thus provides + * the general data structure of Flex-Algo, and the value of extending + * it with the IGP protocol is provided by this property. + */ + void *data; +}; + +typedef void *(*flex_algo_allocator_t)(void *); +typedef void (*flex_algo_releaser_t)(void *); + +struct flex_algos { + flex_algo_allocator_t allocator; + flex_algo_releaser_t releaser; + struct list *flex_algos; +}; + +/* + * Flex-Algo Utilities + */ +struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator, + flex_algo_releaser_t releaser); +struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos, + uint8_t algorithm, void *arg); +struct flex_algo *flex_algo_lookup(struct flex_algos *flex_algos, + uint8_t algorithm); +void flex_algos_free(struct flex_algos *flex_algos); +bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2); +void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm); +bool flex_algo_id_valid(uint16_t algorithm); +char *flex_algo_metric_type_print(char *type_str, size_t sz, + enum flex_algo_metric_type metric_type); + +#endif /* _FRR_FLEX_ALGO_H */ diff --git a/lib/subdir.am b/lib/subdir.am index 318c09663e..0cd68c0e70 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -33,6 +33,7 @@ lib_libfrr_la_SOURCES = \ lib/filter.c \ lib/filter_cli.c \ lib/filter_nb.c \ + lib/flex_algo.c \ lib/frrcu.c \ lib/frrlua.c \ lib/frrscript.c \ @@ -211,6 +212,7 @@ pkginclude_HEADERS += \ lib/distribute.h \ lib/ferr.h \ lib/filter.h \ + lib/flex_algo.h \ lib/freebsd-queue.h \ lib/frrlua.h \ lib/frrscript.h \