2 * Copyright (C) 2020 NetDEF, Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "isisd/isisd.h"
23 #include "isisd/isis_dynhn.h"
24 #include "isisd/isis_mt.h"
26 #include "test_common.h"
28 struct thread_master
*master
;
29 struct zebra_privs_t isisd_privs
;
31 int isis_sock_init(struct isis_circuit
*circuit
)
36 const struct isis_test_node
*
37 test_topology_find_node(const struct isis_topology
*topology
,
38 const char *hostname
, uint8_t pseudonode_id
)
40 for (size_t i
= 0; topology
->nodes
[i
].hostname
[0]; i
++)
41 if (strmatch(hostname
, topology
->nodes
[i
].hostname
)
42 && pseudonode_id
== topology
->nodes
[i
].pseudonode_id
)
43 return &topology
->nodes
[i
];
48 const struct isis_topology
*
49 test_topology_find(struct isis_topology
*test_topologies
, uint16_t number
)
51 for (size_t i
= 0; test_topologies
[i
].number
; i
++)
52 if (test_topologies
[i
].number
== number
)
53 return &test_topologies
[i
];
58 static const struct isis_test_node
*
59 test_find_adjacency(const struct isis_test_node
*tnode
, const char *hostname
)
61 for (size_t i
= 0; tnode
->adjacencies
[i
].hostname
[0]; i
++) {
62 const struct isis_test_adj
*tadj
;
64 tadj
= &tnode
->adjacencies
[i
];
65 if (strmatch(hostname
, tadj
->hostname
))
72 mpls_label_t
test_topology_node_ldp_label(const struct isis_topology
*topology
,
73 struct in_addr router_id
)
75 for (size_t i
= 0; topology
->nodes
[i
].hostname
[0]; i
++) {
76 const struct isis_test_node
*tnode
= &topology
->nodes
[i
];
77 struct in_addr node_router_id
;
79 if (!tnode
->router_id
)
82 (void)inet_pton(AF_INET
, tnode
->router_id
, &node_router_id
);
83 if (IPV4_ADDR_SAME(&router_id
, &node_router_id
))
84 return (50000 + (i
+ 1) * 100);
87 return MPLS_INVALID_LABEL
;
90 static struct isis_lsp
*lsp_add(struct lspdb_head
*lspdb
,
91 struct isis_area
*area
, int level
,
92 const uint8_t *sysid
, uint8_t pseudonode_id
)
95 uint8_t lspid
[ISIS_SYS_ID_LEN
+ 2];
97 memcpy(lspid
, sysid
, ISIS_SYS_ID_LEN
);
98 LSP_PSEUDO_ID(lspid
) = pseudonode_id
;
99 LSP_FRAGMENT(lspid
) = 0;
101 lsp
= lsp_new(area
, lspid
, 6000, 1, 0, 0, NULL
, level
);
102 lsp
->tlvs
= isis_alloc_tlvs();
103 lspdb_add(lspdb
, lsp
);
108 static void lsp_add_ip_reach(struct isis_lsp
*lsp
,
109 const struct isis_test_node
*tnode
,
110 const char *prefix_str
, uint32_t *next_sid_index
)
112 struct prefix prefix
;
113 struct sr_prefix_cfg pcfg
= {};
114 struct sr_prefix_cfg
*pcfg_p
= NULL
;
116 if (str2prefix(prefix_str
, &prefix
) != 1) {
117 zlog_debug("%s: invalid network: %s", __func__
, prefix_str
);
121 if (CHECK_FLAG(tnode
->flags
, F_ISIS_TEST_NODE_SR
)) {
124 pcfg
.sid
= *next_sid_index
;
125 *next_sid_index
= *next_sid_index
+ 1;
126 pcfg
.sid_type
= SR_SID_VALUE_TYPE_INDEX
;
127 pcfg
.node_sid
= true;
128 pcfg
.last_hop_behavior
= SR_LAST_HOP_BEHAVIOR_PHP
;
131 if (prefix
.family
== AF_INET
)
132 isis_tlvs_add_extended_ip_reach(lsp
->tlvs
,
133 (struct prefix_ipv4
*)&prefix
,
136 isis_tlvs_add_ipv6_reach(lsp
->tlvs
, ISIS_MT_IPV6_UNICAST
,
137 (struct prefix_ipv6
*)&prefix
, 10,
141 static void lsp_add_reach(struct isis_lsp
*lsp
,
142 const struct isis_test_node
*tnode
,
143 const uint8_t *ne_id
, uint8_t pseudonode_id
,
144 uint32_t metric
, int family
, mpls_label_t
*next_label
)
146 uint8_t nodeid
[ISIS_SYS_ID_LEN
+ 1];
148 struct isis_ext_subtlvs
*ext
= NULL
;
150 memcpy(nodeid
, ne_id
, ISIS_SYS_ID_LEN
);
151 LSP_PSEUDO_ID(nodeid
) = pseudonode_id
;
153 if (CHECK_FLAG(tnode
->flags
, F_ISIS_TEST_NODE_SR
)) {
154 struct isis_adj_sid
*adj_sid
;
156 adj_sid
= XCALLOC(MTYPE_ISIS_SUBTLV
, sizeof(*adj_sid
));
157 adj_sid
->family
= family
;
158 SET_FLAG(adj_sid
->flags
, EXT_SUBTLV_LINK_ADJ_SID_VFLG
);
159 SET_FLAG(adj_sid
->flags
, EXT_SUBTLV_LINK_ADJ_SID_LFLG
);
160 if (family
== AF_INET6
)
161 SET_FLAG(adj_sid
->flags
, EXT_SUBTLV_LINK_ADJ_SID_FFLG
);
163 adj_sid
->sid
= *next_label
;
164 *next_label
= *next_label
+ 1;
166 ext
= isis_alloc_ext_subtlvs();
167 isis_tlvs_add_adj_sid(ext
, adj_sid
);
170 mtid
= (family
== AF_INET
) ? ISIS_MT_IPV4_UNICAST
171 : ISIS_MT_IPV6_UNICAST
;
173 isis_tlvs_add_extended_reach(lsp
->tlvs
, mtid
, nodeid
, metric
, ext
);
176 static void lsp_add_router_capability(struct isis_lsp
*lsp
,
177 const struct isis_test_node
*tnode
)
179 struct isis_router_cap cap
= {};
181 if (!tnode
->router_id
)
184 if (inet_pton(AF_INET
, tnode
->router_id
, &cap
.router_id
) != 1) {
185 zlog_debug("%s: invalid router-id: %s", __func__
,
190 if (CHECK_FLAG(tnode
->flags
, F_ISIS_TEST_NODE_SR
)) {
192 ISIS_SUBTLV_SRGB_FLAG_I
| ISIS_SUBTLV_SRGB_FLAG_V
;
193 cap
.srgb
.lower_bound
= tnode
->srgb
.lower_bound
194 ? tnode
->srgb
.lower_bound
195 : SRGB_DFTL_LOWER_BOUND
;
196 cap
.srgb
.range_size
= tnode
->srgb
.range_size
197 ? tnode
->srgb
.range_size
198 : SRGB_DFTL_RANGE_SIZE
;
199 cap
.algo
[0] = SR_ALGORITHM_SPF
;
200 cap
.algo
[1] = SR_ALGORITHM_UNSET
;
203 isis_tlvs_set_router_capability(lsp
->tlvs
, &cap
);
206 static void lsp_add_mt_router_info(struct isis_lsp
*lsp
,
207 const struct isis_test_node
*tnode
)
209 if (tnode
->protocols
.ipv4
)
210 isis_tlvs_add_mt_router_info(lsp
->tlvs
, ISIS_MT_IPV4_UNICAST
, 0,
212 if (tnode
->protocols
.ipv6
)
213 isis_tlvs_add_mt_router_info(lsp
->tlvs
, ISIS_MT_IPV6_UNICAST
, 0,
217 static void lsp_add_protocols_supported(struct isis_lsp
*lsp
,
218 const struct isis_test_node
*tnode
)
220 struct nlpids nlpids
= {};
222 if (!tnode
->protocols
.ipv4
&& !tnode
->protocols
.ipv6
)
225 if (tnode
->protocols
.ipv4
) {
226 nlpids
.nlpids
[nlpids
.count
] = NLPID_IP
;
229 if (tnode
->protocols
.ipv6
) {
230 nlpids
.nlpids
[nlpids
.count
] = NLPID_IPV6
;
233 isis_tlvs_set_protocols_supported(lsp
->tlvs
, &nlpids
);
236 static int topology_load_node_level(const struct isis_topology
*topology
,
237 const struct isis_test_node
*tnode
,
238 size_t tnode_index
, struct isis_area
*area
,
239 struct lspdb_head
*lspdb
, int level
)
241 struct isis_lsp
*lsp
;
242 uint32_t next_sid_index
= (tnode_index
+ 1) * 10;
243 mpls_label_t next_label
= 16;
245 lsp
= lsp_add(lspdb
, area
, level
, tnode
->sysid
, tnode
->pseudonode_id
);
246 lsp_add_mt_router_info(lsp
, tnode
);
247 lsp_add_protocols_supported(lsp
, tnode
);
248 lsp_add_router_capability(lsp
, tnode
);
250 /* Add IP Reachability Information. */
251 for (size_t i
= 0; tnode
->networks
[i
]; i
++) {
252 if (i
> MAX_NETWORKS
) {
254 "%s: node has too many networks (maximum is %u)",
255 __func__
, MAX_NETWORKS
);
258 lsp_add_ip_reach(lsp
, tnode
, tnode
->networks
[i
],
262 /* Add IS Reachability Information. */
263 for (size_t i
= 0; tnode
->adjacencies
[i
].hostname
[0]; i
++) {
264 const struct isis_test_adj
*tadj
;
265 const struct isis_test_node
*tadj_node
;
267 if (i
> MAX_ADJACENCIES
) {
269 "%s: node has too many adjacencies (maximum is %u)",
270 __func__
, MAX_ADJACENCIES
);
274 tadj
= &tnode
->adjacencies
[i
];
275 tadj_node
= test_topology_find_node(topology
, tadj
->hostname
,
276 tadj
->pseudonode_id
);
279 "%s: node \"%s\" has an adjacency with non-existing node \"%s\"",
280 __func__
, tnode
->hostname
, tadj
->hostname
);
283 if (!test_find_adjacency(tadj_node
, tnode
->hostname
)) {
285 "%s: node \"%s\" has an one-way adjacency with node \"%s\"",
286 __func__
, tnode
->hostname
, tadj
->hostname
);
290 if (tnode
->pseudonode_id
|| tadj_node
->pseudonode_id
291 || (tnode
->protocols
.ipv4
&& tadj_node
->protocols
.ipv4
))
292 lsp_add_reach(lsp
, tnode
, tadj_node
->sysid
,
293 tadj_node
->pseudonode_id
, tadj
->metric
,
294 AF_INET
, &next_label
);
295 if (tadj_node
->pseudonode_id
296 || (tnode
->protocols
.ipv6
&& tadj_node
->protocols
.ipv6
))
297 lsp_add_reach(lsp
, tnode
, tadj_node
->sysid
,
298 tadj_node
->pseudonode_id
, tadj
->metric
,
299 AF_INET6
, &next_label
);
305 static int topology_load_node(const struct isis_topology
*topology
,
306 const struct isis_test_node
*tnode
,
307 size_t tnode_index
, struct isis_area
*area
,
308 struct lspdb_head lspdb
[])
312 isis_dynhn_insert(area
->isis
, tnode
->sysid
, tnode
->hostname
,
315 for (int level
= IS_LEVEL_1
; level
<= IS_LEVEL_2
; level
++) {
316 if ((tnode
->level
& level
) == 0)
319 ret
= topology_load_node_level(topology
, tnode
, tnode_index
,
320 area
, &lspdb
[level
- 1], level
);
328 int test_topology_load(const struct isis_topology
*topology
,
329 struct isis_area
*area
, struct lspdb_head lspdb
[])
331 for (int level
= IS_LEVEL_1
; level
<= IS_LEVEL_2
; level
++)
332 lsp_db_init(&lspdb
[level
- 1]);
334 for (size_t i
= 0; topology
->nodes
[i
].hostname
[0]; i
++) {
335 const struct isis_test_node
*tnode
= &topology
->nodes
[i
];
340 "%s: topology has too many nodes (maximum is %u)",
341 __func__
, MAX_NODES
);
345 ret
= topology_load_node(topology
, tnode
, i
, area
, lspdb
);