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