summaryrefslogtreecommitdiff
path: root/nest/mpls.h
diff options
context:
space:
mode:
Diffstat (limited to 'nest/mpls.h')
-rw-r--r--nest/mpls.h170
1 files changed, 170 insertions, 0 deletions
diff --git a/nest/mpls.h b/nest/mpls.h
new file mode 100644
index 00000000..a84ede14
--- /dev/null
+++ b/nest/mpls.h
@@ -0,0 +1,170 @@
+/*
+ * BIRD Internet Routing Daemon -- MPLS Structures
+ *
+ * (c) 2022 Ondrej Zajicek <santiago@crfreenet.org>
+ * (c) 2022 CZ.NIC z.s.p.o.
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_MPLS_H_
+#define _BIRD_MPLS_H_
+
+#include "nest/bird.h"
+#include "lib/bitmap.h"
+#include "lib/hash.h"
+#include "nest/route.h"
+#include "nest/protocol.h"
+
+
+#define MPLS_POLICY_NONE 0
+#define MPLS_POLICY_STATIC 1
+#define MPLS_POLICY_PREFIX 2
+#define MPLS_POLICY_AGGREGATE 3
+
+#define MPLS_FEC_DOWN 0
+#define MPLS_FEC_CLEAN 1
+#define MPLS_FEC_DIRTY 2
+
+
+struct mpls_domain_config {
+ node n; /* Node in config.mpls_domains */
+ struct mpls_domain *domain; /* Our instance */
+ const char *name;
+
+ list ranges; /* List of label ranges (struct mpls_range_config) */
+ struct mpls_range_config *static_range; /* Default static label range */
+ struct mpls_range_config *dynamic_range; /* Default dynamic label range */
+};
+
+struct mpls_domain {
+ node n; /* Node in global list of MPLS domains (mpls_domains) */
+ struct mpls_domain_config *cf; /* Our config */
+ const char *name;
+ pool *pool; /* Pool for the domain and associated objects */
+
+ struct lmap labels; /* Bitmap of allocated labels */
+ uint label_count; /* Number of allocated labels */
+ uint use_count; /* Reference counter */
+
+ struct config *removed; /* Deconfigured, waiting for zero use_count,
+ while keeping config obstacle */
+
+ list ranges; /* List of label ranges (struct mpls_range) */
+ list handles; /* List of label handles (struct mpls_handle) */
+};
+
+struct mpls_range_config {
+ node n; /* Node in mpls_domain_config.ranges */
+ struct mpls_range *range; /* Our instance */
+ struct mpls_domain_config *domain; /* Parent MPLS domain */
+ const char *name;
+
+ uint start; /* Label range start, (uint) -1 for undefined */
+ uint length; /* Label range length, (uint) -1 for undefined */
+};
+
+struct mpls_range {
+ node n; /* Node in mpls_domain.ranges */
+ struct mpls_range_config *cf; /* Our config */
+ const char *name;
+
+ uint lo, hi; /* Label range interval */
+ uint label_count; /* Number of allocated labels */
+ uint use_count; /* Reference counter */
+ u8 removed; /* Deconfigured, waiting for zero use_count */
+};
+
+struct mpls_handle {
+ node n; /* Node in mpls_domain.handles */
+
+ struct mpls_range *range; /* Associated range, keeping reference */
+ uint label_count; /* Number of allocated labels */
+};
+
+
+void mpls_init(void);
+struct mpls_domain_config * mpls_domain_config_new(struct symbol *s);
+void mpls_domain_postconfig(struct mpls_domain_config *cf);
+struct mpls_range_config * mpls_range_config_new(struct mpls_domain_config *m, struct symbol *s);
+void mpls_preconfig(struct config *c);
+void mpls_commit(struct config *new, struct config *old);
+uint mpls_new_label(struct mpls_domain *m, struct mpls_handle *h);
+void mpls_free_label(struct mpls_domain *m, struct mpls_handle *h, uint n);
+
+static inline struct mpls_domain_config *cf_default_mpls_domain(struct config *cfg)
+{ return EMPTY_LIST(cfg->mpls_domains) ? NULL : HEAD(cfg->mpls_domains); }
+
+
+struct mpls_channel_config {
+ struct channel_config c;
+
+ struct mpls_domain_config *domain;
+ struct mpls_range_config *range;
+
+ uint label_policy;
+};
+
+struct mpls_channel {
+ struct channel c;
+
+ struct mpls_domain *domain;
+ struct mpls_range *range;
+
+ uint label_policy;
+};
+
+
+void mpls_channel_postconfig(struct channel_config *CF);
+extern struct channel_class channel_mpls;
+
+
+struct mpls_fec {
+ u32 label; /* Label for FEC */
+ u32 hash; /* Hash for primary key (net / rta) */
+ u32 uc; /* Number of LSPs for FEC */
+ union { /* Extension part of key */
+ u32 path_id; /* Source path_id */
+ u32 class_id; /* Aaggregation class */
+ };
+
+ u8 state; /* FEC state (MPLS_FEC_*) */
+ u8 policy; /* Label policy (MPLS_POLICY_*) */
+
+ struct mpls_fec *next_k; /* Next in mpls_fec.net_hash/rta_hash */
+ struct mpls_fec *next_l; /* Next in mpls_fec.label_hash */
+ union { /* Primary key */
+ struct rta *rta;
+ net_addr net[0];
+ };
+};
+
+struct mpls_fec_map {
+ pool *pool; /* Pool for FEC map */
+ slab *slabs[4]; /* Slabs for FEC allocation */
+ HASH(struct mpls_fec) net_hash; /* Hash table for MPLS_POLICY_PREFIX FECs */
+ HASH(struct mpls_fec) rta_hash; /* Hash table for MPLS_POLICY_AGGREGATE FECs */
+ HASH(struct mpls_fec) label_hash; /* Hash table for FEC lookup by label */
+
+ struct channel *channel; /* MPLS channel for FEC announcement */
+ struct mpls_domain *domain; /* MPLS domain, keeping reference */
+ struct mpls_handle *handle; /* Handle for allocation of labels */
+
+ u8 mpls_rts; /* Source value used for MPLS routes (RTS_*) */
+ u8 mpls_scope; /* Scope value used for MPLS routes () */
+};
+
+
+struct mpls_fec_map *mpls_fec_map_new(pool *p, struct channel *c, uint rts);
+void mpls_fec_map_free(struct mpls_fec_map *m);
+struct mpls_fec *mpls_find_fec_by_label(struct mpls_fec_map *x, u32 label);
+struct mpls_fec *mpls_get_fec_by_label(struct mpls_fec_map *m, u32 label);
+struct mpls_fec *mpls_get_fec_by_net(struct mpls_fec_map *m, const net_addr *net, u32 path_id);
+struct mpls_fec *mpls_get_fec_by_rta(struct mpls_fec_map *m, const rta *src, u32 class_id);
+void mpls_free_fec(struct mpls_fec_map *x, struct mpls_fec *fec);
+void mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r, linpool *lp, struct mpls_fec **locked_fec);
+void mpls_handle_rte_cleanup(struct mpls_fec_map *m, struct mpls_fec **locked_fec);
+void mpls_rte_insert(net *n UNUSED, rte *r);
+void mpls_rte_remove(net *n UNUSED, rte *r);
+
+#endif