]> git.proxmox.com Git - mirror_frr.git/blame - lib/link_state.c
Merge pull request #13183 from Pdoijode/pdoijode/pim-json-changes
[mirror_frr.git] / lib / link_state.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
bbd85e20
OD
2/*
3 * Link State Database - link_state.c
4 *
5 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
6 *
7 * Copyright (C) 2020 Orange http://www.orange.com
8 *
9 * This file is part of Free Range Routing (FRR).
bbd85e20
OD
10 */
11
1f8031f7
DL
12#include <zebra.h>
13
bbd85e20
OD
14#include "if.h"
15#include "linklist.h"
16#include "log.h"
17#include "command.h"
18#include "termtable.h"
19#include "memory.h"
20#include "prefix.h"
21#include "table.h"
22#include "vty.h"
23#include "zclient.h"
24#include "stream.h"
b0c0b433
OD
25#include "sbuf.h"
26#include "printfrr.h"
27#include <lib/json.h>
bbd85e20 28#include "link_state.h"
7f9ab3b0 29#include "iso.h"
bbd85e20
OD
30
31/* Link State Memory allocation */
bf8d3d6a 32DEFINE_MTYPE_STATIC(LIB, LS_DB, "Link State Database");
bbd85e20
OD
33
34/**
35 * Link State Node management functions
36 */
f4157b4f
OD
37int ls_node_id_same(struct ls_node_id i1, struct ls_node_id i2)
38{
39 if (i1.origin != i2.origin)
40 return 0;
41
42 if (i1.origin == UNKNOWN)
43 return 1;
44
45 if (i1.origin == ISIS_L1 || i1.origin == ISIS_L2) {
46 if (memcmp(i1.id.iso.sys_id, i2.id.iso.sys_id, ISO_SYS_ID_LEN)
47 != 0
48 || (i1.id.iso.level != i2.id.iso.level))
49 return 0;
50 } else {
51 if (!IPV4_ADDR_SAME(&i1.id.ip.addr, &i2.id.ip.addr)
52 || !IPV4_ADDR_SAME(&i1.id.ip.area_id, &i2.id.ip.area_id))
53 return 1;
54 }
55
56 return 1;
57}
58
bbd85e20
OD
59struct ls_node *ls_node_new(struct ls_node_id adv, struct in_addr rid,
60 struct in6_addr rid6)
61{
62 struct ls_node *new;
63
b0c0b433 64 if (adv.origin == UNKNOWN)
bbd85e20
OD
65 return NULL;
66
67 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
68 new->adv = adv;
69 if (!IPV4_NET0(rid.s_addr)) {
70 new->router_id = rid;
71 SET_FLAG(new->flags, LS_NODE_ROUTER_ID);
72 } else {
73 if (adv.origin == OSPFv2 || adv.origin == STATIC
74 || adv.origin == DIRECT) {
75 new->router_id = adv.id.ip.addr;
76 SET_FLAG(new->flags, LS_NODE_ROUTER_ID);
77 }
78 }
79 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6)) {
8693b4d6 80 new->router_id6 = rid6;
bbd85e20
OD
81 SET_FLAG(new->flags, LS_NODE_ROUTER_ID6);
82 }
83 return new;
84}
85
86void ls_node_del(struct ls_node *node)
87{
b0c0b433
OD
88 if (!node)
89 return;
90
bbd85e20 91 XFREE(MTYPE_LS_DB, node);
bbd85e20
OD
92}
93
94int ls_node_same(struct ls_node *n1, struct ls_node *n2)
95{
f4157b4f 96 /* First, check pointer */
bbd85e20
OD
97 if ((n1 && !n2) || (!n1 && n2))
98 return 0;
99
100 if (n1 == n2)
101 return 1;
102
f4157b4f 103 /* Then, verify Flags and Origin */
bbd85e20
OD
104 if (n1->flags != n2->flags)
105 return 0;
106
f4157b4f 107 if (!ls_node_id_same(n1->adv, n2->adv))
bbd85e20
OD
108 return 0;
109
f4157b4f
OD
110 /* Finally, check each individual parameters that are valid */
111 if (CHECK_FLAG(n1->flags, LS_NODE_NAME)
112 && (strncmp(n1->name, n2->name, MAX_NAME_LENGTH) != 0))
bbd85e20 113 return 0;
f4157b4f
OD
114 if (CHECK_FLAG(n1->flags, LS_NODE_ROUTER_ID)
115 && !IPV4_ADDR_SAME(&n1->router_id, &n2->router_id))
bbd85e20 116 return 0;
f4157b4f 117 if (CHECK_FLAG(n1->flags, LS_NODE_ROUTER_ID6)
8693b4d6 118 && !IPV6_ADDR_SAME(&n1->router_id6, &n2->router_id6))
f4157b4f
OD
119 return 0;
120 if (CHECK_FLAG(n1->flags, LS_NODE_FLAG)
121 && (n1->node_flag != n2->node_flag))
122 return 0;
123 if (CHECK_FLAG(n1->flags, LS_NODE_TYPE) && (n1->type != n2->type))
124 return 0;
125 if (CHECK_FLAG(n1->flags, LS_NODE_AS_NUMBER)
126 && (n1->as_number != n2->as_number))
127 return 0;
128 if (CHECK_FLAG(n1->flags, LS_NODE_SR)) {
129 if (n1->srgb.flag != n2->srgb.flag
130 || n1->srgb.lower_bound != n2->srgb.lower_bound
131 || n1->srgb.range_size != n2->srgb.range_size)
132 return 0;
133 if ((n1->algo[0] != n2->algo[0])
134 || (n1->algo[1] != n2->algo[1]))
135 return 0;
136 if (CHECK_FLAG(n1->flags, LS_NODE_SRLB)
137 && ((n1->srlb.lower_bound != n2->srlb.lower_bound
138 || n1->srlb.range_size != n2->srlb.range_size)))
139 return 0;
140 if (CHECK_FLAG(n1->flags, LS_NODE_MSD) && (n1->msd != n2->msd))
141 return 0;
142 }
143
144 /* OK, n1 & n2 are equal */
145 return 1;
bbd85e20
OD
146}
147
148/**
149 * Link State Attributes management functions
150 */
151struct ls_attributes *ls_attributes_new(struct ls_node_id adv,
152 struct in_addr local,
153 struct in6_addr local6,
154 uint32_t local_id)
155{
156 struct ls_attributes *new;
157
b0c0b433 158 if (adv.origin == UNKNOWN)
bbd85e20
OD
159 return NULL;
160
161 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
162 new->adv = adv;
163 if (!IPV4_NET0(local.s_addr)) {
164 new->standard.local = local;
165 SET_FLAG(new->flags, LS_ATTR_LOCAL_ADDR);
166 }
167 if (!IN6_IS_ADDR_UNSPECIFIED(&local6)) {
168 new->standard.local6 = local6;
169 SET_FLAG(new->flags, LS_ATTR_LOCAL_ADDR6);
170 }
171 if (local_id != 0) {
172 new->standard.local_id = local_id;
173 SET_FLAG(new->flags, LS_ATTR_LOCAL_ID);
174 }
175
176 /* Check that almost one identifier is set */
177 if (!CHECK_FLAG(new->flags, LS_ATTR_LOCAL_ADDR | LS_ATTR_LOCAL_ADDR6
178 | LS_ATTR_LOCAL_ID)) {
179 XFREE(MTYPE_LS_DB, new);
180 return NULL;
181 }
182
bd0581e4
LS
183 admin_group_init(&new->ext_admin_group);
184
bbd85e20
OD
185 return new;
186}
187
b0c0b433 188void ls_attributes_srlg_del(struct ls_attributes *attr)
bbd85e20
OD
189{
190 if (!attr)
191 return;
192
193 if (attr->srlgs)
194 XFREE(MTYPE_LS_DB, attr->srlgs);
195
b0c0b433
OD
196 attr->srlgs = NULL;
197 attr->srlg_len = 0;
198 UNSET_FLAG(attr->flags, LS_ATTR_SRLG);
199}
200
201void ls_attributes_del(struct ls_attributes *attr)
202{
203 if (!attr)
204 return;
205
206 ls_attributes_srlg_del(attr);
207
bd0581e4
LS
208 admin_group_term(&attr->ext_admin_group);
209
bbd85e20 210 XFREE(MTYPE_LS_DB, attr);
bbd85e20
OD
211}
212
213int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
214{
f4157b4f 215 /* First, check pointer */
bbd85e20
OD
216 if ((l1 && !l2) || (!l1 && l2))
217 return 0;
218
219 if (l1 == l2)
220 return 1;
221
f4157b4f 222 /* Then, verify Flags and Origin */
bbd85e20
OD
223 if (l1->flags != l2->flags)
224 return 0;
225
f4157b4f 226 if (!ls_node_id_same(l1->adv, l2->adv))
bbd85e20
OD
227 return 0;
228
f4157b4f
OD
229 /* Finally, check each individual parameters that are valid */
230 if (CHECK_FLAG(l1->flags, LS_ATTR_NAME)
231 && strncmp(l1->name, l2->name, MAX_NAME_LENGTH) != 0)
bbd85e20 232 return 0;
f4157b4f 233 if (CHECK_FLAG(l1->flags, LS_ATTR_METRIC) && (l1->metric != l2->metric))
bbd85e20 234 return 0;
f4157b4f
OD
235 if (CHECK_FLAG(l1->flags, LS_ATTR_TE_METRIC)
236 && (l1->standard.te_metric != l2->standard.te_metric))
237 return 0;
238 if (CHECK_FLAG(l1->flags, LS_ATTR_ADM_GRP)
239 && (l1->standard.admin_group != l2->standard.admin_group))
240 return 0;
bd0581e4
LS
241 if (CHECK_FLAG(l1->flags, LS_ATTR_EXT_ADM_GRP) &&
242 !admin_group_cmp(&l1->ext_admin_group, &l2->ext_admin_group))
243 return 0;
f4157b4f
OD
244 if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ADDR)
245 && !IPV4_ADDR_SAME(&l1->standard.local, &l2->standard.local))
246 return 0;
247 if (CHECK_FLAG(l1->flags, LS_ATTR_NEIGH_ADDR)
248 && !IPV4_ADDR_SAME(&l1->standard.remote, &l2->standard.remote))
249 return 0;
250 if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ADDR6)
251 && !IPV6_ADDR_SAME(&l1->standard.local6, &l2->standard.local6))
252 return 0;
253 if (CHECK_FLAG(l1->flags, LS_ATTR_NEIGH_ADDR6)
254 && !IPV6_ADDR_SAME(&l1->standard.remote6, &l2->standard.remote6))
255 return 0;
256 if (CHECK_FLAG(l1->flags, LS_ATTR_LOCAL_ID)
257 && (l1->standard.local_id != l2->standard.local_id))
258 return 0;
259 if (CHECK_FLAG(l1->flags, LS_ATTR_NEIGH_ID)
260 && (l1->standard.remote_id != l2->standard.remote_id))
261 return 0;
262 if (CHECK_FLAG(l1->flags, LS_ATTR_MAX_BW)
263 && (l1->standard.max_bw != l2->standard.max_bw))
264 return 0;
265 if (CHECK_FLAG(l1->flags, LS_ATTR_MAX_RSV_BW)
266 && (l1->standard.max_rsv_bw != l2->standard.max_rsv_bw))
267 return 0;
268 if (CHECK_FLAG(l1->flags, LS_ATTR_UNRSV_BW)
269 && memcmp(&l1->standard.unrsv_bw, &l2->standard.unrsv_bw, 32) != 0)
270 return 0;
271 if (CHECK_FLAG(l1->flags, LS_ATTR_REMOTE_AS)
272 && (l1->standard.remote_as != l2->standard.remote_as))
273 return 0;
274 if (CHECK_FLAG(l1->flags, LS_ATTR_REMOTE_ADDR)
275 && !IPV4_ADDR_SAME(&l1->standard.remote_addr,
276 &l2->standard.remote_addr))
277 return 0;
278 if (CHECK_FLAG(l1->flags, LS_ATTR_REMOTE_ADDR6)
279 && !IPV6_ADDR_SAME(&l1->standard.remote_addr6,
280 &l2->standard.remote_addr6))
281 return 0;
282 if (CHECK_FLAG(l1->flags, LS_ATTR_DELAY)
283 && (l1->extended.delay != l2->extended.delay))
284 return 0;
285 if (CHECK_FLAG(l1->flags, LS_ATTR_MIN_MAX_DELAY)
286 && ((l1->extended.min_delay != l2->extended.min_delay)
287 || (l1->extended.max_delay != l2->extended.max_delay)))
288 return 0;
289 if (CHECK_FLAG(l1->flags, LS_ATTR_JITTER)
290 && (l1->extended.jitter != l2->extended.jitter))
291 return 0;
292 if (CHECK_FLAG(l1->flags, LS_ATTR_PACKET_LOSS)
293 && (l1->extended.pkt_loss != l2->extended.pkt_loss))
294 return 0;
295 if (CHECK_FLAG(l1->flags, LS_ATTR_AVA_BW)
296 && (l1->extended.ava_bw != l2->extended.ava_bw))
297 return 0;
298 if (CHECK_FLAG(l1->flags, LS_ATTR_RSV_BW)
299 && (l1->extended.rsv_bw != l2->extended.rsv_bw))
300 return 0;
301 if (CHECK_FLAG(l1->flags, LS_ATTR_USE_BW)
302 && (l1->extended.used_bw != l2->extended.used_bw))
303 return 0;
8693b4d6
OD
304 for (int i = 0; i < LS_ADJ_MAX; i++) {
305 if (!CHECK_FLAG(l1->flags, (LS_ATTR_ADJ_SID << i)))
306 continue;
307 if ((l1->adj_sid[i].sid != l2->adj_sid[i].sid)
308 || (l1->adj_sid[i].flags != l2->adj_sid[i].flags)
309 || (l1->adj_sid[i].weight != l2->adj_sid[i].weight))
f4157b4f
OD
310 return 0;
311 if (((l1->adv.origin == ISIS_L1) || (l1->adv.origin == ISIS_L2))
8693b4d6
OD
312 && (memcmp(&l1->adj_sid[i].neighbor.sysid,
313 &l2->adj_sid[i].neighbor.sysid, ISO_SYS_ID_LEN)
f4157b4f
OD
314 != 0))
315 return 0;
316 if (((l1->adv.origin == OSPFv2) || (l1->adv.origin == STATIC)
317 || (l1->adv.origin == DIRECT))
8693b4d6
OD
318 && (i < ADJ_PRI_IPV6)
319 && (!IPV4_ADDR_SAME(&l1->adj_sid[i].neighbor.addr,
320 &l2->adj_sid[i].neighbor.addr)))
f4157b4f
OD
321 return 0;
322 }
323 if (CHECK_FLAG(l1->flags, LS_ATTR_SRLG)
324 && ((l1->srlg_len != l2->srlg_len)
325 || memcmp(l1->srlgs, l2->srlgs,
326 l1->srlg_len * sizeof(uint32_t))
327 != 0))
328 return 0;
329
330 /* OK, l1 & l2 are equal */
331 return 1;
bbd85e20
OD
332}
333
334/**
b0c0b433 335 * Link State prefix management functions
bbd85e20 336 */
b5894669 337struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p)
bbd85e20 338{
b0c0b433 339 struct ls_prefix *new;
bbd85e20 340
b0c0b433 341 if (adv.origin == UNKNOWN)
bbd85e20
OD
342 return NULL;
343
fa0f9ae3 344 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
b0c0b433 345 new->adv = adv;
b5894669 346 new->pref = *p;
bbd85e20
OD
347
348 return new;
349}
350
b0c0b433 351void ls_prefix_del(struct ls_prefix *pref)
bbd85e20 352{
b0c0b433 353 if (!pref)
bbd85e20
OD
354 return;
355
b0c0b433 356 XFREE(MTYPE_LS_DB, pref);
bbd85e20
OD
357}
358
b0c0b433
OD
359int ls_prefix_same(struct ls_prefix *p1, struct ls_prefix *p2)
360{
f4157b4f 361 /* First, check pointer */
b0c0b433
OD
362 if ((p1 && !p2) || (!p1 && p2))
363 return 0;
364
365 if (p1 == p2)
366 return 1;
367
f4157b4f 368 /* Then, verify Flags and Origin */
b0c0b433
OD
369 if (p1->flags != p2->flags)
370 return 0;
371
f4157b4f 372 if (!ls_node_id_same(p1->adv, p2->adv))
b0c0b433
OD
373 return 0;
374
f4157b4f
OD
375 /* Finally, check each individual parameters that are valid */
376 if (prefix_same(&p1->pref, &p2->pref) == 0)
b0c0b433 377 return 0;
f4157b4f
OD
378 if (CHECK_FLAG(p1->flags, LS_PREF_IGP_FLAG)
379 && (p1->igp_flag != p2->igp_flag))
b0c0b433 380 return 0;
f4157b4f
OD
381 if (CHECK_FLAG(p1->flags, LS_PREF_ROUTE_TAG)
382 && (p1->route_tag != p2->route_tag))
383 return 0;
384 if (CHECK_FLAG(p1->flags, LS_PREF_EXTENDED_TAG)
385 && (p1->extended_tag != p2->extended_tag))
386 return 0;
387 if (CHECK_FLAG(p1->flags, LS_PREF_METRIC) && (p1->metric != p2->metric))
388 return 0;
389 if (CHECK_FLAG(p1->flags, LS_PREF_SR)) {
390 if ((p1->sr.algo != p2->sr.algo) || (p1->sr.sid != p2->sr.sid)
391 || (p1->sr.sid_flag != p2->sr.sid_flag))
392 return 0;
393 }
394
395 /* OK, p1 & p2 are equal */
396 return 1;
b0c0b433
OD
397}
398
399/**
400 * Link State Vertices management functions
401 */
8693b4d6
OD
402uint64_t sysid_to_key(const uint8_t sysid[ISO_SYS_ID_LEN])
403{
404 uint64_t key = 0;
405
406#if BYTE_ORDER == LITTLE_ENDIAN
407 uint8_t *byte = (uint8_t *)&key;
408
409 for (int i = 0; i < ISO_SYS_ID_LEN; i++)
410 byte[i] = sysid[ISO_SYS_ID_LEN - i - 1];
411
412 byte[6] = 0;
413 byte[7] = 0;
414#else
415 memcpy(&key, sysid, ISO_SYS_ID_LEN);
416#endif
417
418 return key;
419}
420
bbd85e20
OD
421struct ls_vertex *ls_vertex_add(struct ls_ted *ted, struct ls_node *node)
422{
423 struct ls_vertex *new;
b0c0b433 424 uint64_t key = 0;
bbd85e20
OD
425
426 if ((ted == NULL) || (node == NULL))
427 return NULL;
428
bbd85e20
OD
429 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
430 switch (node->adv.origin) {
431 case OSPFv2:
432 case STATIC:
433 case DIRECT:
b0c0b433
OD
434 key = ((uint64_t)ntohl(node->adv.id.ip.addr.s_addr))
435 & 0xffffffff;
bbd85e20
OD
436 break;
437 case ISIS_L1:
438 case ISIS_L2:
8693b4d6 439 key = sysid_to_key(node->adv.id.iso.sys_id);
bbd85e20 440 break;
bde30e78 441 case UNKNOWN:
b0c0b433 442 key = 0;
bbd85e20
OD
443 break;
444 }
445
b0c0b433
OD
446 /* Check that key is valid */
447 if (key == 0)
bbd85e20 448 return NULL;
bbd85e20 449
b0c0b433
OD
450 /* Create Vertex and add it to the TED */
451 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_vertex));
452 if (!new)
453 return NULL;
454
455 new->key = key;
456 new->node = node;
457 new->status = NEW;
458 new->type = VERTEX;
459 new->incoming_edges = list_new();
460 new->incoming_edges->cmp = (int (*)(void *, void *))edge_cmp;
461 new->outgoing_edges = list_new();
462 new->outgoing_edges->cmp = (int (*)(void *, void *))edge_cmp;
463 new->prefixes = list_new();
464 new->prefixes->cmp = (int (*)(void *, void *))subnet_cmp;
bbd85e20
OD
465 vertices_add(&ted->vertices, new);
466
467 return new;
468}
469
b0c0b433
OD
470void ls_vertex_del(struct ls_ted *ted, struct ls_vertex *vertex)
471{
472 struct listnode *node, *nnode;
473 struct ls_edge *edge;
474 struct ls_subnet *subnet;
475
476 if (!ted || !vertex)
477 return;
478
479 /* Remove outgoing Edges and list */
480 for (ALL_LIST_ELEMENTS(vertex->outgoing_edges, node, nnode, edge))
481 ls_edge_del_all(ted, edge);
482 list_delete(&vertex->outgoing_edges);
483
484 /* Disconnect incoming Edges and remove list */
485 for (ALL_LIST_ELEMENTS(vertex->incoming_edges, node, nnode, edge)) {
486 ls_disconnect(vertex, edge, false);
487 if (edge->source == NULL)
488 ls_edge_del_all(ted, edge);
489 }
490 list_delete(&vertex->incoming_edges);
491
492 /* Remove subnet and list */
493 for (ALL_LIST_ELEMENTS(vertex->prefixes, node, nnode, subnet))
494 ls_subnet_del_all(ted, subnet);
495 list_delete(&vertex->prefixes);
496
497 /* Then remove Vertex from Link State Data Base and free memory */
498 vertices_del(&ted->vertices, vertex);
499 XFREE(MTYPE_LS_DB, vertex);
500 vertex = NULL;
501}
502
503void ls_vertex_del_all(struct ls_ted *ted, struct ls_vertex *vertex)
504{
505 if (!ted || !vertex)
506 return;
507
508 /* First remove associated Link State Node */
509 ls_node_del(vertex->node);
510
511 /* Then, Vertex itself */
512 ls_vertex_del(ted, vertex);
513}
514
bbd85e20
OD
515struct ls_vertex *ls_vertex_update(struct ls_ted *ted, struct ls_node *node)
516{
517 struct ls_vertex *old;
518
519 if (node == NULL)
520 return NULL;
521
522 old = ls_find_vertex_by_id(ted, node->adv);
523 if (old) {
524 if (!ls_node_same(old->node, node)) {
525 ls_node_del(old->node);
526 old->node = node;
527 }
b0c0b433 528 old->status = UPDATE;
bbd85e20
OD
529 return old;
530 }
531
532 return ls_vertex_add(ted, node);
533}
534
bbd85e20
OD
535struct ls_vertex *ls_find_vertex_by_key(struct ls_ted *ted, const uint64_t key)
536{
b0c0b433 537 struct ls_vertex vertex = {};
bbd85e20
OD
538
539 if (key == 0)
540 return NULL;
541
b0c0b433
OD
542 vertex.key = key;
543 return vertices_find(&ted->vertices, &vertex);
bbd85e20
OD
544}
545
546struct ls_vertex *ls_find_vertex_by_id(struct ls_ted *ted,
547 struct ls_node_id nid)
548{
b0c0b433 549 struct ls_vertex vertex = {};
bbd85e20 550
b0c0b433 551 vertex.key = 0;
bbd85e20
OD
552 switch (nid.origin) {
553 case OSPFv2:
554 case STATIC:
555 case DIRECT:
b0c0b433
OD
556 vertex.key =
557 ((uint64_t)ntohl(nid.id.ip.addr.s_addr)) & 0xffffffff;
bbd85e20
OD
558 break;
559 case ISIS_L1:
560 case ISIS_L2:
8693b4d6 561 vertex.key = sysid_to_key(nid.id.iso.sys_id);
bbd85e20 562 break;
bde30e78 563 case UNKNOWN:
bbd85e20
OD
564 return NULL;
565 }
566
b0c0b433 567 return vertices_find(&ted->vertices, &vertex);
bbd85e20
OD
568}
569
570int ls_vertex_same(struct ls_vertex *v1, struct ls_vertex *v2)
571{
572 if ((v1 && !v2) || (!v1 && v2))
573 return 0;
574
575 if (!v1 && !v2)
576 return 1;
577
578 if (v1->key != v2->key)
579 return 0;
580
581 if (v1->node == v2->node)
582 return 1;
583
584 return ls_node_same(v1->node, v2->node);
585}
586
b0c0b433
OD
587void ls_vertex_clean(struct ls_ted *ted, struct ls_vertex *vertex,
588 struct zclient *zclient)
589{
590 struct listnode *node, *nnode;
591 struct ls_edge *edge;
592 struct ls_subnet *subnet;
593 struct ls_message msg;
594
595 /* Remove Orphan Edge ... */
596 for (ALL_LIST_ELEMENTS(vertex->outgoing_edges, node, nnode, edge)) {
597 if (edge->status == ORPHAN) {
598 if (zclient) {
599 edge->status = DELETE;
600 ls_edge2msg(&msg, edge);
601 ls_send_msg(zclient, &msg, NULL);
602 }
603 ls_edge_del_all(ted, edge);
604 }
605 }
606 for (ALL_LIST_ELEMENTS(vertex->incoming_edges, node, nnode, edge)) {
607 if (edge->status == ORPHAN) {
608 if (zclient) {
609 edge->status = DELETE;
610 ls_edge2msg(&msg, edge);
611 ls_send_msg(zclient, &msg, NULL);
612 }
613 ls_edge_del_all(ted, edge);
614 }
615 }
616
617 /* ... and Subnet from the Vertex */
618 for (ALL_LIST_ELEMENTS(vertex->prefixes, node, nnode, subnet)) {
619 if (subnet->status == ORPHAN) {
620 if (zclient) {
621 subnet->status = DELETE;
622 ls_subnet2msg(&msg, subnet);
623 ls_send_msg(zclient, &msg, NULL);
624 }
625 ls_subnet_del_all(ted, subnet);
626 }
627 }
628}
629
bbd85e20
OD
630/**
631 * Link State Edges management functions
632 */
633
634/**
635 * This function allows to connect the Edge to the vertices present in the TED.
636 * A temporary vertex that corresponds to the source of this Edge i.e. the
637 * advertised router, is created if not found in the Data Base. If a Edge that
638 * corresponds to the reverse path is found, the Edge is attached to the
639 * destination vertex as destination and reverse Edge is attached to the source
640 * vertex as source.
641 *
642 * @param ted Link State Data Base
643 * @param edge Link State Edge to be attached
644 */
645static void ls_edge_connect_to(struct ls_ted *ted, struct ls_edge *edge)
646{
647 struct ls_vertex *vertex = NULL;
648 struct ls_node *node;
649 struct ls_edge *dst;
650 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
651
652 /* First, search if there is a Vertex that correspond to the Node ID */
653 vertex = ls_find_vertex_by_id(ted, edge->attributes->adv);
654 if (vertex == NULL) {
655 /* Create a new temporary Node & Vertex if not found */
656 node = ls_node_new(edge->attributes->adv, inaddr_any,
657 in6addr_any);
658 vertex = ls_vertex_add(ted, node);
659 }
660 /* and attach the edge as source to the vertex */
b0c0b433 661 listnode_add_sort_nodup(vertex->outgoing_edges, edge);
bbd85e20
OD
662 edge->source = vertex;
663
664 /* Then search if there is a reverse Edge */
665 dst = ls_find_edge_by_destination(ted, edge->attributes);
666 /* attach the destination edge to the vertex */
667 if (dst) {
b0c0b433 668 listnode_add_sort_nodup(vertex->incoming_edges, dst);
bbd85e20
OD
669 dst->destination = vertex;
670 /* and destination vertex to this edge */
671 vertex = dst->source;
b0c0b433 672 listnode_add_sort_nodup(vertex->incoming_edges, edge);
bbd85e20
OD
673 edge->destination = vertex;
674 }
675}
676
8693b4d6
OD
677static uint64_t get_edge_key(struct ls_attributes *attr, bool dst)
678{
679 uint64_t key = 0;
680 struct ls_standard *std;
681
682 if (!attr)
683 return key;
684
685 std = &attr->standard;
686
687 if (dst) {
688 /* Key is the IPv4 remote address */
689 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
690 key = ((uint64_t)ntohl(std->remote.s_addr))
691 & 0xffffffff;
692 /* or the 64 bits LSB of IPv6 remote address */
693 else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
694 key = ((uint64_t)ntohl(std->remote6.s6_addr32[2]) << 32
695 | (uint64_t)ntohl(std->remote6.s6_addr32[3]));
696 /* of remote identifier if no IP addresses are defined */
697 else if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
698 key = (((uint64_t)std->remote_id) & 0xffffffff)
699 | ((uint64_t)std->local_id << 32);
700 } else {
701 /* Key is the IPv4 local address */
702 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
703 key = ((uint64_t)ntohl(std->local.s_addr)) & 0xffffffff;
704 /* or the 64 bits LSB of IPv6 local address */
705 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
706 key = ((uint64_t)ntohl(std->local6.s6_addr32[2]) << 32
707 | (uint64_t)ntohl(std->local6.s6_addr32[3]));
708 /* of local identifier if no IP addresses are defined */
709 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
710 key = (((uint64_t)std->local_id) & 0xffffffff)
711 | ((uint64_t)std->remote_id << 32);
712 }
713
714 return key;
715}
716
bbd85e20
OD
717struct ls_edge *ls_edge_add(struct ls_ted *ted,
718 struct ls_attributes *attributes)
719{
720 struct ls_edge *new;
b0c0b433 721 uint64_t key = 0;
bbd85e20
OD
722
723 if (attributes == NULL)
724 return NULL;
725
8693b4d6 726 key = get_edge_key(attributes, false);
b0c0b433
OD
727 if (key == 0)
728 return NULL;
729
730 /* Create Edge and add it to the TED */
731 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_edge));
bbd85e20 732
b0c0b433
OD
733 new->attributes = attributes;
734 new->key = key;
735 new->status = NEW;
736 new->type = EDGE;
bbd85e20
OD
737 edges_add(&ted->edges, new);
738
b0c0b433 739 /* Finally, connect Edge to Vertices */
bbd85e20
OD
740 ls_edge_connect_to(ted, new);
741
742 return new;
743}
744
745struct ls_edge *ls_find_edge_by_key(struct ls_ted *ted, const uint64_t key)
746{
747 struct ls_edge edge = {};
748
749 if (key == 0)
750 return NULL;
751
752 edge.key = key;
753 return edges_find(&ted->edges, &edge);
754}
755
756struct ls_edge *ls_find_edge_by_source(struct ls_ted *ted,
757 struct ls_attributes *attributes)
758{
759 struct ls_edge edge = {};
760
761 if (attributes == NULL)
762 return NULL;
763
8693b4d6 764 edge.key = get_edge_key(attributes, false);
bbd85e20
OD
765 if (edge.key == 0)
766 return NULL;
767
768 return edges_find(&ted->edges, &edge);
769}
770
771struct ls_edge *ls_find_edge_by_destination(struct ls_ted *ted,
772 struct ls_attributes *attributes)
773{
774 struct ls_edge edge = {};
775
776 if (attributes == NULL)
777 return NULL;
778
8693b4d6 779 edge.key = get_edge_key(attributes, true);
bbd85e20
OD
780 if (edge.key == 0)
781 return NULL;
782
783 return edges_find(&ted->edges, &edge);
784}
785
786struct ls_edge *ls_edge_update(struct ls_ted *ted,
787 struct ls_attributes *attributes)
788{
789 struct ls_edge *old;
790
791 if (attributes == NULL)
792 return NULL;
793
794 /* First, search for an existing Edge */
795 old = ls_find_edge_by_source(ted, attributes);
796 if (old) {
797 /* Check if attributes are similar */
798 if (!ls_attributes_same(old->attributes, attributes)) {
799 ls_attributes_del(old->attributes);
800 old->attributes = attributes;
801 }
b0c0b433 802 old->status = UPDATE;
bbd85e20
OD
803 return old;
804 }
805
806 /* If not found, add new Edge from the attributes */
807 return ls_edge_add(ted, attributes);
808}
809
b0c0b433
OD
810int ls_edge_same(struct ls_edge *e1, struct ls_edge *e2)
811{
812 if ((e1 && !e2) || (!e1 && e2))
813 return 0;
814
815 if (!e1 && !e2)
816 return 1;
817
818 if (e1->key != e2->key)
819 return 0;
820
821 if (e1->attributes == e2->attributes)
822 return 1;
823
824 return ls_attributes_same(e1->attributes, e2->attributes);
825}
826
bbd85e20
OD
827void ls_edge_del(struct ls_ted *ted, struct ls_edge *edge)
828{
b0c0b433
OD
829 if (!ted || !edge)
830 return;
831
832 /* Fist disconnect Edge from Vertices */
bbd85e20
OD
833 ls_disconnect_edge(edge);
834 /* Then remove it from the Data Base */
835 edges_del(&ted->edges, edge);
836 XFREE(MTYPE_LS_DB, edge);
837}
838
b0c0b433
OD
839void ls_edge_del_all(struct ls_ted *ted, struct ls_edge *edge)
840{
841 if (!ted || !edge)
842 return;
843
844 /* Remove associated Link State Attributes */
845 ls_attributes_del(edge->attributes);
846 /* Then Edge itself */
847 ls_edge_del(ted, edge);
848}
849
bbd85e20
OD
850/**
851 * Link State Subnet Management functions.
852 */
853struct ls_subnet *ls_subnet_add(struct ls_ted *ted,
854 struct ls_prefix *ls_pref)
855{
856 struct ls_subnet *new;
857 struct ls_vertex *vertex;
858 struct ls_node *node;
859 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
860
861 if (ls_pref == NULL)
862 return NULL;
863
864 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_subnet));
865 new->ls_pref = ls_pref;
866 new->key = ls_pref->pref;
b0c0b433
OD
867 new->status = NEW;
868 new->type = SUBNET;
bbd85e20
OD
869
870 /* Find Vertex */
871 vertex = ls_find_vertex_by_id(ted, ls_pref->adv);
872 if (vertex == NULL) {
873 /* Create a new temporary Node & Vertex if not found */
874 node = ls_node_new(ls_pref->adv, inaddr_any, in6addr_any);
875 vertex = ls_vertex_add(ted, node);
876 }
877 /* And attach the subnet to the corresponding Vertex */
878 new->vertex = vertex;
b0c0b433 879 listnode_add_sort_nodup(vertex->prefixes, new);
bbd85e20
OD
880
881 subnets_add(&ted->subnets, new);
882
883 return new;
884}
885
b0c0b433
OD
886struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref)
887{
888 struct ls_subnet *old;
889
890 if (pref == NULL)
891 return NULL;
892
b5894669 893 old = ls_find_subnet(ted, &pref->pref);
b0c0b433
OD
894 if (old) {
895 if (!ls_prefix_same(old->ls_pref, pref)) {
896 ls_prefix_del(old->ls_pref);
897 old->ls_pref = pref;
898 }
899 old->status = UPDATE;
900 return old;
901 }
902
903 return ls_subnet_add(ted, pref);
904}
905
906int ls_subnet_same(struct ls_subnet *s1, struct ls_subnet *s2)
907{
908 if ((s1 && !s2) || (!s1 && s2))
909 return 0;
910
911 if (!s1 && !s2)
912 return 1;
913
914 if (!prefix_same(&s1->key, &s2->key))
915 return 0;
916
917 if (s1->ls_pref == s2->ls_pref)
918 return 1;
919
920 return ls_prefix_same(s1->ls_pref, s2->ls_pref);
921}
922
bbd85e20
OD
923void ls_subnet_del(struct ls_ted *ted, struct ls_subnet *subnet)
924{
b0c0b433
OD
925 if (!ted || !subnet)
926 return;
927
928 /* First, disconnect Subnet from associated Vertex */
929 listnode_delete(subnet->vertex->prefixes, subnet);
930 /* Then delete Subnet */
bbd85e20
OD
931 subnets_del(&ted->subnets, subnet);
932 XFREE(MTYPE_LS_DB, subnet);
933}
934
b0c0b433
OD
935void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet)
936{
937 if (!ted || !subnet)
938 return;
939
940 /* First, remove associated Link State Subnet */
941 ls_prefix_del(subnet->ls_pref);
942 /* Then, delete Subnet itself */
943 ls_subnet_del(ted, subnet);
944}
945
b5894669
DS
946struct ls_subnet *ls_find_subnet(struct ls_ted *ted,
947 const struct prefix *prefix)
bbd85e20
OD
948{
949 struct ls_subnet subnet = {};
950
b5894669 951 subnet.key = *prefix;
bbd85e20
OD
952 return subnets_find(&ted->subnets, &subnet);
953}
954
955/**
956 * Link State TED management functions
957 */
958struct ls_ted *ls_ted_new(const uint32_t key, const char *name,
959 uint32_t as_number)
960{
961 struct ls_ted *new;
962
963 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_ted));
bbd85e20
OD
964
965 /* Set basic information for this ted */
966 new->key = key;
967 new->as_number = as_number;
968 strlcpy(new->name, name, MAX_NAME_LENGTH);
969
970 /* Initialize the various RB tree */
971 vertices_init(&new->vertices);
972 edges_init(&new->edges);
973 subnets_init(&new->subnets);
974
975 return new;
976}
977
978void ls_ted_del(struct ls_ted *ted)
979{
980 if (ted == NULL)
981 return;
982
b0c0b433
OD
983 /* Check that TED is empty */
984 if (vertices_count(&ted->vertices) || edges_count(&ted->edges)
985 || subnets_count(&ted->subnets))
986 return;
987
bbd85e20
OD
988 /* Release RB Tree */
989 vertices_fini(&ted->vertices);
990 edges_fini(&ted->edges);
991 subnets_fini(&ted->subnets);
992
993 XFREE(MTYPE_LS_DB, ted);
bbd85e20
OD
994}
995
aa5ced0a 996void ls_ted_del_all(struct ls_ted **ted)
b0c0b433
OD
997{
998 struct ls_vertex *vertex;
999 struct ls_edge *edge;
1000 struct ls_subnet *subnet;
1001
aa5ced0a 1002 if (*ted == NULL)
b0c0b433
OD
1003 return;
1004
1005 /* First remove Vertices, Edges and Subnets and associated Link State */
aa5ced0a
DS
1006 frr_each_safe (vertices, &(*ted)->vertices, vertex)
1007 ls_vertex_del_all(*ted, vertex);
1008 frr_each_safe (edges, &(*ted)->edges, edge)
1009 ls_edge_del_all(*ted, edge);
1010 frr_each_safe (subnets, &(*ted)->subnets, subnet)
1011 ls_subnet_del_all(*ted, subnet);
b0c0b433
OD
1012
1013 /* then remove TED itself */
aa5ced0a
DS
1014 ls_ted_del(*ted);
1015 *ted = NULL;
b0c0b433
OD
1016}
1017
1018void ls_ted_clean(struct ls_ted *ted)
1019{
1020 struct ls_vertex *vertex;
1021 struct ls_edge *edge;
1022 struct ls_subnet *subnet;
1023
1024 if (ted == NULL)
1025 return;
1026
1027 /* First, start with Vertices */
bb0e6880 1028 frr_each_safe (vertices, &ted->vertices, vertex)
b0c0b433
OD
1029 if (vertex->status == ORPHAN)
1030 ls_vertex_del_all(ted, vertex);
1031
1032 /* Then Edges */
bb0e6880 1033 frr_each_safe (edges, &ted->edges, edge)
b0c0b433
OD
1034 if (edge->status == ORPHAN)
1035 ls_edge_del_all(ted, edge);
1036
1037 /* and Subnets */
bb0e6880 1038 frr_each_safe (subnets, &ted->subnets, subnet)
b0c0b433
OD
1039 if (subnet->status == ORPHAN)
1040 ls_subnet_del_all(ted, subnet);
1041
1042}
1043
bbd85e20
OD
1044void ls_connect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
1045{
1046 if (vertex == NULL || edge == NULL)
1047 return;
1048
1049 if (source) {
b0c0b433 1050 listnode_add_sort_nodup(vertex->outgoing_edges, edge);
bbd85e20
OD
1051 edge->source = vertex;
1052 } else {
b0c0b433 1053 listnode_add_sort_nodup(vertex->incoming_edges, edge);
bbd85e20
OD
1054 edge->destination = vertex;
1055 }
1056}
1057
1058void ls_disconnect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
1059{
1060
1061 if (vertex == NULL || edge == NULL)
1062 return;
1063
1064 if (source) {
1065 listnode_delete(vertex->outgoing_edges, edge);
1066 edge->source = NULL;
1067 } else {
1068 listnode_delete(vertex->incoming_edges, edge);
1069 edge->destination = NULL;
1070 }
1071}
1072
1073void ls_connect_vertices(struct ls_vertex *src, struct ls_vertex *dst,
1074 struct ls_edge *edge)
1075{
1076 if (edge == NULL)
1077 return;
1078
1079 edge->source = src;
1080 edge->destination = dst;
1081
1082 if (src != NULL)
b0c0b433 1083 listnode_add_sort_nodup(src->outgoing_edges, edge);
bbd85e20
OD
1084
1085 if (dst != NULL)
b0c0b433 1086 listnode_add_sort_nodup(dst->incoming_edges, edge);
bbd85e20
OD
1087}
1088
1089void ls_disconnect_edge(struct ls_edge *edge)
1090{
1091 if (edge == NULL)
1092 return;
1093
1094 ls_disconnect(edge->source, edge, true);
1095 ls_disconnect(edge->destination, edge, false);
b0c0b433
OD
1096
1097 /* Mark this Edge as ORPHAN for future cleanup */
1098 edge->status = ORPHAN;
bbd85e20
OD
1099}
1100
1101/**
1102 * Link State Message management functions
1103 */
1104
b0c0b433
OD
1105int ls_register(struct zclient *zclient, bool server)
1106{
1107 int rc;
1108
1109 if (server)
1110 rc = zclient_register_opaque(zclient, LINK_STATE_SYNC);
1111 else
1112 rc = zclient_register_opaque(zclient, LINK_STATE_UPDATE);
1113
1114 return rc;
1115}
1116
1117int ls_unregister(struct zclient *zclient, bool server)
1118{
1119 int rc;
1120
1121 if (server)
1122 rc = zclient_unregister_opaque(zclient, LINK_STATE_SYNC);
1123 else
1124 rc = zclient_unregister_opaque(zclient, LINK_STATE_UPDATE);
1125
1126 return rc;
1127}
1128
1129int ls_request_sync(struct zclient *zclient)
1130{
1131 struct stream *s;
1132 uint16_t flags = 0;
1133
1134 /* Check buffer size */
1135 if (STREAM_SIZE(zclient->obuf)
1136 < (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t)))
1137 return -1;
1138
1139 s = zclient->obuf;
1140 stream_reset(s);
1141
1142 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
1143
1144 /* Set type and flags */
1145 stream_putl(s, LINK_STATE_SYNC);
1146 stream_putw(s, flags);
1147 /* Send destination client info */
1148 stream_putc(s, zclient->redist_default);
1149 stream_putw(s, zclient->instance);
1150 stream_putl(s, zclient->session_id);
1151
1152 /* Put length into the header at the start of the stream. */
1153 stream_putw_at(s, 0, stream_get_endp(s));
1154
1155 return zclient_send_message(zclient);
1156}
1157
bbd85e20
OD
1158static struct ls_node *ls_parse_node(struct stream *s)
1159{
1160 struct ls_node *node;
1161 size_t len;
1162
1163 node = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
bbd85e20
OD
1164
1165 STREAM_GET(&node->adv, s, sizeof(struct ls_node_id));
1166 STREAM_GETW(s, node->flags);
1167 if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
1168 STREAM_GETC(s, len);
1169 STREAM_GET(node->name, s, len);
1170 }
1171 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
1172 node->router_id.s_addr = stream_get_ipv4(s);
1173 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
8693b4d6 1174 STREAM_GET(&node->router_id6, s, IPV6_MAX_BYTELEN);
bbd85e20
OD
1175 if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
1176 STREAM_GETC(s, node->node_flag);
1177 if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
1178 STREAM_GETC(s, node->type);
1179 if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
1180 STREAM_GETL(s, node->as_number);
1181 if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
1182 STREAM_GETL(s, node->srgb.lower_bound);
1183 STREAM_GETL(s, node->srgb.range_size);
1184 STREAM_GETC(s, node->srgb.flag);
1185 STREAM_GET(node->algo, s, 2);
1186 }
1187 if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
1188 STREAM_GETL(s, node->srlb.lower_bound);
1189 STREAM_GETL(s, node->srlb.range_size);
1190 }
1191 if (CHECK_FLAG(node->flags, LS_NODE_MSD))
1192 STREAM_GETC(s, node->msd);
1193
1194 return node;
1195
1196stream_failure:
1197 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__);
1198 XFREE(MTYPE_LS_DB, node);
1199 return NULL;
1200}
1201
1202static struct ls_attributes *ls_parse_attributes(struct stream *s)
1203{
1204 struct ls_attributes *attr;
bd0581e4
LS
1205 uint8_t nb_ext_adm_grp;
1206 uint32_t bitmap_data;
bbd85e20
OD
1207 size_t len;
1208
1209 attr = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
bd0581e4 1210 admin_group_init(&attr->ext_admin_group);
bbd85e20
OD
1211 attr->srlgs = NULL;
1212
1213 STREAM_GET(&attr->adv, s, sizeof(struct ls_node_id));
1214 STREAM_GETL(s, attr->flags);
1215 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
1216 STREAM_GETC(s, len);
1217 STREAM_GET(attr->name, s, len);
1218 }
1219 if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
b0c0b433 1220 STREAM_GETL(s, attr->metric);
bbd85e20
OD
1221 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
1222 STREAM_GETL(s, attr->standard.te_metric);
1223 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
1224 STREAM_GETL(s, attr->standard.admin_group);
bd0581e4
LS
1225 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
1226 /* Extended Administrative Group */
1227 STREAM_GETC(s, nb_ext_adm_grp);
1228 for (size_t i = 0; i < nb_ext_adm_grp; i++) {
1229 STREAM_GETL(s, bitmap_data);
1230 admin_group_bulk_set(&attr->ext_admin_group,
1231 bitmap_data, i);
1232 }
1233 }
bbd85e20
OD
1234 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1235 attr->standard.local.s_addr = stream_get_ipv4(s);
1236 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
1237 attr->standard.remote.s_addr = stream_get_ipv4(s);
1238 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1239 STREAM_GET(&attr->standard.local6, s, IPV6_MAX_BYTELEN);
1240 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
1241 STREAM_GET(&attr->standard.remote6, s, IPV6_MAX_BYTELEN);
1242 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
1243 STREAM_GETL(s, attr->standard.local_id);
1244 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
1245 STREAM_GETL(s, attr->standard.remote_id);
1246 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
1247 STREAM_GETF(s, attr->standard.max_bw);
1248 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
1249 STREAM_GETF(s, attr->standard.max_rsv_bw);
1250 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
1251 for (len = 0; len < MAX_CLASS_TYPE; len++)
1252 STREAM_GETF(s, attr->standard.unrsv_bw[len]);
1253 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
1254 STREAM_GETL(s, attr->standard.remote_as);
1255 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
1256 attr->standard.remote_addr.s_addr = stream_get_ipv4(s);
1257 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
1258 STREAM_GET(&attr->standard.remote_addr6, s, IPV6_MAX_BYTELEN);
1259 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
1260 STREAM_GETL(s, attr->extended.delay);
1261 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
1262 STREAM_GETL(s, attr->extended.min_delay);
1263 STREAM_GETL(s, attr->extended.max_delay);
1264 }
1265 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
1266 STREAM_GETL(s, attr->extended.jitter);
1267 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
1268 STREAM_GETL(s, attr->extended.pkt_loss);
1269 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
1270 STREAM_GETF(s, attr->extended.ava_bw);
1271 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
1272 STREAM_GETF(s, attr->extended.rsv_bw);
1273 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
1274 STREAM_GETF(s, attr->extended.used_bw);
1275 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
8693b4d6
OD
1276 STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
1277 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
1278 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
1279 attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr =
1280 stream_get_ipv4(s);
bbd85e20
OD
1281 }
1282 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
8693b4d6
OD
1283 STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
1284 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
1285 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
1286 attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr =
1287 stream_get_ipv4(s);
1288 }
1289 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
1290 STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
1291 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
1292 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
1293 STREAM_GET(attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid, s,
1294 ISO_SYS_ID_LEN);
1295 }
1296 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
1297 STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
1298 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
1299 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
1300 STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s,
1301 ISO_SYS_ID_LEN);
bbd85e20
OD
1302 }
1303 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
1304 STREAM_GETC(s, len);
1305 attr->srlgs = XCALLOC(MTYPE_LS_DB, len*sizeof(uint32_t));
1306 attr->srlg_len = len;
1307 for (len = 0; len < attr->srlg_len; len++)
1308 STREAM_GETL(s, attr->srlgs[len]);
1309 }
1310
1311 return attr;
1312
1313stream_failure:
1314 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1315 __func__);
b0c0b433 1316 /* Clean memory allocation */
bbd85e20
OD
1317 if (attr->srlgs != NULL)
1318 XFREE(MTYPE_LS_DB, attr->srlgs);
1319 XFREE(MTYPE_LS_DB, attr);
1320 return NULL;
1321
1322}
1323
1324static struct ls_prefix *ls_parse_prefix(struct stream *s)
1325{
1326 struct ls_prefix *ls_pref;
1327 size_t len;
1328
1329 ls_pref = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
bbd85e20
OD
1330
1331 STREAM_GET(&ls_pref->adv, s, sizeof(struct ls_node_id));
1332 STREAM_GETW(s, ls_pref->flags);
1333 STREAM_GETC(s, ls_pref->pref.family);
1334 STREAM_GETW(s, ls_pref->pref.prefixlen);
1335 len = prefix_blen(&ls_pref->pref);
1336 STREAM_GET(&ls_pref->pref.u.prefix, s, len);
1337 if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
1338 STREAM_GETC(s, ls_pref->igp_flag);
1339 if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
1340 STREAM_GETL(s, ls_pref->route_tag);
1341 if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
1342 STREAM_GETQ(s, ls_pref->extended_tag);
1343 if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1344 STREAM_GETL(s, ls_pref->metric);
1345 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
1346 STREAM_GETL(s, ls_pref->sr.sid);
1347 STREAM_GETC(s, ls_pref->sr.sid_flag);
1348 STREAM_GETC(s, ls_pref->sr.algo);
1349 }
1350
1351 return ls_pref;
1352
1353stream_failure:
1354 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__);
1355 XFREE(MTYPE_LS_DB, ls_pref);
1356 return NULL;
1357}
1358
1359struct ls_message *ls_parse_msg(struct stream *s)
1360{
1361 struct ls_message *msg;
1362
1363 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
bbd85e20
OD
1364
1365 /* Read LS Message header */
1366 STREAM_GETC(s, msg->event);
1367 STREAM_GETC(s, msg->type);
bbd85e20
OD
1368
1369 /* Read Message Payload */
1370 switch (msg->type) {
1371 case LS_MSG_TYPE_NODE:
1372 msg->data.node = ls_parse_node(s);
1373 break;
1374 case LS_MSG_TYPE_ATTRIBUTES:
9bf9bd1a 1375 STREAM_GET(&msg->remote_id, s, sizeof(struct ls_node_id));
bbd85e20
OD
1376 msg->data.attr = ls_parse_attributes(s);
1377 break;
1378 case LS_MSG_TYPE_PREFIX:
1379 msg->data.prefix = ls_parse_prefix(s);
1380 break;
1381 default:
1382 zlog_err("Unsupported Payload");
1383 goto stream_failure;
1384 }
1385
1386 if (msg->data.node == NULL || msg->data.attr == NULL
1387 || msg->data.prefix == NULL)
1388 goto stream_failure;
1389
1390 return msg;
1391
1392stream_failure:
1393 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__);
1394 XFREE(MTYPE_LS_DB, msg);
1395 return NULL;
1396}
1397
1398static int ls_format_node(struct stream *s, struct ls_node *node)
1399{
1400 size_t len;
1401
1402 /* Push Advertise node information first */
1403 stream_put(s, &node->adv, sizeof(struct ls_node_id));
1404
1405 /* Push Flags & Origin then Node information if there are present */
1406 stream_putw(s, node->flags);
1407 if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
1408 len = strlen(node->name);
1409 stream_putc(s, len + 1);
1410 stream_put(s, node->name, len);
1411 stream_putc(s, '\0');
1412 }
1413 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
1414 stream_put_ipv4(s, node->router_id.s_addr);
1415 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
8693b4d6 1416 stream_put(s, &node->router_id6, IPV6_MAX_BYTELEN);
bbd85e20
OD
1417 if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
1418 stream_putc(s, node->node_flag);
1419 if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
1420 stream_putc(s, node->type);
1421 if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
1422 stream_putl(s, node->as_number);
1423 if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
1424 stream_putl(s, node->srgb.lower_bound);
1425 stream_putl(s, node->srgb.range_size);
1426 stream_putc(s, node->srgb.flag);
1427 stream_put(s, node->algo, 2);
1428 }
1429 if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
1430 stream_putl(s, node->srlb.lower_bound);
1431 stream_putl(s, node->srlb.range_size);
1432 }
1433 if (CHECK_FLAG(node->flags, LS_NODE_MSD))
1434 stream_putc(s, node->msd);
1435
1436 return 0;
1437}
1438
1439static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
1440{
bd0581e4 1441 size_t len, nb_ext_adm_grp;
bbd85e20
OD
1442
1443 /* Push Advertise node information first */
1444 stream_put(s, &attr->adv, sizeof(struct ls_node_id));
1445
1446 /* Push Flags & Origin then LS attributes if there are present */
1447 stream_putl(s, attr->flags);
1448 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
1449 len = strlen(attr->name);
1450 stream_putc(s, len + 1);
1451 stream_put(s, attr->name, len);
1452 stream_putc(s, '\0');
1453 }
1454 if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
b0c0b433 1455 stream_putl(s, attr->metric);
bbd85e20
OD
1456 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
1457 stream_putl(s, attr->standard.te_metric);
1458 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
1459 stream_putl(s, attr->standard.admin_group);
bd0581e4
LS
1460 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
1461 /* Extended Administrative Group */
1462 nb_ext_adm_grp = admin_group_nb_words(&attr->ext_admin_group);
1463 stream_putc(s, nb_ext_adm_grp);
1464 for (size_t i = 0; i < nb_ext_adm_grp; i++)
1465 stream_putl(s, admin_group_get_offset(
1466 &attr->ext_admin_group, i));
1467 }
bbd85e20
OD
1468 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1469 stream_put_ipv4(s, attr->standard.local.s_addr);
1470 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
1471 stream_put_ipv4(s, attr->standard.remote.s_addr);
1472 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1473 stream_put(s, &attr->standard.local6, IPV6_MAX_BYTELEN);
1474 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
1475 stream_put(s, &attr->standard.remote6, IPV6_MAX_BYTELEN);
1476 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
1477 stream_putl(s, attr->standard.local_id);
1478 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
1479 stream_putl(s, attr->standard.remote_id);
1480 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
1481 stream_putf(s, attr->standard.max_bw);
1482 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
1483 stream_putf(s, attr->standard.max_rsv_bw);
1484 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
1485 for (len = 0; len < MAX_CLASS_TYPE; len++)
1486 stream_putf(s, attr->standard.unrsv_bw[len]);
1487 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
1488 stream_putl(s, attr->standard.remote_as);
1489 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
1490 stream_put_ipv4(s, attr->standard.remote_addr.s_addr);
1491 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
1492 stream_put(s, &attr->standard.remote_addr6, IPV6_MAX_BYTELEN);
1493 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
1494 stream_putl(s, attr->extended.delay);
1495 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
1496 stream_putl(s, attr->extended.min_delay);
1497 stream_putl(s, attr->extended.max_delay);
1498 }
1499 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
1500 stream_putl(s, attr->extended.jitter);
1501 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
1502 stream_putl(s, attr->extended.pkt_loss);
1503 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
1504 stream_putf(s, attr->extended.ava_bw);
1505 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
1506 stream_putf(s, attr->extended.rsv_bw);
1507 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
1508 stream_putf(s, attr->extended.used_bw);
1509 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
8693b4d6
OD
1510 stream_putl(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
1511 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
1512 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
1513 stream_put_ipv4(
1514 s, attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr);
bbd85e20
OD
1515 }
1516 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
8693b4d6
OD
1517 stream_putl(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
1518 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
1519 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
1520 stream_put_ipv4(
1521 s, attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr);
1522 }
1523 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
1524 stream_putl(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
1525 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
1526 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
1527 stream_put(s, attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid,
1528 ISO_SYS_ID_LEN);
1529 }
1530 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
1531 stream_putl(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
1532 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
1533 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
1534 stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid,
1535 ISO_SYS_ID_LEN);
bbd85e20
OD
1536 }
1537 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
1538 stream_putc(s, attr->srlg_len);
1539 for (len = 0; len < attr->srlg_len; len++)
1540 stream_putl(s, attr->srlgs[len]);
1541 }
1542
1543 return 0;
1544}
1545
1546static int ls_format_prefix(struct stream *s, struct ls_prefix *ls_pref)
1547{
1548 size_t len;
1549
1550 /* Push Advertise node information first */
1551 stream_put(s, &ls_pref->adv, sizeof(struct ls_node_id));
1552
1553 /* Push Flags, Origin & Prefix then information if there are present */
1554 stream_putw(s, ls_pref->flags);
1555 stream_putc(s, ls_pref->pref.family);
1556 stream_putw(s, ls_pref->pref.prefixlen);
1557 len = prefix_blen(&ls_pref->pref);
1558 stream_put(s, &ls_pref->pref.u.prefix, len);
1559 if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
1560 stream_putc(s, ls_pref->igp_flag);
1561 if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
1562 stream_putl(s, ls_pref->route_tag);
1563 if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
1564 stream_putq(s, ls_pref->extended_tag);
1565 if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1566 stream_putl(s, ls_pref->metric);
1567 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
1568 stream_putl(s, ls_pref->sr.sid);
1569 stream_putc(s, ls_pref->sr.sid_flag);
1570 stream_putc(s, ls_pref->sr.algo);
1571 }
1572
1573 return 0;
1574}
1575
1576static int ls_format_msg(struct stream *s, struct ls_message *msg)
1577{
1578
1579 /* Prepare Link State header */
1580 stream_putc(s, msg->event);
1581 stream_putc(s, msg->type);
bbd85e20
OD
1582
1583 /* Add Message Payload */
1584 switch (msg->type) {
1585 case LS_MSG_TYPE_NODE:
1586 return ls_format_node(s, msg->data.node);
1587 case LS_MSG_TYPE_ATTRIBUTES:
9bf9bd1a
OD
1588 /* Add remote node first */
1589 stream_put(s, &msg->remote_id, sizeof(struct ls_node_id));
bbd85e20
OD
1590 return ls_format_attributes(s, msg->data.attr);
1591 case LS_MSG_TYPE_PREFIX:
1592 return ls_format_prefix(s, msg->data.prefix);
1593 default:
1594 zlog_warn("Unsupported Payload");
1595 break;
1596 }
1597
1598 return -1;
1599}
1600
1601int ls_send_msg(struct zclient *zclient, struct ls_message *msg,
1602 struct zapi_opaque_reg_info *dst)
1603{
1604 struct stream *s;
1605 uint16_t flags = 0;
1606
b0c0b433
OD
1607 /* Check if we have a valid message */
1608 if (msg->event == LS_MSG_EVENT_UNDEF)
1609 return -1;
1610
bbd85e20
OD
1611 /* Check buffer size */
1612 if (STREAM_SIZE(zclient->obuf) <
1613 (ZEBRA_HEADER_SIZE + sizeof(uint32_t) + sizeof(msg)))
1614 return -1;
1615
1616 s = zclient->obuf;
1617 stream_reset(s);
1618
1619 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
1620
b0c0b433 1621 /* Set sub-type, flags and destination for unicast message */
bbd85e20
OD
1622 stream_putl(s, LINK_STATE_UPDATE);
1623 if (dst != NULL) {
1624 SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
1625 stream_putw(s, flags);
1626 /* Send destination client info */
1627 stream_putc(s, dst->proto);
1628 stream_putw(s, dst->instance);
1629 stream_putl(s, dst->session_id);
b0c0b433 1630 } else {
bbd85e20 1631 stream_putw(s, flags);
b0c0b433 1632 }
bbd85e20
OD
1633
1634 /* Format Link State message */
1635 if (ls_format_msg(s, msg) < 0) {
1636 stream_reset(s);
1637 return -1;
1638 }
1639
1640 /* Put length into the header at the start of the stream. */
1641 stream_putw_at(s, 0, stream_get_endp(s));
1642
1643 return zclient_send_message(zclient);
1644}
bbd85e20
OD
1645struct ls_message *ls_vertex2msg(struct ls_message *msg,
1646 struct ls_vertex *vertex)
1647{
1648 /* Allocate space if needed */
1649 if (msg == NULL)
1650 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1651 else
1652 memset(msg, 0, sizeof(*msg));
1653
1654 msg->type = LS_MSG_TYPE_NODE;
b0c0b433
OD
1655 switch (vertex->status) {
1656 case NEW:
1657 msg->event = LS_MSG_EVENT_ADD;
1658 break;
1659 case UPDATE:
1660 msg->event = LS_MSG_EVENT_UPDATE;
1661 break;
1662 case DELETE:
1663 msg->event = LS_MSG_EVENT_DELETE;
1664 break;
1665 case SYNC:
1666 msg->event = LS_MSG_EVENT_SYNC;
1667 break;
bde30e78
DS
1668 case UNSET:
1669 case ORPHAN:
b0c0b433
OD
1670 msg->event = LS_MSG_EVENT_UNDEF;
1671 break;
1672 }
bbd85e20 1673 msg->data.node = vertex->node;
b0c0b433 1674 msg->remote_id.origin = UNKNOWN;
bbd85e20
OD
1675
1676 return msg;
1677}
1678
1679struct ls_message *ls_edge2msg(struct ls_message *msg, struct ls_edge *edge)
1680{
1681 /* Allocate space if needed */
1682 if (msg == NULL)
1683 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1684 else
1685 memset(msg, 0, sizeof(*msg));
1686
1687 msg->type = LS_MSG_TYPE_ATTRIBUTES;
b0c0b433
OD
1688 switch (edge->status) {
1689 case NEW:
1690 msg->event = LS_MSG_EVENT_ADD;
1691 break;
1692 case UPDATE:
1693 msg->event = LS_MSG_EVENT_UPDATE;
1694 break;
1695 case DELETE:
1696 msg->event = LS_MSG_EVENT_DELETE;
1697 break;
1698 case SYNC:
1699 msg->event = LS_MSG_EVENT_SYNC;
1700 break;
bde30e78
DS
1701 case UNSET:
1702 case ORPHAN:
b0c0b433
OD
1703 msg->event = LS_MSG_EVENT_UNDEF;
1704 break;
1705 }
bbd85e20
OD
1706 msg->data.attr = edge->attributes;
1707 if (edge->destination != NULL)
1708 msg->remote_id = edge->destination->node->adv;
1709 else
b0c0b433 1710 msg->remote_id.origin = UNKNOWN;
bbd85e20
OD
1711
1712 return msg;
1713}
1714
1715struct ls_message *ls_subnet2msg(struct ls_message *msg,
1716 struct ls_subnet *subnet)
1717{
1718 /* Allocate space if needed */
1719 if (msg == NULL)
1720 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1721 else
1722 memset(msg, 0, sizeof(*msg));
1723
1724 msg->type = LS_MSG_TYPE_PREFIX;
b0c0b433
OD
1725 switch (subnet->status) {
1726 case NEW:
1727 msg->event = LS_MSG_EVENT_ADD;
1728 break;
1729 case UPDATE:
1730 msg->event = LS_MSG_EVENT_UPDATE;
1731 break;
1732 case DELETE:
1733 msg->event = LS_MSG_EVENT_DELETE;
1734 break;
1735 case SYNC:
1736 msg->event = LS_MSG_EVENT_SYNC;
1737 break;
bde30e78
DS
1738 case UNSET:
1739 case ORPHAN:
b0c0b433
OD
1740 msg->event = LS_MSG_EVENT_UNDEF;
1741 break;
1742 }
bbd85e20 1743 msg->data.prefix = subnet->ls_pref;
b0c0b433 1744 msg->remote_id.origin = UNKNOWN;
bbd85e20
OD
1745
1746 return msg;
1747}
1748
b0c0b433
OD
1749struct ls_vertex *ls_msg2vertex(struct ls_ted *ted, struct ls_message *msg,
1750 bool delete)
bbd85e20 1751{
b0c0b433
OD
1752 struct ls_node *node = (struct ls_node *)msg->data.node;
1753 struct ls_vertex *vertex = NULL;
1754
1755 switch (msg->event) {
1756 case LS_MSG_EVENT_SYNC:
1757 vertex = ls_vertex_add(ted, node);
1758 if (vertex)
1759 vertex->status = SYNC;
1760 break;
1761 case LS_MSG_EVENT_ADD:
1762 vertex = ls_vertex_add(ted, node);
1763 if (vertex)
1764 vertex->status = NEW;
1765 break;
1766 case LS_MSG_EVENT_UPDATE:
1767 vertex = ls_vertex_update(ted, node);
1768 if (vertex)
1769 vertex->status = UPDATE;
1770 break;
1771 case LS_MSG_EVENT_DELETE:
1772 vertex = ls_find_vertex_by_id(ted, node->adv);
1773 if (vertex) {
1774 if (delete)
1775 ls_vertex_del_all(ted, vertex);
1776 else
1777 vertex->status = DELETE;
1778 }
1779 break;
1780 default:
1781 vertex = NULL;
1782 break;
1783 }
1784
1785 return vertex;
1786}
1787
1788struct ls_edge *ls_msg2edge(struct ls_ted *ted, struct ls_message *msg,
1789 bool delete)
1790{
1791 struct ls_attributes *attr = (struct ls_attributes *)msg->data.attr;
1792 struct ls_edge *edge = NULL;
1793
1794 switch (msg->event) {
1795 case LS_MSG_EVENT_SYNC:
1796 edge = ls_edge_add(ted, attr);
1797 if (edge)
1798 edge->status = SYNC;
1799 break;
1800 case LS_MSG_EVENT_ADD:
1801 edge = ls_edge_add(ted, attr);
1802 if (edge)
1803 edge->status = NEW;
1804 break;
1805 case LS_MSG_EVENT_UPDATE:
1806 edge = ls_edge_update(ted, attr);
1807 if (edge)
1808 edge->status = UPDATE;
1809 break;
1810 case LS_MSG_EVENT_DELETE:
1811 edge = ls_find_edge_by_source(ted, attr);
1812 if (edge) {
43a8e0ac 1813 if (delete) {
b0c0b433 1814 ls_edge_del_all(ted, edge);
43a8e0ac
DS
1815 edge = NULL;
1816 } else
b0c0b433
OD
1817 edge->status = DELETE;
1818 }
1819 break;
1820 default:
1821 edge = NULL;
1822 break;
1823 }
1824
1825 return edge;
1826}
1827
1828struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg,
1829 bool delete)
1830{
1831 struct ls_prefix *pref = (struct ls_prefix *)msg->data.prefix;
1832 struct ls_subnet *subnet = NULL;
1833
1834 switch (msg->event) {
1835 case LS_MSG_EVENT_SYNC:
1836 subnet = ls_subnet_add(ted, pref);
1837 if (subnet)
1838 subnet->status = SYNC;
1839 break;
1840 case LS_MSG_EVENT_ADD:
1841 subnet = ls_subnet_add(ted, pref);
1842 if (subnet)
1843 subnet->status = NEW;
1844 break;
1845 case LS_MSG_EVENT_UPDATE:
1846 subnet = ls_subnet_update(ted, pref);
1847 if (subnet)
1848 subnet->status = UPDATE;
1849 break;
1850 case LS_MSG_EVENT_DELETE:
b5894669 1851 subnet = ls_find_subnet(ted, &pref->pref);
b0c0b433
OD
1852 if (subnet) {
1853 if (delete)
1854 ls_subnet_del_all(ted, subnet);
1855 else
1856 subnet->status = DELETE;
1857 }
1858 break;
1859 default:
1860 subnet = NULL;
1861 break;
1862 }
1863
1864 return subnet;
1865}
1866
1867struct ls_element *ls_msg2ted(struct ls_ted *ted, struct ls_message *msg,
1868 bool delete)
1869{
1870 struct ls_element *lse = NULL;
bbd85e20
OD
1871
1872 switch (msg->type) {
1873 case LS_MSG_TYPE_NODE:
b0c0b433 1874 lse = (struct ls_element *)ls_msg2vertex(ted, msg, delete);
bbd85e20
OD
1875 break;
1876 case LS_MSG_TYPE_ATTRIBUTES:
b0c0b433 1877 lse = (struct ls_element *)ls_msg2edge(ted, msg, delete);
bbd85e20
OD
1878 break;
1879 case LS_MSG_TYPE_PREFIX:
b0c0b433 1880 lse = (struct ls_element *)ls_msg2subnet(ted, msg, delete);
bbd85e20
OD
1881 break;
1882 default:
b0c0b433 1883 lse = NULL;
bbd85e20
OD
1884 break;
1885 }
1886
b0c0b433
OD
1887 return lse;
1888}
1889
1890struct ls_element *ls_stream2ted(struct ls_ted *ted, struct stream *s,
1891 bool delete)
1892{
1893 struct ls_message *msg;
1894 struct ls_element *lse = NULL;
1895
1896 msg = ls_parse_msg(s);
1897 if (msg) {
1898 lse = ls_msg2ted(ted, msg, delete);
1899 ls_delete_msg(msg);
1900 }
1901
1902 return lse;
1903}
1904
1905void ls_delete_msg(struct ls_message *msg)
1906{
1907 if (msg == NULL)
1908 return;
1909
bbd85e20
OD
1910 XFREE(MTYPE_LS_DB, msg);
1911}
1912
1913int ls_sync_ted(struct ls_ted *ted, struct zclient *zclient,
1914 struct zapi_opaque_reg_info *dst)
1915{
1916 struct ls_vertex *vertex;
1917 struct ls_edge *edge;
1918 struct ls_subnet *subnet;
1919 struct ls_message msg;
1920
bbd85e20
OD
1921 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1922 frr_each(vertices, &ted->vertices, vertex) {
1923 ls_vertex2msg(&msg, vertex);
1924 ls_send_msg(zclient, &msg, dst);
1925 }
1926 frr_each(edges, &ted->edges, edge) {
1927 ls_edge2msg(&msg, edge);
1928 ls_send_msg(zclient, &msg, dst);
1929 }
1930 frr_each(subnets, &ted->subnets, subnet) {
1931 ls_subnet2msg(&msg, subnet);
1932 ls_send_msg(zclient, &msg, dst);
1933 }
1934 return 0;
1935}
1936
b0c0b433
OD
1937/**
1938 * Link State Show functions
1939 */
1940static const char *const origin2txt[] = {
1941 "Unknown",
1942 "ISIS_L1",
1943 "ISIS_L2",
1944 "OSPFv2",
1945 "Direct",
1946 "Static"
1947};
1948
1949static const char *const type2txt[] = {
1950 "Unknown",
1951 "Standard",
1952 "ABR",
1953 "ASBR",
1954 "Remote ASBR",
1955 "Pseudo"
1956};
1957
1958static const char *const status2txt[] = {
1959 "Unknown",
1960 "New",
1961 "Update",
1962 "Delete",
1963 "Sync",
1964 "Orphan"
1965};
1966
1967static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str,
1968 size_t size)
1969{
7f9ab3b0
OD
1970 if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2)
1971 snprintfrr(str, size, "%pSY", lnid.id.iso.sys_id);
1972 else
b0c0b433
OD
1973 snprintfrr(str, size, "%pI4", &lnid.id.ip.addr);
1974
1975 return str;
1976}
1977
1978static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
1979 bool verbose)
1980{
1981 struct listnode *node;
1982 struct ls_node *lsn;
1983 struct ls_edge *edge;
8693b4d6 1984 struct ls_attributes *attr;
b0c0b433
OD
1985 struct ls_subnet *subnet;
1986 struct sbuf sbuf;
1987 uint32_t upper;
1988
1989 /* Sanity Check */
1990 if (!vertex)
1991 return;
1992
1993 lsn = vertex->node;
1994
1995 sbuf_init(&sbuf, NULL, 0);
1996
1997 sbuf_push(&sbuf, 2, "Vertex (%" PRIu64 "): %s", vertex->key, lsn->name);
1998 sbuf_push(&sbuf, 0, "\tRouter Id: %pI4", &lsn->router_id);
1999 sbuf_push(&sbuf, 0, "\tOrigin: %s", origin2txt[lsn->adv.origin]);
2000 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[vertex->status]);
2001 if (!verbose) {
2002 sbuf_push(
2003 &sbuf, 0,
2004 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
2005 listcount(vertex->outgoing_edges),
2006 listcount(vertex->incoming_edges),
2007 listcount(vertex->prefixes));
2008 goto end;
2009 }
2010
2011 if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
2012 sbuf_push(&sbuf, 4, "Type: %s\n", type2txt[lsn->type]);
2013 if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
2014 sbuf_push(&sbuf, 4, "AS number: %u\n", lsn->as_number);
2015 if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
2016 sbuf_push(&sbuf, 4, "Segment Routing Capabilities:\n");
2017 upper = lsn->srgb.lower_bound + lsn->srgb.range_size - 1;
2018 sbuf_push(&sbuf, 8, "SRGB: [%d/%d]", lsn->srgb.lower_bound,
2019 upper);
2020 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
2021 upper = lsn->srlb.lower_bound + lsn->srlb.range_size
2022 - 1;
2023 sbuf_push(&sbuf, 0, "\tSRLB: [%d/%d]",
2024 lsn->srlb.lower_bound, upper);
2025 }
2026 sbuf_push(&sbuf, 0, "\tAlgo: ");
2027 for (int i = 0; i < 2; i++) {
2028 if (lsn->algo[i] == 255)
2029 continue;
2030
2031 sbuf_push(&sbuf, 0,
2032 lsn->algo[i] == 0 ? "SPF " : "S-SPF ");
2033 }
2034 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
2035 sbuf_push(&sbuf, 0, "\tMSD: %d", lsn->msd);
2036 sbuf_push(&sbuf, 0, "\n");
2037 }
2038
2039 sbuf_push(&sbuf, 4, "Outgoing Edges: %d\n",
2040 listcount(vertex->outgoing_edges));
2041 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) {
2042 if (edge->destination) {
2043 lsn = edge->destination->node;
2044 sbuf_push(&sbuf, 6, "To:\t%s(%pI4)", lsn->name,
2045 &lsn->router_id);
2046 } else {
2047 sbuf_push(&sbuf, 6, "To:\t- (0.0.0.0)");
2048 }
8693b4d6
OD
2049 attr = edge->attributes;
2050 if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
2051 sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2052 &attr->standard.local,
2053 &attr->standard.remote);
2054 else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
2055 sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2056 &attr->standard.local6,
2057 &attr->standard.remote6);
b0c0b433
OD
2058 }
2059
2060 sbuf_push(&sbuf, 4, "Incoming Edges: %d\n",
2061 listcount(vertex->incoming_edges));
2062 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, node, edge)) {
2063 if (edge->source) {
2064 lsn = edge->source->node;
2065 sbuf_push(&sbuf, 6, "From:\t%s(%pI4)", lsn->name,
2066 &lsn->router_id);
2067 } else {
2068 sbuf_push(&sbuf, 6, "From:\t- (0.0.0.0)");
2069 }
8693b4d6
OD
2070 attr = edge->attributes;
2071 if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
2072 sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2073 &attr->standard.local,
2074 &attr->standard.remote);
2075 else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
2076 sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2077 &attr->standard.local6,
2078 &attr->standard.remote6);
b0c0b433
OD
2079 }
2080
2081 sbuf_push(&sbuf, 4, "Subnets: %d\n", listcount(vertex->prefixes));
2082 for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
2083 sbuf_push(&sbuf, 6, "Prefix:\t%pFX\n", &subnet->key);
2084
2085end:
2086 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2087 sbuf_free(&sbuf);
2088}
2089
2090static void ls_show_vertex_json(struct ls_vertex *vertex,
2091 struct json_object *json)
2092{
2093 struct ls_node *lsn;
2094 json_object *jsr, *jalgo, *jobj;
2095 char buf[INET6_BUFSIZ];
2096
2097 /* Sanity Check */
2098 if (!vertex)
2099 return;
2100
2101 lsn = vertex->node;
2102
2103 json_object_int_add(json, "vertex-id", vertex->key);
2104 json_object_string_add(json, "status", status2txt[vertex->status]);
2105 json_object_string_add(json, "origin", origin2txt[lsn->adv.origin]);
2106 if (CHECK_FLAG(lsn->flags, LS_NODE_NAME))
2107 json_object_string_add(json, "name", lsn->name);
2108 if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID)) {
2109 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &lsn->router_id);
2110 json_object_string_add(json, "router-id", buf);
2111 }
2112 if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID6)) {
8693b4d6 2113 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router_id6);
b0c0b433
OD
2114 json_object_string_add(json, "router-id-v6", buf);
2115 }
2116 if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
2117 json_object_string_add(json, "vertex-type",
2118 type2txt[lsn->type]);
2119 if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
2120 json_object_int_add(json, "asn", lsn->as_number);
2121 if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
2122 jsr = json_object_new_object();
2123 json_object_object_add(json, "segment-routing", jsr);
2124 json_object_int_add(jsr, "srgb-size", lsn->srgb.range_size);
2125 json_object_int_add(jsr, "srgb-lower", lsn->srgb.lower_bound);
2126 jalgo = json_object_new_array();
2127 json_object_object_add(jsr, "algorithms", jalgo);
2128 for (int i = 0; i < 2; i++) {
2129 if (lsn->algo[i] == 255)
2130 continue;
2131 jobj = json_object_new_object();
2132
2133 snprintfrr(buf, 2, "%u", i);
2134 json_object_string_add(
2135 jobj, buf, lsn->algo[i] == 0 ? "SPF" : "S-SPF");
2136 json_object_array_add(jalgo, jobj);
2137 }
2138 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
2139 json_object_int_add(jsr, "srlb-size",
2140 lsn->srlb.range_size);
2141 json_object_int_add(jsr, "srlb-lower",
2142 lsn->srlb.lower_bound);
2143 }
2144 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
2145 json_object_int_add(jsr, "msd", lsn->msd);
2146 }
2147}
2148
2149void ls_show_vertex(struct ls_vertex *vertex, struct vty *vty,
2150 struct json_object *json, bool verbose)
2151{
2152 if (json)
2153 ls_show_vertex_json(vertex, json);
2154 else if (vty)
2155 ls_show_vertex_vty(vertex, vty, verbose);
2156}
2157
2158void ls_show_vertices(struct ls_ted *ted, struct vty *vty,
2159 struct json_object *json, bool verbose)
2160{
2161 struct ls_vertex *vertex;
2162 json_object *jnodes, *jnode;
2163
2164 if (json) {
2165 jnodes = json_object_new_array();
2166 json_object_object_add(json, "vertices", jnodes);
2167 frr_each (vertices, &ted->vertices, vertex) {
2168 jnode = json_object_new_object();
2169 ls_show_vertex(vertex, NULL, jnode, verbose);
2170 json_object_array_add(jnodes, jnode);
2171 }
2172 } else if (vty) {
2173 frr_each (vertices, &ted->vertices, vertex)
2174 ls_show_vertex(vertex, vty, NULL, verbose);
2175 }
2176}
2177
2178static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
2179 bool verbose)
2180{
bd0581e4 2181 char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
b0c0b433
OD
2182 struct ls_attributes *attr;
2183 struct sbuf sbuf;
2184 char buf[INET6_BUFSIZ];
bd0581e4 2185 int indent;
b0c0b433
OD
2186
2187 attr = edge->attributes;
2188 sbuf_init(&sbuf, NULL, 0);
2189
2190 sbuf_push(&sbuf, 2, "Edge (%" PRIu64 "): ", edge->key);
2191 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
2192 sbuf_push(&sbuf, 0, "%pI4", &attr->standard.local);
2193 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
2194 sbuf_push(&sbuf, 0, "%pI6", &attr->standard.local6);
2195 else
2196 sbuf_push(&sbuf, 0, "%u/%u", attr->standard.local_id,
2197 attr->standard.remote_id);
2198 ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
2199 sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
2200 sbuf_push(&sbuf, 0, "\tMetric: %u", attr->metric);
2201 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[edge->status]);
2202
2203 if (!verbose)
2204 goto end;
2205
2206 sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[attr->adv.origin]);
2207 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
2208 sbuf_push(&sbuf, 4, "Name: %s\n", attr->name);
2209 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
2210 sbuf_push(&sbuf, 4, "TE Metric: %u\n",
2211 attr->standard.te_metric);
2212 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
2213 sbuf_push(&sbuf, 4, "Admin Group: 0x%x\n",
2214 attr->standard.admin_group);
bd0581e4
LS
2215 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP) &&
2216 admin_group_nb_words(&attr->ext_admin_group) != 0) {
2217 indent = 4;
2218 sbuf_push(&sbuf, indent, "Ext Admin Group: %s\n",
2219 admin_group_string(
2220 admin_group_buf, ADMIN_GROUP_PRINT_MAX_SIZE,
2221 indent + strlen("Ext Admin Group: "),
2222 &attr->ext_admin_group));
2223 if (admin_group_buf[0] != '\0' &&
2224 (sbuf.pos + strlen(admin_group_buf) +
2225 SBUF_DEFAULT_SIZE / 2) < sbuf.size)
2226 sbuf_push(&sbuf, indent + 2, "Bit positions: %s\n",
2227 admin_group_buf);
2228 }
b0c0b433
OD
2229 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
2230 sbuf_push(&sbuf, 4, "Local IPv4 address: %pI4\n",
2231 &attr->standard.local);
2232 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
2233 sbuf_push(&sbuf, 4, "Remote IPv4 address: %pI4\n",
2234 &attr->standard.remote);
2235 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
2236 sbuf_push(&sbuf, 4, "Local IPv6 address: %pI6\n",
2237 &attr->standard.local6);
2238 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
2239 sbuf_push(&sbuf, 4, "Remote IPv6 address: %pI6\n",
2240 &attr->standard.remote6);
2241 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
2242 sbuf_push(&sbuf, 4, "Local Identifier: %u\n",
2243 attr->standard.local_id);
2244 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
2245 sbuf_push(&sbuf, 4, "Remote Identifier: %u\n",
2246 attr->standard.remote_id);
2247 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
2248 sbuf_push(&sbuf, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2249 attr->standard.max_bw);
2250 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
2251 sbuf_push(&sbuf, 4,
2252 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2253 attr->standard.max_rsv_bw);
2254 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
2255 sbuf_push(&sbuf, 4, "Unreserved Bandwidth per Class Type\n");
2256 for (int i = 0; i < MAX_CLASS_TYPE; i += 2)
2257 sbuf_push(&sbuf, 8,
2258 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2259 i, attr->standard.unrsv_bw[i], i + 1,
2260 attr->standard.unrsv_bw[i + 1]);
2261 }
2262 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
2263 sbuf_push(&sbuf, 4, "Remote AS: %u\n",
2264 attr->standard.remote_as);
2265 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
2266 sbuf_push(&sbuf, 4, "Remote ASBR IPv4 address: %pI4\n",
2267 &attr->standard.remote_addr);
2268 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
2269 sbuf_push(&sbuf, 4, "Remote ASBR IPv6 address: %pI6\n",
2270 &attr->standard.remote_addr6);
2271 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
2272 sbuf_push(&sbuf, 4, "Average Link Delay: %d (micro-sec)\n",
2273 attr->extended.delay);
2274 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY))
2275 sbuf_push(&sbuf, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2276 attr->extended.min_delay, attr->extended.max_delay);
2277 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
2278 sbuf_push(&sbuf, 4, "Delay Variation: %d (micro-sec)\n",
2279 attr->extended.jitter);
2280 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
2281 sbuf_push(&sbuf, 4, "Link Loss: %g (%%)\n",
2282 (float)(attr->extended.pkt_loss * LOSS_PRECISION));
2283 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
2284 sbuf_push(&sbuf, 4, "Available Bandwidth: %g (Bytes/s)\n",
2285 attr->extended.ava_bw);
2286 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
2287 sbuf_push(&sbuf, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2288 attr->extended.rsv_bw);
2289 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
2290 sbuf_push(&sbuf, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2291 attr->extended.used_bw);
2292 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
8693b4d6
OD
2293 sbuf_push(&sbuf, 4, "IPv4 Adjacency-SID: %u",
2294 attr->adj_sid[ADJ_PRI_IPV4].sid);
b0c0b433 2295 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
8693b4d6
OD
2296 attr->adj_sid[ADJ_PRI_IPV4].flags,
2297 attr->adj_sid[ADJ_PRI_IPV4].weight);
b0c0b433
OD
2298 }
2299 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
8693b4d6
OD
2300 sbuf_push(&sbuf, 4, "IPv4 Bck. Adjacency-SID: %u",
2301 attr->adj_sid[ADJ_BCK_IPV4].sid);
2302 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2303 attr->adj_sid[ADJ_BCK_IPV4].flags,
2304 attr->adj_sid[ADJ_BCK_IPV4].weight);
2305 }
2306 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
2307 sbuf_push(&sbuf, 4, "IPv6 Adjacency-SID: %u",
2308 attr->adj_sid[ADJ_PRI_IPV6].sid);
b0c0b433 2309 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
8693b4d6
OD
2310 attr->adj_sid[ADJ_PRI_IPV6].flags,
2311 attr->adj_sid[ADJ_PRI_IPV6].weight);
2312 }
2313 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
2314 sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SID: %u",
2315 attr->adj_sid[ADJ_BCK_IPV6].sid);
2316 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2317 attr->adj_sid[ADJ_BCK_IPV6].flags,
2318 attr->adj_sid[ADJ_BCK_IPV6].weight);
b0c0b433
OD
2319 }
2320 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
2321 sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
2322 for (int i = 1; i < attr->srlg_len; i++) {
2323 if (i % 8)
2324 sbuf_push(&sbuf, 8, "\n%u", attr->srlgs[i]);
2325 else
2326 sbuf_push(&sbuf, 8, ", %u", attr->srlgs[i]);
2327 }
2328 sbuf_push(&sbuf, 0, "\n");
2329 }
2330
2331end:
2332 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2333 sbuf_free(&sbuf);
2334}
2335
2336static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
2337{
2338 struct ls_attributes *attr;
bd0581e4
LS
2339 struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg, *js_ext_ag,
2340 *js_ext_ag_arr_word,
2341 *js_ext_ag_arr_bit;
b0c0b433 2342 char buf[INET6_BUFSIZ];
bd0581e4
LS
2343 char buf_ag[strlen("0xffffffff") + 1];
2344 uint32_t bitmap;
2345 size_t i;
b0c0b433
OD
2346
2347 attr = edge->attributes;
2348
2349 json_object_int_add(json, "edge-id", edge->key);
2350 json_object_string_add(json, "status", status2txt[edge->status]);
2351 json_object_string_add(json, "origin", origin2txt[attr->adv.origin]);
2352 ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
2353 json_object_string_add(json, "advertised-router", buf);
2354 if (edge->source)
2355 json_object_int_add(json, "local-vertex-id", edge->source->key);
2356 if (edge->destination)
2357 json_object_int_add(json, "remote-vertex-id",
2358 edge->destination->key);
2359 json_object_int_add(json, "metric", attr->metric);
2360 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
2361 json_object_string_add(json, "name", attr->name);
2362 jte = json_object_new_object();
2363 json_object_object_add(json, "edge-attributes", jte);
2364 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
2365 json_object_int_add(jte, "te-metric", attr->standard.te_metric);
2366 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
2367 json_object_int_add(jte, "admin-group",
2368 attr->standard.admin_group);
bd0581e4
LS
2369 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
2370 js_ext_ag = json_object_new_object();
2371 json_object_object_add(jte, "extAdminGroup", js_ext_ag);
2372 js_ext_ag_arr_word = json_object_new_array();
2373 json_object_object_add(js_ext_ag, "words", js_ext_ag_arr_word);
2374 js_ext_ag_arr_bit = json_object_new_array();
2375 json_object_object_add(js_ext_ag, "bitPositions",
2376 js_ext_ag_arr_bit);
2377 for (i = 0; i < admin_group_nb_words(&attr->ext_admin_group);
2378 i++) {
2379 bitmap = admin_group_get_offset(&attr->ext_admin_group,
2380 i);
2381 snprintf(buf_ag, sizeof(buf_ag), "0x%08x", bitmap);
2382 json_object_array_add(js_ext_ag_arr_word,
2383 json_object_new_string(buf_ag));
2384 }
2385 for (i = 0;
2386 i < (admin_group_size(&attr->ext_admin_group) * WORD_SIZE);
2387 i++) {
2388 if (admin_group_get(&attr->ext_admin_group, i))
2389 json_object_array_add(js_ext_ag_arr_bit,
2390 json_object_new_int(i));
2391 }
2392 }
b0c0b433
OD
2393 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)) {
2394 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.local);
2395 json_object_string_add(jte, "local-address", buf);
2396 }
2397 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR)) {
2398 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.remote);
2399 json_object_string_add(jte, "remote-address", buf);
2400 }
2401 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)) {
2402 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.local6);
2403 json_object_string_add(jte, "local-address-v6", buf);
2404 }
2405 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6)) {
2406 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.remote6);
2407 json_object_string_add(jte, "remote-address-v6", buf);
2408 }
2409 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
2410 json_object_int_add(jte, "local-identifier",
2411 attr->standard.local_id);
2412 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
2413 json_object_int_add(jte, "remote-identifier",
2414 attr->standard.remote_id);
2415 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
2416 json_object_double_add(jte, "max-link-bandwidth",
2417 attr->standard.max_bw);
2418 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
2419 json_object_double_add(jte, "max-resv-link-bandwidth",
2420 attr->standard.max_rsv_bw);
2421 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
2422 jbw = json_object_new_array();
2423 json_object_object_add(jte, "unreserved-bandwidth", jbw);
2424 for (int i = 0; i < MAX_CLASS_TYPE; i++) {
2425 jobj = json_object_new_object();
2426 snprintfrr(buf, 13, "class-type-%u", i);
2427 json_object_double_add(jobj, buf,
2428 attr->standard.unrsv_bw[i]);
2429 json_object_array_add(jbw, jobj);
2430 }
2431 }
2432 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
2433 json_object_int_add(jte, "remote-asn",
2434 attr->standard.remote_as);
2435 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR)) {
2436 snprintfrr(buf, INET6_BUFSIZ, "%pI4",
2437 &attr->standard.remote_addr);
2438 json_object_string_add(jte, "remote-as-address", buf);
2439 }
2440 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6)) {
2441 snprintfrr(buf, INET6_BUFSIZ, "%pI6",
2442 &attr->standard.remote_addr6);
2443 json_object_string_add(jte, "remote-as-address-v6", buf);
2444 }
2445 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
2446 json_object_int_add(jte, "delay", attr->extended.delay);
2447 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
2448 json_object_int_add(jte, "min-delay", attr->extended.min_delay);
2449 json_object_int_add(jte, "max-delay", attr->extended.max_delay);
2450 }
2451 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
2452 json_object_int_add(jte, "jitter", attr->extended.jitter);
2453 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
2454 json_object_double_add(
2455 jte, "loss", attr->extended.pkt_loss * LOSS_PRECISION);
2456 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
2457 json_object_double_add(jte, "available-bandwidth",
2458 attr->extended.ava_bw);
2459 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
2460 json_object_double_add(jte, "residual-bandwidth",
2461 attr->extended.rsv_bw);
2462 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
2463 json_object_double_add(jte, "utilized-bandwidth",
2464 attr->extended.used_bw);
2465 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
2466 jsrlg = json_object_new_array();
2467 json_object_object_add(jte, "srlgs", jsrlg);
2468 for (int i = 1; i < attr->srlg_len; i++) {
2469 jobj = json_object_new_object();
2470 json_object_int_add(jobj, "srlg", attr->srlgs[i]);
2471 json_object_array_add(jsrlg, jobj);
2472 }
2473 }
2474 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
2475 jsr = json_object_new_array();
2476 json_object_object_add(json, "segment-routing", jsr);
2477 jobj = json_object_new_object();
8693b4d6
OD
2478 json_object_int_add(jobj, "adj-sid",
2479 attr->adj_sid[ADJ_PRI_IPV4].sid);
2480 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV4].flags);
b0c0b433 2481 json_object_string_add(jobj, "flags", buf);
8693b4d6
OD
2482 json_object_int_add(jobj, "weight",
2483 attr->adj_sid[ADJ_PRI_IPV4].weight);
b0c0b433
OD
2484 json_object_array_add(jsr, jobj);
2485 }
2486 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2487 if (!jsr) {
2488 jsr = json_object_new_array();
2489 json_object_object_add(json, "segment-routing", jsr);
2490 }
2491 jobj = json_object_new_object();
8693b4d6
OD
2492 json_object_int_add(jobj, "adj-sid",
2493 attr->adj_sid[ADJ_BCK_IPV4].sid);
2494 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV4].flags);
2495 json_object_string_add(jobj, "flags", buf);
2496 json_object_int_add(jobj, "weight",
2497 attr->adj_sid[ADJ_BCK_IPV4].weight);
2498 json_object_array_add(jsr, jobj);
2499 }
2500 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
2501 jsr = json_object_new_array();
2502 json_object_object_add(json, "segment-routing", jsr);
2503 jobj = json_object_new_object();
2504 json_object_int_add(jobj, "adj-sid",
2505 attr->adj_sid[ADJ_PRI_IPV6].sid);
2506 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV6].flags);
2507 json_object_string_add(jobj, "flags", buf);
2508 json_object_int_add(jobj, "weight",
2509 attr->adj_sid[ADJ_PRI_IPV6].weight);
2510 json_object_array_add(jsr, jobj);
2511 }
2512 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
2513 if (!jsr) {
2514 jsr = json_object_new_array();
2515 json_object_object_add(json, "segment-routing", jsr);
2516 }
2517 jobj = json_object_new_object();
2518 json_object_int_add(jobj, "adj-sid",
2519 attr->adj_sid[ADJ_BCK_IPV6].sid);
2520 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV6].flags);
b0c0b433 2521 json_object_string_add(jobj, "flags", buf);
8693b4d6
OD
2522 json_object_int_add(jobj, "weight",
2523 attr->adj_sid[ADJ_BCK_IPV6].weight);
b0c0b433
OD
2524 json_object_array_add(jsr, jobj);
2525 }
2526}
2527
2528void ls_show_edge(struct ls_edge *edge, struct vty *vty,
2529 struct json_object *json, bool verbose)
2530{
2531 /* Sanity Check */
2532 if (!edge)
2533 return;
2534
2535 if (json)
2536 ls_show_edge_json(edge, json);
2537 else if (vty)
2538 ls_show_edge_vty(edge, vty, verbose);
2539}
2540
2541void ls_show_edges(struct ls_ted *ted, struct vty *vty,
2542 struct json_object *json, bool verbose)
2543{
2544 struct ls_edge *edge;
2545 json_object *jedges, *jedge;
2546
2547 if (json) {
2548 jedges = json_object_new_array();
2549 json_object_object_add(json, "edges", jedges);
2550 frr_each (edges, &ted->edges, edge) {
2551 jedge = json_object_new_object();
2552 ls_show_edge(edge, NULL, jedge, verbose);
2553 json_object_array_add(jedges, jedge);
2554 }
2555 } else if (vty) {
2556 frr_each (edges, &ted->edges, edge)
2557 ls_show_edge(edge, vty, NULL, verbose);
2558 }
2559}
2560
2561static void ls_show_subnet_vty(struct ls_subnet *subnet, struct vty *vty,
2562 bool verbose)
2563{
2564 struct ls_prefix *pref;
2565 struct sbuf sbuf;
2566 char buf[INET6_BUFSIZ];
2567
2568 pref = subnet->ls_pref;
2569 sbuf_init(&sbuf, NULL, 0);
2570
2571 sbuf_push(&sbuf, 2, "Subnet: %pFX", &subnet->key);
2572 ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
2573 sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
2574 sbuf_push(&sbuf, 0, "\tMetric: %d", pref->metric);
2575 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[subnet->status]);
2576
2577 if (!verbose)
2578 goto end;
2579
2580 sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[pref->adv.origin]);
2581 if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG))
2582 sbuf_push(&sbuf, 4, "Flags: %d\n", pref->igp_flag);
2583
2584 if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
2585 sbuf_push(&sbuf, 4, "Tag: %d\n", pref->route_tag);
2586
2587 if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
2588 sbuf_push(&sbuf, 4, "Extended Tag: %" PRIu64 "\n",
2589 pref->extended_tag);
2590
2591 if (CHECK_FLAG(pref->flags, LS_PREF_SR))
2592 sbuf_push(&sbuf, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2593 pref->sr.sid, pref->sr.algo, pref->sr.sid_flag);
2594
2595end:
2596 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2597 sbuf_free(&sbuf);
2598}
2599
2600static void ls_show_subnet_json(struct ls_subnet *subnet,
2601 struct json_object *json)
2602{
2603 struct ls_prefix *pref;
2604 json_object *jsr;
2605 char buf[INET6_BUFSIZ];
2606
2607 pref = subnet->ls_pref;
2608
2609 snprintfrr(buf, INET6_BUFSIZ, "%pFX", &subnet->key);
2610 json_object_string_add(json, "subnet-id", buf);
2611 json_object_string_add(json, "status", status2txt[subnet->status]);
2612 json_object_string_add(json, "origin", origin2txt[pref->adv.origin]);
2613 ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
2614 json_object_string_add(json, "advertised-router", buf);
2615 if (subnet->vertex)
2616 json_object_int_add(json, "vertex-id", subnet->vertex->key);
2617 json_object_int_add(json, "metric", pref->metric);
2618 if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG)) {
2619 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->igp_flag);
2620 json_object_string_add(json, "flags", buf);
2621 }
2622 if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
2623 json_object_int_add(json, "tag", pref->route_tag);
2624 if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
2625 json_object_int_add(json, "extended-tag", pref->extended_tag);
2626 if (CHECK_FLAG(pref->flags, LS_PREF_SR)) {
2627 jsr = json_object_new_object();
2628 json_object_object_add(json, "segment-routing", jsr);
2629 json_object_int_add(jsr, "pref-sid", pref->sr.sid);
2630 json_object_int_add(jsr, "algo", pref->sr.algo);
2631 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
2632 json_object_string_add(jsr, "flags", buf);
2633 }
2634}
2635
2636void ls_show_subnet(struct ls_subnet *subnet, struct vty *vty,
2637 struct json_object *json, bool verbose)
2638{
2639 /* Sanity Check */
2640 if (!subnet)
2641 return;
2642
2643 if (json)
2644 ls_show_subnet_json(subnet, json);
2645 else if (vty)
2646 ls_show_subnet_vty(subnet, vty, verbose);
2647}
2648
2649void ls_show_subnets(struct ls_ted *ted, struct vty *vty,
2650 struct json_object *json, bool verbose)
2651{
2652 struct ls_subnet *subnet;
2653 json_object *jsubs, *jsub;
2654
2655 if (json) {
2656 jsubs = json_object_new_array();
2657 json_object_object_add(json, "subnets", jsubs);
2658 frr_each (subnets, &ted->subnets, subnet) {
2659 jsub = json_object_new_object();
2660 ls_show_subnet(subnet, NULL, jsub, verbose);
2661 json_object_array_add(jsubs, jsub);
2662 }
2663 } else if (vty) {
2664 frr_each (subnets, &ted->subnets, subnet)
2665 ls_show_subnet(subnet, vty, NULL, verbose);
2666 }
2667}
2668
2669void ls_show_ted(struct ls_ted *ted, struct vty *vty, struct json_object *json,
2670 bool verbose)
2671{
2672 json_object *jted;
2673
2674 if (json) {
2675 jted = json_object_new_object();
2676 json_object_object_add(json, "ted", jted);
2677 json_object_string_add(jted, "name", ted->name);
2678 json_object_int_add(jted, "key", ted->key);
2679 json_object_int_add(jted, "verticesCount",
2680 vertices_count(&ted->vertices));
2681 json_object_int_add(jted, "edgesCount",
2682 edges_count(&ted->edges));
2683 json_object_int_add(jted, "subnetsCount",
2684 subnets_count(&ted->subnets));
2685 ls_show_vertices(ted, NULL, jted, verbose);
2686 ls_show_edges(ted, NULL, jted, verbose);
2687 ls_show_subnets(ted, NULL, jted, verbose);
2688 return;
2689 }
2690
2691 if (vty) {
2692 vty_out(vty,
2693 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2694 ted->name, ted->key);
2695 ls_show_vertices(ted, vty, NULL, verbose);
2696 ls_show_edges(ted, vty, NULL, verbose);
2697 ls_show_subnets(ted, vty, NULL, verbose);
2698 vty_out(vty,
2699 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2700 vertices_count(&ted->vertices),
2701 edges_count(&ted->edges), subnets_count(&ted->subnets));
2702 }
2703}
2704
bbd85e20
OD
2705void ls_dump_ted(struct ls_ted *ted)
2706{
2707 struct ls_vertex *vertex;
2708 struct ls_edge *edge;
2709 struct ls_subnet *subnet;
b0c0b433 2710 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
bbd85e20
OD
2711
2712 zlog_debug("(%s) Ted init", __func__);
bbd85e20
OD
2713
2714 /* Loop TED, start printing Node, then Attributes and finally Prefix */
b0c0b433 2715 frr_each (vertices, &ted->vertices, vertex) {
1d5453d6 2716 zlog_debug(" Ted node (%s %pI4 %s)",
bbd85e20
OD
2717 vertex->node->name[0] ? vertex->node->name
2718 : "no name node",
2719 &vertex->node->router_id,
b0c0b433 2720 origin2txt[vertex->node->adv.origin]);
bbd85e20
OD
2721 struct listnode *lst_node;
2722 struct ls_edge *vertex_edge;
2723
2724 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, lst_node,
2725 vertex_edge)) {
2726 zlog_debug(
b0c0b433 2727 " inc edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
bbd85e20
OD
2728 vertex_edge->key,
2729 &vertex_edge->attributes->adv.id.ip.addr,
2730 &vertex_edge->attributes->standard.local,
2731 &vertex_edge->attributes->standard.remote);
2732 }
2733 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, lst_node,
2734 vertex_edge)) {
2735 zlog_debug(
b0c0b433 2736 " out edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
bbd85e20
OD
2737 vertex_edge->key,
2738 &vertex_edge->attributes->adv.id.ip.addr,
2739 &vertex_edge->attributes->standard.local,
2740 &vertex_edge->attributes->standard.remote);
2741 }
2742 }
b0c0b433
OD
2743 frr_each (edges, &ted->edges, edge) {
2744 zlog_debug(" Ted edge key:%" PRIu64 "src:%pI4 dst:%pI4", edge->key,
2745 edge->source ? &edge->source->node->router_id
2746 : &inaddr_any,
2747 edge->destination
2748 ? &edge->destination->node->router_id
2749 : &inaddr_any);
bbd85e20 2750 }
b0c0b433
OD
2751 frr_each (subnets, &ted->subnets, subnet) {
2752 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2753 &subnet->ls_pref->pref,
2754 &subnet->vertex->node->adv.id.ip.addr);
bbd85e20
OD
2755 }
2756 zlog_debug("(%s) Ted end", __func__);
2757}