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