]> git.proxmox.com Git - mirror_frr.git/blob - lib/link_state.c
Merge pull request #8744 from sworleys/RTADV-Fix-Upstream
[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 if (!new)
542 return NULL;
543
544 new->attributes = attributes;
545 new->key = key;
546 new->status = NEW;
547 new->type = EDGE;
548 edges_add(&ted->edges, new);
549
550 /* Finally, connect Edge to Vertices */
551 ls_edge_connect_to(ted, new);
552
553 return new;
554 }
555
556 struct ls_edge *ls_find_edge_by_key(struct ls_ted *ted, const uint64_t key)
557 {
558 struct ls_edge edge = {};
559
560 if (key == 0)
561 return NULL;
562
563 edge.key = key;
564 return edges_find(&ted->edges, &edge);
565 }
566
567 struct ls_edge *ls_find_edge_by_source(struct ls_ted *ted,
568 struct ls_attributes *attributes)
569 {
570 struct ls_edge edge = {};
571
572 if (attributes == NULL)
573 return NULL;
574
575 edge.key = 0;
576 /* Key is the IPv4 local address */
577 if (!IPV4_NET0(attributes->standard.local.s_addr))
578 edge.key = ((uint64_t)ntohl(attributes->standard.local.s_addr))
579 & 0xffffffff;
580 /* or the IPv6 local address if IPv4 is not defined */
581 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.local6))
582 edge.key = (uint64_t)(attributes->standard.local6.s6_addr32[0]
583 & 0xffffffff)
584 | ((uint64_t)attributes->standard.local6.s6_addr32[1]
585 << 32);
586 /* of local identifier if no IP addresses are defined */
587 else if (attributes->standard.local_id != 0)
588 edge.key = (uint64_t)(
589 (attributes->standard.local_id & 0xffffffff)
590 | ((uint64_t)attributes->standard.remote_id << 32));
591
592 if (edge.key == 0)
593 return NULL;
594
595 return edges_find(&ted->edges, &edge);
596 }
597
598 struct ls_edge *ls_find_edge_by_destination(struct ls_ted *ted,
599 struct ls_attributes *attributes)
600 {
601 struct ls_edge edge = {};
602
603 if (attributes == NULL)
604 return NULL;
605
606 edge.key = 0;
607 /* Key is the IPv4 remote address */
608 if (!IPV4_NET0(attributes->standard.remote.s_addr))
609 edge.key = ((uint64_t)ntohl(attributes->standard.remote.s_addr))
610 & 0xffffffff;
611 /* or the IPv6 remote address if IPv4 is not defined */
612 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes->standard.remote6))
613 edge.key =
614 (uint64_t)(attributes->standard.remote6.s6_addr32[0]
615 & 0xffffffff)
616 | ((uint64_t)attributes->standard.remote6.s6_addr32[1]
617 << 32);
618 /* of remote identifier if no IP addresses are defined */
619 else if (attributes->standard.remote_id != 0)
620 edge.key = (uint64_t)(
621 (attributes->standard.remote_id & 0xffffffff)
622 | ((uint64_t)attributes->standard.local_id << 32));
623
624 if (edge.key == 0)
625 return NULL;
626
627 return edges_find(&ted->edges, &edge);
628 }
629
630 struct ls_edge *ls_edge_update(struct ls_ted *ted,
631 struct ls_attributes *attributes)
632 {
633 struct ls_edge *old;
634
635 if (attributes == NULL)
636 return NULL;
637
638 /* First, search for an existing Edge */
639 old = ls_find_edge_by_source(ted, attributes);
640 if (old) {
641 /* Check if attributes are similar */
642 if (!ls_attributes_same(old->attributes, attributes)) {
643 ls_attributes_del(old->attributes);
644 old->attributes = attributes;
645 }
646 old->status = UPDATE;
647 return old;
648 }
649
650 /* If not found, add new Edge from the attributes */
651 return ls_edge_add(ted, attributes);
652 }
653
654 int ls_edge_same(struct ls_edge *e1, struct ls_edge *e2)
655 {
656 if ((e1 && !e2) || (!e1 && e2))
657 return 0;
658
659 if (!e1 && !e2)
660 return 1;
661
662 if (e1->key != e2->key)
663 return 0;
664
665 if (e1->attributes == e2->attributes)
666 return 1;
667
668 return ls_attributes_same(e1->attributes, e2->attributes);
669 }
670
671 void ls_edge_del(struct ls_ted *ted, struct ls_edge *edge)
672 {
673 if (!ted || !edge)
674 return;
675
676 /* Fist disconnect Edge from Vertices */
677 ls_disconnect_edge(edge);
678 /* Then remove it from the Data Base */
679 edges_del(&ted->edges, edge);
680 XFREE(MTYPE_LS_DB, edge);
681 }
682
683 void ls_edge_del_all(struct ls_ted *ted, struct ls_edge *edge)
684 {
685 if (!ted || !edge)
686 return;
687
688 /* Remove associated Link State Attributes */
689 ls_attributes_del(edge->attributes);
690 /* Then Edge itself */
691 ls_edge_del(ted, edge);
692 }
693
694 /**
695 * Link State Subnet Management functions.
696 */
697 struct ls_subnet *ls_subnet_add(struct ls_ted *ted,
698 struct ls_prefix *ls_pref)
699 {
700 struct ls_subnet *new;
701 struct ls_vertex *vertex;
702 struct ls_node *node;
703 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
704
705 if (ls_pref == NULL)
706 return NULL;
707
708 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_subnet));
709 new->ls_pref = ls_pref;
710 new->key = ls_pref->pref;
711 new->status = NEW;
712 new->type = SUBNET;
713
714 /* Find Vertex */
715 vertex = ls_find_vertex_by_id(ted, ls_pref->adv);
716 if (vertex == NULL) {
717 /* Create a new temporary Node & Vertex if not found */
718 node = ls_node_new(ls_pref->adv, inaddr_any, in6addr_any);
719 vertex = ls_vertex_add(ted, node);
720 }
721 /* And attach the subnet to the corresponding Vertex */
722 new->vertex = vertex;
723 listnode_add_sort_nodup(vertex->prefixes, new);
724
725 subnets_add(&ted->subnets, new);
726
727 return new;
728 }
729
730 struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref)
731 {
732 struct ls_subnet *old;
733
734 if (pref == NULL)
735 return NULL;
736
737 old = ls_find_subnet(ted, pref->pref);
738 if (old) {
739 if (!ls_prefix_same(old->ls_pref, pref)) {
740 ls_prefix_del(old->ls_pref);
741 old->ls_pref = pref;
742 }
743 old->status = UPDATE;
744 return old;
745 }
746
747 return ls_subnet_add(ted, pref);
748 }
749
750 int ls_subnet_same(struct ls_subnet *s1, struct ls_subnet *s2)
751 {
752 if ((s1 && !s2) || (!s1 && s2))
753 return 0;
754
755 if (!s1 && !s2)
756 return 1;
757
758 if (!prefix_same(&s1->key, &s2->key))
759 return 0;
760
761 if (s1->ls_pref == s2->ls_pref)
762 return 1;
763
764 return ls_prefix_same(s1->ls_pref, s2->ls_pref);
765 }
766
767 void ls_subnet_del(struct ls_ted *ted, struct ls_subnet *subnet)
768 {
769 if (!ted || !subnet)
770 return;
771
772 /* First, disconnect Subnet from associated Vertex */
773 listnode_delete(subnet->vertex->prefixes, subnet);
774 /* Then delete Subnet */
775 subnets_del(&ted->subnets, subnet);
776 XFREE(MTYPE_LS_DB, subnet);
777 }
778
779 void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet)
780 {
781 if (!ted || !subnet)
782 return;
783
784 /* First, remove associated Link State Subnet */
785 ls_prefix_del(subnet->ls_pref);
786 /* Then, delete Subnet itself */
787 ls_subnet_del(ted, subnet);
788 }
789
790 struct ls_subnet *ls_find_subnet(struct ls_ted *ted, const struct prefix prefix)
791 {
792 struct ls_subnet subnet = {};
793
794 subnet.key = prefix;
795 return subnets_find(&ted->subnets, &subnet);
796 }
797
798 /**
799 * Link State TED management functions
800 */
801 struct ls_ted *ls_ted_new(const uint32_t key, const char *name,
802 uint32_t as_number)
803 {
804 struct ls_ted *new;
805
806 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_ted));
807 if (new == NULL)
808 return new;
809
810 /* Set basic information for this ted */
811 new->key = key;
812 new->as_number = as_number;
813 strlcpy(new->name, name, MAX_NAME_LENGTH);
814
815 /* Initialize the various RB tree */
816 vertices_init(&new->vertices);
817 edges_init(&new->edges);
818 subnets_init(&new->subnets);
819
820 return new;
821 }
822
823 void ls_ted_del(struct ls_ted *ted)
824 {
825 if (ted == NULL)
826 return;
827
828 /* Check that TED is empty */
829 if (vertices_count(&ted->vertices) || edges_count(&ted->edges)
830 || subnets_count(&ted->subnets))
831 return;
832
833 /* Release RB Tree */
834 vertices_fini(&ted->vertices);
835 edges_fini(&ted->edges);
836 subnets_fini(&ted->subnets);
837
838 XFREE(MTYPE_LS_DB, ted);
839 }
840
841 void ls_ted_del_all(struct ls_ted *ted)
842 {
843 struct ls_vertex *vertex;
844 struct ls_edge *edge;
845 struct ls_subnet *subnet;
846
847 if (ted == NULL)
848 return;
849
850 /* First remove Vertices, Edges and Subnets and associated Link State */
851 frr_each (vertices, &ted->vertices, vertex)
852 ls_vertex_del_all(ted, vertex);
853 frr_each (edges, &ted->edges, edge)
854 ls_edge_del_all(ted, edge);
855 frr_each (subnets, &ted->subnets, subnet)
856 ls_subnet_del_all(ted, subnet);
857
858 /* then remove TED itself */
859 ls_ted_del(ted);
860 }
861
862 void ls_ted_clean(struct ls_ted *ted)
863 {
864 struct ls_vertex *vertex;
865 struct ls_edge *edge;
866 struct ls_subnet *subnet;
867
868 if (ted == NULL)
869 return;
870
871 /* First, start with Vertices */
872 frr_each (vertices, &ted->vertices, vertex)
873 if (vertex->status == ORPHAN)
874 ls_vertex_del_all(ted, vertex);
875
876 /* Then Edges */
877 frr_each (edges, &ted->edges, edge)
878 if (edge->status == ORPHAN)
879 ls_edge_del_all(ted, edge);
880
881 /* and Subnets */
882 frr_each (subnets, &ted->subnets, subnet)
883 if (subnet->status == ORPHAN)
884 ls_subnet_del_all(ted, subnet);
885
886 }
887
888 void ls_connect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
889 {
890 if (vertex == NULL || edge == NULL)
891 return;
892
893 if (source) {
894 listnode_add_sort_nodup(vertex->outgoing_edges, edge);
895 edge->source = vertex;
896 } else {
897 listnode_add_sort_nodup(vertex->incoming_edges, edge);
898 edge->destination = vertex;
899 }
900 }
901
902 void ls_disconnect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
903 {
904
905 if (vertex == NULL || edge == NULL)
906 return;
907
908 if (source) {
909 listnode_delete(vertex->outgoing_edges, edge);
910 edge->source = NULL;
911 } else {
912 listnode_delete(vertex->incoming_edges, edge);
913 edge->destination = NULL;
914 }
915 }
916
917 void ls_connect_vertices(struct ls_vertex *src, struct ls_vertex *dst,
918 struct ls_edge *edge)
919 {
920 if (edge == NULL)
921 return;
922
923 edge->source = src;
924 edge->destination = dst;
925
926 if (src != NULL)
927 listnode_add_sort_nodup(src->outgoing_edges, edge);
928
929 if (dst != NULL)
930 listnode_add_sort_nodup(dst->incoming_edges, edge);
931 }
932
933 void ls_disconnect_edge(struct ls_edge *edge)
934 {
935 if (edge == NULL)
936 return;
937
938 ls_disconnect(edge->source, edge, true);
939 ls_disconnect(edge->destination, edge, false);
940
941 /* Mark this Edge as ORPHAN for future cleanup */
942 edge->status = ORPHAN;
943 }
944
945 /**
946 * Link State Message management functions
947 */
948
949 int ls_register(struct zclient *zclient, bool server)
950 {
951 int rc;
952
953 if (server)
954 rc = zclient_register_opaque(zclient, LINK_STATE_SYNC);
955 else
956 rc = zclient_register_opaque(zclient, LINK_STATE_UPDATE);
957
958 return rc;
959 }
960
961 int ls_unregister(struct zclient *zclient, bool server)
962 {
963 int rc;
964
965 if (server)
966 rc = zclient_unregister_opaque(zclient, LINK_STATE_SYNC);
967 else
968 rc = zclient_unregister_opaque(zclient, LINK_STATE_UPDATE);
969
970 return rc;
971 }
972
973 int ls_request_sync(struct zclient *zclient)
974 {
975 struct stream *s;
976 uint16_t flags = 0;
977
978 /* Check buffer size */
979 if (STREAM_SIZE(zclient->obuf)
980 < (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t)))
981 return -1;
982
983 s = zclient->obuf;
984 stream_reset(s);
985
986 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
987
988 /* Set type and flags */
989 stream_putl(s, LINK_STATE_SYNC);
990 stream_putw(s, flags);
991 /* Send destination client info */
992 stream_putc(s, zclient->redist_default);
993 stream_putw(s, zclient->instance);
994 stream_putl(s, zclient->session_id);
995
996 /* Put length into the header at the start of the stream. */
997 stream_putw_at(s, 0, stream_get_endp(s));
998
999 return zclient_send_message(zclient);
1000 }
1001
1002 static struct ls_node *ls_parse_node(struct stream *s)
1003 {
1004 struct ls_node *node;
1005 size_t len;
1006
1007 node = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
1008 if (node == NULL)
1009 return NULL;
1010
1011 STREAM_GET(&node->adv, s, sizeof(struct ls_node_id));
1012 STREAM_GETW(s, node->flags);
1013 if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
1014 STREAM_GETC(s, len);
1015 STREAM_GET(node->name, s, len);
1016 }
1017 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
1018 node->router_id.s_addr = stream_get_ipv4(s);
1019 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
1020 STREAM_GET(&node->router6_id, s, IPV6_MAX_BYTELEN);
1021 if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
1022 STREAM_GETC(s, node->node_flag);
1023 if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
1024 STREAM_GETC(s, node->type);
1025 if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
1026 STREAM_GETL(s, node->as_number);
1027 if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
1028 STREAM_GETL(s, node->srgb.lower_bound);
1029 STREAM_GETL(s, node->srgb.range_size);
1030 STREAM_GETC(s, node->srgb.flag);
1031 STREAM_GET(node->algo, s, 2);
1032 }
1033 if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
1034 STREAM_GETL(s, node->srlb.lower_bound);
1035 STREAM_GETL(s, node->srlb.range_size);
1036 }
1037 if (CHECK_FLAG(node->flags, LS_NODE_MSD))
1038 STREAM_GETC(s, node->msd);
1039
1040 return node;
1041
1042 stream_failure:
1043 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__);
1044 XFREE(MTYPE_LS_DB, node);
1045 return NULL;
1046 }
1047
1048 static struct ls_attributes *ls_parse_attributes(struct stream *s)
1049 {
1050 struct ls_attributes *attr;
1051 size_t len;
1052
1053 attr = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
1054 if (attr == NULL)
1055 return NULL;
1056 attr->srlgs = NULL;
1057
1058 STREAM_GET(&attr->adv, s, sizeof(struct ls_node_id));
1059 STREAM_GETL(s, attr->flags);
1060 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
1061 STREAM_GETC(s, len);
1062 STREAM_GET(attr->name, s, len);
1063 }
1064 if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
1065 STREAM_GETL(s, attr->metric);
1066 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
1067 STREAM_GETL(s, attr->standard.te_metric);
1068 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
1069 STREAM_GETL(s, attr->standard.admin_group);
1070 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1071 attr->standard.local.s_addr = stream_get_ipv4(s);
1072 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
1073 attr->standard.remote.s_addr = stream_get_ipv4(s);
1074 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1075 STREAM_GET(&attr->standard.local6, s, IPV6_MAX_BYTELEN);
1076 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
1077 STREAM_GET(&attr->standard.remote6, s, IPV6_MAX_BYTELEN);
1078 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
1079 STREAM_GETL(s, attr->standard.local_id);
1080 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
1081 STREAM_GETL(s, attr->standard.remote_id);
1082 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
1083 STREAM_GETF(s, attr->standard.max_bw);
1084 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
1085 STREAM_GETF(s, attr->standard.max_rsv_bw);
1086 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
1087 for (len = 0; len < MAX_CLASS_TYPE; len++)
1088 STREAM_GETF(s, attr->standard.unrsv_bw[len]);
1089 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
1090 STREAM_GETL(s, attr->standard.remote_as);
1091 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
1092 attr->standard.remote_addr.s_addr = stream_get_ipv4(s);
1093 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
1094 STREAM_GET(&attr->standard.remote_addr6, s, IPV6_MAX_BYTELEN);
1095 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
1096 STREAM_GETL(s, attr->extended.delay);
1097 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
1098 STREAM_GETL(s, attr->extended.min_delay);
1099 STREAM_GETL(s, attr->extended.max_delay);
1100 }
1101 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
1102 STREAM_GETL(s, attr->extended.jitter);
1103 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
1104 STREAM_GETL(s, attr->extended.pkt_loss);
1105 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
1106 STREAM_GETF(s, attr->extended.ava_bw);
1107 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
1108 STREAM_GETF(s, attr->extended.rsv_bw);
1109 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
1110 STREAM_GETF(s, attr->extended.used_bw);
1111 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
1112 STREAM_GETL(s, attr->adj_sid[0].sid);
1113 STREAM_GETC(s, attr->adj_sid[0].flags);
1114 STREAM_GETC(s, attr->adj_sid[0].weight);
1115 if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
1116 STREAM_GET(attr->adj_sid[0].neighbor.sysid, s,
1117 ISO_SYS_ID_LEN);
1118 else if (attr->adv.origin == OSPFv2)
1119 attr->adj_sid[0].neighbor.addr.s_addr =
1120 stream_get_ipv4(s);
1121 }
1122 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
1123 STREAM_GETL(s, attr->adj_sid[1].sid);
1124 STREAM_GETC(s, attr->adj_sid[1].flags);
1125 STREAM_GETC(s, attr->adj_sid[1].weight);
1126 if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
1127 STREAM_GET(attr->adj_sid[1].neighbor.sysid, s,
1128 ISO_SYS_ID_LEN);
1129 else if (attr->adv.origin == OSPFv2)
1130 attr->adj_sid[1].neighbor.addr.s_addr =
1131 stream_get_ipv4(s);
1132 }
1133 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
1134 STREAM_GETC(s, len);
1135 attr->srlgs = XCALLOC(MTYPE_LS_DB, len*sizeof(uint32_t));
1136 attr->srlg_len = len;
1137 for (len = 0; len < attr->srlg_len; len++)
1138 STREAM_GETL(s, attr->srlgs[len]);
1139 }
1140
1141 return attr;
1142
1143 stream_failure:
1144 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1145 __func__);
1146 /* Clean memory allocation */
1147 if (attr->srlgs != NULL)
1148 XFREE(MTYPE_LS_DB, attr->srlgs);
1149 XFREE(MTYPE_LS_DB, attr);
1150 return NULL;
1151
1152 }
1153
1154 static struct ls_prefix *ls_parse_prefix(struct stream *s)
1155 {
1156 struct ls_prefix *ls_pref;
1157 size_t len;
1158
1159 ls_pref = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
1160 if (ls_pref == NULL)
1161 return NULL;
1162
1163 STREAM_GET(&ls_pref->adv, s, sizeof(struct ls_node_id));
1164 STREAM_GETW(s, ls_pref->flags);
1165 STREAM_GETC(s, ls_pref->pref.family);
1166 STREAM_GETW(s, ls_pref->pref.prefixlen);
1167 len = prefix_blen(&ls_pref->pref);
1168 STREAM_GET(&ls_pref->pref.u.prefix, s, len);
1169 if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
1170 STREAM_GETC(s, ls_pref->igp_flag);
1171 if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
1172 STREAM_GETL(s, ls_pref->route_tag);
1173 if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
1174 STREAM_GETQ(s, ls_pref->extended_tag);
1175 if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1176 STREAM_GETL(s, ls_pref->metric);
1177 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
1178 STREAM_GETL(s, ls_pref->sr.sid);
1179 STREAM_GETC(s, ls_pref->sr.sid_flag);
1180 STREAM_GETC(s, ls_pref->sr.algo);
1181 }
1182
1183 return ls_pref;
1184
1185 stream_failure:
1186 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__);
1187 XFREE(MTYPE_LS_DB, ls_pref);
1188 return NULL;
1189 }
1190
1191 struct ls_message *ls_parse_msg(struct stream *s)
1192 {
1193 struct ls_message *msg;
1194
1195 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1196 if (msg == NULL)
1197 return NULL;
1198
1199 /* Read LS Message header */
1200 STREAM_GETC(s, msg->event);
1201 STREAM_GETC(s, msg->type);
1202 STREAM_GET(&msg->remote_id, s, sizeof(struct ls_node_id));
1203
1204 /* Read Message Payload */
1205 switch (msg->type) {
1206 case LS_MSG_TYPE_NODE:
1207 msg->data.node = ls_parse_node(s);
1208 break;
1209 case LS_MSG_TYPE_ATTRIBUTES:
1210 msg->data.attr = ls_parse_attributes(s);
1211 break;
1212 case LS_MSG_TYPE_PREFIX:
1213 msg->data.prefix = ls_parse_prefix(s);
1214 break;
1215 default:
1216 zlog_err("Unsupported Payload");
1217 goto stream_failure;
1218 }
1219
1220 if (msg->data.node == NULL || msg->data.attr == NULL
1221 || msg->data.prefix == NULL)
1222 goto stream_failure;
1223
1224 return msg;
1225
1226 stream_failure:
1227 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__);
1228 XFREE(MTYPE_LS_DB, msg);
1229 return NULL;
1230 }
1231
1232 static int ls_format_node(struct stream *s, struct ls_node *node)
1233 {
1234 size_t len;
1235
1236 /* Push Advertise node information first */
1237 stream_put(s, &node->adv, sizeof(struct ls_node_id));
1238
1239 /* Push Flags & Origin then Node information if there are present */
1240 stream_putw(s, node->flags);
1241 if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
1242 len = strlen(node->name);
1243 stream_putc(s, len + 1);
1244 stream_put(s, node->name, len);
1245 stream_putc(s, '\0');
1246 }
1247 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
1248 stream_put_ipv4(s, node->router_id.s_addr);
1249 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
1250 stream_put(s, &node->router6_id, IPV6_MAX_BYTELEN);
1251 if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
1252 stream_putc(s, node->node_flag);
1253 if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
1254 stream_putc(s, node->type);
1255 if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
1256 stream_putl(s, node->as_number);
1257 if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
1258 stream_putl(s, node->srgb.lower_bound);
1259 stream_putl(s, node->srgb.range_size);
1260 stream_putc(s, node->srgb.flag);
1261 stream_put(s, node->algo, 2);
1262 }
1263 if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
1264 stream_putl(s, node->srlb.lower_bound);
1265 stream_putl(s, node->srlb.range_size);
1266 }
1267 if (CHECK_FLAG(node->flags, LS_NODE_MSD))
1268 stream_putc(s, node->msd);
1269
1270 return 0;
1271 }
1272
1273 static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
1274 {
1275 size_t len;
1276
1277 /* Push Advertise node information first */
1278 stream_put(s, &attr->adv, sizeof(struct ls_node_id));
1279
1280 /* Push Flags & Origin then LS attributes if there are present */
1281 stream_putl(s, attr->flags);
1282 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
1283 len = strlen(attr->name);
1284 stream_putc(s, len + 1);
1285 stream_put(s, attr->name, len);
1286 stream_putc(s, '\0');
1287 }
1288 if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
1289 stream_putl(s, attr->metric);
1290 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
1291 stream_putl(s, attr->standard.te_metric);
1292 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
1293 stream_putl(s, attr->standard.admin_group);
1294 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1295 stream_put_ipv4(s, attr->standard.local.s_addr);
1296 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
1297 stream_put_ipv4(s, attr->standard.remote.s_addr);
1298 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1299 stream_put(s, &attr->standard.local6, IPV6_MAX_BYTELEN);
1300 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
1301 stream_put(s, &attr->standard.remote6, IPV6_MAX_BYTELEN);
1302 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
1303 stream_putl(s, attr->standard.local_id);
1304 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
1305 stream_putl(s, attr->standard.remote_id);
1306 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
1307 stream_putf(s, attr->standard.max_bw);
1308 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
1309 stream_putf(s, attr->standard.max_rsv_bw);
1310 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
1311 for (len = 0; len < MAX_CLASS_TYPE; len++)
1312 stream_putf(s, attr->standard.unrsv_bw[len]);
1313 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
1314 stream_putl(s, attr->standard.remote_as);
1315 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
1316 stream_put_ipv4(s, attr->standard.remote_addr.s_addr);
1317 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
1318 stream_put(s, &attr->standard.remote_addr6, IPV6_MAX_BYTELEN);
1319 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
1320 stream_putl(s, attr->extended.delay);
1321 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
1322 stream_putl(s, attr->extended.min_delay);
1323 stream_putl(s, attr->extended.max_delay);
1324 }
1325 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
1326 stream_putl(s, attr->extended.jitter);
1327 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
1328 stream_putl(s, attr->extended.pkt_loss);
1329 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
1330 stream_putf(s, attr->extended.ava_bw);
1331 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
1332 stream_putf(s, attr->extended.rsv_bw);
1333 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
1334 stream_putf(s, attr->extended.used_bw);
1335 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
1336 stream_putl(s, attr->adj_sid[0].sid);
1337 stream_putc(s, attr->adj_sid[0].flags);
1338 stream_putc(s, attr->adj_sid[0].weight);
1339 if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
1340 stream_put(s, attr->adj_sid[0].neighbor.sysid,
1341 ISO_SYS_ID_LEN);
1342 else if (attr->adv.origin == OSPFv2)
1343 stream_put_ipv4(s,
1344 attr->adj_sid[0].neighbor.addr.s_addr);
1345 }
1346 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
1347 stream_putl(s, attr->adj_sid[1].sid);
1348 stream_putc(s, attr->adj_sid[1].flags);
1349 stream_putc(s, attr->adj_sid[1].weight);
1350 if (attr->adv.origin == ISIS_L1 || attr->adv.origin == ISIS_L2)
1351 stream_put(s, attr->adj_sid[1].neighbor.sysid,
1352 ISO_SYS_ID_LEN);
1353 else if (attr->adv.origin == OSPFv2)
1354 stream_put_ipv4(s,
1355 attr->adj_sid[1].neighbor.addr.s_addr);
1356 }
1357 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
1358 stream_putc(s, attr->srlg_len);
1359 for (len = 0; len < attr->srlg_len; len++)
1360 stream_putl(s, attr->srlgs[len]);
1361 }
1362
1363 return 0;
1364 }
1365
1366 static int ls_format_prefix(struct stream *s, struct ls_prefix *ls_pref)
1367 {
1368 size_t len;
1369
1370 /* Push Advertise node information first */
1371 stream_put(s, &ls_pref->adv, sizeof(struct ls_node_id));
1372
1373 /* Push Flags, Origin & Prefix then information if there are present */
1374 stream_putw(s, ls_pref->flags);
1375 stream_putc(s, ls_pref->pref.family);
1376 stream_putw(s, ls_pref->pref.prefixlen);
1377 len = prefix_blen(&ls_pref->pref);
1378 stream_put(s, &ls_pref->pref.u.prefix, len);
1379 if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
1380 stream_putc(s, ls_pref->igp_flag);
1381 if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
1382 stream_putl(s, ls_pref->route_tag);
1383 if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
1384 stream_putq(s, ls_pref->extended_tag);
1385 if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1386 stream_putl(s, ls_pref->metric);
1387 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
1388 stream_putl(s, ls_pref->sr.sid);
1389 stream_putc(s, ls_pref->sr.sid_flag);
1390 stream_putc(s, ls_pref->sr.algo);
1391 }
1392
1393 return 0;
1394 }
1395
1396 static int ls_format_msg(struct stream *s, struct ls_message *msg)
1397 {
1398
1399 /* Prepare Link State header */
1400 stream_putc(s, msg->event);
1401 stream_putc(s, msg->type);
1402 stream_put(s, &msg->remote_id, sizeof(struct ls_node_id));
1403
1404 /* Add Message Payload */
1405 switch (msg->type) {
1406 case LS_MSG_TYPE_NODE:
1407 return ls_format_node(s, msg->data.node);
1408 case LS_MSG_TYPE_ATTRIBUTES:
1409 return ls_format_attributes(s, msg->data.attr);
1410 case LS_MSG_TYPE_PREFIX:
1411 return ls_format_prefix(s, msg->data.prefix);
1412 default:
1413 zlog_warn("Unsupported Payload");
1414 break;
1415 }
1416
1417 return -1;
1418 }
1419
1420 int ls_send_msg(struct zclient *zclient, struct ls_message *msg,
1421 struct zapi_opaque_reg_info *dst)
1422 {
1423 struct stream *s;
1424 uint16_t flags = 0;
1425
1426 /* Check if we have a valid message */
1427 if (msg->event == LS_MSG_EVENT_UNDEF)
1428 return -1;
1429
1430 /* Check buffer size */
1431 if (STREAM_SIZE(zclient->obuf) <
1432 (ZEBRA_HEADER_SIZE + sizeof(uint32_t) + sizeof(msg)))
1433 return -1;
1434
1435 s = zclient->obuf;
1436 stream_reset(s);
1437
1438 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
1439
1440 /* Set sub-type, flags and destination for unicast message */
1441 stream_putl(s, LINK_STATE_UPDATE);
1442 if (dst != NULL) {
1443 SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
1444 stream_putw(s, flags);
1445 /* Send destination client info */
1446 stream_putc(s, dst->proto);
1447 stream_putw(s, dst->instance);
1448 stream_putl(s, dst->session_id);
1449 } else {
1450 stream_putw(s, flags);
1451 }
1452
1453 /* Format Link State message */
1454 if (ls_format_msg(s, msg) < 0) {
1455 stream_reset(s);
1456 return -1;
1457 }
1458
1459 /* Put length into the header at the start of the stream. */
1460 stream_putw_at(s, 0, stream_get_endp(s));
1461
1462 return zclient_send_message(zclient);
1463 }
1464
1465 struct ls_message *ls_vertex2msg(struct ls_message *msg,
1466 struct ls_vertex *vertex)
1467 {
1468 /* Allocate space if needed */
1469 if (msg == NULL)
1470 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1471 else
1472 memset(msg, 0, sizeof(*msg));
1473
1474 msg->type = LS_MSG_TYPE_NODE;
1475 switch (vertex->status) {
1476 case NEW:
1477 msg->event = LS_MSG_EVENT_ADD;
1478 break;
1479 case UPDATE:
1480 msg->event = LS_MSG_EVENT_UPDATE;
1481 break;
1482 case DELETE:
1483 msg->event = LS_MSG_EVENT_DELETE;
1484 break;
1485 case SYNC:
1486 msg->event = LS_MSG_EVENT_SYNC;
1487 break;
1488 default:
1489 msg->event = LS_MSG_EVENT_UNDEF;
1490 break;
1491 }
1492 msg->data.node = vertex->node;
1493 msg->remote_id.origin = UNKNOWN;
1494
1495 return msg;
1496 }
1497
1498 struct ls_message *ls_edge2msg(struct ls_message *msg, struct ls_edge *edge)
1499 {
1500 /* Allocate space if needed */
1501 if (msg == NULL)
1502 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1503 else
1504 memset(msg, 0, sizeof(*msg));
1505
1506 msg->type = LS_MSG_TYPE_ATTRIBUTES;
1507 switch (edge->status) {
1508 case NEW:
1509 msg->event = LS_MSG_EVENT_ADD;
1510 break;
1511 case UPDATE:
1512 msg->event = LS_MSG_EVENT_UPDATE;
1513 break;
1514 case DELETE:
1515 msg->event = LS_MSG_EVENT_DELETE;
1516 break;
1517 case SYNC:
1518 msg->event = LS_MSG_EVENT_SYNC;
1519 break;
1520 default:
1521 msg->event = LS_MSG_EVENT_UNDEF;
1522 break;
1523 }
1524 msg->data.attr = edge->attributes;
1525 if (edge->destination != NULL)
1526 msg->remote_id = edge->destination->node->adv;
1527 else
1528 msg->remote_id.origin = UNKNOWN;
1529
1530 return msg;
1531 }
1532
1533 struct ls_message *ls_subnet2msg(struct ls_message *msg,
1534 struct ls_subnet *subnet)
1535 {
1536 /* Allocate space if needed */
1537 if (msg == NULL)
1538 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1539 else
1540 memset(msg, 0, sizeof(*msg));
1541
1542 msg->type = LS_MSG_TYPE_PREFIX;
1543 switch (subnet->status) {
1544 case NEW:
1545 msg->event = LS_MSG_EVENT_ADD;
1546 break;
1547 case UPDATE:
1548 msg->event = LS_MSG_EVENT_UPDATE;
1549 break;
1550 case DELETE:
1551 msg->event = LS_MSG_EVENT_DELETE;
1552 break;
1553 case SYNC:
1554 msg->event = LS_MSG_EVENT_SYNC;
1555 break;
1556 default:
1557 msg->event = LS_MSG_EVENT_UNDEF;
1558 break;
1559 }
1560 msg->data.prefix = subnet->ls_pref;
1561 msg->remote_id.origin = UNKNOWN;
1562
1563 return msg;
1564 }
1565
1566 struct ls_vertex *ls_msg2vertex(struct ls_ted *ted, struct ls_message *msg,
1567 bool delete)
1568 {
1569 struct ls_node *node = (struct ls_node *)msg->data.node;
1570 struct ls_vertex *vertex = NULL;
1571
1572 switch (msg->event) {
1573 case LS_MSG_EVENT_SYNC:
1574 vertex = ls_vertex_add(ted, node);
1575 if (vertex)
1576 vertex->status = SYNC;
1577 break;
1578 case LS_MSG_EVENT_ADD:
1579 vertex = ls_vertex_add(ted, node);
1580 if (vertex)
1581 vertex->status = NEW;
1582 break;
1583 case LS_MSG_EVENT_UPDATE:
1584 vertex = ls_vertex_update(ted, node);
1585 if (vertex)
1586 vertex->status = UPDATE;
1587 break;
1588 case LS_MSG_EVENT_DELETE:
1589 vertex = ls_find_vertex_by_id(ted, node->adv);
1590 if (vertex) {
1591 if (delete)
1592 ls_vertex_del_all(ted, vertex);
1593 else
1594 vertex->status = DELETE;
1595 }
1596 break;
1597 default:
1598 vertex = NULL;
1599 break;
1600 }
1601
1602 return vertex;
1603 }
1604
1605 struct ls_edge *ls_msg2edge(struct ls_ted *ted, struct ls_message *msg,
1606 bool delete)
1607 {
1608 struct ls_attributes *attr = (struct ls_attributes *)msg->data.attr;
1609 struct ls_edge *edge = NULL;
1610
1611 switch (msg->event) {
1612 case LS_MSG_EVENT_SYNC:
1613 edge = ls_edge_add(ted, attr);
1614 if (edge)
1615 edge->status = SYNC;
1616 break;
1617 case LS_MSG_EVENT_ADD:
1618 edge = ls_edge_add(ted, attr);
1619 if (edge)
1620 edge->status = NEW;
1621 break;
1622 case LS_MSG_EVENT_UPDATE:
1623 edge = ls_edge_update(ted, attr);
1624 if (edge)
1625 edge->status = UPDATE;
1626 break;
1627 case LS_MSG_EVENT_DELETE:
1628 edge = ls_find_edge_by_source(ted, attr);
1629 if (edge) {
1630 if (delete)
1631 ls_edge_del_all(ted, edge);
1632 else
1633 edge->status = DELETE;
1634 }
1635 break;
1636 default:
1637 edge = NULL;
1638 break;
1639 }
1640
1641 return edge;
1642 }
1643
1644 struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg,
1645 bool delete)
1646 {
1647 struct ls_prefix *pref = (struct ls_prefix *)msg->data.prefix;
1648 struct ls_subnet *subnet = NULL;
1649
1650 switch (msg->event) {
1651 case LS_MSG_EVENT_SYNC:
1652 subnet = ls_subnet_add(ted, pref);
1653 if (subnet)
1654 subnet->status = SYNC;
1655 break;
1656 case LS_MSG_EVENT_ADD:
1657 subnet = ls_subnet_add(ted, pref);
1658 if (subnet)
1659 subnet->status = NEW;
1660 break;
1661 case LS_MSG_EVENT_UPDATE:
1662 subnet = ls_subnet_update(ted, pref);
1663 if (subnet)
1664 subnet->status = UPDATE;
1665 break;
1666 case LS_MSG_EVENT_DELETE:
1667 subnet = ls_find_subnet(ted, pref->pref);
1668 if (subnet) {
1669 if (delete)
1670 ls_subnet_del_all(ted, subnet);
1671 else
1672 subnet->status = DELETE;
1673 }
1674 break;
1675 default:
1676 subnet = NULL;
1677 break;
1678 }
1679
1680 return subnet;
1681 }
1682
1683 struct ls_element *ls_msg2ted(struct ls_ted *ted, struct ls_message *msg,
1684 bool delete)
1685 {
1686 struct ls_element *lse = NULL;
1687
1688 switch (msg->type) {
1689 case LS_MSG_TYPE_NODE:
1690 lse = (struct ls_element *)ls_msg2vertex(ted, msg, delete);
1691 break;
1692 case LS_MSG_TYPE_ATTRIBUTES:
1693 lse = (struct ls_element *)ls_msg2edge(ted, msg, delete);
1694 break;
1695 case LS_MSG_TYPE_PREFIX:
1696 lse = (struct ls_element *)ls_msg2subnet(ted, msg, delete);
1697 break;
1698 default:
1699 lse = NULL;
1700 break;
1701 }
1702
1703 return lse;
1704 }
1705
1706 struct ls_element *ls_stream2ted(struct ls_ted *ted, struct stream *s,
1707 bool delete)
1708 {
1709 struct ls_message *msg;
1710 struct ls_element *lse = NULL;
1711
1712 msg = ls_parse_msg(s);
1713 if (msg) {
1714 lse = ls_msg2ted(ted, msg, delete);
1715 ls_delete_msg(msg);
1716 }
1717
1718 return lse;
1719 }
1720
1721 void ls_delete_msg(struct ls_message *msg)
1722 {
1723 if (msg == NULL)
1724 return;
1725
1726 XFREE(MTYPE_LS_DB, msg);
1727 }
1728
1729 int ls_sync_ted(struct ls_ted *ted, struct zclient *zclient,
1730 struct zapi_opaque_reg_info *dst)
1731 {
1732 struct ls_vertex *vertex;
1733 struct ls_edge *edge;
1734 struct ls_subnet *subnet;
1735 struct ls_message msg;
1736
1737 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1738 frr_each(vertices, &ted->vertices, vertex) {
1739 ls_vertex2msg(&msg, vertex);
1740 ls_send_msg(zclient, &msg, dst);
1741 }
1742 frr_each(edges, &ted->edges, edge) {
1743 ls_edge2msg(&msg, edge);
1744 ls_send_msg(zclient, &msg, dst);
1745 }
1746 frr_each(subnets, &ted->subnets, subnet) {
1747 ls_subnet2msg(&msg, subnet);
1748 ls_send_msg(zclient, &msg, dst);
1749 }
1750 return 0;
1751 }
1752
1753 /**
1754 * Link State Show functions
1755 */
1756 static const char *const origin2txt[] = {
1757 "Unknown",
1758 "ISIS_L1",
1759 "ISIS_L2",
1760 "OSPFv2",
1761 "Direct",
1762 "Static"
1763 };
1764
1765 static const char *const type2txt[] = {
1766 "Unknown",
1767 "Standard",
1768 "ABR",
1769 "ASBR",
1770 "Remote ASBR",
1771 "Pseudo"
1772 };
1773
1774 static const char *const status2txt[] = {
1775 "Unknown",
1776 "New",
1777 "Update",
1778 "Delete",
1779 "Sync",
1780 "Orphan"
1781 };
1782
1783 static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str,
1784 size_t size)
1785 {
1786 if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) {
1787 uint8_t *id;
1788
1789 id = lnid.id.iso.sys_id;
1790 snprintfrr(str, size, "%02x%02x.%02x%02x.%02x%02x", id[0],
1791 id[1], id[2], id[3], id[4], id[5]);
1792 } else
1793 snprintfrr(str, size, "%pI4", &lnid.id.ip.addr);
1794
1795 return str;
1796 }
1797
1798 static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
1799 bool verbose)
1800 {
1801 struct listnode *node;
1802 struct ls_node *lsn;
1803 struct ls_edge *edge;
1804 struct ls_subnet *subnet;
1805 struct sbuf sbuf;
1806 uint32_t upper;
1807
1808 /* Sanity Check */
1809 if (!vertex)
1810 return;
1811
1812 lsn = vertex->node;
1813
1814 sbuf_init(&sbuf, NULL, 0);
1815
1816 sbuf_push(&sbuf, 2, "Vertex (%" PRIu64 "): %s", vertex->key, lsn->name);
1817 sbuf_push(&sbuf, 0, "\tRouter Id: %pI4", &lsn->router_id);
1818 sbuf_push(&sbuf, 0, "\tOrigin: %s", origin2txt[lsn->adv.origin]);
1819 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[vertex->status]);
1820 if (!verbose) {
1821 sbuf_push(
1822 &sbuf, 0,
1823 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
1824 listcount(vertex->outgoing_edges),
1825 listcount(vertex->incoming_edges),
1826 listcount(vertex->prefixes));
1827 goto end;
1828 }
1829
1830 if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
1831 sbuf_push(&sbuf, 4, "Type: %s\n", type2txt[lsn->type]);
1832 if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
1833 sbuf_push(&sbuf, 4, "AS number: %u\n", lsn->as_number);
1834 if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
1835 sbuf_push(&sbuf, 4, "Segment Routing Capabilities:\n");
1836 upper = lsn->srgb.lower_bound + lsn->srgb.range_size - 1;
1837 sbuf_push(&sbuf, 8, "SRGB: [%d/%d]", lsn->srgb.lower_bound,
1838 upper);
1839 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
1840 upper = lsn->srlb.lower_bound + lsn->srlb.range_size
1841 - 1;
1842 sbuf_push(&sbuf, 0, "\tSRLB: [%d/%d]",
1843 lsn->srlb.lower_bound, upper);
1844 }
1845 sbuf_push(&sbuf, 0, "\tAlgo: ");
1846 for (int i = 0; i < 2; i++) {
1847 if (lsn->algo[i] == 255)
1848 continue;
1849
1850 sbuf_push(&sbuf, 0,
1851 lsn->algo[i] == 0 ? "SPF " : "S-SPF ");
1852 }
1853 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
1854 sbuf_push(&sbuf, 0, "\tMSD: %d", lsn->msd);
1855 sbuf_push(&sbuf, 0, "\n");
1856 }
1857
1858 sbuf_push(&sbuf, 4, "Outgoing Edges: %d\n",
1859 listcount(vertex->outgoing_edges));
1860 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) {
1861 if (edge->destination) {
1862 lsn = edge->destination->node;
1863 sbuf_push(&sbuf, 6, "To:\t%s(%pI4)", lsn->name,
1864 &lsn->router_id);
1865 } else {
1866 sbuf_push(&sbuf, 6, "To:\t- (0.0.0.0)");
1867 }
1868 sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
1869 &edge->attributes->standard.local,
1870 &edge->attributes->standard.remote);
1871 }
1872
1873 sbuf_push(&sbuf, 4, "Incoming Edges: %d\n",
1874 listcount(vertex->incoming_edges));
1875 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, node, edge)) {
1876 if (edge->source) {
1877 lsn = edge->source->node;
1878 sbuf_push(&sbuf, 6, "From:\t%s(%pI4)", lsn->name,
1879 &lsn->router_id);
1880 } else {
1881 sbuf_push(&sbuf, 6, "From:\t- (0.0.0.0)");
1882 }
1883 sbuf_push(&sbuf, 0, "\tRemote: %pI4\tLocal: %pI4\n",
1884 &edge->attributes->standard.local,
1885 &edge->attributes->standard.remote);
1886 }
1887
1888 sbuf_push(&sbuf, 4, "Subnets: %d\n", listcount(vertex->prefixes));
1889 for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
1890 sbuf_push(&sbuf, 6, "Prefix:\t%pFX\n", &subnet->key);
1891
1892 end:
1893 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
1894 sbuf_free(&sbuf);
1895 }
1896
1897 static void ls_show_vertex_json(struct ls_vertex *vertex,
1898 struct json_object *json)
1899 {
1900 struct ls_node *lsn;
1901 json_object *jsr, *jalgo, *jobj;
1902 char buf[INET6_BUFSIZ];
1903
1904 /* Sanity Check */
1905 if (!vertex)
1906 return;
1907
1908 lsn = vertex->node;
1909
1910 json_object_int_add(json, "vertex-id", vertex->key);
1911 json_object_string_add(json, "status", status2txt[vertex->status]);
1912 json_object_string_add(json, "origin", origin2txt[lsn->adv.origin]);
1913 if (CHECK_FLAG(lsn->flags, LS_NODE_NAME))
1914 json_object_string_add(json, "name", lsn->name);
1915 if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID)) {
1916 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &lsn->router_id);
1917 json_object_string_add(json, "router-id", buf);
1918 }
1919 if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID6)) {
1920 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router6_id);
1921 json_object_string_add(json, "router-id-v6", buf);
1922 }
1923 if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
1924 json_object_string_add(json, "vertex-type",
1925 type2txt[lsn->type]);
1926 if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
1927 json_object_int_add(json, "asn", lsn->as_number);
1928 if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
1929 jsr = json_object_new_object();
1930 json_object_object_add(json, "segment-routing", jsr);
1931 json_object_int_add(jsr, "srgb-size", lsn->srgb.range_size);
1932 json_object_int_add(jsr, "srgb-lower", lsn->srgb.lower_bound);
1933 jalgo = json_object_new_array();
1934 json_object_object_add(jsr, "algorithms", jalgo);
1935 for (int i = 0; i < 2; i++) {
1936 if (lsn->algo[i] == 255)
1937 continue;
1938 jobj = json_object_new_object();
1939
1940 snprintfrr(buf, 2, "%u", i);
1941 json_object_string_add(
1942 jobj, buf, lsn->algo[i] == 0 ? "SPF" : "S-SPF");
1943 json_object_array_add(jalgo, jobj);
1944 }
1945 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
1946 json_object_int_add(jsr, "srlb-size",
1947 lsn->srlb.range_size);
1948 json_object_int_add(jsr, "srlb-lower",
1949 lsn->srlb.lower_bound);
1950 }
1951 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
1952 json_object_int_add(jsr, "msd", lsn->msd);
1953 }
1954 }
1955
1956 void ls_show_vertex(struct ls_vertex *vertex, struct vty *vty,
1957 struct json_object *json, bool verbose)
1958 {
1959 if (json)
1960 ls_show_vertex_json(vertex, json);
1961 else if (vty)
1962 ls_show_vertex_vty(vertex, vty, verbose);
1963 }
1964
1965 void ls_show_vertices(struct ls_ted *ted, struct vty *vty,
1966 struct json_object *json, bool verbose)
1967 {
1968 struct ls_vertex *vertex;
1969 json_object *jnodes, *jnode;
1970
1971 if (json) {
1972 jnodes = json_object_new_array();
1973 json_object_object_add(json, "vertices", jnodes);
1974 frr_each (vertices, &ted->vertices, vertex) {
1975 jnode = json_object_new_object();
1976 ls_show_vertex(vertex, NULL, jnode, verbose);
1977 json_object_array_add(jnodes, jnode);
1978 }
1979 } else if (vty) {
1980 frr_each (vertices, &ted->vertices, vertex)
1981 ls_show_vertex(vertex, vty, NULL, verbose);
1982 }
1983 }
1984
1985 static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
1986 bool verbose)
1987 {
1988 struct ls_attributes *attr;
1989 struct sbuf sbuf;
1990 char buf[INET6_BUFSIZ];
1991
1992 attr = edge->attributes;
1993 sbuf_init(&sbuf, NULL, 0);
1994
1995 sbuf_push(&sbuf, 2, "Edge (%" PRIu64 "): ", edge->key);
1996 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1997 sbuf_push(&sbuf, 0, "%pI4", &attr->standard.local);
1998 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1999 sbuf_push(&sbuf, 0, "%pI6", &attr->standard.local6);
2000 else
2001 sbuf_push(&sbuf, 0, "%u/%u", attr->standard.local_id,
2002 attr->standard.remote_id);
2003 ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
2004 sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
2005 sbuf_push(&sbuf, 0, "\tMetric: %u", attr->metric);
2006 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[edge->status]);
2007
2008 if (!verbose)
2009 goto end;
2010
2011 sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[attr->adv.origin]);
2012 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
2013 sbuf_push(&sbuf, 4, "Name: %s\n", attr->name);
2014 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
2015 sbuf_push(&sbuf, 4, "TE Metric: %u\n",
2016 attr->standard.te_metric);
2017 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
2018 sbuf_push(&sbuf, 4, "Admin Group: 0x%x\n",
2019 attr->standard.admin_group);
2020 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
2021 sbuf_push(&sbuf, 4, "Local IPv4 address: %pI4\n",
2022 &attr->standard.local);
2023 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
2024 sbuf_push(&sbuf, 4, "Remote IPv4 address: %pI4\n",
2025 &attr->standard.remote);
2026 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
2027 sbuf_push(&sbuf, 4, "Local IPv6 address: %pI6\n",
2028 &attr->standard.local6);
2029 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
2030 sbuf_push(&sbuf, 4, "Remote IPv6 address: %pI6\n",
2031 &attr->standard.remote6);
2032 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
2033 sbuf_push(&sbuf, 4, "Local Identifier: %u\n",
2034 attr->standard.local_id);
2035 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
2036 sbuf_push(&sbuf, 4, "Remote Identifier: %u\n",
2037 attr->standard.remote_id);
2038 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
2039 sbuf_push(&sbuf, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2040 attr->standard.max_bw);
2041 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
2042 sbuf_push(&sbuf, 4,
2043 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2044 attr->standard.max_rsv_bw);
2045 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
2046 sbuf_push(&sbuf, 4, "Unreserved Bandwidth per Class Type\n");
2047 for (int i = 0; i < MAX_CLASS_TYPE; i += 2)
2048 sbuf_push(&sbuf, 8,
2049 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2050 i, attr->standard.unrsv_bw[i], i + 1,
2051 attr->standard.unrsv_bw[i + 1]);
2052 }
2053 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
2054 sbuf_push(&sbuf, 4, "Remote AS: %u\n",
2055 attr->standard.remote_as);
2056 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
2057 sbuf_push(&sbuf, 4, "Remote ASBR IPv4 address: %pI4\n",
2058 &attr->standard.remote_addr);
2059 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
2060 sbuf_push(&sbuf, 4, "Remote ASBR IPv6 address: %pI6\n",
2061 &attr->standard.remote_addr6);
2062 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
2063 sbuf_push(&sbuf, 4, "Average Link Delay: %d (micro-sec)\n",
2064 attr->extended.delay);
2065 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY))
2066 sbuf_push(&sbuf, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2067 attr->extended.min_delay, attr->extended.max_delay);
2068 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
2069 sbuf_push(&sbuf, 4, "Delay Variation: %d (micro-sec)\n",
2070 attr->extended.jitter);
2071 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
2072 sbuf_push(&sbuf, 4, "Link Loss: %g (%%)\n",
2073 (float)(attr->extended.pkt_loss * LOSS_PRECISION));
2074 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
2075 sbuf_push(&sbuf, 4, "Available Bandwidth: %g (Bytes/s)\n",
2076 attr->extended.ava_bw);
2077 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
2078 sbuf_push(&sbuf, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2079 attr->extended.rsv_bw);
2080 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
2081 sbuf_push(&sbuf, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2082 attr->extended.used_bw);
2083 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
2084 sbuf_push(&sbuf, 4, "Adjacency-SID: %u", attr->adj_sid[0].sid);
2085 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2086 attr->adj_sid[0].flags, attr->adj_sid[0].weight);
2087 }
2088 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2089 sbuf_push(&sbuf, 4, "Bck. Adjacency-SID: %u",
2090 attr->adj_sid[1].sid);
2091 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2092 attr->adj_sid[1].flags, attr->adj_sid[1].weight);
2093 }
2094 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
2095 sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
2096 for (int i = 1; i < attr->srlg_len; i++) {
2097 if (i % 8)
2098 sbuf_push(&sbuf, 8, "\n%u", attr->srlgs[i]);
2099 else
2100 sbuf_push(&sbuf, 8, ", %u", attr->srlgs[i]);
2101 }
2102 sbuf_push(&sbuf, 0, "\n");
2103 }
2104
2105 end:
2106 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2107 sbuf_free(&sbuf);
2108 }
2109
2110 static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
2111 {
2112 struct ls_attributes *attr;
2113 struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg;
2114 char buf[INET6_BUFSIZ];
2115
2116 attr = edge->attributes;
2117
2118 json_object_int_add(json, "edge-id", edge->key);
2119 json_object_string_add(json, "status", status2txt[edge->status]);
2120 json_object_string_add(json, "origin", origin2txt[attr->adv.origin]);
2121 ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
2122 json_object_string_add(json, "advertised-router", buf);
2123 if (edge->source)
2124 json_object_int_add(json, "local-vertex-id", edge->source->key);
2125 if (edge->destination)
2126 json_object_int_add(json, "remote-vertex-id",
2127 edge->destination->key);
2128 json_object_int_add(json, "metric", attr->metric);
2129 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
2130 json_object_string_add(json, "name", attr->name);
2131 jte = json_object_new_object();
2132 json_object_object_add(json, "edge-attributes", jte);
2133 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
2134 json_object_int_add(jte, "te-metric", attr->standard.te_metric);
2135 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
2136 json_object_int_add(jte, "admin-group",
2137 attr->standard.admin_group);
2138 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)) {
2139 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.local);
2140 json_object_string_add(jte, "local-address", buf);
2141 }
2142 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR)) {
2143 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.remote);
2144 json_object_string_add(jte, "remote-address", buf);
2145 }
2146 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)) {
2147 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.local6);
2148 json_object_string_add(jte, "local-address-v6", buf);
2149 }
2150 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6)) {
2151 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.remote6);
2152 json_object_string_add(jte, "remote-address-v6", buf);
2153 }
2154 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
2155 json_object_int_add(jte, "local-identifier",
2156 attr->standard.local_id);
2157 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
2158 json_object_int_add(jte, "remote-identifier",
2159 attr->standard.remote_id);
2160 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
2161 json_object_double_add(jte, "max-link-bandwidth",
2162 attr->standard.max_bw);
2163 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
2164 json_object_double_add(jte, "max-resv-link-bandwidth",
2165 attr->standard.max_rsv_bw);
2166 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
2167 jbw = json_object_new_array();
2168 json_object_object_add(jte, "unreserved-bandwidth", jbw);
2169 for (int i = 0; i < MAX_CLASS_TYPE; i++) {
2170 jobj = json_object_new_object();
2171 snprintfrr(buf, 13, "class-type-%u", i);
2172 json_object_double_add(jobj, buf,
2173 attr->standard.unrsv_bw[i]);
2174 json_object_array_add(jbw, jobj);
2175 }
2176 }
2177 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
2178 json_object_int_add(jte, "remote-asn",
2179 attr->standard.remote_as);
2180 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR)) {
2181 snprintfrr(buf, INET6_BUFSIZ, "%pI4",
2182 &attr->standard.remote_addr);
2183 json_object_string_add(jte, "remote-as-address", buf);
2184 }
2185 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6)) {
2186 snprintfrr(buf, INET6_BUFSIZ, "%pI6",
2187 &attr->standard.remote_addr6);
2188 json_object_string_add(jte, "remote-as-address-v6", buf);
2189 }
2190 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
2191 json_object_int_add(jte, "delay", attr->extended.delay);
2192 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
2193 json_object_int_add(jte, "min-delay", attr->extended.min_delay);
2194 json_object_int_add(jte, "max-delay", attr->extended.max_delay);
2195 }
2196 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
2197 json_object_int_add(jte, "jitter", attr->extended.jitter);
2198 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
2199 json_object_double_add(
2200 jte, "loss", attr->extended.pkt_loss * LOSS_PRECISION);
2201 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
2202 json_object_double_add(jte, "available-bandwidth",
2203 attr->extended.ava_bw);
2204 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
2205 json_object_double_add(jte, "residual-bandwidth",
2206 attr->extended.rsv_bw);
2207 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
2208 json_object_double_add(jte, "utilized-bandwidth",
2209 attr->extended.used_bw);
2210 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
2211 jsrlg = json_object_new_array();
2212 json_object_object_add(jte, "srlgs", jsrlg);
2213 for (int i = 1; i < attr->srlg_len; i++) {
2214 jobj = json_object_new_object();
2215 json_object_int_add(jobj, "srlg", attr->srlgs[i]);
2216 json_object_array_add(jsrlg, jobj);
2217 }
2218 }
2219 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
2220 jsr = json_object_new_array();
2221 json_object_object_add(json, "segment-routing", jsr);
2222 jobj = json_object_new_object();
2223 json_object_int_add(jobj, "adj-sid", attr->adj_sid[0].sid);
2224 snprintfrr(buf, 6, "0x%x", attr->adj_sid[0].flags);
2225 json_object_string_add(jobj, "flags", buf);
2226 json_object_int_add(jobj, "weight", attr->adj_sid[0].weight);
2227 json_object_array_add(jsr, jobj);
2228 }
2229 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2230 if (!jsr) {
2231 jsr = json_object_new_array();
2232 json_object_object_add(json, "segment-routing", jsr);
2233 }
2234 jobj = json_object_new_object();
2235 json_object_int_add(jobj, "adj-sid", attr->adj_sid[1].sid);
2236 snprintfrr(buf, 6, "0x%x", attr->adj_sid[1].flags);
2237 json_object_string_add(jobj, "flags", buf);
2238 json_object_int_add(jobj, "weight", attr->adj_sid[1].weight);
2239 json_object_array_add(jsr, jobj);
2240 }
2241 }
2242
2243 void ls_show_edge(struct ls_edge *edge, struct vty *vty,
2244 struct json_object *json, bool verbose)
2245 {
2246 /* Sanity Check */
2247 if (!edge)
2248 return;
2249
2250 if (json)
2251 ls_show_edge_json(edge, json);
2252 else if (vty)
2253 ls_show_edge_vty(edge, vty, verbose);
2254 }
2255
2256 void ls_show_edges(struct ls_ted *ted, struct vty *vty,
2257 struct json_object *json, bool verbose)
2258 {
2259 struct ls_edge *edge;
2260 json_object *jedges, *jedge;
2261
2262 if (json) {
2263 jedges = json_object_new_array();
2264 json_object_object_add(json, "edges", jedges);
2265 frr_each (edges, &ted->edges, edge) {
2266 jedge = json_object_new_object();
2267 ls_show_edge(edge, NULL, jedge, verbose);
2268 json_object_array_add(jedges, jedge);
2269 }
2270 } else if (vty) {
2271 frr_each (edges, &ted->edges, edge)
2272 ls_show_edge(edge, vty, NULL, verbose);
2273 }
2274 }
2275
2276 static void ls_show_subnet_vty(struct ls_subnet *subnet, struct vty *vty,
2277 bool verbose)
2278 {
2279 struct ls_prefix *pref;
2280 struct sbuf sbuf;
2281 char buf[INET6_BUFSIZ];
2282
2283 pref = subnet->ls_pref;
2284 sbuf_init(&sbuf, NULL, 0);
2285
2286 sbuf_push(&sbuf, 2, "Subnet: %pFX", &subnet->key);
2287 ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
2288 sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
2289 sbuf_push(&sbuf, 0, "\tMetric: %d", pref->metric);
2290 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[subnet->status]);
2291
2292 if (!verbose)
2293 goto end;
2294
2295 sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[pref->adv.origin]);
2296 if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG))
2297 sbuf_push(&sbuf, 4, "Flags: %d\n", pref->igp_flag);
2298
2299 if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
2300 sbuf_push(&sbuf, 4, "Tag: %d\n", pref->route_tag);
2301
2302 if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
2303 sbuf_push(&sbuf, 4, "Extended Tag: %" PRIu64 "\n",
2304 pref->extended_tag);
2305
2306 if (CHECK_FLAG(pref->flags, LS_PREF_SR))
2307 sbuf_push(&sbuf, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2308 pref->sr.sid, pref->sr.algo, pref->sr.sid_flag);
2309
2310 end:
2311 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2312 sbuf_free(&sbuf);
2313 }
2314
2315 static void ls_show_subnet_json(struct ls_subnet *subnet,
2316 struct json_object *json)
2317 {
2318 struct ls_prefix *pref;
2319 json_object *jsr;
2320 char buf[INET6_BUFSIZ];
2321
2322 pref = subnet->ls_pref;
2323
2324 snprintfrr(buf, INET6_BUFSIZ, "%pFX", &subnet->key);
2325 json_object_string_add(json, "subnet-id", buf);
2326 json_object_string_add(json, "status", status2txt[subnet->status]);
2327 json_object_string_add(json, "origin", origin2txt[pref->adv.origin]);
2328 ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
2329 json_object_string_add(json, "advertised-router", buf);
2330 if (subnet->vertex)
2331 json_object_int_add(json, "vertex-id", subnet->vertex->key);
2332 json_object_int_add(json, "metric", pref->metric);
2333 if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG)) {
2334 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->igp_flag);
2335 json_object_string_add(json, "flags", buf);
2336 }
2337 if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
2338 json_object_int_add(json, "tag", pref->route_tag);
2339 if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
2340 json_object_int_add(json, "extended-tag", pref->extended_tag);
2341 if (CHECK_FLAG(pref->flags, LS_PREF_SR)) {
2342 jsr = json_object_new_object();
2343 json_object_object_add(json, "segment-routing", jsr);
2344 json_object_int_add(jsr, "pref-sid", pref->sr.sid);
2345 json_object_int_add(jsr, "algo", pref->sr.algo);
2346 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
2347 json_object_string_add(jsr, "flags", buf);
2348 }
2349 }
2350
2351 void ls_show_subnet(struct ls_subnet *subnet, struct vty *vty,
2352 struct json_object *json, bool verbose)
2353 {
2354 /* Sanity Check */
2355 if (!subnet)
2356 return;
2357
2358 if (json)
2359 ls_show_subnet_json(subnet, json);
2360 else if (vty)
2361 ls_show_subnet_vty(subnet, vty, verbose);
2362 }
2363
2364 void ls_show_subnets(struct ls_ted *ted, struct vty *vty,
2365 struct json_object *json, bool verbose)
2366 {
2367 struct ls_subnet *subnet;
2368 json_object *jsubs, *jsub;
2369
2370 if (json) {
2371 jsubs = json_object_new_array();
2372 json_object_object_add(json, "subnets", jsubs);
2373 frr_each (subnets, &ted->subnets, subnet) {
2374 jsub = json_object_new_object();
2375 ls_show_subnet(subnet, NULL, jsub, verbose);
2376 json_object_array_add(jsubs, jsub);
2377 }
2378 } else if (vty) {
2379 frr_each (subnets, &ted->subnets, subnet)
2380 ls_show_subnet(subnet, vty, NULL, verbose);
2381 }
2382 }
2383
2384 void ls_show_ted(struct ls_ted *ted, struct vty *vty, struct json_object *json,
2385 bool verbose)
2386 {
2387 json_object *jted;
2388
2389 if (json) {
2390 jted = json_object_new_object();
2391 json_object_object_add(json, "ted", jted);
2392 json_object_string_add(jted, "name", ted->name);
2393 json_object_int_add(jted, "key", ted->key);
2394 json_object_int_add(jted, "verticesCount",
2395 vertices_count(&ted->vertices));
2396 json_object_int_add(jted, "edgesCount",
2397 edges_count(&ted->edges));
2398 json_object_int_add(jted, "subnetsCount",
2399 subnets_count(&ted->subnets));
2400 ls_show_vertices(ted, NULL, jted, verbose);
2401 ls_show_edges(ted, NULL, jted, verbose);
2402 ls_show_subnets(ted, NULL, jted, verbose);
2403 return;
2404 }
2405
2406 if (vty) {
2407 vty_out(vty,
2408 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2409 ted->name, ted->key);
2410 ls_show_vertices(ted, vty, NULL, verbose);
2411 ls_show_edges(ted, vty, NULL, verbose);
2412 ls_show_subnets(ted, vty, NULL, verbose);
2413 vty_out(vty,
2414 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2415 vertices_count(&ted->vertices),
2416 edges_count(&ted->edges), subnets_count(&ted->subnets));
2417 }
2418 }
2419
2420 void ls_dump_ted(struct ls_ted *ted)
2421 {
2422 struct ls_vertex *vertex;
2423 struct ls_edge *edge;
2424 struct ls_subnet *subnet;
2425 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
2426
2427 zlog_debug("(%s) Ted init", __func__);
2428
2429 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2430 frr_each (vertices, &ted->vertices, vertex) {
2431 zlog_debug(" Ted node (%s %pI4 %s)",
2432 vertex->node->name[0] ? vertex->node->name
2433 : "no name node",
2434 &vertex->node->router_id,
2435 origin2txt[vertex->node->adv.origin]);
2436 struct listnode *lst_node;
2437 struct ls_edge *vertex_edge;
2438
2439 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, lst_node,
2440 vertex_edge)) {
2441 zlog_debug(
2442 " inc edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2443 vertex_edge->key,
2444 &vertex_edge->attributes->adv.id.ip.addr,
2445 &vertex_edge->attributes->standard.local,
2446 &vertex_edge->attributes->standard.remote);
2447 }
2448 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, lst_node,
2449 vertex_edge)) {
2450 zlog_debug(
2451 " out edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2452 vertex_edge->key,
2453 &vertex_edge->attributes->adv.id.ip.addr,
2454 &vertex_edge->attributes->standard.local,
2455 &vertex_edge->attributes->standard.remote);
2456 }
2457 }
2458 frr_each (edges, &ted->edges, edge) {
2459 zlog_debug(" Ted edge key:%" PRIu64 "src:%pI4 dst:%pI4", edge->key,
2460 edge->source ? &edge->source->node->router_id
2461 : &inaddr_any,
2462 edge->destination
2463 ? &edge->destination->node->router_id
2464 : &inaddr_any);
2465 }
2466 frr_each (subnets, &ted->subnets, subnet) {
2467 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2468 &subnet->ls_pref->pref,
2469 &subnet->vertex->node->adv.id.ip.addr);
2470 }
2471 zlog_debug("(%s) Ted end", __func__);
2472 }