]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
064f4896 CF |
2 | /* |
3 | * IS-IS Rout(e)ing protocol - Multi Topology Support | |
4 | * | |
5 | * Copyright (C) 2017 Christian Franke | |
6 | * | |
8678d638 | 7 | * This file is part of FRRouting (FRR) |
064f4896 CF |
8 | */ |
9 | #include <zebra.h> | |
10 | #include "isisd/isisd.h" | |
064f4896 | 11 | #include "isisd/isis_circuit.h" |
d8fba7d9 | 12 | #include "isisd/isis_adjacency.h" |
206f4aae CF |
13 | #include "isisd/isis_misc.h" |
14 | #include "isisd/isis_lsp.h" | |
064f4896 | 15 | #include "isisd/isis_mt.h" |
841791b6 | 16 | #include "isisd/isis_tlvs.h" |
064f4896 | 17 | |
bf8d3d6a DL |
18 | DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting"); |
19 | DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting"); | |
20 | DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info"); | |
c3ae3127 | 21 | |
d43d2df5 CF |
22 | bool isis_area_ipv6_dstsrc_enabled(struct isis_area *area) |
23 | { | |
24 | struct isis_area_mt_setting *area_mt_setting; | |
25 | area_mt_setting = area_lookup_mt_setting(area, ISIS_MT_IPV6_DSTSRC); | |
26 | ||
27 | return (area_mt_setting && area_mt_setting->enabled); | |
28 | } | |
29 | ||
c3ae3127 CF |
30 | uint16_t isis_area_ipv6_topology(struct isis_area *area) |
31 | { | |
d62a17ae | 32 | struct isis_area_mt_setting *area_mt_setting; |
33 | area_mt_setting = area_lookup_mt_setting(area, ISIS_MT_IPV6_UNICAST); | |
c3ae3127 | 34 | |
d62a17ae | 35 | if (area_mt_setting && area_mt_setting->enabled) |
36 | return ISIS_MT_IPV6_UNICAST; | |
37 | return ISIS_MT_IPV4_UNICAST; | |
c3ae3127 | 38 | } |
064f4896 CF |
39 | |
40 | /* MT naming api */ | |
41 | const char *isis_mtid2str(uint16_t mtid) | |
42 | { | |
d62a17ae | 43 | static char buf[sizeof("65535")]; |
44 | ||
45 | switch (mtid) { | |
a15014f3 PG |
46 | case ISIS_MT_STANDARD: |
47 | return "standard"; | |
d62a17ae | 48 | case ISIS_MT_IPV4_MGMT: |
49 | return "ipv4-mgmt"; | |
50 | case ISIS_MT_IPV6_UNICAST: | |
51 | return "ipv6-unicast"; | |
52 | case ISIS_MT_IPV4_MULTICAST: | |
53 | return "ipv4-multicast"; | |
54 | case ISIS_MT_IPV6_MULTICAST: | |
55 | return "ipv6-multicast"; | |
56 | case ISIS_MT_IPV6_MGMT: | |
57 | return "ipv6-mgmt"; | |
d43d2df5 CF |
58 | case ISIS_MT_IPV6_DSTSRC: |
59 | return "ipv6-dstsrc"; | |
d62a17ae | 60 | default: |
6cde4b45 | 61 | snprintf(buf, sizeof(buf), "%hu", mtid); |
d62a17ae | 62 | return buf; |
63 | } | |
064f4896 CF |
64 | } |
65 | ||
66 | uint16_t isis_str2mtid(const char *name) | |
67 | { | |
d62a17ae | 68 | if (!strcmp(name, "ipv4-unicast")) |
69 | return ISIS_MT_IPV4_UNICAST; | |
a15014f3 PG |
70 | if (!strcmp(name, "standard")) |
71 | return ISIS_MT_STANDARD; | |
d62a17ae | 72 | if (!strcmp(name, "ipv4-mgmt")) |
73 | return ISIS_MT_IPV4_MGMT; | |
74 | if (!strcmp(name, "ipv6-unicast")) | |
75 | return ISIS_MT_IPV6_UNICAST; | |
76 | if (!strcmp(name, "ipv4-multicast")) | |
77 | return ISIS_MT_IPV4_MULTICAST; | |
78 | if (!strcmp(name, "ipv6-multicast")) | |
79 | return ISIS_MT_IPV6_MULTICAST; | |
80 | if (!strcmp(name, "ipv6-mgmt")) | |
81 | return ISIS_MT_IPV6_MGMT; | |
d43d2df5 CF |
82 | if (!strcmp(name, "ipv6-dstsrc")) |
83 | return ISIS_MT_IPV6_DSTSRC; | |
d62a17ae | 84 | return -1; |
064f4896 CF |
85 | } |
86 | ||
87 | /* General MT settings api */ | |
88 | ||
89 | struct mt_setting { | |
90 | ISIS_MT_INFO_FIELDS; | |
91 | }; | |
92 | ||
d62a17ae | 93 | static void *lookup_mt_setting(struct list *mt_list, uint16_t mtid) |
064f4896 | 94 | { |
d62a17ae | 95 | struct listnode *node; |
96 | struct mt_setting *setting; | |
064f4896 | 97 | |
d62a17ae | 98 | for (ALL_LIST_ELEMENTS_RO(mt_list, node, setting)) { |
99 | if (setting->mtid == mtid) | |
100 | return setting; | |
101 | } | |
102 | return NULL; | |
064f4896 CF |
103 | } |
104 | ||
d62a17ae | 105 | static void add_mt_setting(struct list **mt_list, void *setting) |
064f4896 | 106 | { |
d62a17ae | 107 | if (!*mt_list) |
108 | *mt_list = list_new(); | |
109 | listnode_add(*mt_list, setting); | |
064f4896 CF |
110 | } |
111 | ||
112 | /* Area specific MT settings api */ | |
113 | ||
d62a17ae | 114 | struct isis_area_mt_setting *area_lookup_mt_setting(struct isis_area *area, |
115 | uint16_t mtid) | |
064f4896 | 116 | { |
d62a17ae | 117 | return lookup_mt_setting(area->mt_settings, mtid); |
064f4896 CF |
118 | } |
119 | ||
d62a17ae | 120 | struct isis_area_mt_setting *area_new_mt_setting(struct isis_area *area, |
121 | uint16_t mtid) | |
064f4896 | 122 | { |
d62a17ae | 123 | struct isis_area_mt_setting *setting; |
064f4896 | 124 | |
d62a17ae | 125 | setting = XCALLOC(MTYPE_MT_AREA_SETTING, sizeof(*setting)); |
126 | setting->mtid = mtid; | |
127 | return setting; | |
064f4896 CF |
128 | } |
129 | ||
d62a17ae | 130 | static void area_free_mt_setting(void *setting) |
064f4896 | 131 | { |
d62a17ae | 132 | XFREE(MTYPE_MT_AREA_SETTING, setting); |
064f4896 CF |
133 | } |
134 | ||
d62a17ae | 135 | void area_add_mt_setting(struct isis_area *area, |
136 | struct isis_area_mt_setting *setting) | |
064f4896 | 137 | { |
d62a17ae | 138 | add_mt_setting(&area->mt_settings, setting); |
064f4896 CF |
139 | } |
140 | ||
d62a17ae | 141 | void area_mt_init(struct isis_area *area) |
064f4896 | 142 | { |
d62a17ae | 143 | struct isis_area_mt_setting *v4_unicast_setting; |
064f4896 | 144 | |
d62a17ae | 145 | /* MTID 0 is always enabled */ |
146 | v4_unicast_setting = area_new_mt_setting(area, ISIS_MT_IPV4_UNICAST); | |
147 | v4_unicast_setting->enabled = true; | |
148 | add_mt_setting(&area->mt_settings, v4_unicast_setting); | |
149 | area->mt_settings->del = area_free_mt_setting; | |
064f4896 CF |
150 | } |
151 | ||
d62a17ae | 152 | void area_mt_finish(struct isis_area *area) |
064f4896 | 153 | { |
6a154c88 | 154 | list_delete(&area->mt_settings); |
064f4896 CF |
155 | } |
156 | ||
d62a17ae | 157 | struct isis_area_mt_setting *area_get_mt_setting(struct isis_area *area, |
158 | uint16_t mtid) | |
064f4896 | 159 | { |
d62a17ae | 160 | struct isis_area_mt_setting *setting; |
064f4896 | 161 | |
d62a17ae | 162 | setting = area_lookup_mt_setting(area, mtid); |
163 | if (!setting) { | |
164 | setting = area_new_mt_setting(area, mtid); | |
165 | area_add_mt_setting(area, setting); | |
166 | } | |
167 | return setting; | |
064f4896 CF |
168 | } |
169 | ||
d62a17ae | 170 | int area_write_mt_settings(struct isis_area *area, struct vty *vty) |
064f4896 | 171 | { |
d62a17ae | 172 | int written = 0; |
173 | struct listnode *node; | |
174 | struct isis_area_mt_setting *setting; | |
064f4896 | 175 | |
d62a17ae | 176 | for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) { |
177 | const char *name = isis_mtid2str(setting->mtid); | |
178 | if (name && setting->enabled) { | |
179 | if (setting->mtid == ISIS_MT_IPV4_UNICAST) | |
180 | continue; /* always enabled, no need to write | |
181 | out config */ | |
182 | vty_out(vty, " topology %s%s\n", name, | |
183 | setting->overload ? " overload" : ""); | |
184 | written++; | |
185 | } | |
186 | } | |
187 | return written; | |
064f4896 CF |
188 | } |
189 | ||
99894f9a CF |
190 | bool area_is_mt(struct isis_area *area) |
191 | { | |
d62a17ae | 192 | struct listnode *node, *node2; |
193 | struct isis_area_mt_setting *setting; | |
194 | struct isis_circuit *circuit; | |
195 | struct isis_circuit_mt_setting *csetting; | |
99894f9a | 196 | |
d62a17ae | 197 | for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) { |
198 | if (setting->enabled && setting->mtid != ISIS_MT_IPV4_UNICAST) | |
199 | return true; | |
200 | } | |
201 | for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { | |
202 | for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node2, | |
203 | csetting)) { | |
204 | if (!csetting->enabled | |
205 | && csetting->mtid == ISIS_MT_IPV4_UNICAST) | |
206 | return true; | |
207 | } | |
208 | } | |
99894f9a | 209 | |
d62a17ae | 210 | return false; |
99894f9a CF |
211 | } |
212 | ||
d62a17ae | 213 | struct isis_area_mt_setting **area_mt_settings(struct isis_area *area, |
214 | unsigned int *mt_count) | |
99894f9a | 215 | { |
d62a17ae | 216 | static unsigned int size = 0; |
217 | static struct isis_area_mt_setting **rv = NULL; | |
99894f9a | 218 | |
d62a17ae | 219 | unsigned int count = 0; |
220 | struct listnode *node; | |
221 | struct isis_area_mt_setting *setting; | |
99894f9a | 222 | |
d62a17ae | 223 | for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) { |
224 | if (!setting->enabled) | |
225 | continue; | |
99894f9a | 226 | |
d62a17ae | 227 | count++; |
228 | if (count > size) { | |
229 | rv = XREALLOC(MTYPE_TMP, rv, count * sizeof(*rv)); | |
230 | size = count; | |
231 | } | |
232 | rv[count - 1] = setting; | |
233 | } | |
99894f9a | 234 | |
d62a17ae | 235 | *mt_count = count; |
236 | return rv; | |
99894f9a CF |
237 | } |
238 | ||
064f4896 CF |
239 | /* Circuit specific MT settings api */ |
240 | ||
d62a17ae | 241 | struct isis_circuit_mt_setting * |
064f4896 CF |
242 | circuit_lookup_mt_setting(struct isis_circuit *circuit, uint16_t mtid) |
243 | { | |
d62a17ae | 244 | return lookup_mt_setting(circuit->mt_settings, mtid); |
064f4896 CF |
245 | } |
246 | ||
d62a17ae | 247 | struct isis_circuit_mt_setting * |
064f4896 CF |
248 | circuit_new_mt_setting(struct isis_circuit *circuit, uint16_t mtid) |
249 | { | |
d62a17ae | 250 | struct isis_circuit_mt_setting *setting; |
064f4896 | 251 | |
d62a17ae | 252 | setting = XCALLOC(MTYPE_MT_CIRCUIT_SETTING, sizeof(*setting)); |
253 | setting->mtid = mtid; | |
254 | setting->enabled = true; /* Enabled is default for circuit */ | |
255 | return setting; | |
064f4896 CF |
256 | } |
257 | ||
d62a17ae | 258 | static void circuit_free_mt_setting(void *setting) |
064f4896 | 259 | { |
d62a17ae | 260 | XFREE(MTYPE_MT_CIRCUIT_SETTING, setting); |
064f4896 CF |
261 | } |
262 | ||
d62a17ae | 263 | void circuit_add_mt_setting(struct isis_circuit *circuit, |
264 | struct isis_circuit_mt_setting *setting) | |
064f4896 | 265 | { |
d62a17ae | 266 | add_mt_setting(&circuit->mt_settings, setting); |
064f4896 CF |
267 | } |
268 | ||
d62a17ae | 269 | void circuit_mt_init(struct isis_circuit *circuit) |
064f4896 | 270 | { |
d62a17ae | 271 | circuit->mt_settings = list_new(); |
272 | circuit->mt_settings->del = circuit_free_mt_setting; | |
064f4896 CF |
273 | } |
274 | ||
d62a17ae | 275 | void circuit_mt_finish(struct isis_circuit *circuit) |
064f4896 | 276 | { |
6a154c88 | 277 | list_delete(&circuit->mt_settings); |
064f4896 CF |
278 | } |
279 | ||
d62a17ae | 280 | struct isis_circuit_mt_setting * |
064f4896 CF |
281 | circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid) |
282 | { | |
d62a17ae | 283 | struct isis_circuit_mt_setting *setting; |
064f4896 | 284 | |
d62a17ae | 285 | setting = circuit_lookup_mt_setting(circuit, mtid); |
286 | if (!setting) { | |
287 | setting = circuit_new_mt_setting(circuit, mtid); | |
288 | circuit_add_mt_setting(circuit, setting); | |
289 | } | |
290 | return setting; | |
064f4896 CF |
291 | } |
292 | ||
05e4ec37 | 293 | #ifdef FABRICD |
5489eb45 CF |
294 | static int circuit_write_mt_settings(struct isis_circuit *circuit, |
295 | struct vty *vty) | |
064f4896 | 296 | { |
d62a17ae | 297 | int written = 0; |
298 | struct listnode *node; | |
299 | struct isis_circuit_mt_setting *setting; | |
064f4896 | 300 | |
d62a17ae | 301 | for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node, setting)) { |
302 | const char *name = isis_mtid2str(setting->mtid); | |
303 | if (name && !setting->enabled) { | |
7c0cbd0e | 304 | vty_out(vty, " no " PROTO_NAME " topology %s\n", name); |
d62a17ae | 305 | written++; |
306 | } | |
307 | } | |
308 | return written; | |
064f4896 | 309 | } |
05e4ec37 | 310 | #endif |
99894f9a | 311 | |
d62a17ae | 312 | struct isis_circuit_mt_setting ** |
99894f9a CF |
313 | circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count) |
314 | { | |
d62a17ae | 315 | static unsigned int size = 0; |
316 | static struct isis_circuit_mt_setting **rv = NULL; | |
99894f9a | 317 | |
d62a17ae | 318 | struct isis_area_mt_setting **area_settings; |
319 | unsigned int area_count; | |
99894f9a | 320 | |
d62a17ae | 321 | unsigned int count = 0; |
99894f9a | 322 | |
d62a17ae | 323 | struct listnode *node; |
324 | struct isis_circuit_mt_setting *setting; | |
99894f9a | 325 | |
d62a17ae | 326 | area_settings = area_mt_settings(circuit->area, &area_count); |
99894f9a | 327 | |
d62a17ae | 328 | for (unsigned int i = 0; i < area_count; i++) { |
329 | for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node, | |
330 | setting)) { | |
331 | if (setting->mtid != area_settings[i]->mtid) | |
332 | continue; | |
333 | break; | |
334 | } | |
335 | if (!setting) | |
336 | setting = circuit_get_mt_setting( | |
337 | circuit, area_settings[i]->mtid); | |
99894f9a | 338 | |
d62a17ae | 339 | if (!setting->enabled) |
340 | continue; | |
99894f9a | 341 | |
d62a17ae | 342 | count++; |
343 | if (count > size) { | |
344 | rv = XREALLOC(MTYPE_TMP, rv, count * sizeof(*rv)); | |
345 | size = count; | |
346 | } | |
347 | rv[count - 1] = setting; | |
348 | } | |
99894f9a | 349 | |
d62a17ae | 350 | *mt_count = count; |
351 | return rv; | |
99894f9a | 352 | } |
d8fba7d9 | 353 | |
206f4aae | 354 | /* ADJ specific MT API */ |
d8fba7d9 | 355 | static void adj_mt_set(struct isis_adjacency *adj, unsigned int index, |
d62a17ae | 356 | uint16_t mtid) |
357 | { | |
358 | if (adj->mt_count < index + 1) { | |
359 | adj->mt_set = XREALLOC(MTYPE_MT_ADJ_INFO, adj->mt_set, | |
360 | (index + 1) * sizeof(*adj->mt_set)); | |
361 | adj->mt_count = index + 1; | |
362 | } | |
363 | adj->mt_set[index] = mtid; | |
364 | } | |
365 | ||
0c1bd758 | 366 | bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable, |
d62a17ae | 367 | struct isis_adjacency *adj) |
368 | { | |
369 | struct isis_circuit_mt_setting **mt_settings; | |
370 | unsigned int circuit_mt_count; | |
371 | ||
372 | unsigned int intersect_count = 0; | |
373 | ||
374 | uint16_t *old_mt_set = NULL; | |
375 | unsigned int old_mt_count; | |
376 | ||
377 | old_mt_count = adj->mt_count; | |
378 | if (old_mt_count) { | |
379 | old_mt_set = | |
380 | XCALLOC(MTYPE_TMP, old_mt_count * sizeof(*old_mt_set)); | |
381 | memcpy(old_mt_set, adj->mt_set, | |
382 | old_mt_count * sizeof(*old_mt_set)); | |
383 | } | |
384 | ||
385 | mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count); | |
386 | for (unsigned int i = 0; i < circuit_mt_count; i++) { | |
af8ac8f9 CF |
387 | if (!tlvs->mt_router_info.count |
388 | && !tlvs->mt_router_info_empty) { | |
d62a17ae | 389 | /* Other end does not have MT enabled */ |
390 | if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST | |
7d26945a | 391 | && (v4_usable || v6_usable)) |
d62a17ae | 392 | adj_mt_set(adj, intersect_count++, |
393 | ISIS_MT_IPV4_UNICAST); | |
394 | } else { | |
0c1bd758 CF |
395 | struct isis_mt_router_info *info_head; |
396 | ||
397 | info_head = (struct isis_mt_router_info *) | |
398 | tlvs->mt_router_info.head; | |
399 | for (struct isis_mt_router_info *info = info_head; info; | |
400 | info = info->next) { | |
d62a17ae | 401 | if (mt_settings[i]->mtid == info->mtid) { |
402 | bool usable; | |
403 | switch (info->mtid) { | |
404 | case ISIS_MT_IPV4_UNICAST: | |
405 | case ISIS_MT_IPV4_MGMT: | |
406 | case ISIS_MT_IPV4_MULTICAST: | |
407 | usable = v4_usable; | |
408 | break; | |
409 | case ISIS_MT_IPV6_UNICAST: | |
410 | case ISIS_MT_IPV6_MGMT: | |
411 | case ISIS_MT_IPV6_MULTICAST: | |
412 | usable = v6_usable; | |
413 | break; | |
414 | default: | |
415 | usable = true; | |
416 | break; | |
417 | } | |
418 | if (usable) | |
419 | adj_mt_set(adj, | |
420 | intersect_count++, | |
421 | info->mtid); | |
422 | } | |
423 | } | |
424 | } | |
425 | } | |
426 | adj->mt_count = intersect_count; | |
427 | ||
428 | bool changed = false; | |
429 | ||
430 | if (adj->mt_count != old_mt_count) | |
431 | changed = true; | |
432 | ||
433 | if (!changed && old_mt_count | |
434 | && memcmp(adj->mt_set, old_mt_set, | |
435 | old_mt_count * sizeof(*old_mt_set))) | |
436 | changed = true; | |
437 | ||
438 | if (old_mt_count) | |
439 | XFREE(MTYPE_TMP, old_mt_set); | |
440 | ||
441 | return changed; | |
442 | } | |
443 | ||
444 | bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid) | |
445 | { | |
446 | for (unsigned int i = 0; i < adj->mt_count; i++) | |
447 | if (adj->mt_set[i] == mtid) | |
448 | return true; | |
449 | return false; | |
450 | } | |
451 | ||
452 | void adj_mt_finish(struct isis_adjacency *adj) | |
453 | { | |
454 | XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set); | |
455 | adj->mt_count = 0; | |
d8fba7d9 | 456 | } |
206f4aae | 457 | |
d62a17ae | 458 | static void mt_set_add(uint16_t **mt_set, unsigned int *size, |
459 | unsigned int *index, uint16_t mtid) | |
206f4aae | 460 | { |
d62a17ae | 461 | for (unsigned int i = 0; i < *index; i++) { |
462 | if ((*mt_set)[i] == mtid) | |
463 | return; | |
464 | } | |
206f4aae | 465 | |
d62a17ae | 466 | if (*index >= *size) { |
467 | *mt_set = XREALLOC(MTYPE_TMP, *mt_set, | |
468 | sizeof(**mt_set) * ((*index) + 1)); | |
469 | *size = (*index) + 1; | |
470 | } | |
206f4aae | 471 | |
d62a17ae | 472 | (*mt_set)[*index] = mtid; |
473 | *index = (*index) + 1; | |
206f4aae CF |
474 | } |
475 | ||
d62a17ae | 476 | static uint16_t *circuit_bcast_mt_set(struct isis_circuit *circuit, int level, |
477 | unsigned int *mt_count) | |
206f4aae | 478 | { |
d62a17ae | 479 | static uint16_t *rv; |
480 | static unsigned int size; | |
481 | struct listnode *node; | |
482 | struct isis_adjacency *adj; | |
206f4aae | 483 | |
d62a17ae | 484 | unsigned int count = 0; |
206f4aae | 485 | |
d62a17ae | 486 | if (circuit->circ_type != CIRCUIT_T_BROADCAST) { |
487 | *mt_count = 0; | |
488 | return NULL; | |
489 | } | |
206f4aae | 490 | |
d62a17ae | 491 | for (ALL_LIST_ELEMENTS_RO(circuit->u.bc.adjdb[level - 1], node, adj)) { |
492 | if (adj->adj_state != ISIS_ADJ_UP) | |
493 | continue; | |
494 | for (unsigned int i = 0; i < adj->mt_count; i++) | |
495 | mt_set_add(&rv, &size, &count, adj->mt_set[i]); | |
496 | } | |
206f4aae | 497 | |
d62a17ae | 498 | *mt_count = count; |
499 | return rv; | |
206f4aae CF |
500 | } |
501 | ||
af8ac8f9 | 502 | static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs, |
d62a17ae | 503 | unsigned int mt_count, uint16_t *mt_set, |
1b3f47d0 OD |
504 | uint8_t *id, uint32_t metric, |
505 | struct isis_ext_subtlvs *ext) | |
206f4aae | 506 | { |
173f8887 OD |
507 | /* Check if MT is enable for this area */ |
508 | if (!area_is_mt(area)) { | |
509 | lsp_debug( | |
510 | "ISIS (%s): Adding %s.%02x as te-style neighbor (MT disable)", | |
511 | area->area_tag, sysid_print(id), LSP_PSEUDO_ID(id)); | |
512 | isis_tlvs_add_extended_reach(tlvs, ISIS_MT_DISABLE, id, metric, | |
513 | ext); | |
514 | return; | |
515 | } | |
516 | ||
517 | /* Process Multi-Topology */ | |
d62a17ae | 518 | for (unsigned int i = 0; i < mt_count; i++) { |
519 | uint16_t mtid = mt_set[i]; | |
d62a17ae | 520 | if (mt_set[i] == ISIS_MT_IPV4_UNICAST) { |
d62a17ae | 521 | lsp_debug( |
522 | "ISIS (%s): Adding %s.%02x as te-style neighbor", | |
af8ac8f9 CF |
523 | area->area_tag, sysid_print(id), |
524 | LSP_PSEUDO_ID(id)); | |
d62a17ae | 525 | } else { |
d62a17ae | 526 | lsp_debug( |
527 | "ISIS (%s): Adding %s.%02x as mt-style neighbor for %s", | |
af8ac8f9 CF |
528 | area->area_tag, sysid_print(id), |
529 | LSP_PSEUDO_ID(id), isis_mtid2str(mtid)); | |
d62a17ae | 530 | } |
1b3f47d0 | 531 | isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, ext); |
d62a17ae | 532 | } |
206f4aae CF |
533 | } |
534 | ||
af8ac8f9 | 535 | void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit, |
1b3f47d0 | 536 | int level, uint8_t *id, uint32_t metric) |
206f4aae | 537 | { |
d62a17ae | 538 | unsigned int mt_count; |
539 | uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, &mt_count); | |
206f4aae | 540 | |
af8ac8f9 | 541 | tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, id, metric, |
1b3f47d0 | 542 | circuit->ext); |
d62a17ae | 543 | } |
544 | ||
af8ac8f9 | 545 | void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit, |
1b3f47d0 | 546 | uint8_t *id, uint32_t metric) |
206f4aae | 547 | { |
d62a17ae | 548 | struct isis_adjacency *adj = circuit->u.p2p.neighbor; |
206f4aae | 549 | |
af8ac8f9 | 550 | tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id, |
1b3f47d0 | 551 | metric, circuit->ext); |
206f4aae | 552 | } |
d56afe53 CF |
553 | |
554 | void mt_init(void) | |
555 | { | |
05e4ec37 | 556 | #ifdef FABRICD |
d56afe53 CF |
557 | hook_register(isis_circuit_config_write, |
558 | circuit_write_mt_settings); | |
05e4ec37 | 559 | #endif |
d56afe53 | 560 | } |