3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
11 #include <netinet/in.h>
12 #include "ldp_struct.h"
13 #include "ldp_inet_addr.h"
14 #include "ldp_session.h"
15 #include "ldp_entity.h"
16 #include "ldp_global.h"
17 #include "ldp_nexthop.h"
18 #include "ldp_outlabel.h"
19 #include "ldp_inlabel.h"
20 #include "ldp_hello.h"
27 #include "ldp_label_mapping.h"
28 #include "ldp_tunnel.h"
29 #include "ldp_resource.h"
30 #include "ldp_hop_list.h"
32 #include "mpls_compare.h"
34 #include "mpls_socket_impl.h"
35 #include "mpls_timer_impl.h"
36 #include "mpls_ifmgr_impl.h"
37 #include "mpls_tree_impl.h"
38 #include "mpls_lock_impl.h"
39 #include "mpls_fib_impl.h"
40 #include "mpls_policy_impl.h"
41 #include "mpls_mm_impl.h"
42 #include "mpls_trace_impl.h"
47 #include "mpls_mpls_impl.h"
50 ldp_global
*ldp_global_create(mpls_instance_handle data
)
52 ldp_global
*g
= (ldp_global
*) mpls_malloc(sizeof(ldp_global
));
55 memset(g
, 0, sizeof(ldp_global
));
57 LDP_ENTER(g
->user_data
, "ldp_global_create");
59 g
->global_lock
= mpls_lock_create("_ldp_global_lock_");
60 mpls_lock_get(g
->global_lock
);
62 MPLS_LIST_INIT(&g
->hop_list
, ldp_hop_list
);
63 MPLS_LIST_INIT(&g
->outlabel
, ldp_outlabel
);
64 MPLS_LIST_INIT(&g
->resource
, ldp_resource
);
65 MPLS_LIST_INIT(&g
->inlabel
, ldp_inlabel
);
66 MPLS_LIST_INIT(&g
->session
, ldp_session
);
67 MPLS_LIST_INIT(&g
->nexthop
, ldp_nexthop
);
68 MPLS_LIST_INIT(&g
->tunnel
, ldp_tunnel
);
69 MPLS_LIST_INIT(&g
->entity
, ldp_entity
);
70 MPLS_LIST_INIT(&g
->addr
, ldp_addr
);
71 MPLS_LIST_INIT(&g
->attr
, ldp_attr
);
72 MPLS_LIST_INIT(&g
->peer
, ldp_peer
);
73 MPLS_LIST_INIT(&g
->fec
, ldp_fec
);
74 MPLS_LIST_INIT(&g
->adj
, ldp_adj
);
75 MPLS_LIST_INIT(&g
->iff
, ldp_if
);
77 g
->message_identifier
= 1;
78 g
->configuration_sequence_number
= 1;
79 g
->lsp_control_mode
= LDP_GLOBAL_DEF_CONTROL_MODE
;
80 g
->label_retention_mode
= LDP_GLOBAL_DEF_RETENTION_MODE
;
81 g
->lsp_repair_mode
= LDP_GLOBAL_DEF_REPAIR_MODE
;
82 g
->propagate_release
= LDP_GLOBAL_DEF_PROPOGATE_RELEASE
;
83 g
->label_merge
= LDP_GLOBAL_DEF_LABEL_MERGE
;
84 g
->loop_detection_mode
= LDP_GLOBAL_DEF_LOOP_DETECTION_MODE
;
85 g
->ttl_less_domain
= LDP_GLOBAL_DEF_TTLLESS_DOMAIN
;
86 g
->local_tcp_port
= LDP_GLOBAL_DEF_LOCAL_TCP_PORT
;
87 g
->local_udp_port
= LDP_GLOBAL_DEF_LOCAL_UDP_PORT
;
88 g
->send_address_messages
= LDP_GLOBAL_DEF_SEND_ADDR_MSG
;
89 g
->backoff_step
= LDP_GLOBAL_DEF_BACKOFF_STEP
;
90 g
->send_lsrid_mapping
= LDP_GLOBAL_DEF_SEND_LSRID_MAPPING
;
91 g
->no_route_to_peer_time
= LDP_GLOBAL_DEF_NO_ROUTE_RETRY_TIME
;
93 g
->keepalive_timer
= LDP_ENTITY_DEF_KEEPALIVE_TIMER
;
94 g
->keepalive_interval
= LDP_ENTITY_DEF_KEEPALIVE_INTERVAL
;
95 g
->hellotime_timer
= LDP_ENTITY_DEF_HELLOTIME_TIMER
;
96 g
->hellotime_interval
= LDP_ENTITY_DEF_HELLOTIME_INTERVAL
;
98 g
->admin_state
= MPLS_ADMIN_DISABLE
;
101 g
->addr_tree
= mpls_tree_create(32);
102 g
->fec_tree
= mpls_tree_create(32);
104 mpls_lock_release(g
->global_lock
);
106 LDP_EXIT(g
->user_data
, "ldp_global_create");
112 mpls_return_enum
ldp_global_startup(ldp_global
* g
)
114 ldp_entity
*e
= NULL
;
117 MPLS_ASSERT(g
!= NULL
);
119 LDP_ENTER(g
->user_data
, "ldp_global_startup");
121 if (g
->lsr_identifier
.type
== MPLS_FAMILY_NONE
) {
122 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_ERROR
,
123 "ldp_global_startup: invalid LSRID\n");
124 goto ldp_global_startup_cleanup
;
127 g
->timer_handle
= mpls_timer_open(g
->user_data
);
128 if (mpls_timer_mgr_handle_verify(g
->timer_handle
) == MPLS_BOOL_FALSE
) {
129 goto ldp_global_startup_cleanup
;
132 g
->socket_handle
= mpls_socket_mgr_open(g
->user_data
);
133 if (mpls_socket_mgr_handle_verify(g
->socket_handle
) == MPLS_BOOL_FALSE
) {
134 goto ldp_global_startup_cleanup
;
137 g
->ifmgr_handle
= mpls_ifmgr_open(g
->user_data
, g
);
138 if (mpls_ifmgr_handle_verify(g
->ifmgr_handle
) == MPLS_BOOL_FALSE
) {
139 goto ldp_global_startup_cleanup
;
142 g
->fib_handle
= mpls_fib_open(g
->user_data
, g
);
143 if (mpls_fib_handle_verify(g
->fib_handle
) == MPLS_BOOL_FALSE
) {
144 goto ldp_global_startup_cleanup
;
148 if (!g
->lsr_handle
) {
149 goto ldp_global_startup_cleanup
;
152 g
->mpls_handle
= mpls_mpls_open(g
->user_data
);
153 if (mpls_mpls_handle_verify(g
->mpls_handle
) == MPLS_BOOL_FALSE
) {
154 goto ldp_global_startup_cleanup
;
158 g
->hello_socket
= mpls_socket_create_udp(g
->socket_handle
);
159 if (mpls_socket_handle_verify(g
->socket_handle
, g
->hello_socket
) == MPLS_BOOL_FALSE
) {
160 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
161 "ldp_global_startup: error creating UDP socket\n");
162 goto ldp_global_startup_cleanup
;
165 dest
.addr
.type
= MPLS_FAMILY_IPV4
;
166 dest
.port
= g
->local_udp_port
;
167 dest
.addr
.u
.ipv4
= INADDR_ANY
;
168 // dest.addr.u.ipv4 = INADDR_ALLRTRS_GROUP;
170 if (mpls_socket_bind(g
->socket_handle
, g
->hello_socket
, &dest
) == MPLS_FAILURE
) {
171 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
172 "ldp_global_startup: error binding UDP socket\n");
173 goto ldp_global_startup_cleanup
;
176 if (mpls_socket_options(g
->socket_handle
, g
->hello_socket
,
177 MPLS_SOCKOP_NONBLOCK
| MPLS_SOCKOP_REUSE
) == MPLS_FAILURE
) {
178 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
179 "ldp_global_startup: error setting UDP socket options\n");
180 goto ldp_global_startup_cleanup
;
182 if (mpls_socket_multicast_options(g
->socket_handle
, g
->hello_socket
, 1, 0) ==
184 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
185 "ldp_global_startup: error setting UDP socket multicast options\n");
186 goto ldp_global_startup_cleanup
;
188 mpls_socket_readlist_add(g
->socket_handle
, g
->hello_socket
, 0, MPLS_SOCKET_UDP_DATA
);
190 g
->listen_socket
= mpls_socket_create_tcp(g
->socket_handle
);
191 if (mpls_socket_handle_verify(g
->socket_handle
, g
->listen_socket
) == MPLS_BOOL_FALSE
) {
192 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
193 "ldp_global_startup: error creating TCP socket\n");
194 goto ldp_global_startup_cleanup
;
196 if (mpls_socket_options(g
->socket_handle
, g
->listen_socket
,
197 MPLS_SOCKOP_NONBLOCK
| MPLS_SOCKOP_REUSE
) == MPLS_FAILURE
) {
198 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
199 "ldp_global_startup: error setting TCP socket options\n");
200 goto ldp_global_startup_cleanup
;
203 dest
.addr
.type
= MPLS_FAMILY_IPV4
;
204 dest
.port
= g
->local_tcp_port
;
205 dest
.addr
.u
.ipv4
= INADDR_ANY
;
207 if (mpls_socket_bind(g
->socket_handle
, g
->listen_socket
, &dest
) == MPLS_FAILURE
) {
208 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
209 "ldp_global_startup: error binding TCP socket\n");
210 goto ldp_global_startup_cleanup
;
213 if (mpls_socket_tcp_listen(g
->socket_handle
, g
->listen_socket
, 15) ==
215 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
216 "ldp_global_startup: error setting listen buffer for TCP socket\n");
217 goto ldp_global_startup_cleanup
;
220 mpls_socket_readlist_add(g
->socket_handle
, g
->listen_socket
, 0,
221 MPLS_SOCKET_TCP_LISTEN
);
223 g
->admin_state
= MPLS_ADMIN_ENABLE
;
225 e
= MPLS_LIST_HEAD(&g
->entity
);
227 ldp_entity_startup(g
, e
);
228 e
= MPLS_LIST_NEXT(&g
->entity
, e
, _global
);
231 LDP_EXIT(g
->user_data
, "ldp_global_startup");
234 ldp_global_startup_cleanup
:
235 ldp_global_shutdown(g
);
236 mpls_socket_close(g
->socket_handle
, g
->hello_socket
);
237 mpls_socket_close(g
->socket_handle
, g
->listen_socket
);
239 g
->listen_socket
= 0;
241 LDP_EXIT(g
->user_data
, "ldp_global_startup-error");
246 mpls_return_enum
ldp_global_shutdown(ldp_global
* g
)
248 ldp_entity
*e
= NULL
;
256 LDP_ENTER(g
->user_data
, "ldp_global_shutdown");
258 e
= MPLS_LIST_HEAD(&g
->entity
);
260 ldp_entity_shutdown(g
, e
, 1);
261 e
= MPLS_LIST_NEXT(&g
->entity
, e
, _global
);
264 g
->admin_state
= MPLS_ADMIN_DISABLE
;
266 mpls_socket_readlist_del(g
->socket_handle
, g
->hello_socket
);
267 mpls_socket_close(g
->socket_handle
, g
->hello_socket
);
269 mpls_socket_readlist_del(g
->socket_handle
, g
->listen_socket
);
270 mpls_socket_close(g
->socket_handle
, g
->listen_socket
);
272 mpls_lock_release(g
->global_lock
);
273 mpls_timer_close(g
->timer_handle
);
274 mpls_lock_get(g
->global_lock
);
276 mpls_socket_mgr_close(g
->socket_handle
);
277 mpls_ifmgr_close(g
->ifmgr_handle
);
278 mpls_fib_close(g
->fib_handle
);
282 mpls_mpls_close(g
->mpls_handle
);
285 LDP_EXIT(g
->user_data
, "ldp_global_shutdown");
290 mpls_return_enum
ldp_global_delete(ldp_global
* g
)
310 /* clean up the entities that were configured, sessions and adj should
311 * already have been cleaned up when the entity was shutdown
313 ep
= MPLS_LIST_HEAD(&g
->entity
);
315 nep
= MPLS_LIST_NEXT(&g
->entity
, ep
, _global
);
316 switch (ep
->entity_type
) {
318 ldp_entity_del_if(g
,ep
);
321 ldp_entity_del_peer(ep
);
326 _ldp_global_del_entity(g
, ep
);
330 /* need to properly purge FECs/nexthops/interfaces/addresses */
332 fp
= MPLS_LIST_HEAD(&g
->fec
);
334 nfp
= MPLS_LIST_NEXT(&g
->fec
, fp
, _global
);
336 nhp
= MPLS_LIST_HEAD(&fp
->nh_root
);
338 nnhp
= MPLS_LIST_NEXT(&fp
->nh_root
, nhp
, _fec
);
339 ldp_fec_del_nexthop(g
, fp
, nhp
);
342 MPLS_REFCNT_RELEASE2(g
, fp
, ldp_fec_delete
);
347 ifp
= MPLS_LIST_HEAD(&g
->iff
);
348 while (ifp
!= NULL
) {
349 nifp
= MPLS_LIST_NEXT(&g
->iff
, ifp
, _global
);
351 ap
= MPLS_LIST_HEAD(&ifp
->addr_root
);
353 nap
= MPLS_LIST_NEXT(&ifp
->addr_root
, ap
, _if
);
354 ldp_if_del_addr(g
, ifp
, ap
);
357 MPLS_REFCNT_RELEASE2(g
, ifp
, ldp_if_delete
);
362 nhp
= MPLS_LIST_HEAD(&g
->nexthop
);
363 while (nhp
!= NULL
) {
364 LDP_PRINT(g
->user_data
,"Left over NH: %p type %d ref %d",
365 nhp
, nhp
->info
.type
, nhp
->_refcnt
);
366 switch(nhp
->info
.type
) {
368 LDP_PRINT(g
->user_data
," IP %08x addr %p",
369 nhp
->info
.ip
.u
.ipv4
, nhp
->addr
);
372 LDP_PRINT(g
->user_data
," IF %s handle %p",
373 nhp
->info
.if_handle
->name
, nhp
->iff
);
375 case MPLS_NH_OUTSEGMENT
:
376 LDP_PRINT(g
->user_data
," OS %p", nhp
->outlabel
);
379 LDP_PRINT(g
->user_data
," EMPTY");
382 nnhp
= MPLS_LIST_NEXT(&g
->nexthop
, nhp
, _global
);
383 // _ldp_global_del_nexthop(g, nhp);
387 ap
= MPLS_LIST_HEAD(&g
->addr
);
389 LDP_PRINT(g
->user_data
, "Left over ADDR: %p address %08x",
390 ap
, ap
->address
.u
.ipv4
);
391 nap
= MPLS_LIST_NEXT(&g
->addr
, ap
, _global
);
392 // _ldp_global_del_addr(g, ap);
396 atp
= MPLS_LIST_HEAD(&g
->attr
);
397 while (atp
!= NULL
) {
398 LDP_PRINT(g
->user_data
, "Left over ATTR: %p %d", atp
, atp
->_refcnt
);
399 natp
= MPLS_LIST_NEXT(&g
->attr
, atp
, _global
);
400 // _ldp_global_del_attr(g, atp);
404 inp
= MPLS_LIST_HEAD(&g
->inlabel
);
405 while (inp
!= NULL
) {
406 LDP_PRINT(g
->user_data
,"Left over INLABEL: %p %d", inp
, inp
->_refcnt
);
407 ninp
= MPLS_LIST_NEXT(&g
->inlabel
, inp
, _global
);
411 outp
= MPLS_LIST_HEAD(&g
->outlabel
);
412 while (outp
!= NULL
) {
413 LDP_PRINT(g
->user_data
, "Left over OUTLABEL: %p %d", outp
, outp
->_refcnt
);
414 noutp
= MPLS_LIST_NEXT(&g
->outlabel
, outp
, _global
);
418 mpls_tree_delete(g
->addr_tree
);
419 mpls_tree_delete(g
->fec_tree
);
421 mpls_lock_delete(g
->global_lock
);
422 LDP_PRINT(g
->user_data
, "global delete");
428 void _ldp_global_add_attr(ldp_global
* g
, ldp_attr
* a
)
433 ap
= MPLS_LIST_HEAD(&g
->attr
);
435 if (ap
->index
> a
->index
) {
436 MPLS_LIST_INSERT_BEFORE(&g
->attr
, ap
, a
, _global
);
439 ap
= MPLS_LIST_NEXT(&g
->attr
, ap
, _global
);
441 MPLS_LIST_ADD_TAIL(&g
->attr
, a
, _global
, ldp_attr
);
444 void _ldp_global_del_attr(ldp_global
* g
, ldp_attr
* a
)
447 MPLS_LIST_REMOVE(&g
->attr
, a
, _global
);
450 void _ldp_global_add_peer(ldp_global
* g
, ldp_peer
* p
)
456 pp
= MPLS_LIST_HEAD(&g
->peer
);
458 if (pp
->index
> p
->index
) {
459 MPLS_LIST_INSERT_BEFORE(&g
->peer
, pp
, p
, _global
);
462 pp
= MPLS_LIST_NEXT(&g
->peer
, pp
, _global
);
464 MPLS_LIST_ADD_TAIL(&g
->peer
, p
, _global
, ldp_peer
);
467 void _ldp_global_del_peer(ldp_global
* g
, ldp_peer
* p
)
470 MPLS_LIST_REMOVE(&g
->peer
, p
, _global
);
471 MPLS_REFCNT_RELEASE(p
, ldp_peer_delete
);
475 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
476 * not the same as the rest of the global_add/del functions. They
477 * do not hold refcnts, they are used as part of the create and delete
478 * process of these structures
481 void _ldp_global_add_if(ldp_global
* g
, ldp_if
* i
)
486 ip
= MPLS_LIST_HEAD(&g
->iff
);
488 if (ip
->index
> i
->index
) {
489 MPLS_LIST_INSERT_BEFORE(&g
->iff
, ip
, i
, _global
);
492 ip
= MPLS_LIST_NEXT(&g
->iff
, ip
, _global
);
494 MPLS_LIST_ADD_TAIL(&g
->iff
, i
, _global
, ldp_if
);
497 void _ldp_global_del_if(ldp_global
* g
, ldp_if
* i
)
500 MPLS_LIST_REMOVE(&g
->iff
, i
, _global
);
503 void _ldp_global_add_addr(ldp_global
* g
, ldp_addr
* a
)
508 ap
= MPLS_LIST_HEAD(&g
->addr
);
510 if (ap
->index
> a
->index
) {
511 MPLS_LIST_INSERT_BEFORE(&g
->addr
, ap
, a
, _global
);
514 ap
= MPLS_LIST_NEXT(&g
->addr
, ap
, _global
);
516 MPLS_LIST_ADD_TAIL(&g
->addr
, a
, _global
, ldp_addr
);
519 void _ldp_global_del_addr(ldp_global
* g
, ldp_addr
* a
)
522 MPLS_LIST_REMOVE(&g
->addr
, a
, _global
);
525 void _ldp_global_add_adj(ldp_global
* g
, ldp_adj
* a
)
531 ap
= MPLS_LIST_HEAD(&g
->adj
);
533 if (ap
->index
> a
->index
) {
534 MPLS_LIST_INSERT_BEFORE(&g
->adj
, ap
, a
, _global
);
537 ap
= MPLS_LIST_NEXT(&g
->adj
, ap
, _global
);
539 MPLS_LIST_ADD_TAIL(&g
->adj
, a
, _global
, ldp_adj
);
542 void _ldp_global_del_adj(ldp_global
* g
, ldp_adj
* a
)
545 MPLS_LIST_REMOVE(&g
->adj
, a
, _global
);
546 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
549 void _ldp_global_add_entity(ldp_global
* g
, ldp_entity
* e
)
551 ldp_entity
*ep
= NULL
;
555 ep
= MPLS_LIST_HEAD(&g
->entity
);
557 if (ep
->index
> e
->index
) {
558 MPLS_LIST_INSERT_BEFORE(&g
->entity
, ep
, e
, _global
);
561 ep
= MPLS_LIST_NEXT(&g
->entity
, ep
, _global
);
563 MPLS_LIST_ADD_TAIL(&g
->entity
, e
, _global
, ldp_entity
);
566 void _ldp_global_del_entity(ldp_global
* g
, ldp_entity
* e
)
569 MPLS_LIST_REMOVE(&g
->entity
, e
, _global
);
570 MPLS_REFCNT_RELEASE(e
, ldp_entity_delete
);
573 void _ldp_global_add_session(ldp_global
* g
, ldp_session
* s
)
575 ldp_session
*sp
= NULL
;
579 s
->on_global
= MPLS_BOOL_TRUE
;
580 sp
= MPLS_LIST_HEAD(&g
->session
);
582 if (sp
->index
> s
->index
) {
583 MPLS_LIST_INSERT_BEFORE(&g
->session
, sp
, s
, _global
);
586 sp
= MPLS_LIST_NEXT(&g
->session
, sp
, _global
);
588 MPLS_LIST_ADD_TAIL(&g
->session
, s
, _global
, ldp_session
);
591 void _ldp_global_del_session(ldp_global
* g
, ldp_session
* s
)
594 MPLS_ASSERT(s
->on_global
== MPLS_BOOL_TRUE
);
595 MPLS_LIST_REMOVE(&g
->session
, s
, _global
);
596 s
->on_global
= MPLS_BOOL_FALSE
;
597 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
600 mpls_return_enum
_ldp_global_add_inlabel(ldp_global
* g
, ldp_inlabel
* i
)
602 ldp_inlabel
*ip
= NULL
;
603 mpls_return_enum result
;
610 memcpy(&iseg
.info
,&i
->info
,sizeof(mpls_insegment
));
611 result
= lsr_cfg_insegment_set(g
->lsr_handle
, &iseg
, LSR_CFG_ADD
|
612 LSR_INSEGMENT_CFG_NPOP
|LSR_INSEGMENT_CFG_FAMILY
|
613 LSR_INSEGMENT_CFG_LABELSPACE
|LSR_INSEGMENT_CFG_LABEL
|
614 LSR_INSEGMENT_CFG_OWNER
);
615 memcpy(&i
->info
, &iseg
.info
, sizeof(mpls_insegment
));
616 i
->info
.handle
= iseg
.index
;
619 result
= mpls_mpls_insegment_add(g
->mpls_handle
, &i
->info
);
621 if (result
!= MPLS_SUCCESS
) {
625 ip
= MPLS_LIST_HEAD(&g
->inlabel
);
627 if (ip
->index
> i
->index
) {
628 MPLS_LIST_INSERT_BEFORE(&g
->inlabel
, ip
, i
, _global
);
631 ip
= MPLS_LIST_NEXT(&g
->inlabel
, ip
, _global
);
633 MPLS_LIST_ADD_TAIL(&g
->inlabel
, i
, _global
, ldp_inlabel
);
637 mpls_return_enum
_ldp_global_del_inlabel(ldp_global
* g
, ldp_inlabel
* i
)
640 MPLS_ASSERT(i
->reuse_count
== 0);
644 iseg
.index
= i
->info
.handle
;
645 lsr_cfg_insegment_set(g
->lsr_handle
, &iseg
, LSR_CFG_DEL
);
648 mpls_mpls_insegment_del(g
->mpls_handle
, &i
->info
);
650 MPLS_LIST_REMOVE(&g
->inlabel
, i
, _global
);
654 mpls_return_enum
_ldp_global_add_outlabel(ldp_global
* g
, ldp_outlabel
* o
)
656 ldp_outlabel
*op
= NULL
;
657 mpls_return_enum result
;
663 memcpy(&oseg
.info
, &o
->info
, sizeof(mpls_outsegment
));
664 result
= lsr_cfg_outsegment_set(g
->lsr_handle
, &oseg
, LSR_CFG_ADD
|
665 LSR_OUTSEGMENT_CFG_PUSH_LABEL
|LSR_OUTSEGMENT_CFG_OWNER
|
666 LSR_OUTSEGMENT_CFG_INTERFACE
|LSR_OUTSEGMENT_CFG_LABEL
|
667 LSR_OUTSEGMENT_CFG_NEXTHOP
);
668 o
->info
.handle
= oseg
.index
;
671 result
= mpls_mpls_outsegment_add(g
->mpls_handle
, &o
->info
);
674 if (result
!= MPLS_SUCCESS
) {
678 o
->switching
= MPLS_BOOL_TRUE
;
679 op
= MPLS_LIST_HEAD(&g
->outlabel
);
681 if (op
->index
> o
->index
) {
682 MPLS_LIST_INSERT_BEFORE(&g
->outlabel
, op
, o
, _global
);
685 op
= MPLS_LIST_NEXT(&g
->outlabel
, op
, _global
);
687 MPLS_LIST_ADD_TAIL(&g
->outlabel
, o
, _global
, ldp_outlabel
);
691 mpls_return_enum
_ldp_global_del_outlabel(ldp_global
* g
, ldp_outlabel
* o
)
697 oseg
.index
= o
->info
.handle
;
698 lsr_cfg_outsegment_set(g
->lsr_handle
, &oseg
, LSR_CFG_DEL
);
701 mpls_mpls_outsegment_del(g
->mpls_handle
, &o
->info
);
704 o
->switching
= MPLS_BOOL_FALSE
;
705 MPLS_ASSERT(o
->merge_count
== 0);
706 MPLS_LIST_REMOVE(&g
->outlabel
, o
, _global
);
710 mpls_return_enum
ldp_global_find_attr_index(ldp_global
* g
, uint32_t index
,
715 if (g
&& index
> 0) {
717 /* because we sort our inserts by index, this lets us know
718 if we've "walked" past the end of the list */
720 a
= MPLS_LIST_TAIL(&g
->attr
);
721 if (a
== NULL
|| a
->index
< index
) {
722 return MPLS_END_OF_LIST
;
726 a
= MPLS_LIST_HEAD(&g
->attr
);
728 if (a
->index
== index
) {
732 a
= MPLS_LIST_NEXT(&g
->attr
, a
, _global
);
739 mpls_return_enum
ldp_global_find_session_index(ldp_global
* g
, uint32_t index
,
740 ldp_session
** session
)
742 ldp_session
*s
= NULL
;
744 if (g
&& index
> 0) {
746 /* because we sort our inserts by index, this lets us know
747 if we've "walked" past the end of the list */
749 s
= MPLS_LIST_TAIL(&g
->session
);
750 if (s
== NULL
|| s
->index
< index
) {
752 return MPLS_END_OF_LIST
;
755 s
= MPLS_LIST_HEAD(&g
->session
);
757 if (s
->index
== index
) {
761 s
= MPLS_LIST_NEXT(&g
->session
, s
, _global
);
768 mpls_return_enum
ldp_global_find_inlabel_index(ldp_global
* g
, uint32_t index
,
769 ldp_inlabel
** inlabel
)
771 ldp_inlabel
*i
= NULL
;
773 if (g
&& index
> 0) {
775 /* because we sort our inserts by index, this lets us know
776 if we've "walked" past the end of the list */
778 i
= MPLS_LIST_TAIL(&g
->inlabel
);
779 if (i
== NULL
|| i
->index
< index
) {
781 return MPLS_END_OF_LIST
;
784 i
= MPLS_LIST_HEAD(&g
->inlabel
);
786 if (i
->index
== index
) {
790 i
= MPLS_LIST_NEXT(&g
->inlabel
, i
, _global
);
797 mpls_return_enum
ldp_global_find_outlabel_index(ldp_global
* g
, uint32_t index
,
798 ldp_outlabel
** outlabel
)
800 ldp_outlabel
*o
= NULL
;
802 if (g
&& index
> 0) {
804 /* because we sort our inserts by index, this lets us know
805 if we've "walked" past the end of the list */
807 o
= MPLS_LIST_TAIL(&g
->outlabel
);
808 if (o
== NULL
|| o
->index
< index
) {
810 return MPLS_END_OF_LIST
;
813 o
= MPLS_LIST_HEAD(&g
->outlabel
);
815 if (o
->index
== index
) {
819 o
= MPLS_LIST_NEXT(&g
->outlabel
, o
, _global
);
826 ldp_outlabel
*ldp_global_find_outlabel_handle(ldp_global
* g
,
827 mpls_outsegment_handle handle
)
829 ldp_outlabel
*o
= MPLS_LIST_HEAD(&g
->outlabel
);
833 if (!mpls_outsegment_handle_compare(o
->info
.handle
, handle
))
836 o
= MPLS_LIST_NEXT(&g
->outlabel
, o
, _global
);
842 mpls_return_enum
ldp_global_find_entity_index(ldp_global
* g
, uint32_t index
,
843 ldp_entity
** entity
)
845 ldp_entity
*e
= NULL
;
847 if (g
&& index
> 0) {
849 /* because we sort our inserts by index, this lets us know
850 if we've "walked" past the end of the list */
852 e
= MPLS_LIST_TAIL(&g
->entity
);
853 if (e
== NULL
|| e
->index
< index
) {
855 return MPLS_END_OF_LIST
;
858 e
= MPLS_LIST_HEAD(&g
->entity
);
860 if (e
->index
== index
) {
864 e
= MPLS_LIST_NEXT(&g
->entity
, e
, _global
);
871 ldp_peer
*ldp_global_find_peer_addr(ldp_global
* g
, mpls_inet_addr
* addr
)
875 MPLS_ASSERT(g
&& addr
);
877 /* JLEU: we will need to add a tree to optimize this search,
878 known peers will be in tree, unknown will take a "slow path" to
879 verify them, then be added to tree */
881 p
= MPLS_LIST_HEAD(&g
->peer
);
883 LDP_PRINT(g
->user_data
,
884 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
885 p
->dest
.addr
.u
.ipv4
, addr
->u
.ipv4
);
886 if (!mpls_inet_addr_compare(&p
->dest
.addr
, addr
)) {
889 p
= MPLS_LIST_NEXT(&g
->peer
, p
, _global
);
894 mpls_return_enum
ldp_global_find_adj_index(ldp_global
* g
, uint32_t index
,
899 if (g
&& index
> 0) {
900 /* because we sort our inserts by index, this lets us know
901 if we've "walked" past the end of the list */
903 a
= MPLS_LIST_TAIL(&g
->adj
);
904 if (a
== NULL
|| a
->index
< index
) {
905 return MPLS_END_OF_LIST
;
909 a
= MPLS_LIST_HEAD(&g
->adj
);
911 if (a
->index
== index
) {
915 a
= MPLS_LIST_NEXT(&g
->adj
, a
, _global
);
922 mpls_return_enum
ldp_global_find_peer_index(ldp_global
* g
, uint32_t index
,
927 if (g
&& index
> 0) {
928 /* because we sort our inserts by index, this lets us know
929 if we've "walked" past the end of the list */
931 p
= MPLS_LIST_TAIL(&g
->peer
);
932 if (p
== NULL
|| p
->index
< index
) {
934 return MPLS_END_OF_LIST
;
937 p
= MPLS_LIST_HEAD(&g
->peer
);
939 if (p
->index
== index
) {
943 p
= MPLS_LIST_NEXT(&g
->peer
, p
, _global
);
950 mpls_return_enum
ldp_global_find_fec_index(ldp_global
* g
, uint32_t index
,
955 if (g
&& index
> 0) {
956 /* because we sort our inserts by index, this lets us know
957 if we've "walked" past the end of the list */
959 f
= MPLS_LIST_TAIL(&g
->fec
);
960 if (f
== NULL
|| f
->index
< index
) {
962 return MPLS_END_OF_LIST
;
965 f
= MPLS_LIST_HEAD(&g
->fec
);
967 if (f
->index
== index
) {
971 f
= MPLS_LIST_NEXT(&g
->fec
, f
, _global
);
978 mpls_return_enum
ldp_global_find_fec(ldp_global
* g
, mpls_fec
* m
,
985 f
= MPLS_LIST_HEAD(&g
->fec
);
987 if (!mpls_fec_compare(m
, &f
->info
)) {
991 } while((f
= MPLS_LIST_NEXT(&g
->fec
, f
, _global
)));
996 mpls_return_enum
ldp_global_find_addr_index(ldp_global
* g
, uint32_t index
,
1001 if (g
&& index
> 0) {
1003 /* because we sort our inserts by index, this lets us know
1004 if we've "walked" past the end of the list */
1006 a
= MPLS_LIST_TAIL(&g
->addr
);
1007 if (a
== NULL
|| a
->index
< index
) {
1009 return MPLS_END_OF_LIST
;
1012 a
= MPLS_LIST_HEAD(&g
->addr
);
1014 if (a
->index
== index
) {
1016 return MPLS_SUCCESS
;
1018 a
= MPLS_LIST_NEXT(&g
->addr
, a
, _global
);
1022 return MPLS_FAILURE
;
1025 mpls_return_enum
ldp_global_find_if_index(ldp_global
* g
, uint32_t index
,
1030 if (g
&& index
> 0) {
1032 /* because we sort our inserts by index, this lets us know
1033 if we've "walked" past the end of the list */
1035 i
= MPLS_LIST_TAIL(&g
->iff
);
1036 if (i
== NULL
|| i
->index
< index
) {
1038 return MPLS_END_OF_LIST
;
1041 i
= MPLS_LIST_HEAD(&g
->iff
);
1043 if (i
->index
== index
) {
1045 return MPLS_SUCCESS
;
1047 i
= MPLS_LIST_NEXT(&g
->iff
, i
, _global
);
1051 return MPLS_FAILURE
;
1054 ldp_if
*ldp_global_find_if_handle(ldp_global
* g
, mpls_if_handle handle
)
1056 ldp_if
*i
= MPLS_LIST_HEAD(&g
->iff
);
1060 if (!mpls_if_handle_compare(i
->handle
, handle
))
1063 i
= MPLS_LIST_NEXT(&g
->iff
, i
, _global
);
1069 ldp_adj
*ldp_global_find_adj_ldpid(ldp_global
* g
, mpls_inet_addr
* lsraddr
,
1073 ldp_adj
*a
= MPLS_LIST_HEAD(&g
->adj
);
1076 if ((!mpls_inet_addr_compare(lsraddr
, &a
->remote_lsr_address
)) &&
1077 labelspace
== a
->remote_label_space
)
1080 a
= MPLS_LIST_NEXT(&g
->adj
, a
, _global
);
1085 mpls_return_enum
ldp_global_find_tunnel_index(ldp_global
* g
, uint32_t index
,
1086 ldp_tunnel
** tunnel
)
1088 ldp_tunnel
*t
= NULL
;
1090 if (g
&& index
> 0) {
1091 /* because we sort our inserts by index, this lets us know
1092 if we've "walked" past the end of the list */
1094 t
= MPLS_LIST_TAIL(&g
->tunnel
);
1095 if (t
== NULL
|| t
->index
< index
) {
1097 return MPLS_END_OF_LIST
;
1100 t
= MPLS_LIST_HEAD(&g
->tunnel
);
1102 if (t
->index
== index
) {
1104 return MPLS_SUCCESS
;
1106 t
= MPLS_LIST_NEXT(&g
->tunnel
, t
, _global
);
1110 return MPLS_FAILURE
;
1113 mpls_return_enum
ldp_global_find_resource_index(ldp_global
* g
, uint32_t index
,
1114 ldp_resource
** resource
)
1116 ldp_resource
*r
= NULL
;
1118 if (g
&& index
> 0) {
1119 /* because we sort our inserts by index, this lets us know
1120 if we've "walked" past the end of the list */
1122 r
= MPLS_LIST_TAIL(&g
->resource
);
1123 if (r
== NULL
|| r
->index
< index
) {
1125 return MPLS_END_OF_LIST
;
1128 r
= MPLS_LIST_HEAD(&g
->resource
);
1130 if (r
->index
== index
) {
1132 return MPLS_SUCCESS
;
1134 r
= MPLS_LIST_NEXT(&g
->resource
, r
, _global
);
1138 return MPLS_FAILURE
;
1141 mpls_return_enum
ldp_global_find_hop_list_index(ldp_global
* g
, uint32_t index
,
1142 ldp_hop_list
** hop_list
)
1144 ldp_hop_list
*h
= NULL
;
1146 if (g
&& index
> 0) {
1147 /* because we sort our inserts by index, this lets us know
1148 if we've "walked" past the end of the list */
1150 h
= MPLS_LIST_TAIL(&g
->hop_list
);
1151 if (h
== NULL
|| h
->index
< index
) {
1153 return MPLS_END_OF_LIST
;
1156 h
= MPLS_LIST_HEAD(&g
->hop_list
);
1158 if (h
->index
== index
) {
1160 return MPLS_SUCCESS
;
1162 h
= MPLS_LIST_NEXT(&g
->hop_list
, h
, _global
);
1166 return MPLS_FAILURE
;
1169 void _ldp_global_add_tunnel(ldp_global
* g
, ldp_tunnel
* t
)
1171 ldp_tunnel
*tp
= NULL
;
1173 MPLS_ASSERT(g
&& t
);
1174 MPLS_REFCNT_HOLD(t
);
1175 tp
= MPLS_LIST_HEAD(&g
->tunnel
);
1176 while (tp
!= NULL
) {
1177 if (tp
->index
> t
->index
) {
1178 MPLS_LIST_INSERT_BEFORE(&g
->tunnel
, tp
, t
, _global
);
1181 tp
= MPLS_LIST_NEXT(&g
->tunnel
, tp
, _global
);
1183 MPLS_LIST_ADD_TAIL(&g
->tunnel
, t
, _global
, ldp_tunnel
);
1186 void _ldp_global_del_tunnel(ldp_global
* g
, ldp_tunnel
* t
)
1188 MPLS_ASSERT(g
&& t
);
1189 MPLS_LIST_REMOVE(&g
->tunnel
, t
, _global
);
1190 MPLS_REFCNT_RELEASE(t
, ldp_tunnel_delete
);
1193 void _ldp_global_add_resource(ldp_global
* g
, ldp_resource
* r
)
1195 ldp_resource
*rp
= NULL
;
1197 MPLS_ASSERT(g
&& r
);
1198 MPLS_REFCNT_HOLD(r
);
1199 rp
= MPLS_LIST_HEAD(&g
->resource
);
1200 while (rp
!= NULL
) {
1201 if (rp
->index
> r
->index
) {
1202 MPLS_LIST_INSERT_BEFORE(&g
->resource
, rp
, r
, _global
);
1205 rp
= MPLS_LIST_NEXT(&g
->resource
, rp
, _global
);
1207 MPLS_LIST_ADD_TAIL(&g
->resource
, r
, _global
, ldp_resource
);
1210 void _ldp_global_del_resource(ldp_global
* g
, ldp_resource
* r
)
1212 MPLS_ASSERT(g
&& r
);
1213 MPLS_LIST_REMOVE(&g
->resource
, r
, _global
);
1214 MPLS_REFCNT_RELEASE(r
, ldp_resource_delete
);
1217 void _ldp_global_add_hop_list(ldp_global
* g
, ldp_hop_list
* h
)
1219 ldp_hop_list
*hp
= NULL
;
1221 MPLS_ASSERT(g
&& h
);
1222 MPLS_REFCNT_HOLD(h
);
1223 hp
= MPLS_LIST_HEAD(&g
->hop_list
);
1224 while (hp
!= NULL
) {
1225 if (hp
->index
> h
->index
) {
1226 MPLS_LIST_INSERT_BEFORE(&g
->hop_list
, hp
, h
, _global
);
1229 hp
= MPLS_LIST_NEXT(&g
->hop_list
, hp
, _global
);
1231 MPLS_LIST_ADD_TAIL(&g
->hop_list
, h
, _global
, ldp_hop_list
);
1234 void _ldp_global_del_hop_list(ldp_global
* g
, ldp_hop_list
* h
)
1236 MPLS_ASSERT(g
&& h
);
1237 MPLS_LIST_REMOVE(&g
->hop_list
, h
, _global
);
1238 MPLS_REFCNT_RELEASE(h
, ldp_hop_list_delete
);
1241 void _ldp_global_add_fec(ldp_global
* g
, ldp_fec
* f
)
1245 MPLS_ASSERT(g
&& f
);
1247 * TESTING: jleu 6/7/2004, since I want the FEC to be cleaned up
1248 * when it no longer has a nexthop, addr, or label, the only things that
1249 * should increment the ref are those (nh, addr, label etc), not global
1250 * nor inserting into the tree. I also added this comment in
1252 * MPLS_REFCNT_HOLD(f);
1254 fp
= MPLS_LIST_HEAD(&g
->fec
);
1255 while (fp
!= NULL
) {
1256 if (fp
->index
> f
->index
) {
1257 MPLS_LIST_INSERT_BEFORE(&g
->fec
, fp
, f
, _global
);
1260 fp
= MPLS_LIST_NEXT(&g
->fec
, fp
, _global
);
1262 MPLS_LIST_ADD_TAIL(&g
->fec
, f
, _global
, ldp_fec
);
1265 void _ldp_global_del_fec(ldp_global
* g
, ldp_fec
* f
)
1267 MPLS_ASSERT(g
&& f
);
1268 MPLS_LIST_REMOVE(&g
->fec
, f
, _global
);
1271 void _ldp_global_add_nexthop(ldp_global
* g
, ldp_nexthop
* nh
)
1273 ldp_nexthop
*nhp
= NULL
;
1275 MPLS_ASSERT(g
&& nh
);
1276 nhp
= MPLS_LIST_HEAD(&g
->nexthop
);
1277 while (nhp
!= NULL
) {
1278 if (nhp
->index
> nh
->index
) {
1279 MPLS_LIST_INSERT_BEFORE(&g
->nexthop
, nhp
, nh
, _global
);
1282 nhp
= MPLS_LIST_NEXT(&g
->nexthop
, nhp
, _global
);
1284 MPLS_LIST_ADD_TAIL(&g
->nexthop
, nh
, _global
, ldp_nexthop
);
1287 void _ldp_global_del_nexthop(ldp_global
* g
, ldp_nexthop
* nh
)
1289 MPLS_ASSERT(g
&& nh
);
1290 MPLS_LIST_REMOVE(&g
->nexthop
, nh
, _global
);