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