Coverage Report

Created: 2025-11-11 06:17

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