]> git.proxmox.com Git - mirror_frr.git/blob - lib/link_state.c
Merge pull request #13227 from mjstapp/ospf_sock_bufsizes
[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,
946 const struct prefix *prefix)
947 {
948 struct ls_subnet subnet = {};
949
950 subnet.key = *prefix;
951 return subnets_find(&ted->subnets, &subnet);
952 }
953
954 /**
955 * Link State TED management functions
956 */
957 struct ls_ted *ls_ted_new(const uint32_t key, const char *name,
958 uint32_t as_number)
959 {
960 struct ls_ted *new;
961
962 new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_ted));
963
964 /* Set basic information for this ted */
965 new->key = key;
966 new->as_number = as_number;
967 strlcpy(new->name, name, MAX_NAME_LENGTH);
968
969 /* Initialize the various RB tree */
970 vertices_init(&new->vertices);
971 edges_init(&new->edges);
972 subnets_init(&new->subnets);
973
974 return new;
975 }
976
977 void ls_ted_del(struct ls_ted *ted)
978 {
979 if (ted == NULL)
980 return;
981
982 /* Check that TED is empty */
983 if (vertices_count(&ted->vertices) || edges_count(&ted->edges)
984 || subnets_count(&ted->subnets))
985 return;
986
987 /* Release RB Tree */
988 vertices_fini(&ted->vertices);
989 edges_fini(&ted->edges);
990 subnets_fini(&ted->subnets);
991
992 XFREE(MTYPE_LS_DB, ted);
993 }
994
995 void ls_ted_del_all(struct ls_ted **ted)
996 {
997 struct ls_vertex *vertex;
998 struct ls_edge *edge;
999 struct ls_subnet *subnet;
1000
1001 if (*ted == NULL)
1002 return;
1003
1004 /* First remove Vertices, Edges and Subnets and associated Link State */
1005 frr_each_safe (vertices, &(*ted)->vertices, vertex)
1006 ls_vertex_del_all(*ted, vertex);
1007 frr_each_safe (edges, &(*ted)->edges, edge)
1008 ls_edge_del_all(*ted, edge);
1009 frr_each_safe (subnets, &(*ted)->subnets, subnet)
1010 ls_subnet_del_all(*ted, subnet);
1011
1012 /* then remove TED itself */
1013 ls_ted_del(*ted);
1014 *ted = NULL;
1015 }
1016
1017 void ls_ted_clean(struct ls_ted *ted)
1018 {
1019 struct ls_vertex *vertex;
1020 struct ls_edge *edge;
1021 struct ls_subnet *subnet;
1022
1023 if (ted == NULL)
1024 return;
1025
1026 /* First, start with Vertices */
1027 frr_each_safe (vertices, &ted->vertices, vertex)
1028 if (vertex->status == ORPHAN)
1029 ls_vertex_del_all(ted, vertex);
1030
1031 /* Then Edges */
1032 frr_each_safe (edges, &ted->edges, edge)
1033 if (edge->status == ORPHAN)
1034 ls_edge_del_all(ted, edge);
1035
1036 /* and Subnets */
1037 frr_each_safe (subnets, &ted->subnets, subnet)
1038 if (subnet->status == ORPHAN)
1039 ls_subnet_del_all(ted, subnet);
1040
1041 }
1042
1043 void ls_connect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
1044 {
1045 if (vertex == NULL || edge == NULL)
1046 return;
1047
1048 if (source) {
1049 listnode_add_sort_nodup(vertex->outgoing_edges, edge);
1050 edge->source = vertex;
1051 } else {
1052 listnode_add_sort_nodup(vertex->incoming_edges, edge);
1053 edge->destination = vertex;
1054 }
1055 }
1056
1057 void ls_disconnect(struct ls_vertex *vertex, struct ls_edge *edge, bool source)
1058 {
1059
1060 if (vertex == NULL || edge == NULL)
1061 return;
1062
1063 if (source) {
1064 listnode_delete(vertex->outgoing_edges, edge);
1065 edge->source = NULL;
1066 } else {
1067 listnode_delete(vertex->incoming_edges, edge);
1068 edge->destination = NULL;
1069 }
1070 }
1071
1072 void ls_connect_vertices(struct ls_vertex *src, struct ls_vertex *dst,
1073 struct ls_edge *edge)
1074 {
1075 if (edge == NULL)
1076 return;
1077
1078 edge->source = src;
1079 edge->destination = dst;
1080
1081 if (src != NULL)
1082 listnode_add_sort_nodup(src->outgoing_edges, edge);
1083
1084 if (dst != NULL)
1085 listnode_add_sort_nodup(dst->incoming_edges, edge);
1086 }
1087
1088 void ls_disconnect_edge(struct ls_edge *edge)
1089 {
1090 if (edge == NULL)
1091 return;
1092
1093 ls_disconnect(edge->source, edge, true);
1094 ls_disconnect(edge->destination, edge, false);
1095
1096 /* Mark this Edge as ORPHAN for future cleanup */
1097 edge->status = ORPHAN;
1098 }
1099
1100 /**
1101 * Link State Message management functions
1102 */
1103
1104 int ls_register(struct zclient *zclient, bool server)
1105 {
1106 int rc;
1107
1108 if (server)
1109 rc = zclient_register_opaque(zclient, LINK_STATE_SYNC);
1110 else
1111 rc = zclient_register_opaque(zclient, LINK_STATE_UPDATE);
1112
1113 return rc;
1114 }
1115
1116 int ls_unregister(struct zclient *zclient, bool server)
1117 {
1118 int rc;
1119
1120 if (server)
1121 rc = zclient_unregister_opaque(zclient, LINK_STATE_SYNC);
1122 else
1123 rc = zclient_unregister_opaque(zclient, LINK_STATE_UPDATE);
1124
1125 return rc;
1126 }
1127
1128 int ls_request_sync(struct zclient *zclient)
1129 {
1130 struct stream *s;
1131 uint16_t flags = 0;
1132
1133 /* Check buffer size */
1134 if (STREAM_SIZE(zclient->obuf)
1135 < (ZEBRA_HEADER_SIZE + 3 * sizeof(uint32_t)))
1136 return -1;
1137
1138 s = zclient->obuf;
1139 stream_reset(s);
1140
1141 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
1142
1143 /* Set type and flags */
1144 stream_putl(s, LINK_STATE_SYNC);
1145 stream_putw(s, flags);
1146 /* Send destination client info */
1147 stream_putc(s, zclient->redist_default);
1148 stream_putw(s, zclient->instance);
1149 stream_putl(s, zclient->session_id);
1150
1151 /* Put length into the header at the start of the stream. */
1152 stream_putw_at(s, 0, stream_get_endp(s));
1153
1154 return zclient_send_message(zclient);
1155 }
1156
1157 static struct ls_node *ls_parse_node(struct stream *s)
1158 {
1159 struct ls_node *node;
1160 size_t len;
1161
1162 node = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_node));
1163
1164 STREAM_GET(&node->adv, s, sizeof(struct ls_node_id));
1165 STREAM_GETW(s, node->flags);
1166 if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
1167 STREAM_GETC(s, len);
1168 STREAM_GET(node->name, s, len);
1169 }
1170 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
1171 node->router_id.s_addr = stream_get_ipv4(s);
1172 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
1173 STREAM_GET(&node->router_id6, s, IPV6_MAX_BYTELEN);
1174 if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
1175 STREAM_GETC(s, node->node_flag);
1176 if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
1177 STREAM_GETC(s, node->type);
1178 if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
1179 STREAM_GETL(s, node->as_number);
1180 if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
1181 STREAM_GETL(s, node->srgb.lower_bound);
1182 STREAM_GETL(s, node->srgb.range_size);
1183 STREAM_GETC(s, node->srgb.flag);
1184 STREAM_GET(node->algo, s, 2);
1185 }
1186 if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
1187 STREAM_GETL(s, node->srlb.lower_bound);
1188 STREAM_GETL(s, node->srlb.range_size);
1189 }
1190 if (CHECK_FLAG(node->flags, LS_NODE_MSD))
1191 STREAM_GETC(s, node->msd);
1192
1193 return node;
1194
1195 stream_failure:
1196 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__);
1197 XFREE(MTYPE_LS_DB, node);
1198 return NULL;
1199 }
1200
1201 static struct ls_attributes *ls_parse_attributes(struct stream *s)
1202 {
1203 struct ls_attributes *attr;
1204 uint8_t nb_ext_adm_grp;
1205 uint32_t bitmap_data;
1206 size_t len;
1207
1208 attr = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_attributes));
1209 admin_group_init(&attr->ext_admin_group);
1210 attr->srlgs = NULL;
1211
1212 STREAM_GET(&attr->adv, s, sizeof(struct ls_node_id));
1213 STREAM_GETL(s, attr->flags);
1214 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
1215 STREAM_GETC(s, len);
1216 STREAM_GET(attr->name, s, len);
1217 }
1218 if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
1219 STREAM_GETL(s, attr->metric);
1220 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
1221 STREAM_GETL(s, attr->standard.te_metric);
1222 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
1223 STREAM_GETL(s, attr->standard.admin_group);
1224 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
1225 /* Extended Administrative Group */
1226 STREAM_GETC(s, nb_ext_adm_grp);
1227 for (size_t i = 0; i < nb_ext_adm_grp; i++) {
1228 STREAM_GETL(s, bitmap_data);
1229 admin_group_bulk_set(&attr->ext_admin_group,
1230 bitmap_data, i);
1231 }
1232 }
1233 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1234 attr->standard.local.s_addr = stream_get_ipv4(s);
1235 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
1236 attr->standard.remote.s_addr = stream_get_ipv4(s);
1237 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1238 STREAM_GET(&attr->standard.local6, s, IPV6_MAX_BYTELEN);
1239 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
1240 STREAM_GET(&attr->standard.remote6, s, IPV6_MAX_BYTELEN);
1241 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
1242 STREAM_GETL(s, attr->standard.local_id);
1243 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
1244 STREAM_GETL(s, attr->standard.remote_id);
1245 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
1246 STREAM_GETF(s, attr->standard.max_bw);
1247 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
1248 STREAM_GETF(s, attr->standard.max_rsv_bw);
1249 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
1250 for (len = 0; len < MAX_CLASS_TYPE; len++)
1251 STREAM_GETF(s, attr->standard.unrsv_bw[len]);
1252 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
1253 STREAM_GETL(s, attr->standard.remote_as);
1254 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
1255 attr->standard.remote_addr.s_addr = stream_get_ipv4(s);
1256 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
1257 STREAM_GET(&attr->standard.remote_addr6, s, IPV6_MAX_BYTELEN);
1258 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
1259 STREAM_GETL(s, attr->extended.delay);
1260 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
1261 STREAM_GETL(s, attr->extended.min_delay);
1262 STREAM_GETL(s, attr->extended.max_delay);
1263 }
1264 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
1265 STREAM_GETL(s, attr->extended.jitter);
1266 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
1267 STREAM_GETL(s, attr->extended.pkt_loss);
1268 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
1269 STREAM_GETF(s, attr->extended.ava_bw);
1270 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
1271 STREAM_GETF(s, attr->extended.rsv_bw);
1272 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
1273 STREAM_GETF(s, attr->extended.used_bw);
1274 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
1275 STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
1276 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
1277 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
1278 attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr =
1279 stream_get_ipv4(s);
1280 }
1281 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
1282 STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
1283 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
1284 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
1285 attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr =
1286 stream_get_ipv4(s);
1287 }
1288 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
1289 STREAM_GETL(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
1290 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
1291 STREAM_GETC(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
1292 STREAM_GET(attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid, s,
1293 ISO_SYS_ID_LEN);
1294 }
1295 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
1296 STREAM_GETL(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
1297 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
1298 STREAM_GETC(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
1299 STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s,
1300 ISO_SYS_ID_LEN);
1301 }
1302 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
1303 STREAM_GETC(s, len);
1304 attr->srlgs = XCALLOC(MTYPE_LS_DB, len*sizeof(uint32_t));
1305 attr->srlg_len = len;
1306 for (len = 0; len < attr->srlg_len; len++)
1307 STREAM_GETL(s, attr->srlgs[len]);
1308 }
1309
1310 return attr;
1311
1312 stream_failure:
1313 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1314 __func__);
1315 /* Clean memory allocation */
1316 if (attr->srlgs != NULL)
1317 XFREE(MTYPE_LS_DB, attr->srlgs);
1318 XFREE(MTYPE_LS_DB, attr);
1319 return NULL;
1320
1321 }
1322
1323 static struct ls_prefix *ls_parse_prefix(struct stream *s)
1324 {
1325 struct ls_prefix *ls_pref;
1326 size_t len;
1327
1328 ls_pref = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix));
1329
1330 STREAM_GET(&ls_pref->adv, s, sizeof(struct ls_node_id));
1331 STREAM_GETW(s, ls_pref->flags);
1332 STREAM_GETC(s, ls_pref->pref.family);
1333 STREAM_GETW(s, ls_pref->pref.prefixlen);
1334 len = prefix_blen(&ls_pref->pref);
1335 STREAM_GET(&ls_pref->pref.u.prefix, s, len);
1336 if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
1337 STREAM_GETC(s, ls_pref->igp_flag);
1338 if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
1339 STREAM_GETL(s, ls_pref->route_tag);
1340 if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
1341 STREAM_GETQ(s, ls_pref->extended_tag);
1342 if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1343 STREAM_GETL(s, ls_pref->metric);
1344 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
1345 STREAM_GETL(s, ls_pref->sr.sid);
1346 STREAM_GETC(s, ls_pref->sr.sid_flag);
1347 STREAM_GETC(s, ls_pref->sr.algo);
1348 }
1349
1350 return ls_pref;
1351
1352 stream_failure:
1353 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__);
1354 XFREE(MTYPE_LS_DB, ls_pref);
1355 return NULL;
1356 }
1357
1358 struct ls_message *ls_parse_msg(struct stream *s)
1359 {
1360 struct ls_message *msg;
1361
1362 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1363
1364 /* Read LS Message header */
1365 STREAM_GETC(s, msg->event);
1366 STREAM_GETC(s, msg->type);
1367
1368 /* Read Message Payload */
1369 switch (msg->type) {
1370 case LS_MSG_TYPE_NODE:
1371 msg->data.node = ls_parse_node(s);
1372 break;
1373 case LS_MSG_TYPE_ATTRIBUTES:
1374 STREAM_GET(&msg->remote_id, s, sizeof(struct ls_node_id));
1375 msg->data.attr = ls_parse_attributes(s);
1376 break;
1377 case LS_MSG_TYPE_PREFIX:
1378 msg->data.prefix = ls_parse_prefix(s);
1379 break;
1380 default:
1381 zlog_err("Unsupported Payload");
1382 goto stream_failure;
1383 }
1384
1385 if (msg->data.node == NULL || msg->data.attr == NULL
1386 || msg->data.prefix == NULL)
1387 goto stream_failure;
1388
1389 return msg;
1390
1391 stream_failure:
1392 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__);
1393 XFREE(MTYPE_LS_DB, msg);
1394 return NULL;
1395 }
1396
1397 static int ls_format_node(struct stream *s, struct ls_node *node)
1398 {
1399 size_t len;
1400
1401 /* Push Advertise node information first */
1402 stream_put(s, &node->adv, sizeof(struct ls_node_id));
1403
1404 /* Push Flags & Origin then Node information if there are present */
1405 stream_putw(s, node->flags);
1406 if (CHECK_FLAG(node->flags, LS_NODE_NAME)) {
1407 len = strlen(node->name);
1408 stream_putc(s, len + 1);
1409 stream_put(s, node->name, len);
1410 stream_putc(s, '\0');
1411 }
1412 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID))
1413 stream_put_ipv4(s, node->router_id.s_addr);
1414 if (CHECK_FLAG(node->flags, LS_NODE_ROUTER_ID6))
1415 stream_put(s, &node->router_id6, IPV6_MAX_BYTELEN);
1416 if (CHECK_FLAG(node->flags, LS_NODE_FLAG))
1417 stream_putc(s, node->node_flag);
1418 if (CHECK_FLAG(node->flags, LS_NODE_TYPE))
1419 stream_putc(s, node->type);
1420 if (CHECK_FLAG(node->flags, LS_NODE_AS_NUMBER))
1421 stream_putl(s, node->as_number);
1422 if (CHECK_FLAG(node->flags, LS_NODE_SR)) {
1423 stream_putl(s, node->srgb.lower_bound);
1424 stream_putl(s, node->srgb.range_size);
1425 stream_putc(s, node->srgb.flag);
1426 stream_put(s, node->algo, 2);
1427 }
1428 if (CHECK_FLAG(node->flags, LS_NODE_SRLB)) {
1429 stream_putl(s, node->srlb.lower_bound);
1430 stream_putl(s, node->srlb.range_size);
1431 }
1432 if (CHECK_FLAG(node->flags, LS_NODE_MSD))
1433 stream_putc(s, node->msd);
1434
1435 return 0;
1436 }
1437
1438 static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
1439 {
1440 size_t len, nb_ext_adm_grp;
1441
1442 /* Push Advertise node information first */
1443 stream_put(s, &attr->adv, sizeof(struct ls_node_id));
1444
1445 /* Push Flags & Origin then LS attributes if there are present */
1446 stream_putl(s, attr->flags);
1447 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME)) {
1448 len = strlen(attr->name);
1449 stream_putc(s, len + 1);
1450 stream_put(s, attr->name, len);
1451 stream_putc(s, '\0');
1452 }
1453 if (CHECK_FLAG(attr->flags, LS_ATTR_METRIC))
1454 stream_putl(s, attr->metric);
1455 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
1456 stream_putl(s, attr->standard.te_metric);
1457 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
1458 stream_putl(s, attr->standard.admin_group);
1459 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
1460 /* Extended Administrative Group */
1461 nb_ext_adm_grp = admin_group_nb_words(&attr->ext_admin_group);
1462 stream_putc(s, nb_ext_adm_grp);
1463 for (size_t i = 0; i < nb_ext_adm_grp; i++)
1464 stream_putl(s, admin_group_get_offset(
1465 &attr->ext_admin_group, i));
1466 }
1467 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
1468 stream_put_ipv4(s, attr->standard.local.s_addr);
1469 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
1470 stream_put_ipv4(s, attr->standard.remote.s_addr);
1471 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
1472 stream_put(s, &attr->standard.local6, IPV6_MAX_BYTELEN);
1473 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
1474 stream_put(s, &attr->standard.remote6, IPV6_MAX_BYTELEN);
1475 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
1476 stream_putl(s, attr->standard.local_id);
1477 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
1478 stream_putl(s, attr->standard.remote_id);
1479 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
1480 stream_putf(s, attr->standard.max_bw);
1481 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
1482 stream_putf(s, attr->standard.max_rsv_bw);
1483 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW))
1484 for (len = 0; len < MAX_CLASS_TYPE; len++)
1485 stream_putf(s, attr->standard.unrsv_bw[len]);
1486 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
1487 stream_putl(s, attr->standard.remote_as);
1488 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
1489 stream_put_ipv4(s, attr->standard.remote_addr.s_addr);
1490 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
1491 stream_put(s, &attr->standard.remote_addr6, IPV6_MAX_BYTELEN);
1492 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
1493 stream_putl(s, attr->extended.delay);
1494 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
1495 stream_putl(s, attr->extended.min_delay);
1496 stream_putl(s, attr->extended.max_delay);
1497 }
1498 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
1499 stream_putl(s, attr->extended.jitter);
1500 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
1501 stream_putl(s, attr->extended.pkt_loss);
1502 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
1503 stream_putf(s, attr->extended.ava_bw);
1504 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
1505 stream_putf(s, attr->extended.rsv_bw);
1506 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
1507 stream_putf(s, attr->extended.used_bw);
1508 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
1509 stream_putl(s, attr->adj_sid[ADJ_PRI_IPV4].sid);
1510 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].flags);
1511 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV4].weight);
1512 stream_put_ipv4(
1513 s, attr->adj_sid[ADJ_PRI_IPV4].neighbor.addr.s_addr);
1514 }
1515 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
1516 stream_putl(s, attr->adj_sid[ADJ_BCK_IPV4].sid);
1517 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].flags);
1518 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV4].weight);
1519 stream_put_ipv4(
1520 s, attr->adj_sid[ADJ_BCK_IPV4].neighbor.addr.s_addr);
1521 }
1522 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
1523 stream_putl(s, attr->adj_sid[ADJ_PRI_IPV6].sid);
1524 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].flags);
1525 stream_putc(s, attr->adj_sid[ADJ_PRI_IPV6].weight);
1526 stream_put(s, attr->adj_sid[ADJ_PRI_IPV6].neighbor.sysid,
1527 ISO_SYS_ID_LEN);
1528 }
1529 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
1530 stream_putl(s, attr->adj_sid[ADJ_BCK_IPV6].sid);
1531 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].flags);
1532 stream_putc(s, attr->adj_sid[ADJ_BCK_IPV6].weight);
1533 stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid,
1534 ISO_SYS_ID_LEN);
1535 }
1536 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
1537 stream_putc(s, attr->srlg_len);
1538 for (len = 0; len < attr->srlg_len; len++)
1539 stream_putl(s, attr->srlgs[len]);
1540 }
1541
1542 return 0;
1543 }
1544
1545 static int ls_format_prefix(struct stream *s, struct ls_prefix *ls_pref)
1546 {
1547 size_t len;
1548
1549 /* Push Advertise node information first */
1550 stream_put(s, &ls_pref->adv, sizeof(struct ls_node_id));
1551
1552 /* Push Flags, Origin & Prefix then information if there are present */
1553 stream_putw(s, ls_pref->flags);
1554 stream_putc(s, ls_pref->pref.family);
1555 stream_putw(s, ls_pref->pref.prefixlen);
1556 len = prefix_blen(&ls_pref->pref);
1557 stream_put(s, &ls_pref->pref.u.prefix, len);
1558 if (CHECK_FLAG(ls_pref->flags, LS_PREF_IGP_FLAG))
1559 stream_putc(s, ls_pref->igp_flag);
1560 if (CHECK_FLAG(ls_pref->flags, LS_PREF_ROUTE_TAG))
1561 stream_putl(s, ls_pref->route_tag);
1562 if (CHECK_FLAG(ls_pref->flags, LS_PREF_EXTENDED_TAG))
1563 stream_putq(s, ls_pref->extended_tag);
1564 if (CHECK_FLAG(ls_pref->flags, LS_PREF_METRIC))
1565 stream_putl(s, ls_pref->metric);
1566 if (CHECK_FLAG(ls_pref->flags, LS_PREF_SR)) {
1567 stream_putl(s, ls_pref->sr.sid);
1568 stream_putc(s, ls_pref->sr.sid_flag);
1569 stream_putc(s, ls_pref->sr.algo);
1570 }
1571
1572 return 0;
1573 }
1574
1575 static int ls_format_msg(struct stream *s, struct ls_message *msg)
1576 {
1577
1578 /* Prepare Link State header */
1579 stream_putc(s, msg->event);
1580 stream_putc(s, msg->type);
1581
1582 /* Add Message Payload */
1583 switch (msg->type) {
1584 case LS_MSG_TYPE_NODE:
1585 return ls_format_node(s, msg->data.node);
1586 case LS_MSG_TYPE_ATTRIBUTES:
1587 /* Add remote node first */
1588 stream_put(s, &msg->remote_id, sizeof(struct ls_node_id));
1589 return ls_format_attributes(s, msg->data.attr);
1590 case LS_MSG_TYPE_PREFIX:
1591 return ls_format_prefix(s, msg->data.prefix);
1592 default:
1593 zlog_warn("Unsupported Payload");
1594 break;
1595 }
1596
1597 return -1;
1598 }
1599
1600 int ls_send_msg(struct zclient *zclient, struct ls_message *msg,
1601 struct zapi_opaque_reg_info *dst)
1602 {
1603 struct stream *s;
1604 uint16_t flags = 0;
1605
1606 /* Check if we have a valid message */
1607 if (msg->event == LS_MSG_EVENT_UNDEF)
1608 return -1;
1609
1610 /* Check buffer size */
1611 if (STREAM_SIZE(zclient->obuf) <
1612 (ZEBRA_HEADER_SIZE + sizeof(uint32_t) + sizeof(msg)))
1613 return -1;
1614
1615 s = zclient->obuf;
1616 stream_reset(s);
1617
1618 zclient_create_header(s, ZEBRA_OPAQUE_MESSAGE, VRF_DEFAULT);
1619
1620 /* Set sub-type, flags and destination for unicast message */
1621 stream_putl(s, LINK_STATE_UPDATE);
1622 if (dst != NULL) {
1623 SET_FLAG(flags, ZAPI_OPAQUE_FLAG_UNICAST);
1624 stream_putw(s, flags);
1625 /* Send destination client info */
1626 stream_putc(s, dst->proto);
1627 stream_putw(s, dst->instance);
1628 stream_putl(s, dst->session_id);
1629 } else {
1630 stream_putw(s, flags);
1631 }
1632
1633 /* Format Link State message */
1634 if (ls_format_msg(s, msg) < 0) {
1635 stream_reset(s);
1636 return -1;
1637 }
1638
1639 /* Put length into the header at the start of the stream. */
1640 stream_putw_at(s, 0, stream_get_endp(s));
1641
1642 return zclient_send_message(zclient);
1643 }
1644 struct ls_message *ls_vertex2msg(struct ls_message *msg,
1645 struct ls_vertex *vertex)
1646 {
1647 /* Allocate space if needed */
1648 if (msg == NULL)
1649 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1650 else
1651 memset(msg, 0, sizeof(*msg));
1652
1653 msg->type = LS_MSG_TYPE_NODE;
1654 switch (vertex->status) {
1655 case NEW:
1656 msg->event = LS_MSG_EVENT_ADD;
1657 break;
1658 case UPDATE:
1659 msg->event = LS_MSG_EVENT_UPDATE;
1660 break;
1661 case DELETE:
1662 msg->event = LS_MSG_EVENT_DELETE;
1663 break;
1664 case SYNC:
1665 msg->event = LS_MSG_EVENT_SYNC;
1666 break;
1667 case UNSET:
1668 case ORPHAN:
1669 msg->event = LS_MSG_EVENT_UNDEF;
1670 break;
1671 }
1672 msg->data.node = vertex->node;
1673 msg->remote_id.origin = UNKNOWN;
1674
1675 return msg;
1676 }
1677
1678 struct ls_message *ls_edge2msg(struct ls_message *msg, struct ls_edge *edge)
1679 {
1680 /* Allocate space if needed */
1681 if (msg == NULL)
1682 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1683 else
1684 memset(msg, 0, sizeof(*msg));
1685
1686 msg->type = LS_MSG_TYPE_ATTRIBUTES;
1687 switch (edge->status) {
1688 case NEW:
1689 msg->event = LS_MSG_EVENT_ADD;
1690 break;
1691 case UPDATE:
1692 msg->event = LS_MSG_EVENT_UPDATE;
1693 break;
1694 case DELETE:
1695 msg->event = LS_MSG_EVENT_DELETE;
1696 break;
1697 case SYNC:
1698 msg->event = LS_MSG_EVENT_SYNC;
1699 break;
1700 case UNSET:
1701 case ORPHAN:
1702 msg->event = LS_MSG_EVENT_UNDEF;
1703 break;
1704 }
1705 msg->data.attr = edge->attributes;
1706 if (edge->destination != NULL)
1707 msg->remote_id = edge->destination->node->adv;
1708 else
1709 msg->remote_id.origin = UNKNOWN;
1710
1711 return msg;
1712 }
1713
1714 struct ls_message *ls_subnet2msg(struct ls_message *msg,
1715 struct ls_subnet *subnet)
1716 {
1717 /* Allocate space if needed */
1718 if (msg == NULL)
1719 msg = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_message));
1720 else
1721 memset(msg, 0, sizeof(*msg));
1722
1723 msg->type = LS_MSG_TYPE_PREFIX;
1724 switch (subnet->status) {
1725 case NEW:
1726 msg->event = LS_MSG_EVENT_ADD;
1727 break;
1728 case UPDATE:
1729 msg->event = LS_MSG_EVENT_UPDATE;
1730 break;
1731 case DELETE:
1732 msg->event = LS_MSG_EVENT_DELETE;
1733 break;
1734 case SYNC:
1735 msg->event = LS_MSG_EVENT_SYNC;
1736 break;
1737 case UNSET:
1738 case ORPHAN:
1739 msg->event = LS_MSG_EVENT_UNDEF;
1740 break;
1741 }
1742 msg->data.prefix = subnet->ls_pref;
1743 msg->remote_id.origin = UNKNOWN;
1744
1745 return msg;
1746 }
1747
1748 struct ls_vertex *ls_msg2vertex(struct ls_ted *ted, struct ls_message *msg,
1749 bool delete)
1750 {
1751 struct ls_node *node = (struct ls_node *)msg->data.node;
1752 struct ls_vertex *vertex = NULL;
1753
1754 switch (msg->event) {
1755 case LS_MSG_EVENT_SYNC:
1756 vertex = ls_vertex_add(ted, node);
1757 if (vertex)
1758 vertex->status = SYNC;
1759 break;
1760 case LS_MSG_EVENT_ADD:
1761 vertex = ls_vertex_add(ted, node);
1762 if (vertex)
1763 vertex->status = NEW;
1764 break;
1765 case LS_MSG_EVENT_UPDATE:
1766 vertex = ls_vertex_update(ted, node);
1767 if (vertex)
1768 vertex->status = UPDATE;
1769 break;
1770 case LS_MSG_EVENT_DELETE:
1771 vertex = ls_find_vertex_by_id(ted, node->adv);
1772 if (vertex) {
1773 if (delete)
1774 ls_vertex_del_all(ted, vertex);
1775 else
1776 vertex->status = DELETE;
1777 }
1778 break;
1779 default:
1780 vertex = NULL;
1781 break;
1782 }
1783
1784 return vertex;
1785 }
1786
1787 struct ls_edge *ls_msg2edge(struct ls_ted *ted, struct ls_message *msg,
1788 bool delete)
1789 {
1790 struct ls_attributes *attr = (struct ls_attributes *)msg->data.attr;
1791 struct ls_edge *edge = NULL;
1792
1793 switch (msg->event) {
1794 case LS_MSG_EVENT_SYNC:
1795 edge = ls_edge_add(ted, attr);
1796 if (edge)
1797 edge->status = SYNC;
1798 break;
1799 case LS_MSG_EVENT_ADD:
1800 edge = ls_edge_add(ted, attr);
1801 if (edge)
1802 edge->status = NEW;
1803 break;
1804 case LS_MSG_EVENT_UPDATE:
1805 edge = ls_edge_update(ted, attr);
1806 if (edge)
1807 edge->status = UPDATE;
1808 break;
1809 case LS_MSG_EVENT_DELETE:
1810 edge = ls_find_edge_by_source(ted, attr);
1811 if (edge) {
1812 if (delete) {
1813 ls_edge_del_all(ted, edge);
1814 edge = NULL;
1815 } else
1816 edge->status = DELETE;
1817 }
1818 break;
1819 default:
1820 edge = NULL;
1821 break;
1822 }
1823
1824 return edge;
1825 }
1826
1827 struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg,
1828 bool delete)
1829 {
1830 struct ls_prefix *pref = (struct ls_prefix *)msg->data.prefix;
1831 struct ls_subnet *subnet = NULL;
1832
1833 switch (msg->event) {
1834 case LS_MSG_EVENT_SYNC:
1835 subnet = ls_subnet_add(ted, pref);
1836 if (subnet)
1837 subnet->status = SYNC;
1838 break;
1839 case LS_MSG_EVENT_ADD:
1840 subnet = ls_subnet_add(ted, pref);
1841 if (subnet)
1842 subnet->status = NEW;
1843 break;
1844 case LS_MSG_EVENT_UPDATE:
1845 subnet = ls_subnet_update(ted, pref);
1846 if (subnet)
1847 subnet->status = UPDATE;
1848 break;
1849 case LS_MSG_EVENT_DELETE:
1850 subnet = ls_find_subnet(ted, &pref->pref);
1851 if (subnet) {
1852 if (delete)
1853 ls_subnet_del_all(ted, subnet);
1854 else
1855 subnet->status = DELETE;
1856 }
1857 break;
1858 default:
1859 subnet = NULL;
1860 break;
1861 }
1862
1863 return subnet;
1864 }
1865
1866 struct ls_element *ls_msg2ted(struct ls_ted *ted, struct ls_message *msg,
1867 bool delete)
1868 {
1869 struct ls_element *lse = NULL;
1870
1871 switch (msg->type) {
1872 case LS_MSG_TYPE_NODE:
1873 lse = (struct ls_element *)ls_msg2vertex(ted, msg, delete);
1874 break;
1875 case LS_MSG_TYPE_ATTRIBUTES:
1876 lse = (struct ls_element *)ls_msg2edge(ted, msg, delete);
1877 break;
1878 case LS_MSG_TYPE_PREFIX:
1879 lse = (struct ls_element *)ls_msg2subnet(ted, msg, delete);
1880 break;
1881 default:
1882 lse = NULL;
1883 break;
1884 }
1885
1886 return lse;
1887 }
1888
1889 struct ls_element *ls_stream2ted(struct ls_ted *ted, struct stream *s,
1890 bool delete)
1891 {
1892 struct ls_message *msg;
1893 struct ls_element *lse = NULL;
1894
1895 msg = ls_parse_msg(s);
1896 if (msg) {
1897 lse = ls_msg2ted(ted, msg, delete);
1898 ls_delete_msg(msg);
1899 }
1900
1901 return lse;
1902 }
1903
1904 void ls_delete_msg(struct ls_message *msg)
1905 {
1906 if (msg == NULL)
1907 return;
1908
1909 XFREE(MTYPE_LS_DB, msg);
1910 }
1911
1912 int ls_sync_ted(struct ls_ted *ted, struct zclient *zclient,
1913 struct zapi_opaque_reg_info *dst)
1914 {
1915 struct ls_vertex *vertex;
1916 struct ls_edge *edge;
1917 struct ls_subnet *subnet;
1918 struct ls_message msg;
1919
1920 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1921 frr_each(vertices, &ted->vertices, vertex) {
1922 ls_vertex2msg(&msg, vertex);
1923 ls_send_msg(zclient, &msg, dst);
1924 }
1925 frr_each(edges, &ted->edges, edge) {
1926 ls_edge2msg(&msg, edge);
1927 ls_send_msg(zclient, &msg, dst);
1928 }
1929 frr_each(subnets, &ted->subnets, subnet) {
1930 ls_subnet2msg(&msg, subnet);
1931 ls_send_msg(zclient, &msg, dst);
1932 }
1933 return 0;
1934 }
1935
1936 /**
1937 * Link State Show functions
1938 */
1939 static const char *const origin2txt[] = {
1940 "Unknown",
1941 "ISIS_L1",
1942 "ISIS_L2",
1943 "OSPFv2",
1944 "Direct",
1945 "Static"
1946 };
1947
1948 static const char *const type2txt[] = {
1949 "Unknown",
1950 "Standard",
1951 "ABR",
1952 "ASBR",
1953 "Remote ASBR",
1954 "Pseudo"
1955 };
1956
1957 static const char *const status2txt[] = {
1958 "Unknown",
1959 "New",
1960 "Update",
1961 "Delete",
1962 "Sync",
1963 "Orphan"
1964 };
1965
1966 static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str,
1967 size_t size)
1968 {
1969 if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) {
1970 uint8_t *id;
1971
1972 id = lnid.id.iso.sys_id;
1973 snprintfrr(str, size, "%02x%02x.%02x%02x.%02x%02x", id[0],
1974 id[1], id[2], id[3], id[4], id[5]);
1975 } else
1976 snprintfrr(str, size, "%pI4", &lnid.id.ip.addr);
1977
1978 return str;
1979 }
1980
1981 static void ls_show_vertex_vty(struct ls_vertex *vertex, struct vty *vty,
1982 bool verbose)
1983 {
1984 struct listnode *node;
1985 struct ls_node *lsn;
1986 struct ls_edge *edge;
1987 struct ls_attributes *attr;
1988 struct ls_subnet *subnet;
1989 struct sbuf sbuf;
1990 uint32_t upper;
1991
1992 /* Sanity Check */
1993 if (!vertex)
1994 return;
1995
1996 lsn = vertex->node;
1997
1998 sbuf_init(&sbuf, NULL, 0);
1999
2000 sbuf_push(&sbuf, 2, "Vertex (%" PRIu64 "): %s", vertex->key, lsn->name);
2001 sbuf_push(&sbuf, 0, "\tRouter Id: %pI4", &lsn->router_id);
2002 sbuf_push(&sbuf, 0, "\tOrigin: %s", origin2txt[lsn->adv.origin]);
2003 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[vertex->status]);
2004 if (!verbose) {
2005 sbuf_push(
2006 &sbuf, 0,
2007 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
2008 listcount(vertex->outgoing_edges),
2009 listcount(vertex->incoming_edges),
2010 listcount(vertex->prefixes));
2011 goto end;
2012 }
2013
2014 if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
2015 sbuf_push(&sbuf, 4, "Type: %s\n", type2txt[lsn->type]);
2016 if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
2017 sbuf_push(&sbuf, 4, "AS number: %u\n", lsn->as_number);
2018 if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
2019 sbuf_push(&sbuf, 4, "Segment Routing Capabilities:\n");
2020 upper = lsn->srgb.lower_bound + lsn->srgb.range_size - 1;
2021 sbuf_push(&sbuf, 8, "SRGB: [%d/%d]", lsn->srgb.lower_bound,
2022 upper);
2023 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
2024 upper = lsn->srlb.lower_bound + lsn->srlb.range_size
2025 - 1;
2026 sbuf_push(&sbuf, 0, "\tSRLB: [%d/%d]",
2027 lsn->srlb.lower_bound, upper);
2028 }
2029 sbuf_push(&sbuf, 0, "\tAlgo: ");
2030 for (int i = 0; i < 2; i++) {
2031 if (lsn->algo[i] == 255)
2032 continue;
2033
2034 sbuf_push(&sbuf, 0,
2035 lsn->algo[i] == 0 ? "SPF " : "S-SPF ");
2036 }
2037 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
2038 sbuf_push(&sbuf, 0, "\tMSD: %d", lsn->msd);
2039 sbuf_push(&sbuf, 0, "\n");
2040 }
2041
2042 sbuf_push(&sbuf, 4, "Outgoing Edges: %d\n",
2043 listcount(vertex->outgoing_edges));
2044 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, node, edge)) {
2045 if (edge->destination) {
2046 lsn = edge->destination->node;
2047 sbuf_push(&sbuf, 6, "To:\t%s(%pI4)", lsn->name,
2048 &lsn->router_id);
2049 } else {
2050 sbuf_push(&sbuf, 6, "To:\t- (0.0.0.0)");
2051 }
2052 attr = edge->attributes;
2053 if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
2054 sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2055 &attr->standard.local,
2056 &attr->standard.remote);
2057 else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
2058 sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2059 &attr->standard.local6,
2060 &attr->standard.remote6);
2061 }
2062
2063 sbuf_push(&sbuf, 4, "Incoming Edges: %d\n",
2064 listcount(vertex->incoming_edges));
2065 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, node, edge)) {
2066 if (edge->source) {
2067 lsn = edge->source->node;
2068 sbuf_push(&sbuf, 6, "From:\t%s(%pI4)", lsn->name,
2069 &lsn->router_id);
2070 } else {
2071 sbuf_push(&sbuf, 6, "From:\t- (0.0.0.0)");
2072 }
2073 attr = edge->attributes;
2074 if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)))
2075 sbuf_push(&sbuf, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2076 &attr->standard.local,
2077 &attr->standard.remote);
2078 else if ((CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)))
2079 sbuf_push(&sbuf, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2080 &attr->standard.local6,
2081 &attr->standard.remote6);
2082 }
2083
2084 sbuf_push(&sbuf, 4, "Subnets: %d\n", listcount(vertex->prefixes));
2085 for (ALL_LIST_ELEMENTS_RO(vertex->prefixes, node, subnet))
2086 sbuf_push(&sbuf, 6, "Prefix:\t%pFX\n", &subnet->key);
2087
2088 end:
2089 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2090 sbuf_free(&sbuf);
2091 }
2092
2093 static void ls_show_vertex_json(struct ls_vertex *vertex,
2094 struct json_object *json)
2095 {
2096 struct ls_node *lsn;
2097 json_object *jsr, *jalgo, *jobj;
2098 char buf[INET6_BUFSIZ];
2099
2100 /* Sanity Check */
2101 if (!vertex)
2102 return;
2103
2104 lsn = vertex->node;
2105
2106 json_object_int_add(json, "vertex-id", vertex->key);
2107 json_object_string_add(json, "status", status2txt[vertex->status]);
2108 json_object_string_add(json, "origin", origin2txt[lsn->adv.origin]);
2109 if (CHECK_FLAG(lsn->flags, LS_NODE_NAME))
2110 json_object_string_add(json, "name", lsn->name);
2111 if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID)) {
2112 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &lsn->router_id);
2113 json_object_string_add(json, "router-id", buf);
2114 }
2115 if (CHECK_FLAG(lsn->flags, LS_NODE_ROUTER_ID6)) {
2116 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &lsn->router_id6);
2117 json_object_string_add(json, "router-id-v6", buf);
2118 }
2119 if (CHECK_FLAG(lsn->flags, LS_NODE_TYPE))
2120 json_object_string_add(json, "vertex-type",
2121 type2txt[lsn->type]);
2122 if (CHECK_FLAG(lsn->flags, LS_NODE_AS_NUMBER))
2123 json_object_int_add(json, "asn", lsn->as_number);
2124 if (CHECK_FLAG(lsn->flags, LS_NODE_SR)) {
2125 jsr = json_object_new_object();
2126 json_object_object_add(json, "segment-routing", jsr);
2127 json_object_int_add(jsr, "srgb-size", lsn->srgb.range_size);
2128 json_object_int_add(jsr, "srgb-lower", lsn->srgb.lower_bound);
2129 jalgo = json_object_new_array();
2130 json_object_object_add(jsr, "algorithms", jalgo);
2131 for (int i = 0; i < 2; i++) {
2132 if (lsn->algo[i] == 255)
2133 continue;
2134 jobj = json_object_new_object();
2135
2136 snprintfrr(buf, 2, "%u", i);
2137 json_object_string_add(
2138 jobj, buf, lsn->algo[i] == 0 ? "SPF" : "S-SPF");
2139 json_object_array_add(jalgo, jobj);
2140 }
2141 if (CHECK_FLAG(lsn->flags, LS_NODE_SRLB)) {
2142 json_object_int_add(jsr, "srlb-size",
2143 lsn->srlb.range_size);
2144 json_object_int_add(jsr, "srlb-lower",
2145 lsn->srlb.lower_bound);
2146 }
2147 if (CHECK_FLAG(lsn->flags, LS_NODE_MSD))
2148 json_object_int_add(jsr, "msd", lsn->msd);
2149 }
2150 }
2151
2152 void ls_show_vertex(struct ls_vertex *vertex, struct vty *vty,
2153 struct json_object *json, bool verbose)
2154 {
2155 if (json)
2156 ls_show_vertex_json(vertex, json);
2157 else if (vty)
2158 ls_show_vertex_vty(vertex, vty, verbose);
2159 }
2160
2161 void ls_show_vertices(struct ls_ted *ted, struct vty *vty,
2162 struct json_object *json, bool verbose)
2163 {
2164 struct ls_vertex *vertex;
2165 json_object *jnodes, *jnode;
2166
2167 if (json) {
2168 jnodes = json_object_new_array();
2169 json_object_object_add(json, "vertices", jnodes);
2170 frr_each (vertices, &ted->vertices, vertex) {
2171 jnode = json_object_new_object();
2172 ls_show_vertex(vertex, NULL, jnode, verbose);
2173 json_object_array_add(jnodes, jnode);
2174 }
2175 } else if (vty) {
2176 frr_each (vertices, &ted->vertices, vertex)
2177 ls_show_vertex(vertex, vty, NULL, verbose);
2178 }
2179 }
2180
2181 static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
2182 bool verbose)
2183 {
2184 char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
2185 struct ls_attributes *attr;
2186 struct sbuf sbuf;
2187 char buf[INET6_BUFSIZ];
2188 int indent;
2189
2190 attr = edge->attributes;
2191 sbuf_init(&sbuf, NULL, 0);
2192
2193 sbuf_push(&sbuf, 2, "Edge (%" PRIu64 "): ", edge->key);
2194 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
2195 sbuf_push(&sbuf, 0, "%pI4", &attr->standard.local);
2196 else if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
2197 sbuf_push(&sbuf, 0, "%pI6", &attr->standard.local6);
2198 else
2199 sbuf_push(&sbuf, 0, "%u/%u", attr->standard.local_id,
2200 attr->standard.remote_id);
2201 ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
2202 sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
2203 sbuf_push(&sbuf, 0, "\tMetric: %u", attr->metric);
2204 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[edge->status]);
2205
2206 if (!verbose)
2207 goto end;
2208
2209 sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[attr->adv.origin]);
2210 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
2211 sbuf_push(&sbuf, 4, "Name: %s\n", attr->name);
2212 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
2213 sbuf_push(&sbuf, 4, "TE Metric: %u\n",
2214 attr->standard.te_metric);
2215 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
2216 sbuf_push(&sbuf, 4, "Admin Group: 0x%x\n",
2217 attr->standard.admin_group);
2218 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP) &&
2219 admin_group_nb_words(&attr->ext_admin_group) != 0) {
2220 indent = 4;
2221 sbuf_push(&sbuf, indent, "Ext Admin Group: %s\n",
2222 admin_group_string(
2223 admin_group_buf, ADMIN_GROUP_PRINT_MAX_SIZE,
2224 indent + strlen("Ext Admin Group: "),
2225 &attr->ext_admin_group));
2226 if (admin_group_buf[0] != '\0' &&
2227 (sbuf.pos + strlen(admin_group_buf) +
2228 SBUF_DEFAULT_SIZE / 2) < sbuf.size)
2229 sbuf_push(&sbuf, indent + 2, "Bit positions: %s\n",
2230 admin_group_buf);
2231 }
2232 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR))
2233 sbuf_push(&sbuf, 4, "Local IPv4 address: %pI4\n",
2234 &attr->standard.local);
2235 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR))
2236 sbuf_push(&sbuf, 4, "Remote IPv4 address: %pI4\n",
2237 &attr->standard.remote);
2238 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6))
2239 sbuf_push(&sbuf, 4, "Local IPv6 address: %pI6\n",
2240 &attr->standard.local6);
2241 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6))
2242 sbuf_push(&sbuf, 4, "Remote IPv6 address: %pI6\n",
2243 &attr->standard.remote6);
2244 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
2245 sbuf_push(&sbuf, 4, "Local Identifier: %u\n",
2246 attr->standard.local_id);
2247 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
2248 sbuf_push(&sbuf, 4, "Remote Identifier: %u\n",
2249 attr->standard.remote_id);
2250 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
2251 sbuf_push(&sbuf, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2252 attr->standard.max_bw);
2253 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
2254 sbuf_push(&sbuf, 4,
2255 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2256 attr->standard.max_rsv_bw);
2257 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
2258 sbuf_push(&sbuf, 4, "Unreserved Bandwidth per Class Type\n");
2259 for (int i = 0; i < MAX_CLASS_TYPE; i += 2)
2260 sbuf_push(&sbuf, 8,
2261 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2262 i, attr->standard.unrsv_bw[i], i + 1,
2263 attr->standard.unrsv_bw[i + 1]);
2264 }
2265 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
2266 sbuf_push(&sbuf, 4, "Remote AS: %u\n",
2267 attr->standard.remote_as);
2268 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR))
2269 sbuf_push(&sbuf, 4, "Remote ASBR IPv4 address: %pI4\n",
2270 &attr->standard.remote_addr);
2271 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6))
2272 sbuf_push(&sbuf, 4, "Remote ASBR IPv6 address: %pI6\n",
2273 &attr->standard.remote_addr6);
2274 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
2275 sbuf_push(&sbuf, 4, "Average Link Delay: %d (micro-sec)\n",
2276 attr->extended.delay);
2277 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY))
2278 sbuf_push(&sbuf, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2279 attr->extended.min_delay, attr->extended.max_delay);
2280 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
2281 sbuf_push(&sbuf, 4, "Delay Variation: %d (micro-sec)\n",
2282 attr->extended.jitter);
2283 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
2284 sbuf_push(&sbuf, 4, "Link Loss: %g (%%)\n",
2285 (float)(attr->extended.pkt_loss * LOSS_PRECISION));
2286 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
2287 sbuf_push(&sbuf, 4, "Available Bandwidth: %g (Bytes/s)\n",
2288 attr->extended.ava_bw);
2289 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
2290 sbuf_push(&sbuf, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2291 attr->extended.rsv_bw);
2292 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
2293 sbuf_push(&sbuf, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2294 attr->extended.used_bw);
2295 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
2296 sbuf_push(&sbuf, 4, "IPv4 Adjacency-SID: %u",
2297 attr->adj_sid[ADJ_PRI_IPV4].sid);
2298 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2299 attr->adj_sid[ADJ_PRI_IPV4].flags,
2300 attr->adj_sid[ADJ_PRI_IPV4].weight);
2301 }
2302 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2303 sbuf_push(&sbuf, 4, "IPv4 Bck. Adjacency-SID: %u",
2304 attr->adj_sid[ADJ_BCK_IPV4].sid);
2305 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2306 attr->adj_sid[ADJ_BCK_IPV4].flags,
2307 attr->adj_sid[ADJ_BCK_IPV4].weight);
2308 }
2309 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
2310 sbuf_push(&sbuf, 4, "IPv6 Adjacency-SID: %u",
2311 attr->adj_sid[ADJ_PRI_IPV6].sid);
2312 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2313 attr->adj_sid[ADJ_PRI_IPV6].flags,
2314 attr->adj_sid[ADJ_PRI_IPV6].weight);
2315 }
2316 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
2317 sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SID: %u",
2318 attr->adj_sid[ADJ_BCK_IPV6].sid);
2319 sbuf_push(&sbuf, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2320 attr->adj_sid[ADJ_BCK_IPV6].flags,
2321 attr->adj_sid[ADJ_BCK_IPV6].weight);
2322 }
2323 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
2324 sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
2325 for (int i = 1; i < attr->srlg_len; i++) {
2326 if (i % 8)
2327 sbuf_push(&sbuf, 8, "\n%u", attr->srlgs[i]);
2328 else
2329 sbuf_push(&sbuf, 8, ", %u", attr->srlgs[i]);
2330 }
2331 sbuf_push(&sbuf, 0, "\n");
2332 }
2333
2334 end:
2335 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2336 sbuf_free(&sbuf);
2337 }
2338
2339 static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
2340 {
2341 struct ls_attributes *attr;
2342 struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg, *js_ext_ag,
2343 *js_ext_ag_arr_word,
2344 *js_ext_ag_arr_bit;
2345 char buf[INET6_BUFSIZ];
2346 char buf_ag[strlen("0xffffffff") + 1];
2347 uint32_t bitmap;
2348 size_t i;
2349
2350 attr = edge->attributes;
2351
2352 json_object_int_add(json, "edge-id", edge->key);
2353 json_object_string_add(json, "status", status2txt[edge->status]);
2354 json_object_string_add(json, "origin", origin2txt[attr->adv.origin]);
2355 ls_node_id_to_text(attr->adv, buf, INET6_BUFSIZ);
2356 json_object_string_add(json, "advertised-router", buf);
2357 if (edge->source)
2358 json_object_int_add(json, "local-vertex-id", edge->source->key);
2359 if (edge->destination)
2360 json_object_int_add(json, "remote-vertex-id",
2361 edge->destination->key);
2362 json_object_int_add(json, "metric", attr->metric);
2363 if (CHECK_FLAG(attr->flags, LS_ATTR_NAME))
2364 json_object_string_add(json, "name", attr->name);
2365 jte = json_object_new_object();
2366 json_object_object_add(json, "edge-attributes", jte);
2367 if (CHECK_FLAG(attr->flags, LS_ATTR_TE_METRIC))
2368 json_object_int_add(jte, "te-metric", attr->standard.te_metric);
2369 if (CHECK_FLAG(attr->flags, LS_ATTR_ADM_GRP))
2370 json_object_int_add(jte, "admin-group",
2371 attr->standard.admin_group);
2372 if (CHECK_FLAG(attr->flags, LS_ATTR_EXT_ADM_GRP)) {
2373 js_ext_ag = json_object_new_object();
2374 json_object_object_add(jte, "extAdminGroup", js_ext_ag);
2375 js_ext_ag_arr_word = json_object_new_array();
2376 json_object_object_add(js_ext_ag, "words", js_ext_ag_arr_word);
2377 js_ext_ag_arr_bit = json_object_new_array();
2378 json_object_object_add(js_ext_ag, "bitPositions",
2379 js_ext_ag_arr_bit);
2380 for (i = 0; i < admin_group_nb_words(&attr->ext_admin_group);
2381 i++) {
2382 bitmap = admin_group_get_offset(&attr->ext_admin_group,
2383 i);
2384 snprintf(buf_ag, sizeof(buf_ag), "0x%08x", bitmap);
2385 json_object_array_add(js_ext_ag_arr_word,
2386 json_object_new_string(buf_ag));
2387 }
2388 for (i = 0;
2389 i < (admin_group_size(&attr->ext_admin_group) * WORD_SIZE);
2390 i++) {
2391 if (admin_group_get(&attr->ext_admin_group, i))
2392 json_object_array_add(js_ext_ag_arr_bit,
2393 json_object_new_int(i));
2394 }
2395 }
2396 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR)) {
2397 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.local);
2398 json_object_string_add(jte, "local-address", buf);
2399 }
2400 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR)) {
2401 snprintfrr(buf, INET6_BUFSIZ, "%pI4", &attr->standard.remote);
2402 json_object_string_add(jte, "remote-address", buf);
2403 }
2404 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ADDR6)) {
2405 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.local6);
2406 json_object_string_add(jte, "local-address-v6", buf);
2407 }
2408 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ADDR6)) {
2409 snprintfrr(buf, INET6_BUFSIZ, "%pI6", &attr->standard.remote6);
2410 json_object_string_add(jte, "remote-address-v6", buf);
2411 }
2412 if (CHECK_FLAG(attr->flags, LS_ATTR_LOCAL_ID))
2413 json_object_int_add(jte, "local-identifier",
2414 attr->standard.local_id);
2415 if (CHECK_FLAG(attr->flags, LS_ATTR_NEIGH_ID))
2416 json_object_int_add(jte, "remote-identifier",
2417 attr->standard.remote_id);
2418 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_BW))
2419 json_object_double_add(jte, "max-link-bandwidth",
2420 attr->standard.max_bw);
2421 if (CHECK_FLAG(attr->flags, LS_ATTR_MAX_RSV_BW))
2422 json_object_double_add(jte, "max-resv-link-bandwidth",
2423 attr->standard.max_rsv_bw);
2424 if (CHECK_FLAG(attr->flags, LS_ATTR_UNRSV_BW)) {
2425 jbw = json_object_new_array();
2426 json_object_object_add(jte, "unreserved-bandwidth", jbw);
2427 for (int i = 0; i < MAX_CLASS_TYPE; i++) {
2428 jobj = json_object_new_object();
2429 snprintfrr(buf, 13, "class-type-%u", i);
2430 json_object_double_add(jobj, buf,
2431 attr->standard.unrsv_bw[i]);
2432 json_object_array_add(jbw, jobj);
2433 }
2434 }
2435 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_AS))
2436 json_object_int_add(jte, "remote-asn",
2437 attr->standard.remote_as);
2438 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR)) {
2439 snprintfrr(buf, INET6_BUFSIZ, "%pI4",
2440 &attr->standard.remote_addr);
2441 json_object_string_add(jte, "remote-as-address", buf);
2442 }
2443 if (CHECK_FLAG(attr->flags, LS_ATTR_REMOTE_ADDR6)) {
2444 snprintfrr(buf, INET6_BUFSIZ, "%pI6",
2445 &attr->standard.remote_addr6);
2446 json_object_string_add(jte, "remote-as-address-v6", buf);
2447 }
2448 if (CHECK_FLAG(attr->flags, LS_ATTR_DELAY))
2449 json_object_int_add(jte, "delay", attr->extended.delay);
2450 if (CHECK_FLAG(attr->flags, LS_ATTR_MIN_MAX_DELAY)) {
2451 json_object_int_add(jte, "min-delay", attr->extended.min_delay);
2452 json_object_int_add(jte, "max-delay", attr->extended.max_delay);
2453 }
2454 if (CHECK_FLAG(attr->flags, LS_ATTR_JITTER))
2455 json_object_int_add(jte, "jitter", attr->extended.jitter);
2456 if (CHECK_FLAG(attr->flags, LS_ATTR_PACKET_LOSS))
2457 json_object_double_add(
2458 jte, "loss", attr->extended.pkt_loss * LOSS_PRECISION);
2459 if (CHECK_FLAG(attr->flags, LS_ATTR_AVA_BW))
2460 json_object_double_add(jte, "available-bandwidth",
2461 attr->extended.ava_bw);
2462 if (CHECK_FLAG(attr->flags, LS_ATTR_RSV_BW))
2463 json_object_double_add(jte, "residual-bandwidth",
2464 attr->extended.rsv_bw);
2465 if (CHECK_FLAG(attr->flags, LS_ATTR_USE_BW))
2466 json_object_double_add(jte, "utilized-bandwidth",
2467 attr->extended.used_bw);
2468 if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
2469 jsrlg = json_object_new_array();
2470 json_object_object_add(jte, "srlgs", jsrlg);
2471 for (int i = 1; i < attr->srlg_len; i++) {
2472 jobj = json_object_new_object();
2473 json_object_int_add(jobj, "srlg", attr->srlgs[i]);
2474 json_object_array_add(jsrlg, jobj);
2475 }
2476 }
2477 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID)) {
2478 jsr = json_object_new_array();
2479 json_object_object_add(json, "segment-routing", jsr);
2480 jobj = json_object_new_object();
2481 json_object_int_add(jobj, "adj-sid",
2482 attr->adj_sid[ADJ_PRI_IPV4].sid);
2483 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV4].flags);
2484 json_object_string_add(jobj, "flags", buf);
2485 json_object_int_add(jobj, "weight",
2486 attr->adj_sid[ADJ_PRI_IPV4].weight);
2487 json_object_array_add(jsr, jobj);
2488 }
2489 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID)) {
2490 if (!jsr) {
2491 jsr = json_object_new_array();
2492 json_object_object_add(json, "segment-routing", jsr);
2493 }
2494 jobj = json_object_new_object();
2495 json_object_int_add(jobj, "adj-sid",
2496 attr->adj_sid[ADJ_BCK_IPV4].sid);
2497 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV4].flags);
2498 json_object_string_add(jobj, "flags", buf);
2499 json_object_int_add(jobj, "weight",
2500 attr->adj_sid[ADJ_BCK_IPV4].weight);
2501 json_object_array_add(jsr, jobj);
2502 }
2503 if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SID6)) {
2504 jsr = json_object_new_array();
2505 json_object_object_add(json, "segment-routing", jsr);
2506 jobj = json_object_new_object();
2507 json_object_int_add(jobj, "adj-sid",
2508 attr->adj_sid[ADJ_PRI_IPV6].sid);
2509 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_PRI_IPV6].flags);
2510 json_object_string_add(jobj, "flags", buf);
2511 json_object_int_add(jobj, "weight",
2512 attr->adj_sid[ADJ_PRI_IPV6].weight);
2513 json_object_array_add(jsr, jobj);
2514 }
2515 if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SID6)) {
2516 if (!jsr) {
2517 jsr = json_object_new_array();
2518 json_object_object_add(json, "segment-routing", jsr);
2519 }
2520 jobj = json_object_new_object();
2521 json_object_int_add(jobj, "adj-sid",
2522 attr->adj_sid[ADJ_BCK_IPV6].sid);
2523 snprintfrr(buf, 6, "0x%x", attr->adj_sid[ADJ_BCK_IPV6].flags);
2524 json_object_string_add(jobj, "flags", buf);
2525 json_object_int_add(jobj, "weight",
2526 attr->adj_sid[ADJ_BCK_IPV6].weight);
2527 json_object_array_add(jsr, jobj);
2528 }
2529 }
2530
2531 void ls_show_edge(struct ls_edge *edge, struct vty *vty,
2532 struct json_object *json, bool verbose)
2533 {
2534 /* Sanity Check */
2535 if (!edge)
2536 return;
2537
2538 if (json)
2539 ls_show_edge_json(edge, json);
2540 else if (vty)
2541 ls_show_edge_vty(edge, vty, verbose);
2542 }
2543
2544 void ls_show_edges(struct ls_ted *ted, struct vty *vty,
2545 struct json_object *json, bool verbose)
2546 {
2547 struct ls_edge *edge;
2548 json_object *jedges, *jedge;
2549
2550 if (json) {
2551 jedges = json_object_new_array();
2552 json_object_object_add(json, "edges", jedges);
2553 frr_each (edges, &ted->edges, edge) {
2554 jedge = json_object_new_object();
2555 ls_show_edge(edge, NULL, jedge, verbose);
2556 json_object_array_add(jedges, jedge);
2557 }
2558 } else if (vty) {
2559 frr_each (edges, &ted->edges, edge)
2560 ls_show_edge(edge, vty, NULL, verbose);
2561 }
2562 }
2563
2564 static void ls_show_subnet_vty(struct ls_subnet *subnet, struct vty *vty,
2565 bool verbose)
2566 {
2567 struct ls_prefix *pref;
2568 struct sbuf sbuf;
2569 char buf[INET6_BUFSIZ];
2570
2571 pref = subnet->ls_pref;
2572 sbuf_init(&sbuf, NULL, 0);
2573
2574 sbuf_push(&sbuf, 2, "Subnet: %pFX", &subnet->key);
2575 ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
2576 sbuf_push(&sbuf, 0, "\tAdv. Vertex: %s", buf);
2577 sbuf_push(&sbuf, 0, "\tMetric: %d", pref->metric);
2578 sbuf_push(&sbuf, 0, "\tStatus: %s\n", status2txt[subnet->status]);
2579
2580 if (!verbose)
2581 goto end;
2582
2583 sbuf_push(&sbuf, 4, "Origin: %s\n", origin2txt[pref->adv.origin]);
2584 if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG))
2585 sbuf_push(&sbuf, 4, "Flags: %d\n", pref->igp_flag);
2586
2587 if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
2588 sbuf_push(&sbuf, 4, "Tag: %d\n", pref->route_tag);
2589
2590 if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
2591 sbuf_push(&sbuf, 4, "Extended Tag: %" PRIu64 "\n",
2592 pref->extended_tag);
2593
2594 if (CHECK_FLAG(pref->flags, LS_PREF_SR))
2595 sbuf_push(&sbuf, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2596 pref->sr.sid, pref->sr.algo, pref->sr.sid_flag);
2597
2598 end:
2599 vty_out(vty, "%s\n", sbuf_buf(&sbuf));
2600 sbuf_free(&sbuf);
2601 }
2602
2603 static void ls_show_subnet_json(struct ls_subnet *subnet,
2604 struct json_object *json)
2605 {
2606 struct ls_prefix *pref;
2607 json_object *jsr;
2608 char buf[INET6_BUFSIZ];
2609
2610 pref = subnet->ls_pref;
2611
2612 snprintfrr(buf, INET6_BUFSIZ, "%pFX", &subnet->key);
2613 json_object_string_add(json, "subnet-id", buf);
2614 json_object_string_add(json, "status", status2txt[subnet->status]);
2615 json_object_string_add(json, "origin", origin2txt[pref->adv.origin]);
2616 ls_node_id_to_text(pref->adv, buf, INET6_BUFSIZ);
2617 json_object_string_add(json, "advertised-router", buf);
2618 if (subnet->vertex)
2619 json_object_int_add(json, "vertex-id", subnet->vertex->key);
2620 json_object_int_add(json, "metric", pref->metric);
2621 if (CHECK_FLAG(pref->flags, LS_PREF_IGP_FLAG)) {
2622 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->igp_flag);
2623 json_object_string_add(json, "flags", buf);
2624 }
2625 if (CHECK_FLAG(pref->flags, LS_PREF_ROUTE_TAG))
2626 json_object_int_add(json, "tag", pref->route_tag);
2627 if (CHECK_FLAG(pref->flags, LS_PREF_EXTENDED_TAG))
2628 json_object_int_add(json, "extended-tag", pref->extended_tag);
2629 if (CHECK_FLAG(pref->flags, LS_PREF_SR)) {
2630 jsr = json_object_new_object();
2631 json_object_object_add(json, "segment-routing", jsr);
2632 json_object_int_add(jsr, "pref-sid", pref->sr.sid);
2633 json_object_int_add(jsr, "algo", pref->sr.algo);
2634 snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
2635 json_object_string_add(jsr, "flags", buf);
2636 }
2637 }
2638
2639 void ls_show_subnet(struct ls_subnet *subnet, struct vty *vty,
2640 struct json_object *json, bool verbose)
2641 {
2642 /* Sanity Check */
2643 if (!subnet)
2644 return;
2645
2646 if (json)
2647 ls_show_subnet_json(subnet, json);
2648 else if (vty)
2649 ls_show_subnet_vty(subnet, vty, verbose);
2650 }
2651
2652 void ls_show_subnets(struct ls_ted *ted, struct vty *vty,
2653 struct json_object *json, bool verbose)
2654 {
2655 struct ls_subnet *subnet;
2656 json_object *jsubs, *jsub;
2657
2658 if (json) {
2659 jsubs = json_object_new_array();
2660 json_object_object_add(json, "subnets", jsubs);
2661 frr_each (subnets, &ted->subnets, subnet) {
2662 jsub = json_object_new_object();
2663 ls_show_subnet(subnet, NULL, jsub, verbose);
2664 json_object_array_add(jsubs, jsub);
2665 }
2666 } else if (vty) {
2667 frr_each (subnets, &ted->subnets, subnet)
2668 ls_show_subnet(subnet, vty, NULL, verbose);
2669 }
2670 }
2671
2672 void ls_show_ted(struct ls_ted *ted, struct vty *vty, struct json_object *json,
2673 bool verbose)
2674 {
2675 json_object *jted;
2676
2677 if (json) {
2678 jted = json_object_new_object();
2679 json_object_object_add(json, "ted", jted);
2680 json_object_string_add(jted, "name", ted->name);
2681 json_object_int_add(jted, "key", ted->key);
2682 json_object_int_add(jted, "verticesCount",
2683 vertices_count(&ted->vertices));
2684 json_object_int_add(jted, "edgesCount",
2685 edges_count(&ted->edges));
2686 json_object_int_add(jted, "subnetsCount",
2687 subnets_count(&ted->subnets));
2688 ls_show_vertices(ted, NULL, jted, verbose);
2689 ls_show_edges(ted, NULL, jted, verbose);
2690 ls_show_subnets(ted, NULL, jted, verbose);
2691 return;
2692 }
2693
2694 if (vty) {
2695 vty_out(vty,
2696 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2697 ted->name, ted->key);
2698 ls_show_vertices(ted, vty, NULL, verbose);
2699 ls_show_edges(ted, vty, NULL, verbose);
2700 ls_show_subnets(ted, vty, NULL, verbose);
2701 vty_out(vty,
2702 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2703 vertices_count(&ted->vertices),
2704 edges_count(&ted->edges), subnets_count(&ted->subnets));
2705 }
2706 }
2707
2708 void ls_dump_ted(struct ls_ted *ted)
2709 {
2710 struct ls_vertex *vertex;
2711 struct ls_edge *edge;
2712 struct ls_subnet *subnet;
2713 const struct in_addr inaddr_any = {.s_addr = INADDR_ANY};
2714
2715 zlog_debug("(%s) Ted init", __func__);
2716
2717 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2718 frr_each (vertices, &ted->vertices, vertex) {
2719 zlog_debug(" Ted node (%s %pI4 %s)",
2720 vertex->node->name[0] ? vertex->node->name
2721 : "no name node",
2722 &vertex->node->router_id,
2723 origin2txt[vertex->node->adv.origin]);
2724 struct listnode *lst_node;
2725 struct ls_edge *vertex_edge;
2726
2727 for (ALL_LIST_ELEMENTS_RO(vertex->incoming_edges, lst_node,
2728 vertex_edge)) {
2729 zlog_debug(
2730 " inc edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2731 vertex_edge->key,
2732 &vertex_edge->attributes->adv.id.ip.addr,
2733 &vertex_edge->attributes->standard.local,
2734 &vertex_edge->attributes->standard.remote);
2735 }
2736 for (ALL_LIST_ELEMENTS_RO(vertex->outgoing_edges, lst_node,
2737 vertex_edge)) {
2738 zlog_debug(
2739 " out edge key:%" PRIu64 " attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2740 vertex_edge->key,
2741 &vertex_edge->attributes->adv.id.ip.addr,
2742 &vertex_edge->attributes->standard.local,
2743 &vertex_edge->attributes->standard.remote);
2744 }
2745 }
2746 frr_each (edges, &ted->edges, edge) {
2747 zlog_debug(" Ted edge key:%" PRIu64 "src:%pI4 dst:%pI4", edge->key,
2748 edge->source ? &edge->source->node->router_id
2749 : &inaddr_any,
2750 edge->destination
2751 ? &edge->destination->node->router_id
2752 : &inaddr_any);
2753 }
2754 frr_each (subnets, &ted->subnets, subnet) {
2755 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2756 &subnet->ls_pref->pref,
2757 &subnet->vertex->node->adv.id.ip.addr);
2758 }
2759 zlog_debug("(%s) Ted end", __func__);
2760 }