]>
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
29 #include "termtable.h"
36 #include "link_state.h"
38 /* Link State Memory allocation */
39 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
42 * Link State Node management functions
44 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
49 if (adv
.origin
== NONE
)
52 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
54 if (!IPV4_NET0(rid
.s_addr
)) {
56 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
58 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
59 || adv
.origin
== DIRECT
) {
60 new->router_id
= adv
.id
.ip
.addr
;
61 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
64 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
65 new->router6_id
= rid6
;
66 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
71 void ls_node_del(struct ls_node
*node
)
73 XFREE(MTYPE_LS_DB
, node
);
77 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
79 if ((n1
&& !n2
) || (!n1
&& n2
))
85 if (n1
->flags
!= n2
->flags
)
88 if (n1
->adv
.origin
!= n2
->adv
.origin
)
91 if (!memcmp(&n1
->adv
.id
, &n2
->adv
.id
, sizeof(struct ls_node_id
)))
94 /* Do we need to test individually each field, instead performing a
95 * global memcmp? There is a risk that an old value that is bit masked
96 * i.e. corresponding flag = 0, will result into a false negative
98 if (!memcmp(n1
, n2
, sizeof(struct ls_node
)))
105 * Link State Attributes management functions
107 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
108 struct in_addr local
,
109 struct in6_addr local6
,
112 struct ls_attributes
*new;
114 if (adv
.origin
== NONE
)
117 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
119 if (!IPV4_NET0(local
.s_addr
)) {
120 new->standard
.local
= local
;
121 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
123 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
124 new->standard
.local6
= local6
;
125 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
128 new->standard
.local_id
= local_id
;
129 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
132 /* Check that almost one identifier is set */
133 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
134 | LS_ATTR_LOCAL_ID
)) {
135 XFREE(MTYPE_LS_DB
, new);
142 void ls_attributes_del(struct ls_attributes
*attr
)
148 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
150 XFREE(MTYPE_LS_DB
, attr
);
154 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
156 if ((l1
&& !l2
) || (!l1
&& l2
))
162 if (l1
->flags
!= l2
->flags
)
165 if (l1
->adv
.origin
!= l2
->adv
.origin
)
168 if (!memcmp(&l1
->adv
.id
, &l2
->adv
.id
, sizeof(struct ls_node_id
)))
171 /* Do we need to test individually each field, instead performing a
172 * global memcmp? There is a risk that an old value that is bit masked
173 * i.e. corresponding flag = 0, will result into a false negative
175 if (!memcmp(l1
, l2
, sizeof(struct ls_attributes
)))
182 * Link State Vertices management functions
184 struct ls_vertex
*ls_vertex_new(struct ls_node
*node
)
186 struct ls_vertex
*new;
191 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
193 new->incoming_edges
= list_new();
194 new->outgoing_edges
= list_new();
195 new->prefixes
= list_new();
200 void ls_vertex_del(struct ls_vertex
*vertex
)
205 list_delete_all_node(vertex
->incoming_edges
);
206 list_delete_all_node(vertex
->outgoing_edges
);
207 list_delete_all_node(vertex
->prefixes
);
208 XFREE(MTYPE_LS_DB
, vertex
);
212 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
214 struct ls_vertex
*new;
216 if ((ted
== NULL
) || (node
== NULL
))
219 new = ls_vertex_new(node
);
223 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
224 switch (node
->adv
.origin
) {
228 memcpy(&new->key
, &node
->adv
.id
.ip
.addr
, IPV4_MAX_BYTELEN
);
232 memcpy(&new->key
, &node
->adv
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
239 /* Remove Vertex if key is not set */
245 /* Add Vertex to TED */
246 vertices_add(&ted
->vertices
, new);
251 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
253 struct ls_vertex
*old
;
258 old
= ls_find_vertex_by_id(ted
, node
->adv
);
260 if (!ls_node_same(old
->node
, node
)) {
261 ls_node_del(old
->node
);
267 return ls_vertex_add(ted
, node
);
270 void ls_vertex_remove(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
272 vertices_del(&ted
->vertices
, vertex
);
273 ls_vertex_del(vertex
);
276 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
278 struct ls_vertex node
= {};
284 return vertices_find(&ted
->vertices
, &node
);
287 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
288 struct ls_node_id nid
)
290 struct ls_vertex node
= {};
292 switch (nid
.origin
) {
296 memcpy(&node
.key
, &nid
.id
.ip
.addr
, IPV4_MAX_BYTELEN
);
300 memcpy(&node
.key
, &nid
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
306 return vertices_find(&ted
->vertices
, &node
);
309 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
311 if ((v1
&& !v2
) || (!v1
&& v2
))
317 if (v1
->key
!= v2
->key
)
320 if (v1
->node
== v2
->node
)
323 return ls_node_same(v1
->node
, v2
->node
);
327 * Link State Edges management functions
331 * This function allows to connect the Edge to the vertices present in the TED.
332 * A temporary vertex that corresponds to the source of this Edge i.e. the
333 * advertised router, is created if not found in the Data Base. If a Edge that
334 * corresponds to the reverse path is found, the Edge is attached to the
335 * destination vertex as destination and reverse Edge is attached to the source
338 * @param ted Link State Data Base
339 * @param edge Link State Edge to be attached
341 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
343 struct ls_vertex
*vertex
= NULL
;
344 struct ls_node
*node
;
346 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
348 /* First, search if there is a Vertex that correspond to the Node ID */
349 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
350 if (vertex
== NULL
) {
351 /* Create a new temporary Node & Vertex if not found */
352 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
354 vertex
= ls_vertex_add(ted
, node
);
356 /* and attach the edge as source to the vertex */
357 listnode_add(vertex
->outgoing_edges
, edge
);
358 edge
->source
= vertex
;
360 /* Then search if there is a reverse Edge */
361 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
362 /* attach the destination edge to the vertex */
364 listnode_add(vertex
->incoming_edges
, dst
);
365 dst
->destination
= vertex
;
366 /* and destination vertex to this edge */
367 vertex
= dst
->source
;
368 listnode_add(vertex
->incoming_edges
, edge
);
369 edge
->destination
= vertex
;
373 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
374 struct ls_attributes
*attributes
)
378 if (attributes
== NULL
)
381 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
382 new->attributes
= attributes
;
383 /* Key is the IPv4 local address */
384 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
385 new->key
= ((uint64_t)attributes
->standard
.local
.s_addr
)
387 /* or the IPv6 local address if IPv4 is not defined */
388 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
389 new->key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
391 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
393 /* of local identifier if no IP addresses are defined */
394 else if (attributes
->standard
.local_id
!= 0)
395 new->key
= (uint64_t)(
396 (attributes
->standard
.local_id
& 0xffffffff)
397 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
399 /* Remove Edge if key is not known */
401 XFREE(MTYPE_LS_DB
, new);
405 edges_add(&ted
->edges
, new);
407 /* Finally, connect edge to vertices */
408 ls_edge_connect_to(ted
, new);
413 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
415 struct ls_edge edge
= {};
421 return edges_find(&ted
->edges
, &edge
);
424 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
425 struct ls_attributes
*attributes
)
427 struct ls_edge edge
= {};
429 if (attributes
== NULL
)
432 /* Key is the IPv4 local address */
433 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
434 edge
.key
= ((uint64_t)attributes
->standard
.local
.s_addr
)
436 /* or the IPv6 local address if IPv4 is not defined */
437 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
438 edge
.key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
440 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
442 /* of local identifier if no IP addresses are defined */
443 else if (attributes
->standard
.local_id
!= 0)
444 edge
.key
= (uint64_t)(
445 (attributes
->standard
.local_id
& 0xffffffff)
446 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
451 return edges_find(&ted
->edges
, &edge
);
454 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
455 struct ls_attributes
*attributes
)
457 struct ls_edge edge
= {};
459 if (attributes
== NULL
)
462 /* Key is the IPv4 local address */
463 if (!IPV4_NET0(attributes
->standard
.remote
.s_addr
))
464 edge
.key
= ((uint64_t)attributes
->standard
.remote
.s_addr
)
466 /* or the IPv6 local address if IPv4 is not defined */
467 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.remote6
))
469 (uint64_t)(attributes
->standard
.remote6
.s6_addr32
[0]
471 | ((uint64_t)attributes
->standard
.remote6
.s6_addr32
[1]
473 /* of local identifier if no IP addresses are defined */
474 else if (attributes
->standard
.remote_id
!= 0)
475 edge
.key
= (uint64_t)(
476 (attributes
->standard
.remote_id
& 0xffffffff)
477 | ((uint64_t)attributes
->standard
.local_id
<< 32));
482 return edges_find(&ted
->edges
, &edge
);
485 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
486 struct ls_attributes
*attributes
)
490 if (attributes
== NULL
)
493 /* First, search for an existing Edge */
494 old
= ls_find_edge_by_source(ted
, attributes
);
496 /* Check if attributes are similar */
497 if (!ls_attributes_same(old
->attributes
, attributes
)) {
498 ls_attributes_del(old
->attributes
);
499 old
->attributes
= attributes
;
504 /* If not found, add new Edge from the attributes */
505 return ls_edge_add(ted
, attributes
);
508 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
510 /* Fist disconnect Edge */
511 ls_disconnect_edge(edge
);
512 /* Then remove it from the Data Base */
513 edges_del(&ted
->edges
, edge
);
514 XFREE(MTYPE_LS_DB
, edge
);
518 * Link State Subnet Management functions.
520 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
521 struct ls_prefix
*ls_pref
)
523 struct ls_subnet
*new;
524 struct ls_vertex
*vertex
;
525 struct ls_node
*node
;
526 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
531 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
532 new->ls_pref
= ls_pref
;
533 new->key
= ls_pref
->pref
;
536 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
537 if (vertex
== NULL
) {
538 /* Create a new temporary Node & Vertex if not found */
539 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
540 vertex
= ls_vertex_add(ted
, node
);
542 /* And attach the subnet to the corresponding Vertex */
543 new->vertex
= vertex
;
544 listnode_add(vertex
->prefixes
, new);
546 subnets_add(&ted
->subnets
, new);
551 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
553 subnets_del(&ted
->subnets
, subnet
);
554 XFREE(MTYPE_LS_DB
, subnet
);
557 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
559 struct ls_subnet subnet
= {};
562 return subnets_find(&ted
->subnets
, &subnet
);
566 * Link State TED management functions
568 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
573 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
577 /* Set basic information for this ted */
579 new->as_number
= as_number
;
580 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
582 /* Initialize the various RB tree */
583 vertices_init(&new->vertices
);
584 edges_init(&new->edges
);
585 subnets_init(&new->subnets
);
590 void ls_ted_del(struct ls_ted
*ted
)
595 /* Release RB Tree */
596 vertices_fini(&ted
->vertices
);
597 edges_fini(&ted
->edges
);
598 subnets_fini(&ted
->subnets
);
600 XFREE(MTYPE_LS_DB
, ted
);
604 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
606 if (vertex
== NULL
|| edge
== NULL
)
610 listnode_add(vertex
->outgoing_edges
, edge
);
611 edge
->source
= vertex
;
613 listnode_add(vertex
->incoming_edges
, edge
);
614 edge
->destination
= vertex
;
618 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
621 if (vertex
== NULL
|| edge
== NULL
)
625 listnode_delete(vertex
->outgoing_edges
, edge
);
628 listnode_delete(vertex
->incoming_edges
, edge
);
629 edge
->destination
= NULL
;
633 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
634 struct ls_edge
*edge
)
640 edge
->destination
= dst
;
643 listnode_add(src
->outgoing_edges
, edge
);
646 listnode_add(dst
->incoming_edges
, edge
);
650 void ls_disconnect_edge(struct ls_edge
*edge
)
655 ls_disconnect(edge
->source
, edge
, true);
656 ls_disconnect(edge
->destination
, edge
, false);
660 * Link State Message management functions
663 static struct ls_node
*ls_parse_node(struct stream
*s
)
665 struct ls_node
*node
;
668 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
672 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
673 STREAM_GETW(s
, node
->flags
);
674 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
676 STREAM_GET(node
->name
, s
, len
);
678 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
679 node
->router_id
.s_addr
= stream_get_ipv4(s
);
680 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
681 STREAM_GET(&node
->router6_id
, s
, IPV6_MAX_BYTELEN
);
682 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
683 STREAM_GETC(s
, node
->node_flag
);
684 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
685 STREAM_GETC(s
, node
->type
);
686 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
687 STREAM_GETL(s
, node
->as_number
);
688 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
689 STREAM_GETL(s
, node
->srgb
.lower_bound
);
690 STREAM_GETL(s
, node
->srgb
.range_size
);
691 STREAM_GETC(s
, node
->srgb
.flag
);
692 STREAM_GET(node
->algo
, s
, 2);
694 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
695 STREAM_GETL(s
, node
->srlb
.lower_bound
);
696 STREAM_GETL(s
, node
->srlb
.range_size
);
698 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
699 STREAM_GETC(s
, node
->msd
);
704 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
705 XFREE(MTYPE_LS_DB
, node
);
709 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
711 struct ls_attributes
*attr
;
714 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
719 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
720 STREAM_GETL(s
, attr
->flags
);
721 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
723 STREAM_GET(attr
->name
, s
, len
);
725 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
726 STREAM_GETL(s
, attr
->standard
.metric
);
727 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
728 STREAM_GETL(s
, attr
->standard
.te_metric
);
729 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
730 STREAM_GETL(s
, attr
->standard
.admin_group
);
731 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
732 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
733 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
734 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
735 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
736 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
737 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
738 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
739 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
740 STREAM_GETL(s
, attr
->standard
.local_id
);
741 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
742 STREAM_GETL(s
, attr
->standard
.remote_id
);
743 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
744 STREAM_GETF(s
, attr
->standard
.max_bw
);
745 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
746 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
747 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
748 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
749 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
750 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
751 STREAM_GETL(s
, attr
->standard
.remote_as
);
752 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
753 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
754 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
755 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
756 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
757 STREAM_GETL(s
, attr
->extended
.delay
);
758 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
759 STREAM_GETL(s
, attr
->extended
.min_delay
);
760 STREAM_GETL(s
, attr
->extended
.max_delay
);
762 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
763 STREAM_GETL(s
, attr
->extended
.jitter
);
764 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
765 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
766 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
767 STREAM_GETF(s
, attr
->extended
.ava_bw
);
768 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
769 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
770 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
771 STREAM_GETF(s
, attr
->extended
.used_bw
);
772 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
773 STREAM_GETL(s
, attr
->adj_sid
[0].sid
);
774 STREAM_GETC(s
, attr
->adj_sid
[0].flags
);
775 STREAM_GETC(s
, attr
->adj_sid
[0].weight
);
776 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
777 STREAM_GET(attr
->adj_sid
[0].neighbor
.sysid
, s
,
779 else if (attr
->adv
.origin
== OSPFv2
)
780 attr
->adj_sid
[0].neighbor
.addr
.s_addr
=
783 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
784 STREAM_GETL(s
, attr
->adj_sid
[1].sid
);
785 STREAM_GETC(s
, attr
->adj_sid
[1].flags
);
786 STREAM_GETC(s
, attr
->adj_sid
[1].weight
);
787 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
788 STREAM_GET(attr
->adj_sid
[1].neighbor
.sysid
, s
,
790 else if (attr
->adv
.origin
== OSPFv2
)
791 attr
->adj_sid
[1].neighbor
.addr
.s_addr
=
794 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
796 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
797 attr
->srlg_len
= len
;
798 for (len
= 0; len
< attr
->srlg_len
; len
++)
799 STREAM_GETL(s
, attr
->srlgs
[len
]);
805 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
807 /* Clean memeory allocation */
808 if (attr
->srlgs
!= NULL
)
809 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
810 XFREE(MTYPE_LS_DB
, attr
);
815 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
817 struct ls_prefix
*ls_pref
;
820 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
824 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
825 STREAM_GETW(s
, ls_pref
->flags
);
826 STREAM_GETC(s
, ls_pref
->pref
.family
);
827 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
828 len
= prefix_blen(&ls_pref
->pref
);
829 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
830 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
831 STREAM_GETC(s
, ls_pref
->igp_flag
);
832 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
833 STREAM_GETL(s
, ls_pref
->route_tag
);
834 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
835 STREAM_GETQ(s
, ls_pref
->extended_tag
);
836 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
837 STREAM_GETL(s
, ls_pref
->metric
);
838 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
839 STREAM_GETL(s
, ls_pref
->sr
.sid
);
840 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
841 STREAM_GETC(s
, ls_pref
->sr
.algo
);
847 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
848 XFREE(MTYPE_LS_DB
, ls_pref
);
852 struct ls_message
*ls_parse_msg(struct stream
*s
)
854 struct ls_message
*msg
;
856 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
860 /* Read LS Message header */
861 STREAM_GETC(s
, msg
->event
);
862 STREAM_GETC(s
, msg
->type
);
863 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
865 /* Read Message Payload */
867 case LS_MSG_TYPE_NODE
:
868 msg
->data
.node
= ls_parse_node(s
);
870 case LS_MSG_TYPE_ATTRIBUTES
:
871 msg
->data
.attr
= ls_parse_attributes(s
);
873 case LS_MSG_TYPE_PREFIX
:
874 msg
->data
.prefix
= ls_parse_prefix(s
);
877 zlog_err("Unsupported Payload");
881 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
882 || msg
->data
.prefix
== NULL
)
888 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
889 XFREE(MTYPE_LS_DB
, msg
);
893 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
897 /* Push Advertise node information first */
898 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
900 /* Push Flags & Origin then Node information if there are present */
901 stream_putw(s
, node
->flags
);
902 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
903 len
= strlen(node
->name
);
904 stream_putc(s
, len
+ 1);
905 stream_put(s
, node
->name
, len
);
906 stream_putc(s
, '\0');
908 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
909 stream_put_ipv4(s
, node
->router_id
.s_addr
);
910 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
911 stream_put(s
, &node
->router6_id
, IPV6_MAX_BYTELEN
);
912 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
913 stream_putc(s
, node
->node_flag
);
914 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
915 stream_putc(s
, node
->type
);
916 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
917 stream_putl(s
, node
->as_number
);
918 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
919 stream_putl(s
, node
->srgb
.lower_bound
);
920 stream_putl(s
, node
->srgb
.range_size
);
921 stream_putc(s
, node
->srgb
.flag
);
922 stream_put(s
, node
->algo
, 2);
924 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
925 stream_putl(s
, node
->srlb
.lower_bound
);
926 stream_putl(s
, node
->srlb
.range_size
);
928 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
929 stream_putc(s
, node
->msd
);
934 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
938 /* Push Advertise node information first */
939 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
941 /* Push Flags & Origin then LS attributes if there are present */
942 stream_putl(s
, attr
->flags
);
943 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
944 len
= strlen(attr
->name
);
945 stream_putc(s
, len
+ 1);
946 stream_put(s
, attr
->name
, len
);
947 stream_putc(s
, '\0');
949 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
950 stream_putl(s
, attr
->standard
.metric
);
951 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
952 stream_putl(s
, attr
->standard
.te_metric
);
953 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
954 stream_putl(s
, attr
->standard
.admin_group
);
955 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
956 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
957 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
958 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
959 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
960 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
961 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
962 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
963 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
964 stream_putl(s
, attr
->standard
.local_id
);
965 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
966 stream_putl(s
, attr
->standard
.remote_id
);
967 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
968 stream_putf(s
, attr
->standard
.max_bw
);
969 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
970 stream_putf(s
, attr
->standard
.max_rsv_bw
);
971 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
972 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
973 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
974 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
975 stream_putl(s
, attr
->standard
.remote_as
);
976 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
977 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
978 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
979 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
980 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
981 stream_putl(s
, attr
->extended
.delay
);
982 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
983 stream_putl(s
, attr
->extended
.min_delay
);
984 stream_putl(s
, attr
->extended
.max_delay
);
986 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
987 stream_putl(s
, attr
->extended
.jitter
);
988 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
989 stream_putl(s
, attr
->extended
.pkt_loss
);
990 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
991 stream_putf(s
, attr
->extended
.ava_bw
);
992 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
993 stream_putf(s
, attr
->extended
.rsv_bw
);
994 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
995 stream_putf(s
, attr
->extended
.used_bw
);
996 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
997 stream_putl(s
, attr
->adj_sid
[0].sid
);
998 stream_putc(s
, attr
->adj_sid
[0].flags
);
999 stream_putc(s
, attr
->adj_sid
[0].weight
);
1000 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1001 stream_put(s
, attr
->adj_sid
[0].neighbor
.sysid
,
1003 else if (attr
->adv
.origin
== OSPFv2
)
1005 attr
->adj_sid
[0].neighbor
.addr
.s_addr
);
1007 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1008 stream_putl(s
, attr
->adj_sid
[1].sid
);
1009 stream_putc(s
, attr
->adj_sid
[1].flags
);
1010 stream_putc(s
, attr
->adj_sid
[1].weight
);
1011 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1012 stream_put(s
, attr
->adj_sid
[1].neighbor
.sysid
,
1014 else if (attr
->adv
.origin
== OSPFv2
)
1016 attr
->adj_sid
[1].neighbor
.addr
.s_addr
);
1018 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1019 stream_putc(s
, attr
->srlg_len
);
1020 for (len
= 0; len
< attr
->srlg_len
; len
++)
1021 stream_putl(s
, attr
->srlgs
[len
]);
1027 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1031 /* Push Advertise node information first */
1032 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1034 /* Push Flags, Origin & Prefix then information if there are present */
1035 stream_putw(s
, ls_pref
->flags
);
1036 stream_putc(s
, ls_pref
->pref
.family
);
1037 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1038 len
= prefix_blen(&ls_pref
->pref
);
1039 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1040 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1041 stream_putc(s
, ls_pref
->igp_flag
);
1042 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1043 stream_putl(s
, ls_pref
->route_tag
);
1044 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1045 stream_putq(s
, ls_pref
->extended_tag
);
1046 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1047 stream_putl(s
, ls_pref
->metric
);
1048 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1049 stream_putl(s
, ls_pref
->sr
.sid
);
1050 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1051 stream_putc(s
, ls_pref
->sr
.algo
);
1057 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1060 /* Prepare Link State header */
1061 stream_putc(s
, msg
->event
);
1062 stream_putc(s
, msg
->type
);
1063 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1065 /* Add Message Payload */
1066 switch (msg
->type
) {
1067 case LS_MSG_TYPE_NODE
:
1068 return ls_format_node(s
, msg
->data
.node
);
1069 case LS_MSG_TYPE_ATTRIBUTES
:
1070 return ls_format_attributes(s
, msg
->data
.attr
);
1071 case LS_MSG_TYPE_PREFIX
:
1072 return ls_format_prefix(s
, msg
->data
.prefix
);
1074 zlog_warn("Unsupported Payload");
1081 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1082 struct zapi_opaque_reg_info
*dst
)
1087 /* Check buffer size */
1088 if (STREAM_SIZE(zclient
->obuf
) <
1089 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1095 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1097 /* Send sub-type, flags and destination for unicast message */
1098 stream_putl(s
, LINK_STATE_UPDATE
);
1100 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1101 stream_putw(s
, flags
);
1102 /* Send destination client info */
1103 stream_putc(s
, dst
->proto
);
1104 stream_putw(s
, dst
->instance
);
1105 stream_putl(s
, dst
->session_id
);
1107 stream_putw(s
, flags
);
1109 /* Format Link State message */
1110 if (ls_format_msg(s
, msg
) < 0) {
1115 /* Put length into the header at the start of the stream. */
1116 stream_putw_at(s
, 0, stream_get_endp(s
));
1118 return zclient_send_message(zclient
);
1121 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1122 struct ls_vertex
*vertex
)
1124 /* Allocate space if needed */
1126 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1128 memset(msg
, 0, sizeof(*msg
));
1130 msg
->type
= LS_MSG_TYPE_NODE
;
1131 msg
->data
.node
= vertex
->node
;
1132 msg
->remote_id
.origin
= NONE
;
1137 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1139 /* Allocate space if needed */
1141 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1143 memset(msg
, 0, sizeof(*msg
));
1145 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1146 msg
->data
.attr
= edge
->attributes
;
1147 if (edge
->destination
!= NULL
)
1148 msg
->remote_id
= edge
->destination
->node
->adv
;
1150 msg
->remote_id
.origin
= NONE
;
1155 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1156 struct ls_subnet
*subnet
)
1158 /* Allocate space if needed */
1160 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1162 memset(msg
, 0, sizeof(*msg
));
1164 msg
->type
= LS_MSG_TYPE_PREFIX
;
1165 msg
->data
.prefix
= subnet
->ls_pref
;
1166 msg
->remote_id
.origin
= NONE
;
1171 void ls_delete_msg(struct ls_message
*msg
)
1176 switch (msg
->type
) {
1177 case LS_MSG_TYPE_NODE
:
1179 XFREE(MTYPE_LS_DB
, msg
->data
.node
);
1181 case LS_MSG_TYPE_ATTRIBUTES
:
1183 XFREE(MTYPE_LS_DB
, msg
->data
.attr
);
1185 case LS_MSG_TYPE_PREFIX
:
1186 if (msg
->data
.prefix
)
1187 XFREE(MTYPE_LS_DB
, msg
->data
.prefix
);
1193 XFREE(MTYPE_LS_DB
, msg
);
1196 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1197 struct zapi_opaque_reg_info
*dst
)
1199 struct ls_vertex
*vertex
;
1200 struct ls_edge
*edge
;
1201 struct ls_subnet
*subnet
;
1202 struct ls_message msg
;
1204 /* Prepare message */
1205 msg
.event
= LS_MSG_EVENT_SYNC
;
1207 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1208 frr_each(vertices
, &ted
->vertices
, vertex
) {
1209 ls_vertex2msg(&msg
, vertex
);
1210 ls_send_msg(zclient
, &msg
, dst
);
1212 frr_each(edges
, &ted
->edges
, edge
) {
1213 ls_edge2msg(&msg
, edge
);
1214 ls_send_msg(zclient
, &msg
, dst
);
1216 frr_each(subnets
, &ted
->subnets
, subnet
) {
1217 ls_subnet2msg(&msg
, subnet
);
1218 ls_send_msg(zclient
, &msg
, dst
);
1223 void ls_dump_ted(struct ls_ted
*ted
)
1225 struct ls_vertex
*vertex
;
1226 struct ls_edge
*edge
;
1227 struct ls_subnet
*subnet
;
1228 struct ls_message msg
;
1230 zlog_debug("(%s) Ted init", __func__
);
1231 /* Prepare message */
1232 msg
.event
= LS_MSG_EVENT_SYNC
;
1234 /* Loop TED, start printing Node, then Attributes and finally Prefix */
1235 frr_each(vertices
, &ted
->vertices
, vertex
) {
1236 ls_vertex2msg(&msg
, vertex
);
1237 zlog_debug(" Ted node (%s %pI4 %s)",
1238 vertex
->node
->name
[0] ? vertex
->node
->name
1240 &vertex
->node
->router_id
,
1241 vertex
->node
->adv
.origin
== DIRECT
? "DIRECT"
1243 struct listnode
*lst_node
;
1244 struct ls_edge
*vertex_edge
;
1246 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
1249 " inc edge key:%"PRIu64
"n attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
1251 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
1252 &vertex_edge
->attributes
->standard
.local
,
1253 &vertex_edge
->attributes
->standard
.remote
);
1255 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
1258 " out edge key:%"PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
1260 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
1261 &vertex_edge
->attributes
->standard
.local
,
1262 &vertex_edge
->attributes
->standard
.remote
);
1265 frr_each(edges
, &ted
->edges
, edge
) {
1266 ls_edge2msg(&msg
, edge
);
1267 zlog_debug(" Ted edge key:%"PRIu64
" src:%s dst:%s",
1269 edge
->source
? edge
->source
->node
->name
1271 edge
->destination
? edge
->destination
->node
->name
1274 frr_each(subnets
, &ted
->subnets
, subnet
) {
1275 ls_subnet2msg(&msg
, subnet
);
1277 " Ted subnet key:%pFX vertex:%pI4 pfx:%pFX",
1279 &subnet
->vertex
->node
->adv
.id
.ip
.addr
,
1280 &subnet
->ls_pref
->pref
);
1282 zlog_debug("(%s) Ted end", __func__
);