]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: add library for igp flexible-algorithm
authorHiroki Shirokura <hiroki.shirokura@linecorp.com>
Sat, 22 Jan 2022 11:08:05 +0000 (11:08 +0000)
committerLouis Scalbert <louis.scalbert@6wind.com>
Tue, 18 Apr 2023 08:13:58 +0000 (10:13 +0200)
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 <hiroki.shirokura@linecorp.com>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
lib/flex_algo.c [new file with mode: 0644]
lib/flex_algo.h [new file with mode: 0644]
lib/subdir.am

diff --git a/lib/flex_algo.c b/lib/flex_algo.c
new file mode 100644 (file)
index 0000000..bafbf8b
--- /dev/null
@@ -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 (file)
index 0000000..e012f46
--- /dev/null
@@ -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 */
index 318c09663ec6143c0e484e2304b4ca14647392cf..0cd68c0e7092ddf7c5be32203e43b864fbdfb5db 100644 (file)
@@ -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 \