1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020 NetDEF, Inc.
9 #include "isisd/isisd.h"
10 #include "isisd/isis_dynhn.h"
11 #include "isisd/isis_mt.h"
13 #include "test_common.h"
15 struct event_loop
*master
;
16 struct zebra_privs_t isisd_privs
;
18 int isis_sock_init(struct isis_circuit
*circuit
)
23 const struct isis_test_node
*
24 test_topology_find_node(const struct isis_topology
*topology
,
25 const char *hostname
, uint8_t pseudonode_id
)
27 for (size_t i
= 0; topology
->nodes
[i
].hostname
[0]; i
++)
28 if (strmatch(hostname
, topology
->nodes
[i
].hostname
)
29 && pseudonode_id
== topology
->nodes
[i
].pseudonode_id
)
30 return &topology
->nodes
[i
];
35 const struct isis_topology
*
36 test_topology_find(struct isis_topology
*test_topologies
, uint16_t number
)
38 for (size_t i
= 0; test_topologies
[i
].number
; i
++)
39 if (test_topologies
[i
].number
== number
)
40 return &test_topologies
[i
];
45 static const struct isis_test_node
*
46 test_find_adjacency(const struct isis_test_node
*tnode
, const char *hostname
)
48 for (size_t i
= 0; tnode
->adjacencies
[i
].hostname
[0]; i
++) {
49 const struct isis_test_adj
*tadj
;
51 tadj
= &tnode
->adjacencies
[i
];
52 if (strmatch(hostname
, tadj
->hostname
))
59 mpls_label_t
test_topology_node_ldp_label(const struct isis_topology
*topology
,
60 struct in_addr router_id
)
62 for (size_t i
= 0; topology
->nodes
[i
].hostname
[0]; i
++) {
63 const struct isis_test_node
*tnode
= &topology
->nodes
[i
];
64 struct in_addr node_router_id
;
66 if (!tnode
->router_id
)
69 (void)inet_pton(AF_INET
, tnode
->router_id
, &node_router_id
);
70 if (IPV4_ADDR_SAME(&router_id
, &node_router_id
))
71 return (50000 + (i
+ 1) * 100);
74 return MPLS_INVALID_LABEL
;
77 static struct isis_lsp
*lsp_add(struct lspdb_head
*lspdb
,
78 struct isis_area
*area
, int level
,
79 const uint8_t *sysid
, uint8_t pseudonode_id
)
82 uint8_t lspid
[ISIS_SYS_ID_LEN
+ 2];
84 memcpy(lspid
, sysid
, ISIS_SYS_ID_LEN
);
85 LSP_PSEUDO_ID(lspid
) = pseudonode_id
;
86 LSP_FRAGMENT(lspid
) = 0;
88 lsp
= lsp_new(area
, lspid
, 6000, 1, 0, 0, NULL
, level
);
89 lsp
->tlvs
= isis_alloc_tlvs();
90 lspdb_add(lspdb
, lsp
);
95 static void lsp_add_ip_reach(struct isis_lsp
*lsp
,
96 const struct isis_test_node
*tnode
,
97 const char *prefix_str
, uint32_t *next_sid_index
)
100 struct sr_prefix_cfg pcfg
= {};
101 struct sr_prefix_cfg
*pcfg_p
= NULL
;
103 if (str2prefix(prefix_str
, &prefix
) != 1) {
104 zlog_debug("%s: invalid network: %s", __func__
, prefix_str
);
108 if (CHECK_FLAG(tnode
->flags
, F_ISIS_TEST_NODE_SR
)) {
111 pcfg
.sid
= *next_sid_index
;
112 *next_sid_index
= *next_sid_index
+ 1;
113 pcfg
.sid_type
= SR_SID_VALUE_TYPE_INDEX
;
114 pcfg
.node_sid
= true;
115 pcfg
.last_hop_behavior
= SR_LAST_HOP_BEHAVIOR_PHP
;
118 if (prefix
.family
== AF_INET
)
119 isis_tlvs_add_extended_ip_reach(lsp
->tlvs
,
120 (struct prefix_ipv4
*)&prefix
,
123 isis_tlvs_add_ipv6_reach(lsp
->tlvs
, ISIS_MT_IPV6_UNICAST
,
124 (struct prefix_ipv6
*)&prefix
, 10,
128 static void lsp_add_reach(struct isis_lsp
*lsp
,
129 const struct isis_test_node
*tnode
,
130 const uint8_t *ne_id
, uint8_t pseudonode_id
,
131 uint32_t metric
, int family
, mpls_label_t
*next_label
)
133 uint8_t nodeid
[ISIS_SYS_ID_LEN
+ 1];
135 struct isis_ext_subtlvs
*ext
= NULL
;
137 memcpy(nodeid
, ne_id
, ISIS_SYS_ID_LEN
);
138 LSP_PSEUDO_ID(nodeid
) = pseudonode_id
;
140 if (CHECK_FLAG(tnode
->flags
, F_ISIS_TEST_NODE_SR
)) {
141 struct isis_adj_sid
*adj_sid
;
143 adj_sid
= XCALLOC(MTYPE_ISIS_SUBTLV
, sizeof(*adj_sid
));
144 adj_sid
->family
= family
;
145 SET_FLAG(adj_sid
->flags
, EXT_SUBTLV_LINK_ADJ_SID_VFLG
);
146 SET_FLAG(adj_sid
->flags
, EXT_SUBTLV_LINK_ADJ_SID_LFLG
);
147 if (family
== AF_INET6
)
148 SET_FLAG(adj_sid
->flags
, EXT_SUBTLV_LINK_ADJ_SID_FFLG
);
150 adj_sid
->sid
= *next_label
;
151 *next_label
= *next_label
+ 1;
153 ext
= isis_alloc_ext_subtlvs();
154 isis_tlvs_add_adj_sid(ext
, adj_sid
);
157 mtid
= (family
== AF_INET
) ? ISIS_MT_IPV4_UNICAST
158 : ISIS_MT_IPV6_UNICAST
;
160 isis_tlvs_add_extended_reach(lsp
->tlvs
, mtid
, nodeid
, metric
, ext
);
163 static void lsp_add_router_capability(struct isis_lsp
*lsp
,
164 const struct isis_test_node
*tnode
)
166 struct isis_router_cap cap
= {};
168 if (!tnode
->router_id
)
171 if (inet_pton(AF_INET
, tnode
->router_id
, &cap
.router_id
) != 1) {
172 zlog_debug("%s: invalid router-id: %s", __func__
,
177 if (CHECK_FLAG(tnode
->flags
, F_ISIS_TEST_NODE_SR
)) {
179 ISIS_SUBTLV_SRGB_FLAG_I
| ISIS_SUBTLV_SRGB_FLAG_V
;
180 cap
.srgb
.lower_bound
= tnode
->srgb
.lower_bound
181 ? tnode
->srgb
.lower_bound
182 : SRGB_DFTL_LOWER_BOUND
;
183 cap
.srgb
.range_size
= tnode
->srgb
.range_size
184 ? tnode
->srgb
.range_size
185 : SRGB_DFTL_RANGE_SIZE
;
186 cap
.algo
[0] = SR_ALGORITHM_SPF
;
187 cap
.algo
[1] = SR_ALGORITHM_UNSET
;
190 isis_tlvs_set_router_capability(lsp
->tlvs
, &cap
);
193 static void lsp_add_mt_router_info(struct isis_lsp
*lsp
,
194 const struct isis_test_node
*tnode
)
196 if (tnode
->protocols
.ipv4
)
197 isis_tlvs_add_mt_router_info(lsp
->tlvs
, ISIS_MT_IPV4_UNICAST
, 0,
199 if (tnode
->protocols
.ipv6
)
200 isis_tlvs_add_mt_router_info(lsp
->tlvs
, ISIS_MT_IPV6_UNICAST
, 0,
204 static void lsp_add_protocols_supported(struct isis_lsp
*lsp
,
205 const struct isis_test_node
*tnode
)
207 struct nlpids nlpids
= {};
209 if (!tnode
->protocols
.ipv4
&& !tnode
->protocols
.ipv6
)
212 if (tnode
->protocols
.ipv4
) {
213 nlpids
.nlpids
[nlpids
.count
] = NLPID_IP
;
216 if (tnode
->protocols
.ipv6
) {
217 nlpids
.nlpids
[nlpids
.count
] = NLPID_IPV6
;
220 isis_tlvs_set_protocols_supported(lsp
->tlvs
, &nlpids
);
223 static int topology_load_node_level(const struct isis_topology
*topology
,
224 const struct isis_test_node
*tnode
,
225 size_t tnode_index
, struct isis_area
*area
,
226 struct lspdb_head
*lspdb
, int level
)
228 struct isis_lsp
*lsp
;
229 uint32_t next_sid_index
= (tnode_index
+ 1) * 10;
230 mpls_label_t next_label
= 16;
232 lsp
= lsp_add(lspdb
, area
, level
, tnode
->sysid
, tnode
->pseudonode_id
);
233 lsp_add_mt_router_info(lsp
, tnode
);
234 lsp_add_protocols_supported(lsp
, tnode
);
235 lsp_add_router_capability(lsp
, tnode
);
237 /* Add IP Reachability Information. */
238 for (size_t i
= 0; tnode
->networks
[i
]; i
++) {
239 if (i
> MAX_NETWORKS
) {
241 "%s: node has too many networks (maximum is %u)",
242 __func__
, MAX_NETWORKS
);
245 lsp_add_ip_reach(lsp
, tnode
, tnode
->networks
[i
],
249 /* Add IS Reachability Information. */
250 for (size_t i
= 0; tnode
->adjacencies
[i
].hostname
[0]; i
++) {
251 const struct isis_test_adj
*tadj
;
252 const struct isis_test_node
*tadj_node
;
254 if (i
> MAX_ADJACENCIES
) {
256 "%s: node has too many adjacencies (maximum is %u)",
257 __func__
, MAX_ADJACENCIES
);
261 tadj
= &tnode
->adjacencies
[i
];
262 tadj_node
= test_topology_find_node(topology
, tadj
->hostname
,
263 tadj
->pseudonode_id
);
266 "%s: node \"%s\" has an adjacency with non-existing node \"%s\"",
267 __func__
, tnode
->hostname
, tadj
->hostname
);
270 if (!test_find_adjacency(tadj_node
, tnode
->hostname
)) {
272 "%s: node \"%s\" has an one-way adjacency with node \"%s\"",
273 __func__
, tnode
->hostname
, tadj
->hostname
);
277 if (tnode
->pseudonode_id
|| tadj_node
->pseudonode_id
278 || (tnode
->protocols
.ipv4
&& tadj_node
->protocols
.ipv4
))
279 lsp_add_reach(lsp
, tnode
, tadj_node
->sysid
,
280 tadj_node
->pseudonode_id
, tadj
->metric
,
281 AF_INET
, &next_label
);
282 if (tadj_node
->pseudonode_id
283 || (tnode
->protocols
.ipv6
&& tadj_node
->protocols
.ipv6
))
284 lsp_add_reach(lsp
, tnode
, tadj_node
->sysid
,
285 tadj_node
->pseudonode_id
, tadj
->metric
,
286 AF_INET6
, &next_label
);
292 static int topology_load_node(const struct isis_topology
*topology
,
293 const struct isis_test_node
*tnode
,
294 size_t tnode_index
, struct isis_area
*area
,
295 struct lspdb_head lspdb
[])
299 isis_dynhn_insert(area
->isis
, tnode
->sysid
, tnode
->hostname
,
302 for (int level
= IS_LEVEL_1
; level
<= IS_LEVEL_2
; level
++) {
303 if ((tnode
->level
& level
) == 0)
306 ret
= topology_load_node_level(topology
, tnode
, tnode_index
,
307 area
, &lspdb
[level
- 1], level
);
315 int test_topology_load(const struct isis_topology
*topology
,
316 struct isis_area
*area
, struct lspdb_head lspdb
[])
318 for (int level
= IS_LEVEL_1
; level
<= IS_LEVEL_2
; level
++)
319 lsp_db_init(&lspdb
[level
- 1]);
321 for (size_t i
= 0; topology
->nodes
[i
].hostname
[0]; i
++) {
322 const struct isis_test_node
*tnode
= &topology
->nodes
[i
];
327 "%s: topology has too many nodes (maximum is %u)",
328 __func__
, MAX_NODES
);
332 ret
= topology_load_node(topology
, tnode
, i
, area
, lspdb
);