summaryrefslogtreecommitdiffstats
path: root/isisd/isis_srv6.h
blob: 7f16712ae3064e24b22d0d9dfaf2299448dc56ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * This is an implementation of Segment Routing over IPv6 (SRv6) for IS-IS
 * as per RFC 9352
 * https://datatracker.ietf.org/doc/html/rfc9352
 *
 * Copyright (C) 2023 Carmine Scarpitta - University of Rome Tor Vergata
 */

#ifndef _FRR_ISIS_SRV6_H
#define _FRR_ISIS_SRV6_H

#include "lib/srv6.h"
#include "isisd/isis_tlvs.h"

#define ISIS_DEFAULT_SRV6_MAX_SEG_LEFT_MSD        3
#define ISIS_DEFAULT_SRV6_MAX_END_POP_MSD         3
#define ISIS_DEFAULT_SRV6_MAX_H_ENCAPS_MSD        2
#define ISIS_DEFAULT_SRV6_MAX_END_D_MSD           5
#define ISIS_DEFAULT_SRV6_IFNAME                 "sr0"

/* SRv6 SID structure */
struct isis_srv6_sid_structure {
	uint8_t loc_block_len;
	uint8_t loc_node_len;
	uint8_t func_len;
	uint8_t arg_len;
};

/* SRv6 SID not bound to any adjacency */
struct isis_srv6_sid {
	struct isis_srv6_sid *next;

	/* SID flags */
	uint8_t flags;

	/* SID value */
	struct in6_addr sid;

	/* Endpoint behavior bound to the SID */
	enum srv6_endpoint_behavior_codepoint behavior;

	/* SRv6 SID structure */
	struct isis_srv6_sid_structure structure;

	/* Parent SRv6 locator */
	struct srv6_locator_chunk *locator;

	/* Backpointer to IS-IS area */
	struct isis_area *area;
};

/* SRv6 Locator */
struct isis_srv6_locator {
	struct isis_srv6_locator *next;

	uint32_t metric;

	uint8_t flags;
#define ISIS_SRV6_LOCATOR_FLAG_D 1 << 7

	uint8_t algorithm;
	struct prefix_ipv6 prefix;

	struct list *srv6_sid;
};

/* SRv6 Adjacency-SID type */
enum srv6_adj_type {
	ISIS_SRV6_ADJ_NORMAL = 0,
	ISIS_SRV6_ADJ_BACKUP,
};

/* SRv6 Adjacency. */
struct srv6_adjacency {
	/* Adjacency type */
	enum srv6_adj_type type;

	/* SID flags */
	uint8_t flags;

	/* SID value */
	struct in6_addr sid;

	/* Endpoint behavior bound to the SID */
	enum srv6_endpoint_behavior_codepoint behavior;

	/* SRv6 SID structure */
	struct isis_srv6_sid_structure structure;

	/* Parent SRv6 locator */
	struct srv6_locator_chunk *locator;

	/* Adjacency-SID nexthop information */
	struct in6_addr nexthop;

	/* End.X SID TI-LFA backup nexthops */
	struct list *backup_nexthops;

	/* SRv6 (LAN) End.X SID Sub-TLV */
	union {
		struct isis_srv6_endx_sid_subtlv *endx_sid;
		struct isis_srv6_lan_endx_sid_subtlv *lendx_sid;
	} u;

	/* Back pointer to IS-IS adjacency. */
	struct isis_adjacency *adj;
};

/* Per-area IS-IS SRv6 Data Base (SRv6 DB) */
struct isis_srv6_db {

	/* List of SRv6 Locator chunks */
	struct list *srv6_locator_chunks;

	/* List of SRv6 SIDs allocated by the IS-IS instance */
	struct list *srv6_sids;

	/* List of SRv6 End.X SIDs allocated by the IS-IS instance */
	struct list *srv6_endx_sids;

	/* Area SRv6 configuration. */
	struct {
		/* Administrative status of SRv6 */
		bool enabled;

		/* Name of the SRv6 Locator */
		char srv6_locator_name[SRV6_LOCNAME_SIZE];

		/* Maximum Segments Left Depth supported by the router */
		uint8_t max_seg_left_msd;

		/* Maximum Maximum End Pop Depth supported by the router */
		uint8_t max_end_pop_msd;

		/* Maximum H.Encaps supported by the router */
		uint8_t max_h_encaps_msd;

		/* Maximum End D MSD supported by the router */
		uint8_t max_end_d_msd;

		/* Interface used for installing SRv6 SIDs into the data plane */
		char srv6_ifname[IF_NAMESIZE];
	} config;
};

bool isis_srv6_locator_unset(struct isis_area *area);

void isis_srv6_interface_set(struct isis_area *area, const char *ifname);

struct isis_srv6_sid *
isis_srv6_sid_alloc(struct isis_area *area, struct srv6_locator_chunk *chunk,
		    enum srv6_endpoint_behavior_codepoint behavior,
		    int sid_func);
extern void isis_srv6_sid_free(struct isis_srv6_sid *sid);

extern void isis_srv6_area_init(struct isis_area *area);
extern void isis_srv6_area_term(struct isis_area *area);

void isis_srv6_init(void);
void isis_srv6_term(void);

void isis_srv6_sid_structure2subsubtlv(
	const struct isis_srv6_sid *sid,
	struct isis_srv6_sid_structure_subsubtlv *structure_subsubtlv);
void isis_srv6_end_sid2subtlv(const struct isis_srv6_sid *sid,
			      struct isis_srv6_end_sid_subtlv *sid_subtlv);
void isis_srv6_locator2tlv(const struct isis_srv6_locator *loc,
			   struct isis_srv6_locator_tlv *loc_tlv);

void srv6_endx_sid_add_single(struct isis_adjacency *adj, bool backup,
			      struct list *nexthops);
void srv6_endx_sid_add(struct isis_adjacency *adj);
void srv6_endx_sid_del(struct srv6_adjacency *sra);
struct srv6_adjacency *isis_srv6_endx_sid_find(struct isis_adjacency *adj,
					       enum srv6_adj_type type);
void isis_area_delete_backup_srv6_endx_sids(struct isis_area *area, int level);

int isis_srv6_ifp_up_notify(struct interface *ifp);

#endif /* _FRR_ISIS_SRV6_H */