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