]>
git.proxmox.com Git - mirror_frr.git/blob - lib/link_state.c
2 * Link State Database - link_state.c
4 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
6 * Copyright (C) 2020 Orange http://www.orange.com
8 * This file is part of Free Range Routing (FRR).
10 * FRR is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2, or (at your option) any
15 * FRR is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; see the file COPYING; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "termtable.h"
41 #include "link_state.h"
43 /* Link State Memory allocation */
44 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
47 * Link State Node management functions
49 int ls_node_id_same(struct ls_node_id i1
, struct ls_node_id i2
)
51 if (i1
.origin
!= i2
.origin
)
54 if (i1
.origin
== UNKNOWN
)
57 if (i1
.origin
== ISIS_L1
|| i1
.origin
== ISIS_L2
) {
58 if (memcmp(i1
.id
.iso
.sys_id
, i2
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
)
60 || (i1
.id
.iso
.level
!= i2
.id
.iso
.level
))
63 if (!IPV4_ADDR_SAME(&i1
.id
.ip
.addr
, &i2
.id
.ip
.addr
)
64 || !IPV4_ADDR_SAME(&i1
.id
.ip
.area_id
, &i2
.id
.ip
.area_id
))
71 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
76 if (adv
.origin
== UNKNOWN
)
79 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
81 if (!IPV4_NET0(rid
.s_addr
)) {
83 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
85 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
86 || adv
.origin
== DIRECT
) {
87 new->router_id
= adv
.id
.ip
.addr
;
88 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
91 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
92 new->router_id6
= rid6
;
93 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
98 void ls_node_del(struct ls_node
*node
)
103 XFREE(MTYPE_LS_DB
, node
);
106 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
108 /* First, check pointer */
109 if ((n1
&& !n2
) || (!n1
&& n2
))
115 /* Then, verify Flags and Origin */
116 if (n1
->flags
!= n2
->flags
)
119 if (!ls_node_id_same(n1
->adv
, n2
->adv
))
122 /* Finally, check each individual parameters that are valid */
123 if (CHECK_FLAG(n1
->flags
, LS_NODE_NAME
)
124 && (strncmp(n1
->name
, n2
->name
, MAX_NAME_LENGTH
) != 0))
126 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID
)
127 && !IPV4_ADDR_SAME(&n1
->router_id
, &n2
->router_id
))
129 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID6
)
130 && !IPV6_ADDR_SAME(&n1
->router_id6
, &n2
->router_id6
))
132 if (CHECK_FLAG(n1
->flags
, LS_NODE_FLAG
)
133 && (n1
->node_flag
!= n2
->node_flag
))
135 if (CHECK_FLAG(n1
->flags
, LS_NODE_TYPE
) && (n1
->type
!= n2
->type
))
137 if (CHECK_FLAG(n1
->flags
, LS_NODE_AS_NUMBER
)
138 && (n1
->as_number
!= n2
->as_number
))
140 if (CHECK_FLAG(n1
->flags
, LS_NODE_SR
)) {
141 if (n1
->srgb
.flag
!= n2
->srgb
.flag
142 || n1
->srgb
.lower_bound
!= n2
->srgb
.lower_bound
143 || n1
->srgb
.range_size
!= n2
->srgb
.range_size
)
145 if ((n1
->algo
[0] != n2
->algo
[0])
146 || (n1
->algo
[1] != n2
->algo
[1]))
148 if (CHECK_FLAG(n1
->flags
, LS_NODE_SRLB
)
149 && ((n1
->srlb
.lower_bound
!= n2
->srlb
.lower_bound
150 || n1
->srlb
.range_size
!= n2
->srlb
.range_size
)))
152 if (CHECK_FLAG(n1
->flags
, LS_NODE_MSD
) && (n1
->msd
!= n2
->msd
))
156 /* OK, n1 & n2 are equal */
161 * Link State Attributes management functions
163 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
164 struct in_addr local
,
165 struct in6_addr local6
,
168 struct ls_attributes
*new;
170 if (adv
.origin
== UNKNOWN
)
173 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
175 if (!IPV4_NET0(local
.s_addr
)) {
176 new->standard
.local
= local
;
177 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
179 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
180 new->standard
.local6
= local6
;
181 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
184 new->standard
.local_id
= local_id
;
185 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
188 /* Check that almost one identifier is set */
189 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
190 | LS_ATTR_LOCAL_ID
)) {
191 XFREE(MTYPE_LS_DB
, new);
198 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
204 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
208 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
211 void ls_attributes_del(struct ls_attributes
*attr
)
216 ls_attributes_srlg_del(attr
);
218 XFREE(MTYPE_LS_DB
, attr
);
221 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
223 /* First, check pointer */
224 if ((l1
&& !l2
) || (!l1
&& l2
))
230 /* Then, verify Flags and Origin */
231 if (l1
->flags
!= l2
->flags
)
234 if (!ls_node_id_same(l1
->adv
, l2
->adv
))
237 /* Finally, check each individual parameters that are valid */
238 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NAME
)
239 && strncmp(l1
->name
, l2
->name
, MAX_NAME_LENGTH
) != 0)
241 if (CHECK_FLAG(l1
->flags
, LS_ATTR_METRIC
) && (l1
->metric
!= l2
->metric
))
243 if (CHECK_FLAG(l1
->flags
, LS_ATTR_TE_METRIC
)
244 && (l1
->standard
.te_metric
!= l2
->standard
.te_metric
))
246 if (CHECK_FLAG(l1
->flags
, LS_ATTR_ADM_GRP
)
247 && (l1
->standard
.admin_group
!= l2
->standard
.admin_group
))
249 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR
)
250 && !IPV4_ADDR_SAME(&l1
->standard
.local
, &l2
->standard
.local
))
252 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR
)
253 && !IPV4_ADDR_SAME(&l1
->standard
.remote
, &l2
->standard
.remote
))
255 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR6
)
256 && !IPV6_ADDR_SAME(&l1
->standard
.local6
, &l2
->standard
.local6
))
258 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR6
)
259 && !IPV6_ADDR_SAME(&l1
->standard
.remote6
, &l2
->standard
.remote6
))
261 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ID
)
262 && (l1
->standard
.local_id
!= l2
->standard
.local_id
))
264 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ID
)
265 && (l1
->standard
.remote_id
!= l2
->standard
.remote_id
))
267 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_BW
)
268 && (l1
->standard
.max_bw
!= l2
->standard
.max_bw
))
270 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_RSV_BW
)
271 && (l1
->standard
.max_rsv_bw
!= l2
->standard
.max_rsv_bw
))
273 if (CHECK_FLAG(l1
->flags
, LS_ATTR_UNRSV_BW
)
274 && memcmp(&l1
->standard
.unrsv_bw
, &l2
->standard
.unrsv_bw
, 32) != 0)
276 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_AS
)
277 && (l1
->standard
.remote_as
!= l2
->standard
.remote_as
))
279 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR
)
280 && !IPV4_ADDR_SAME(&l1
->standard
.remote_addr
,
281 &l2
->standard
.remote_addr
))
283 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR6
)
284 && !IPV6_ADDR_SAME(&l1
->standard
.remote_addr6
,
285 &l2
->standard
.remote_addr6
))
287 if (CHECK_FLAG(l1
->flags
, LS_ATTR_DELAY
)
288 && (l1
->extended
.delay
!= l2
->extended
.delay
))
290 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MIN_MAX_DELAY
)
291 && ((l1
->extended
.min_delay
!= l2
->extended
.min_delay
)
292 || (l1
->extended
.max_delay
!= l2
->extended
.max_delay
)))
294 if (CHECK_FLAG(l1
->flags
, LS_ATTR_JITTER
)
295 && (l1
->extended
.jitter
!= l2
->extended
.jitter
))
297 if (CHECK_FLAG(l1
->flags
, LS_ATTR_PACKET_LOSS
)
298 && (l1
->extended
.pkt_loss
!= l2
->extended
.pkt_loss
))
300 if (CHECK_FLAG(l1
->flags
, LS_ATTR_AVA_BW
)
301 && (l1
->extended
.ava_bw
!= l2
->extended
.ava_bw
))
303 if (CHECK_FLAG(l1
->flags
, LS_ATTR_RSV_BW
)
304 && (l1
->extended
.rsv_bw
!= l2
->extended
.rsv_bw
))
306 if (CHECK_FLAG(l1
->flags
, LS_ATTR_USE_BW
)
307 && (l1
->extended
.used_bw
!= l2
->extended
.used_bw
))
309 for (int i
= 0; i
< LS_ADJ_MAX
; i
++) {
310 if (!CHECK_FLAG(l1
->flags
, (LS_ATTR_ADJ_SID
<< i
)))
312 if ((l1
->adj_sid
[i
].sid
!= l2
->adj_sid
[i
].sid
)
313 || (l1
->adj_sid
[i
].flags
!= l2
->adj_sid
[i
].flags
)
314 || (l1
->adj_sid
[i
].weight
!= l2
->adj_sid
[i
].weight
))
316 if (((l1
->adv
.origin
== ISIS_L1
) || (l1
->adv
.origin
== ISIS_L2
))
317 && (memcmp(&l1
->adj_sid
[i
].neighbor
.sysid
,
318 &l2
->adj_sid
[i
].neighbor
.sysid
, ISO_SYS_ID_LEN
)
321 if (((l1
->adv
.origin
== OSPFv2
) || (l1
->adv
.origin
== STATIC
)
322 || (l1
->adv
.origin
== DIRECT
))
323 && (i
< ADJ_PRI_IPV6
)
324 && (!IPV4_ADDR_SAME(&l1
->adj_sid
[i
].neighbor
.addr
,
325 &l2
->adj_sid
[i
].neighbor
.addr
)))
328 if (CHECK_FLAG(l1
->flags
, LS_ATTR_SRLG
)
329 && ((l1
->srlg_len
!= l2
->srlg_len
)
330 || memcmp(l1
->srlgs
, l2
->srlgs
,
331 l1
->srlg_len
* sizeof(uint32_t))
335 /* OK, l1 & l2 are equal */
340 * Link State prefix management functions
342 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix p
)
344 struct ls_prefix
*new;
346 if (adv
.origin
== UNKNOWN
)
349 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
356 void ls_prefix_del(struct ls_prefix
*pref
)
361 XFREE(MTYPE_LS_DB
, pref
);
364 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
366 /* First, check pointer */
367 if ((p1
&& !p2
) || (!p1
&& p2
))
373 /* Then, verify Flags and Origin */
374 if (p1
->flags
!= p2
->flags
)
377 if (!ls_node_id_same(p1
->adv
, p2
->adv
))
380 /* Finally, check each individual parameters that are valid */
381 if (prefix_same(&p1
->pref
, &p2
->pref
) == 0)
383 if (CHECK_FLAG(p1
->flags
, LS_PREF_IGP_FLAG
)
384 && (p1
->igp_flag
!= p2
->igp_flag
))
386 if (CHECK_FLAG(p1
->flags
, LS_PREF_ROUTE_TAG
)
387 && (p1
->route_tag
!= p2
->route_tag
))
389 if (CHECK_FLAG(p1
->flags
, LS_PREF_EXTENDED_TAG
)
390 && (p1
->extended_tag
!= p2
->extended_tag
))
392 if (CHECK_FLAG(p1
->flags
, LS_PREF_METRIC
) && (p1
->metric
!= p2
->metric
))
394 if (CHECK_FLAG(p1
->flags
, LS_PREF_SR
)) {
395 if ((p1
->sr
.algo
!= p2
->sr
.algo
) || (p1
->sr
.sid
!= p2
->sr
.sid
)
396 || (p1
->sr
.sid_flag
!= p2
->sr
.sid_flag
))
400 /* OK, p1 & p2 are equal */
405 * Link State Vertices management functions
407 uint64_t sysid_to_key(const uint8_t sysid
[ISO_SYS_ID_LEN
])
411 #if BYTE_ORDER == LITTLE_ENDIAN
412 uint8_t *byte
= (uint8_t *)&key
;
414 for (int i
= 0; i
< ISO_SYS_ID_LEN
; i
++)
415 byte
[i
] = sysid
[ISO_SYS_ID_LEN
- i
- 1];
420 memcpy(&key
, sysid
, ISO_SYS_ID_LEN
);
426 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
428 struct ls_vertex
*new;
431 if ((ted
== NULL
) || (node
== NULL
))
434 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
435 switch (node
->adv
.origin
) {
439 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
444 key
= sysid_to_key(node
->adv
.id
.iso
.sys_id
);
451 /* Check that key is valid */
455 /* Create Vertex and add it to the TED */
456 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
464 new->incoming_edges
= list_new();
465 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
466 new->outgoing_edges
= list_new();
467 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
468 new->prefixes
= list_new();
469 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
470 vertices_add(&ted
->vertices
, new);
475 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
477 struct listnode
*node
, *nnode
;
478 struct ls_edge
*edge
;
479 struct ls_subnet
*subnet
;
484 /* Remove outgoing Edges and list */
485 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
486 ls_edge_del_all(ted
, edge
);
487 list_delete(&vertex
->outgoing_edges
);
489 /* Disconnect incoming Edges and remove list */
490 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
491 ls_disconnect(vertex
, edge
, false);
492 if (edge
->source
== NULL
)
493 ls_edge_del_all(ted
, edge
);
495 list_delete(&vertex
->incoming_edges
);
497 /* Remove subnet and list */
498 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
499 ls_subnet_del_all(ted
, subnet
);
500 list_delete(&vertex
->prefixes
);
502 /* Then remove Vertex from Link State Data Base and free memory */
503 vertices_del(&ted
->vertices
, vertex
);
504 XFREE(MTYPE_LS_DB
, vertex
);
508 void ls_vertex_del_all(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
513 /* First remove associated Link State Node */
514 ls_node_del(vertex
->node
);
516 /* Then, Vertex itself */
517 ls_vertex_del(ted
, vertex
);
520 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
522 struct ls_vertex
*old
;
527 old
= ls_find_vertex_by_id(ted
, node
->adv
);
529 if (!ls_node_same(old
->node
, node
)) {
530 ls_node_del(old
->node
);
533 old
->status
= UPDATE
;
537 return ls_vertex_add(ted
, node
);
540 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
542 struct ls_vertex vertex
= {};
548 return vertices_find(&ted
->vertices
, &vertex
);
551 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
552 struct ls_node_id nid
)
554 struct ls_vertex vertex
= {};
557 switch (nid
.origin
) {
562 ((uint64_t)ntohl(nid
.id
.ip
.addr
.s_addr
)) & 0xffffffff;
566 vertex
.key
= sysid_to_key(nid
.id
.iso
.sys_id
);
572 return vertices_find(&ted
->vertices
, &vertex
);
575 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
577 if ((v1
&& !v2
) || (!v1
&& v2
))
583 if (v1
->key
!= v2
->key
)
586 if (v1
->node
== v2
->node
)
589 return ls_node_same(v1
->node
, v2
->node
);
592 void ls_vertex_clean(struct ls_ted
*ted
, struct ls_vertex
*vertex
,
593 struct zclient
*zclient
)
595 struct listnode
*node
, *nnode
;
596 struct ls_edge
*edge
;
597 struct ls_subnet
*subnet
;
598 struct ls_message msg
;
600 /* Remove Orphan Edge ... */
601 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
)) {
602 if (edge
->status
== ORPHAN
) {
604 edge
->status
= DELETE
;
605 ls_edge2msg(&msg
, edge
);
606 ls_send_msg(zclient
, &msg
, NULL
);
608 ls_edge_del_all(ted
, edge
);
611 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
612 if (edge
->status
== ORPHAN
) {
614 edge
->status
= DELETE
;
615 ls_edge2msg(&msg
, edge
);
616 ls_send_msg(zclient
, &msg
, NULL
);
618 ls_edge_del_all(ted
, edge
);
622 /* ... and Subnet from the Vertex */
623 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
)) {
624 if (subnet
->status
== ORPHAN
) {
626 subnet
->status
= DELETE
;
627 ls_subnet2msg(&msg
, subnet
);
628 ls_send_msg(zclient
, &msg
, NULL
);
630 ls_subnet_del_all(ted
, subnet
);
636 * Link State Edges management functions
640 * This function allows to connect the Edge to the vertices present in the TED.
641 * A temporary vertex that corresponds to the source of this Edge i.e. the
642 * advertised router, is created if not found in the Data Base. If a Edge that
643 * corresponds to the reverse path is found, the Edge is attached to the
644 * destination vertex as destination and reverse Edge is attached to the source
647 * @param ted Link State Data Base
648 * @param edge Link State Edge to be attached
650 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
652 struct ls_vertex
*vertex
= NULL
;
653 struct ls_node
*node
;
655 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
657 /* First, search if there is a Vertex that correspond to the Node ID */
658 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
659 if (vertex
== NULL
) {
660 /* Create a new temporary Node & Vertex if not found */
661 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
663 vertex
= ls_vertex_add(ted
, node
);
665 /* and attach the edge as source to the vertex */
666 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
667 edge
->source
= vertex
;
669 /* Then search if there is a reverse Edge */
670 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
671 /* attach the destination edge to the vertex */
673 listnode_add_sort_nodup(vertex
->incoming_edges
, dst
);
674 dst
->destination
= vertex
;
675 /* and destination vertex to this edge */
676 vertex
= dst
->source
;
677 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
678 edge
->destination
= vertex
;
682 static uint64_t get_edge_key(struct ls_attributes
*attr
, bool dst
)
685 struct ls_standard
*std
;
690 std
= &attr
->standard
;
693 /* Key is the IPv4 remote address */
694 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
695 key
= ((uint64_t)ntohl(std
->remote
.s_addr
))
697 /* or the 64 bits LSB of IPv6 remote address */
698 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
699 key
= ((uint64_t)ntohl(std
->remote6
.s6_addr32
[2]) << 32
700 | (uint64_t)ntohl(std
->remote6
.s6_addr32
[3]));
701 /* of remote identifier if no IP addresses are defined */
702 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
703 key
= (((uint64_t)std
->remote_id
) & 0xffffffff)
704 | ((uint64_t)std
->local_id
<< 32);
706 /* Key is the IPv4 local address */
707 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
708 key
= ((uint64_t)ntohl(std
->local
.s_addr
)) & 0xffffffff;
709 /* or the 64 bits LSB of IPv6 local address */
710 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
711 key
= ((uint64_t)ntohl(std
->local6
.s6_addr32
[2]) << 32
712 | (uint64_t)ntohl(std
->local6
.s6_addr32
[3]));
713 /* of local identifier if no IP addresses are defined */
714 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
715 key
= (((uint64_t)std
->local_id
) & 0xffffffff)
716 | ((uint64_t)std
->remote_id
<< 32);
722 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
723 struct ls_attributes
*attributes
)
728 if (attributes
== NULL
)
731 key
= get_edge_key(attributes
, false);
735 /* Create Edge and add it to the TED */
736 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
738 new->attributes
= attributes
;
742 edges_add(&ted
->edges
, new);
744 /* Finally, connect Edge to Vertices */
745 ls_edge_connect_to(ted
, new);
750 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
752 struct ls_edge edge
= {};
758 return edges_find(&ted
->edges
, &edge
);
761 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
762 struct ls_attributes
*attributes
)
764 struct ls_edge edge
= {};
766 if (attributes
== NULL
)
769 edge
.key
= get_edge_key(attributes
, false);
773 return edges_find(&ted
->edges
, &edge
);
776 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
777 struct ls_attributes
*attributes
)
779 struct ls_edge edge
= {};
781 if (attributes
== NULL
)
784 edge
.key
= get_edge_key(attributes
, true);
788 return edges_find(&ted
->edges
, &edge
);
791 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
792 struct ls_attributes
*attributes
)
796 if (attributes
== NULL
)
799 /* First, search for an existing Edge */
800 old
= ls_find_edge_by_source(ted
, attributes
);
802 /* Check if attributes are similar */
803 if (!ls_attributes_same(old
->attributes
, attributes
)) {
804 ls_attributes_del(old
->attributes
);
805 old
->attributes
= attributes
;
807 old
->status
= UPDATE
;
811 /* If not found, add new Edge from the attributes */
812 return ls_edge_add(ted
, attributes
);
815 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
817 if ((e1
&& !e2
) || (!e1
&& e2
))
823 if (e1
->key
!= e2
->key
)
826 if (e1
->attributes
== e2
->attributes
)
829 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
832 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
837 /* Fist disconnect Edge from Vertices */
838 ls_disconnect_edge(edge
);
839 /* Then remove it from the Data Base */
840 edges_del(&ted
->edges
, edge
);
841 XFREE(MTYPE_LS_DB
, edge
);
844 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
849 /* Remove associated Link State Attributes */
850 ls_attributes_del(edge
->attributes
);
851 /* Then Edge itself */
852 ls_edge_del(ted
, edge
);
856 * Link State Subnet Management functions.
858 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
859 struct ls_prefix
*ls_pref
)
861 struct ls_subnet
*new;
862 struct ls_vertex
*vertex
;
863 struct ls_node
*node
;
864 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
869 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
870 new->ls_pref
= ls_pref
;
871 new->key
= ls_pref
->pref
;
876 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
877 if (vertex
== NULL
) {
878 /* Create a new temporary Node & Vertex if not found */
879 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
880 vertex
= ls_vertex_add(ted
, node
);
882 /* And attach the subnet to the corresponding Vertex */
883 new->vertex
= vertex
;
884 listnode_add_sort_nodup(vertex
->prefixes
, new);
886 subnets_add(&ted
->subnets
, new);
891 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
893 struct ls_subnet
*old
;
898 old
= ls_find_subnet(ted
, pref
->pref
);
900 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
901 ls_prefix_del(old
->ls_pref
);
904 old
->status
= UPDATE
;
908 return ls_subnet_add(ted
, pref
);
911 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
913 if ((s1
&& !s2
) || (!s1
&& s2
))
919 if (!prefix_same(&s1
->key
, &s2
->key
))
922 if (s1
->ls_pref
== s2
->ls_pref
)
925 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
928 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
933 /* First, disconnect Subnet from associated Vertex */
934 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
935 /* Then delete Subnet */
936 subnets_del(&ted
->subnets
, subnet
);
937 XFREE(MTYPE_LS_DB
, subnet
);
940 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
945 /* First, remove associated Link State Subnet */
946 ls_prefix_del(subnet
->ls_pref
);
947 /* Then, delete Subnet itself */
948 ls_subnet_del(ted
, subnet
);
951 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
953 struct ls_subnet subnet
= {};
956 return subnets_find(&ted
->subnets
, &subnet
);
960 * Link State TED management functions
962 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
967 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
969 /* Set basic information for this ted */
971 new->as_number
= as_number
;
972 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
974 /* Initialize the various RB tree */
975 vertices_init(&new->vertices
);
976 edges_init(&new->edges
);
977 subnets_init(&new->subnets
);
982 void ls_ted_del(struct ls_ted
*ted
)
987 /* Check that TED is empty */
988 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
989 || subnets_count(&ted
->subnets
))
992 /* Release RB Tree */
993 vertices_fini(&ted
->vertices
);
994 edges_fini(&ted
->edges
);
995 subnets_fini(&ted
->subnets
);
997 XFREE(MTYPE_LS_DB
, ted
);
1000 void ls_ted_del_all(struct ls_ted
**ted
)
1002 struct ls_vertex
*vertex
;
1003 struct ls_edge
*edge
;
1004 struct ls_subnet
*subnet
;
1009 /* First remove Vertices, Edges and Subnets and associated Link State */
1010 frr_each_safe (vertices
, &(*ted
)->vertices
, vertex
)
1011 ls_vertex_del_all(*ted
, vertex
);
1012 frr_each_safe (edges
, &(*ted
)->edges
, edge
)
1013 ls_edge_del_all(*ted
, edge
);
1014 frr_each_safe (subnets
, &(*ted
)->subnets
, subnet
)
1015 ls_subnet_del_all(*ted
, subnet
);
1017 /* then remove TED itself */
1022 void ls_ted_clean(struct ls_ted
*ted
)
1024 struct ls_vertex
*vertex
;
1025 struct ls_edge
*edge
;
1026 struct ls_subnet
*subnet
;
1031 /* First, start with Vertices */
1032 frr_each_safe (vertices
, &ted
->vertices
, vertex
)
1033 if (vertex
->status
== ORPHAN
)
1034 ls_vertex_del_all(ted
, vertex
);
1037 frr_each_safe (edges
, &ted
->edges
, edge
)
1038 if (edge
->status
== ORPHAN
)
1039 ls_edge_del_all(ted
, edge
);
1042 frr_each_safe (subnets
, &ted
->subnets
, subnet
)
1043 if (subnet
->status
== ORPHAN
)
1044 ls_subnet_del_all(ted
, subnet
);
1048 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1050 if (vertex
== NULL
|| edge
== NULL
)
1054 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
1055 edge
->source
= vertex
;
1057 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
1058 edge
->destination
= vertex
;
1062 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1065 if (vertex
== NULL
|| edge
== NULL
)
1069 listnode_delete(vertex
->outgoing_edges
, edge
);
1070 edge
->source
= NULL
;
1072 listnode_delete(vertex
->incoming_edges
, edge
);
1073 edge
->destination
= NULL
;
1077 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
1078 struct ls_edge
*edge
)
1084 edge
->destination
= dst
;
1087 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
1090 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
1093 void ls_disconnect_edge(struct ls_edge
*edge
)
1098 ls_disconnect(edge
->source
, edge
, true);
1099 ls_disconnect(edge
->destination
, edge
, false);
1101 /* Mark this Edge as ORPHAN for future cleanup */
1102 edge
->status
= ORPHAN
;
1106 * Link State Message management functions
1109 int ls_register(struct zclient
*zclient
, bool server
)
1114 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
1116 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
1121 int ls_unregister(struct zclient
*zclient
, bool server
)
1126 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
1128 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
1133 int ls_request_sync(struct zclient
*zclient
)
1138 /* Check buffer size */
1139 if (STREAM_SIZE(zclient
->obuf
)
1140 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
1146 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1148 /* Set type and flags */
1149 stream_putl(s
, LINK_STATE_SYNC
);
1150 stream_putw(s
, flags
);
1151 /* Send destination client info */
1152 stream_putc(s
, zclient
->redist_default
);
1153 stream_putw(s
, zclient
->instance
);
1154 stream_putl(s
, zclient
->session_id
);
1156 /* Put length into the header at the start of the stream. */
1157 stream_putw_at(s
, 0, stream_get_endp(s
));
1159 return zclient_send_message(zclient
);
1162 static struct ls_node
*ls_parse_node(struct stream
*s
)
1164 struct ls_node
*node
;
1167 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1169 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1170 STREAM_GETW(s
, node
->flags
);
1171 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1172 STREAM_GETC(s
, len
);
1173 STREAM_GET(node
->name
, s
, len
);
1175 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1176 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1177 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1178 STREAM_GET(&node
->router_id6
, s
, IPV6_MAX_BYTELEN
);
1179 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1180 STREAM_GETC(s
, node
->node_flag
);
1181 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1182 STREAM_GETC(s
, node
->type
);
1183 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1184 STREAM_GETL(s
, node
->as_number
);
1185 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1186 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1187 STREAM_GETL(s
, node
->srgb
.range_size
);
1188 STREAM_GETC(s
, node
->srgb
.flag
);
1189 STREAM_GET(node
->algo
, s
, 2);
1191 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1192 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1193 STREAM_GETL(s
, node
->srlb
.range_size
);
1195 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1196 STREAM_GETC(s
, node
->msd
);
1201 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1202 XFREE(MTYPE_LS_DB
, node
);
1206 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1208 struct ls_attributes
*attr
;
1211 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1214 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1215 STREAM_GETL(s
, attr
->flags
);
1216 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1217 STREAM_GETC(s
, len
);
1218 STREAM_GET(attr
->name
, s
, len
);
1220 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1221 STREAM_GETL(s
, attr
->metric
);
1222 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1223 STREAM_GETL(s
, attr
->standard
.te_metric
);
1224 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1225 STREAM_GETL(s
, attr
->standard
.admin_group
);
1226 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1227 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1228 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1229 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1230 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1231 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1232 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1233 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1234 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1235 STREAM_GETL(s
, attr
->standard
.local_id
);
1236 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1237 STREAM_GETL(s
, attr
->standard
.remote_id
);
1238 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1239 STREAM_GETF(s
, attr
->standard
.max_bw
);
1240 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1241 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1242 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1243 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1244 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1245 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1246 STREAM_GETL(s
, attr
->standard
.remote_as
);
1247 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1248 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1249 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1250 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1251 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1252 STREAM_GETL(s
, attr
->extended
.delay
);
1253 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1254 STREAM_GETL(s
, attr
->extended
.min_delay
);
1255 STREAM_GETL(s
, attr
->extended
.max_delay
);
1257 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1258 STREAM_GETL(s
, attr
->extended
.jitter
);
1259 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1260 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1261 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1262 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1263 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1264 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1265 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1266 STREAM_GETF(s
, attr
->extended
.used_bw
);
1267 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1268 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1269 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1270 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1271 attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
=
1274 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1275 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1276 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1277 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1278 attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
=
1281 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1282 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1283 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1284 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1285 STREAM_GET(attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
, s
,
1288 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1289 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1290 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1291 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1292 STREAM_GET(attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
, s
,
1295 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1296 STREAM_GETC(s
, len
);
1297 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1298 attr
->srlg_len
= len
;
1299 for (len
= 0; len
< attr
->srlg_len
; len
++)
1300 STREAM_GETL(s
, attr
->srlgs
[len
]);
1306 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1308 /* Clean memory allocation */
1309 if (attr
->srlgs
!= NULL
)
1310 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1311 XFREE(MTYPE_LS_DB
, attr
);
1316 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1318 struct ls_prefix
*ls_pref
;
1321 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1323 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1324 STREAM_GETW(s
, ls_pref
->flags
);
1325 STREAM_GETC(s
, ls_pref
->pref
.family
);
1326 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1327 len
= prefix_blen(&ls_pref
->pref
);
1328 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1329 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1330 STREAM_GETC(s
, ls_pref
->igp_flag
);
1331 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1332 STREAM_GETL(s
, ls_pref
->route_tag
);
1333 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1334 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1335 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1336 STREAM_GETL(s
, ls_pref
->metric
);
1337 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1338 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1339 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1340 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1346 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1347 XFREE(MTYPE_LS_DB
, ls_pref
);
1351 struct ls_message
*ls_parse_msg(struct stream
*s
)
1353 struct ls_message
*msg
;
1355 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1357 /* Read LS Message header */
1358 STREAM_GETC(s
, msg
->event
);
1359 STREAM_GETC(s
, msg
->type
);
1360 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1362 /* Read Message Payload */
1363 switch (msg
->type
) {
1364 case LS_MSG_TYPE_NODE
:
1365 msg
->data
.node
= ls_parse_node(s
);
1367 case LS_MSG_TYPE_ATTRIBUTES
:
1368 msg
->data
.attr
= ls_parse_attributes(s
);
1370 case LS_MSG_TYPE_PREFIX
:
1371 msg
->data
.prefix
= ls_parse_prefix(s
);
1374 zlog_err("Unsupported Payload");
1375 goto stream_failure
;
1378 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1379 || msg
->data
.prefix
== NULL
)
1380 goto stream_failure
;
1385 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1386 XFREE(MTYPE_LS_DB
, msg
);
1390 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1394 /* Push Advertise node information first */
1395 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1397 /* Push Flags & Origin then Node information if there are present */
1398 stream_putw(s
, node
->flags
);
1399 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1400 len
= strlen(node
->name
);
1401 stream_putc(s
, len
+ 1);
1402 stream_put(s
, node
->name
, len
);
1403 stream_putc(s
, '\0');
1405 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1406 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1407 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1408 stream_put(s
, &node
->router_id6
, IPV6_MAX_BYTELEN
);
1409 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1410 stream_putc(s
, node
->node_flag
);
1411 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1412 stream_putc(s
, node
->type
);
1413 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1414 stream_putl(s
, node
->as_number
);
1415 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1416 stream_putl(s
, node
->srgb
.lower_bound
);
1417 stream_putl(s
, node
->srgb
.range_size
);
1418 stream_putc(s
, node
->srgb
.flag
);
1419 stream_put(s
, node
->algo
, 2);
1421 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1422 stream_putl(s
, node
->srlb
.lower_bound
);
1423 stream_putl(s
, node
->srlb
.range_size
);
1425 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1426 stream_putc(s
, node
->msd
);
1431 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1435 /* Push Advertise node information first */
1436 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1438 /* Push Flags & Origin then LS attributes if there are present */
1439 stream_putl(s
, attr
->flags
);
1440 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1441 len
= strlen(attr
->name
);
1442 stream_putc(s
, len
+ 1);
1443 stream_put(s
, attr
->name
, len
);
1444 stream_putc(s
, '\0');
1446 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1447 stream_putl(s
, attr
->metric
);
1448 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1449 stream_putl(s
, attr
->standard
.te_metric
);
1450 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1451 stream_putl(s
, attr
->standard
.admin_group
);
1452 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1453 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1454 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1455 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1456 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1457 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1458 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1459 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1460 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1461 stream_putl(s
, attr
->standard
.local_id
);
1462 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1463 stream_putl(s
, attr
->standard
.remote_id
);
1464 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1465 stream_putf(s
, attr
->standard
.max_bw
);
1466 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1467 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1468 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1469 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1470 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1471 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1472 stream_putl(s
, attr
->standard
.remote_as
);
1473 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1474 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1475 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1476 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1477 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1478 stream_putl(s
, attr
->extended
.delay
);
1479 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1480 stream_putl(s
, attr
->extended
.min_delay
);
1481 stream_putl(s
, attr
->extended
.max_delay
);
1483 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1484 stream_putl(s
, attr
->extended
.jitter
);
1485 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1486 stream_putl(s
, attr
->extended
.pkt_loss
);
1487 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1488 stream_putf(s
, attr
->extended
.ava_bw
);
1489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1490 stream_putf(s
, attr
->extended
.rsv_bw
);
1491 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1492 stream_putf(s
, attr
->extended
.used_bw
);
1493 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1494 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1495 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1496 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1498 s
, attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
);
1500 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1501 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1502 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1503 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1505 s
, attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
);
1507 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1508 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1509 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1510 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1511 stream_put(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
,
1514 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1515 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1516 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1517 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1518 stream_put(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
,
1521 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1522 stream_putc(s
, attr
->srlg_len
);
1523 for (len
= 0; len
< attr
->srlg_len
; len
++)
1524 stream_putl(s
, attr
->srlgs
[len
]);
1530 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1534 /* Push Advertise node information first */
1535 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1537 /* Push Flags, Origin & Prefix then information if there are present */
1538 stream_putw(s
, ls_pref
->flags
);
1539 stream_putc(s
, ls_pref
->pref
.family
);
1540 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1541 len
= prefix_blen(&ls_pref
->pref
);
1542 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1543 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1544 stream_putc(s
, ls_pref
->igp_flag
);
1545 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1546 stream_putl(s
, ls_pref
->route_tag
);
1547 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1548 stream_putq(s
, ls_pref
->extended_tag
);
1549 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1550 stream_putl(s
, ls_pref
->metric
);
1551 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1552 stream_putl(s
, ls_pref
->sr
.sid
);
1553 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1554 stream_putc(s
, ls_pref
->sr
.algo
);
1560 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1563 /* Prepare Link State header */
1564 stream_putc(s
, msg
->event
);
1565 stream_putc(s
, msg
->type
);
1566 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1568 /* Add Message Payload */
1569 switch (msg
->type
) {
1570 case LS_MSG_TYPE_NODE
:
1571 return ls_format_node(s
, msg
->data
.node
);
1572 case LS_MSG_TYPE_ATTRIBUTES
:
1573 return ls_format_attributes(s
, msg
->data
.attr
);
1574 case LS_MSG_TYPE_PREFIX
:
1575 return ls_format_prefix(s
, msg
->data
.prefix
);
1577 zlog_warn("Unsupported Payload");
1584 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1585 struct zapi_opaque_reg_info
*dst
)
1590 /* Check if we have a valid message */
1591 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1594 /* Check buffer size */
1595 if (STREAM_SIZE(zclient
->obuf
) <
1596 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1602 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1604 /* Set sub-type, flags and destination for unicast message */
1605 stream_putl(s
, LINK_STATE_UPDATE
);
1607 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1608 stream_putw(s
, flags
);
1609 /* Send destination client info */
1610 stream_putc(s
, dst
->proto
);
1611 stream_putw(s
, dst
->instance
);
1612 stream_putl(s
, dst
->session_id
);
1614 stream_putw(s
, flags
);
1617 /* Format Link State message */
1618 if (ls_format_msg(s
, msg
) < 0) {
1623 /* Put length into the header at the start of the stream. */
1624 stream_putw_at(s
, 0, stream_get_endp(s
));
1626 return zclient_send_message(zclient
);
1629 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1630 struct ls_vertex
*vertex
)
1632 /* Allocate space if needed */
1634 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1636 memset(msg
, 0, sizeof(*msg
));
1638 msg
->type
= LS_MSG_TYPE_NODE
;
1639 switch (vertex
->status
) {
1641 msg
->event
= LS_MSG_EVENT_ADD
;
1644 msg
->event
= LS_MSG_EVENT_UPDATE
;
1647 msg
->event
= LS_MSG_EVENT_DELETE
;
1650 msg
->event
= LS_MSG_EVENT_SYNC
;
1653 msg
->event
= LS_MSG_EVENT_UNDEF
;
1656 msg
->data
.node
= vertex
->node
;
1657 msg
->remote_id
.origin
= UNKNOWN
;
1662 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1664 /* Allocate space if needed */
1666 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1668 memset(msg
, 0, sizeof(*msg
));
1670 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1671 switch (edge
->status
) {
1673 msg
->event
= LS_MSG_EVENT_ADD
;
1676 msg
->event
= LS_MSG_EVENT_UPDATE
;
1679 msg
->event
= LS_MSG_EVENT_DELETE
;
1682 msg
->event
= LS_MSG_EVENT_SYNC
;
1685 msg
->event
= LS_MSG_EVENT_UNDEF
;
1688 msg
->data
.attr
= edge
->attributes
;
1689 if (edge
->destination
!= NULL
)
1690 msg
->remote_id
= edge
->destination
->node
->adv
;
1692 msg
->remote_id
.origin
= UNKNOWN
;
1697 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1698 struct ls_subnet
*subnet
)
1700 /* Allocate space if needed */
1702 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1704 memset(msg
, 0, sizeof(*msg
));
1706 msg
->type
= LS_MSG_TYPE_PREFIX
;
1707 switch (subnet
->status
) {
1709 msg
->event
= LS_MSG_EVENT_ADD
;
1712 msg
->event
= LS_MSG_EVENT_UPDATE
;
1715 msg
->event
= LS_MSG_EVENT_DELETE
;
1718 msg
->event
= LS_MSG_EVENT_SYNC
;
1721 msg
->event
= LS_MSG_EVENT_UNDEF
;
1724 msg
->data
.prefix
= subnet
->ls_pref
;
1725 msg
->remote_id
.origin
= UNKNOWN
;
1730 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1733 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1734 struct ls_vertex
*vertex
= NULL
;
1736 switch (msg
->event
) {
1737 case LS_MSG_EVENT_SYNC
:
1738 vertex
= ls_vertex_add(ted
, node
);
1740 vertex
->status
= SYNC
;
1742 case LS_MSG_EVENT_ADD
:
1743 vertex
= ls_vertex_add(ted
, node
);
1745 vertex
->status
= NEW
;
1747 case LS_MSG_EVENT_UPDATE
:
1748 vertex
= ls_vertex_update(ted
, node
);
1750 vertex
->status
= UPDATE
;
1752 case LS_MSG_EVENT_DELETE
:
1753 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1756 ls_vertex_del_all(ted
, vertex
);
1758 vertex
->status
= DELETE
;
1769 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1772 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1773 struct ls_edge
*edge
= NULL
;
1775 switch (msg
->event
) {
1776 case LS_MSG_EVENT_SYNC
:
1777 edge
= ls_edge_add(ted
, attr
);
1779 edge
->status
= SYNC
;
1781 case LS_MSG_EVENT_ADD
:
1782 edge
= ls_edge_add(ted
, attr
);
1786 case LS_MSG_EVENT_UPDATE
:
1787 edge
= ls_edge_update(ted
, attr
);
1789 edge
->status
= UPDATE
;
1791 case LS_MSG_EVENT_DELETE
:
1792 edge
= ls_find_edge_by_source(ted
, attr
);
1795 ls_edge_del_all(ted
, edge
);
1797 edge
->status
= DELETE
;
1808 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1811 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1812 struct ls_subnet
*subnet
= NULL
;
1814 switch (msg
->event
) {
1815 case LS_MSG_EVENT_SYNC
:
1816 subnet
= ls_subnet_add(ted
, pref
);
1818 subnet
->status
= SYNC
;
1820 case LS_MSG_EVENT_ADD
:
1821 subnet
= ls_subnet_add(ted
, pref
);
1823 subnet
->status
= NEW
;
1825 case LS_MSG_EVENT_UPDATE
:
1826 subnet
= ls_subnet_update(ted
, pref
);
1828 subnet
->status
= UPDATE
;
1830 case LS_MSG_EVENT_DELETE
:
1831 subnet
= ls_find_subnet(ted
, pref
->pref
);
1834 ls_subnet_del_all(ted
, subnet
);
1836 subnet
->status
= DELETE
;
1847 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1850 struct ls_element
*lse
= NULL
;
1852 switch (msg
->type
) {
1853 case LS_MSG_TYPE_NODE
:
1854 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1856 case LS_MSG_TYPE_ATTRIBUTES
:
1857 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1859 case LS_MSG_TYPE_PREFIX
:
1860 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1870 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1873 struct ls_message
*msg
;
1874 struct ls_element
*lse
= NULL
;
1876 msg
= ls_parse_msg(s
);
1878 lse
= ls_msg2ted(ted
, msg
, delete);
1885 void ls_delete_msg(struct ls_message
*msg
)
1890 XFREE(MTYPE_LS_DB
, msg
);
1893 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1894 struct zapi_opaque_reg_info
*dst
)
1896 struct ls_vertex
*vertex
;
1897 struct ls_edge
*edge
;
1898 struct ls_subnet
*subnet
;
1899 struct ls_message msg
;
1901 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1902 frr_each(vertices
, &ted
->vertices
, vertex
) {
1903 ls_vertex2msg(&msg
, vertex
);
1904 ls_send_msg(zclient
, &msg
, dst
);
1906 frr_each(edges
, &ted
->edges
, edge
) {
1907 ls_edge2msg(&msg
, edge
);
1908 ls_send_msg(zclient
, &msg
, dst
);
1910 frr_each(subnets
, &ted
->subnets
, subnet
) {
1911 ls_subnet2msg(&msg
, subnet
);
1912 ls_send_msg(zclient
, &msg
, dst
);
1918 * Link State Show functions
1920 static const char *const origin2txt
[] = {
1929 static const char *const type2txt
[] = {
1938 static const char *const status2txt
[] = {
1947 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1950 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1953 id
= lnid
.id
.iso
.sys_id
;
1954 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1955 id
[1], id
[2], id
[3], id
[4], id
[5]);
1957 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1962 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1965 struct listnode
*node
;
1966 struct ls_node
*lsn
;
1967 struct ls_edge
*edge
;
1968 struct ls_attributes
*attr
;
1969 struct ls_subnet
*subnet
;
1979 sbuf_init(&sbuf
, NULL
, 0);
1981 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
1982 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
1983 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
1984 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
1988 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
1989 listcount(vertex
->outgoing_edges
),
1990 listcount(vertex
->incoming_edges
),
1991 listcount(vertex
->prefixes
));
1995 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1996 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
1997 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1998 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
1999 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2000 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
2001 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
2002 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
2004 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2005 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
2007 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
2008 lsn
->srlb
.lower_bound
, upper
);
2010 sbuf_push(&sbuf
, 0, "\tAlgo: ");
2011 for (int i
= 0; i
< 2; i
++) {
2012 if (lsn
->algo
[i
] == 255)
2016 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
2018 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2019 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
2020 sbuf_push(&sbuf
, 0, "\n");
2023 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
2024 listcount(vertex
->outgoing_edges
));
2025 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
2026 if (edge
->destination
) {
2027 lsn
= edge
->destination
->node
;
2028 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
2031 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
2033 attr
= edge
->attributes
;
2034 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2035 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2036 &attr
->standard
.local
,
2037 &attr
->standard
.remote
);
2038 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2039 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2040 &attr
->standard
.local6
,
2041 &attr
->standard
.remote6
);
2044 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
2045 listcount(vertex
->incoming_edges
));
2046 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
2048 lsn
= edge
->source
->node
;
2049 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
2052 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
2054 attr
= edge
->attributes
;
2055 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2056 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2057 &attr
->standard
.local
,
2058 &attr
->standard
.remote
);
2059 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2060 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2061 &attr
->standard
.local6
,
2062 &attr
->standard
.remote6
);
2065 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
2066 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
2067 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
2070 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2074 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
2075 struct json_object
*json
)
2077 struct ls_node
*lsn
;
2078 json_object
*jsr
, *jalgo
, *jobj
;
2079 char buf
[INET6_BUFSIZ
];
2087 json_object_int_add(json
, "vertex-id", vertex
->key
);
2088 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
2089 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
2090 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
2091 json_object_string_add(json
, "name", lsn
->name
);
2092 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
2093 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
2094 json_object_string_add(json
, "router-id", buf
);
2096 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
2097 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router_id6
);
2098 json_object_string_add(json
, "router-id-v6", buf
);
2100 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2101 json_object_string_add(json
, "vertex-type",
2102 type2txt
[lsn
->type
]);
2103 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2104 json_object_int_add(json
, "asn", lsn
->as_number
);
2105 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2106 jsr
= json_object_new_object();
2107 json_object_object_add(json
, "segment-routing", jsr
);
2108 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
2109 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
2110 jalgo
= json_object_new_array();
2111 json_object_object_add(jsr
, "algorithms", jalgo
);
2112 for (int i
= 0; i
< 2; i
++) {
2113 if (lsn
->algo
[i
] == 255)
2115 jobj
= json_object_new_object();
2117 snprintfrr(buf
, 2, "%u", i
);
2118 json_object_string_add(
2119 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
2120 json_object_array_add(jalgo
, jobj
);
2122 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2123 json_object_int_add(jsr
, "srlb-size",
2124 lsn
->srlb
.range_size
);
2125 json_object_int_add(jsr
, "srlb-lower",
2126 lsn
->srlb
.lower_bound
);
2128 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2129 json_object_int_add(jsr
, "msd", lsn
->msd
);
2133 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
2134 struct json_object
*json
, bool verbose
)
2137 ls_show_vertex_json(vertex
, json
);
2139 ls_show_vertex_vty(vertex
, vty
, verbose
);
2142 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
2143 struct json_object
*json
, bool verbose
)
2145 struct ls_vertex
*vertex
;
2146 json_object
*jnodes
, *jnode
;
2149 jnodes
= json_object_new_array();
2150 json_object_object_add(json
, "vertices", jnodes
);
2151 frr_each (vertices
, &ted
->vertices
, vertex
) {
2152 jnode
= json_object_new_object();
2153 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
2154 json_object_array_add(jnodes
, jnode
);
2157 frr_each (vertices
, &ted
->vertices
, vertex
)
2158 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
2162 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
2165 struct ls_attributes
*attr
;
2167 char buf
[INET6_BUFSIZ
];
2169 attr
= edge
->attributes
;
2170 sbuf_init(&sbuf
, NULL
, 0);
2172 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
2173 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2174 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2175 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2176 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2178 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2179 attr
->standard
.remote_id
);
2180 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2181 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2182 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2183 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2188 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2189 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2190 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2191 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2192 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2193 attr
->standard
.te_metric
);
2194 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2195 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2196 attr
->standard
.admin_group
);
2197 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2198 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2199 &attr
->standard
.local
);
2200 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2201 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2202 &attr
->standard
.remote
);
2203 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2204 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2205 &attr
->standard
.local6
);
2206 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2207 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2208 &attr
->standard
.remote6
);
2209 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2210 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2211 attr
->standard
.local_id
);
2212 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2213 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2214 attr
->standard
.remote_id
);
2215 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2216 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2217 attr
->standard
.max_bw
);
2218 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2220 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2221 attr
->standard
.max_rsv_bw
);
2222 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2223 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2224 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2226 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2227 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2228 attr
->standard
.unrsv_bw
[i
+ 1]);
2230 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2231 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2232 attr
->standard
.remote_as
);
2233 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2234 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2235 &attr
->standard
.remote_addr
);
2236 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2237 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2238 &attr
->standard
.remote_addr6
);
2239 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2240 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2241 attr
->extended
.delay
);
2242 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2243 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2244 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2245 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2246 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2247 attr
->extended
.jitter
);
2248 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2249 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2250 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2251 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2252 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2253 attr
->extended
.ava_bw
);
2254 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2255 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2256 attr
->extended
.rsv_bw
);
2257 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2258 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2259 attr
->extended
.used_bw
);
2260 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2261 sbuf_push(&sbuf
, 4, "IPv4 Adjacency-SID: %u",
2262 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2263 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2264 attr
->adj_sid
[ADJ_PRI_IPV4
].flags
,
2265 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2267 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2268 sbuf_push(&sbuf
, 4, "IPv4 Bck. Adjacency-SID: %u",
2269 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2270 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2271 attr
->adj_sid
[ADJ_BCK_IPV4
].flags
,
2272 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2274 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2275 sbuf_push(&sbuf
, 4, "IPv6 Adjacency-SID: %u",
2276 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2277 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2278 attr
->adj_sid
[ADJ_PRI_IPV6
].flags
,
2279 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2281 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2282 sbuf_push(&sbuf
, 4, "IPv6 Bck. Adjacency-SID: %u",
2283 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2284 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2285 attr
->adj_sid
[ADJ_BCK_IPV6
].flags
,
2286 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2288 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2289 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2290 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2292 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2294 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2296 sbuf_push(&sbuf
, 0, "\n");
2300 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2304 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2306 struct ls_attributes
*attr
;
2307 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
;
2308 char buf
[INET6_BUFSIZ
];
2310 attr
= edge
->attributes
;
2312 json_object_int_add(json
, "edge-id", edge
->key
);
2313 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2314 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2315 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2316 json_object_string_add(json
, "advertised-router", buf
);
2318 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2319 if (edge
->destination
)
2320 json_object_int_add(json
, "remote-vertex-id",
2321 edge
->destination
->key
);
2322 json_object_int_add(json
, "metric", attr
->metric
);
2323 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2324 json_object_string_add(json
, "name", attr
->name
);
2325 jte
= json_object_new_object();
2326 json_object_object_add(json
, "edge-attributes", jte
);
2327 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2328 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2329 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2330 json_object_int_add(jte
, "admin-group",
2331 attr
->standard
.admin_group
);
2332 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2333 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2334 json_object_string_add(jte
, "local-address", buf
);
2336 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2337 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2338 json_object_string_add(jte
, "remote-address", buf
);
2340 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2341 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2342 json_object_string_add(jte
, "local-address-v6", buf
);
2344 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2345 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2346 json_object_string_add(jte
, "remote-address-v6", buf
);
2348 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2349 json_object_int_add(jte
, "local-identifier",
2350 attr
->standard
.local_id
);
2351 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2352 json_object_int_add(jte
, "remote-identifier",
2353 attr
->standard
.remote_id
);
2354 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2355 json_object_double_add(jte
, "max-link-bandwidth",
2356 attr
->standard
.max_bw
);
2357 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2358 json_object_double_add(jte
, "max-resv-link-bandwidth",
2359 attr
->standard
.max_rsv_bw
);
2360 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2361 jbw
= json_object_new_array();
2362 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2363 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2364 jobj
= json_object_new_object();
2365 snprintfrr(buf
, 13, "class-type-%u", i
);
2366 json_object_double_add(jobj
, buf
,
2367 attr
->standard
.unrsv_bw
[i
]);
2368 json_object_array_add(jbw
, jobj
);
2371 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2372 json_object_int_add(jte
, "remote-asn",
2373 attr
->standard
.remote_as
);
2374 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2375 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2376 &attr
->standard
.remote_addr
);
2377 json_object_string_add(jte
, "remote-as-address", buf
);
2379 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2380 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2381 &attr
->standard
.remote_addr6
);
2382 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2384 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2385 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2386 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2387 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2388 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2390 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2391 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2392 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2393 json_object_double_add(
2394 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2395 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2396 json_object_double_add(jte
, "available-bandwidth",
2397 attr
->extended
.ava_bw
);
2398 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2399 json_object_double_add(jte
, "residual-bandwidth",
2400 attr
->extended
.rsv_bw
);
2401 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2402 json_object_double_add(jte
, "utilized-bandwidth",
2403 attr
->extended
.used_bw
);
2404 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2405 jsrlg
= json_object_new_array();
2406 json_object_object_add(jte
, "srlgs", jsrlg
);
2407 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2408 jobj
= json_object_new_object();
2409 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2410 json_object_array_add(jsrlg
, jobj
);
2413 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2414 jsr
= json_object_new_array();
2415 json_object_object_add(json
, "segment-routing", jsr
);
2416 jobj
= json_object_new_object();
2417 json_object_int_add(jobj
, "adj-sid",
2418 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2419 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
2420 json_object_string_add(jobj
, "flags", buf
);
2421 json_object_int_add(jobj
, "weight",
2422 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2423 json_object_array_add(jsr
, jobj
);
2425 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2427 jsr
= json_object_new_array();
2428 json_object_object_add(json
, "segment-routing", jsr
);
2430 jobj
= json_object_new_object();
2431 json_object_int_add(jobj
, "adj-sid",
2432 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2433 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
2434 json_object_string_add(jobj
, "flags", buf
);
2435 json_object_int_add(jobj
, "weight",
2436 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2437 json_object_array_add(jsr
, jobj
);
2439 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2440 jsr
= json_object_new_array();
2441 json_object_object_add(json
, "segment-routing", jsr
);
2442 jobj
= json_object_new_object();
2443 json_object_int_add(jobj
, "adj-sid",
2444 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2445 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
2446 json_object_string_add(jobj
, "flags", buf
);
2447 json_object_int_add(jobj
, "weight",
2448 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2449 json_object_array_add(jsr
, jobj
);
2451 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2453 jsr
= json_object_new_array();
2454 json_object_object_add(json
, "segment-routing", jsr
);
2456 jobj
= json_object_new_object();
2457 json_object_int_add(jobj
, "adj-sid",
2458 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2459 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
2460 json_object_string_add(jobj
, "flags", buf
);
2461 json_object_int_add(jobj
, "weight",
2462 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2463 json_object_array_add(jsr
, jobj
);
2467 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2468 struct json_object
*json
, bool verbose
)
2475 ls_show_edge_json(edge
, json
);
2477 ls_show_edge_vty(edge
, vty
, verbose
);
2480 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2481 struct json_object
*json
, bool verbose
)
2483 struct ls_edge
*edge
;
2484 json_object
*jedges
, *jedge
;
2487 jedges
= json_object_new_array();
2488 json_object_object_add(json
, "edges", jedges
);
2489 frr_each (edges
, &ted
->edges
, edge
) {
2490 jedge
= json_object_new_object();
2491 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2492 json_object_array_add(jedges
, jedge
);
2495 frr_each (edges
, &ted
->edges
, edge
)
2496 ls_show_edge(edge
, vty
, NULL
, verbose
);
2500 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2503 struct ls_prefix
*pref
;
2505 char buf
[INET6_BUFSIZ
];
2507 pref
= subnet
->ls_pref
;
2508 sbuf_init(&sbuf
, NULL
, 0);
2510 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2511 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2512 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2513 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2514 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2519 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2520 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2521 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2523 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2524 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2526 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2527 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2528 pref
->extended_tag
);
2530 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2531 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2532 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2535 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2539 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2540 struct json_object
*json
)
2542 struct ls_prefix
*pref
;
2544 char buf
[INET6_BUFSIZ
];
2546 pref
= subnet
->ls_pref
;
2548 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2549 json_object_string_add(json
, "subnet-id", buf
);
2550 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2551 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2552 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2553 json_object_string_add(json
, "advertised-router", buf
);
2555 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2556 json_object_int_add(json
, "metric", pref
->metric
);
2557 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2558 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2559 json_object_string_add(json
, "flags", buf
);
2561 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2562 json_object_int_add(json
, "tag", pref
->route_tag
);
2563 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2564 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2565 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2566 jsr
= json_object_new_object();
2567 json_object_object_add(json
, "segment-routing", jsr
);
2568 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2569 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2570 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2571 json_object_string_add(jsr
, "flags", buf
);
2575 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2576 struct json_object
*json
, bool verbose
)
2583 ls_show_subnet_json(subnet
, json
);
2585 ls_show_subnet_vty(subnet
, vty
, verbose
);
2588 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2589 struct json_object
*json
, bool verbose
)
2591 struct ls_subnet
*subnet
;
2592 json_object
*jsubs
, *jsub
;
2595 jsubs
= json_object_new_array();
2596 json_object_object_add(json
, "subnets", jsubs
);
2597 frr_each (subnets
, &ted
->subnets
, subnet
) {
2598 jsub
= json_object_new_object();
2599 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2600 json_object_array_add(jsubs
, jsub
);
2603 frr_each (subnets
, &ted
->subnets
, subnet
)
2604 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2608 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2614 jted
= json_object_new_object();
2615 json_object_object_add(json
, "ted", jted
);
2616 json_object_string_add(jted
, "name", ted
->name
);
2617 json_object_int_add(jted
, "key", ted
->key
);
2618 json_object_int_add(jted
, "verticesCount",
2619 vertices_count(&ted
->vertices
));
2620 json_object_int_add(jted
, "edgesCount",
2621 edges_count(&ted
->edges
));
2622 json_object_int_add(jted
, "subnetsCount",
2623 subnets_count(&ted
->subnets
));
2624 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2625 ls_show_edges(ted
, NULL
, jted
, verbose
);
2626 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2632 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2633 ted
->name
, ted
->key
);
2634 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2635 ls_show_edges(ted
, vty
, NULL
, verbose
);
2636 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2638 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2639 vertices_count(&ted
->vertices
),
2640 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2644 void ls_dump_ted(struct ls_ted
*ted
)
2646 struct ls_vertex
*vertex
;
2647 struct ls_edge
*edge
;
2648 struct ls_subnet
*subnet
;
2649 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2651 zlog_debug("(%s) Ted init", __func__
);
2653 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2654 frr_each (vertices
, &ted
->vertices
, vertex
) {
2655 zlog_debug(" Ted node (%s %pI4 %s)",
2656 vertex
->node
->name
[0] ? vertex
->node
->name
2658 &vertex
->node
->router_id
,
2659 origin2txt
[vertex
->node
->adv
.origin
]);
2660 struct listnode
*lst_node
;
2661 struct ls_edge
*vertex_edge
;
2663 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2666 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2668 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2669 &vertex_edge
->attributes
->standard
.local
,
2670 &vertex_edge
->attributes
->standard
.remote
);
2672 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2675 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2677 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2678 &vertex_edge
->attributes
->standard
.local
,
2679 &vertex_edge
->attributes
->standard
.remote
);
2682 frr_each (edges
, &ted
->edges
, edge
) {
2683 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2684 edge
->source
? &edge
->source
->node
->router_id
2687 ? &edge
->destination
->node
->router_id
2690 frr_each (subnets
, &ted
->subnets
, subnet
) {
2691 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2692 &subnet
->ls_pref
->pref
,
2693 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2695 zlog_debug("(%s) Ted end", __func__
);