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