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