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 <sys/socket.h>
13 #include "ldp_struct.h"
14 #include "ldp_global.h"
15 #include "ldp_entity.h"
16 #include "ldp_nexthop.h"
17 #include "ldp_nortel.h"
23 #include "ldp_hello.h"
25 #include "mpls_assert.h"
26 #include "mpls_mm_impl.h"
27 #include "mpls_compare.h"
28 #include "mpls_socket_impl.h"
29 #include "mpls_timer_impl.h"
30 #include "mpls_ifmgr_impl.h"
31 #include "mpls_trace_impl.h"
33 extern uint32_t _ldp_sub_entity_next_index
;
35 ldp_if
*ldp_if_create(ldp_global
*g
)
37 ldp_if
*i
= (ldp_if
*) mpls_malloc(sizeof(ldp_if
));
40 memset(i
, 0, sizeof(ldp_if
));
42 * note: this is init to 1 for a reason!
43 * We're placing it in the global list, so this is our refcnt
44 * when this refcnt gets to zero, it will be removed from the
45 * global list and deleted
48 * TESTING: jleu 6/7/2004, since I want the iff to be cleaned up
49 * when it no longer has a nexthop, fec, or label, the only things that
50 * should increment the ref are those (nh, fec, label etc), not global
51 * nor inserting into the tree.
52 MPLS_REFCNT_INIT(i, 1);
54 MPLS_LIST_ELEM_INIT(i
, _global
);
55 MPLS_LIST_INIT(&i
->nh_root
, ldp_nexthop
);
56 MPLS_LIST_INIT(&i
->addr_root
, ldp_addr
);
58 i
->dest
.addr
.type
= MPLS_FAMILY_IPV4
;
59 i
->dest
.addr
.u
.ipv4
= INADDR_ALLRTRS_GROUP
;
60 i
->tx_buffer
= ldp_buf_create(MPLS_PDUMAXLEN
);
61 i
->tx_message
= ldp_mesg_create();
62 i
->index
= _ldp_if_get_next_index();
63 i
->oper_state
= MPLS_OPER_DOWN
;
64 i
->is_p2p
= MPLS_BOOL_FALSE
;
65 _ldp_global_add_if(g
, i
);
70 void ldp_if_delete(ldp_global
*g
, ldp_if
* i
)
72 fprintf(stderr
, "if delete: %p\n", i
);
73 MPLS_REFCNT_ASSERT(i
, 0);
74 mpls_free(i
->tx_buffer
);
75 mpls_free(i
->tx_message
);
78 _ldp_global_del_if(g
, i
);
83 * ldp_if_insert and ldp_if_remove should ONLY be used in conjuction with
84 * adding and removing nexthops (or fecs).
87 ldp_if
*ldp_if_insert(ldp_global
*g
, mpls_if_handle handle
)
92 MPLS_ASSERT(mpls_if_handle_verify(g
->ifmgr_handle
, handle
) == MPLS_BOOL_TRUE
);
94 if ((iff
= ldp_if_create(g
)) == NULL
) {
95 LDP_PRINT(g
->user_data
,"ldp_if_insert: unable to alloc ldp_if\n");
103 void ldp_if_remove(ldp_global
*g
, ldp_if
*iff
)
105 MPLS_ASSERT(g
&& iff
);
106 MPLS_REFCNT_RELEASE2(g
, iff
, ldp_if_delete
);
111 * We do not hold a ref to the nexthop. The nexthop holds a ref to the
112 * if. Nexthop creation calls ldp_if_add_nexthop, nexthop deletion
113 * calls ldp_if_del_nexthop. There is no way a nexthop can be deleted
114 * without removing the ifs ref to the nexthop.
116 void ldp_if_add_nexthop(ldp_if
* i
, ldp_nexthop
* n
)
118 ldp_nexthop
*np
= NULL
;
122 ldp_nexthop_add_if(n
,i
);
124 np
= MPLS_LIST_HEAD(&i
->nh_root
);
126 if (np
->index
> n
->index
) {
127 MPLS_LIST_INSERT_BEFORE(&i
->nh_root
, np
, n
, _if
);
130 np
= MPLS_LIST_NEXT(&i
->nh_root
, np
, _if
);
132 MPLS_LIST_ADD_TAIL(&i
->nh_root
, n
, _if
, ldp_nexthop
);
135 void ldp_if_del_nexthop(ldp_global
*g
, ldp_if
* i
, ldp_nexthop
* n
)
138 MPLS_LIST_REMOVE(&i
->nh_root
, n
, _if
);
139 ldp_nexthop_del_if(g
, n
);
142 void ldp_if_add_addr(ldp_if
* i
, ldp_addr
* a
)
149 ldp_addr_add_if(a
,i
);
151 ap
= MPLS_LIST_HEAD(&i
->addr_root
);
153 if (ap
->index
> a
->index
) {
154 MPLS_LIST_INSERT_BEFORE(&i
->addr_root
, ap
, a
, _if
);
157 ap
= MPLS_LIST_NEXT(&i
->addr_root
, ap
, _if
);
159 MPLS_LIST_ADD_TAIL(&i
->addr_root
, a
, _if
, ldp_addr
);
162 void ldp_if_del_addr(ldp_global
*g
, ldp_if
* i
, ldp_addr
* a
)
165 MPLS_LIST_REMOVE(&i
->addr_root
, a
, _if
);
166 ldp_addr_del_if(g
, a
);
167 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
170 mpls_return_enum
ldp_if_find_addr_index(ldp_if
*i
, int index
, ldp_addr
**a
)
178 /* because we sort our inserts by index, this lets us know
179 if we've "walked" past the end of the list */
181 ap
= MPLS_LIST_TAIL(&i
->addr_root
);
182 if (!ap
|| ap
->index
< index
) {
184 return MPLS_END_OF_LIST
;
187 ap
= MPLS_LIST_HEAD(&i
->addr_root
);
189 if (ap
->index
== index
) {
193 } while((ap
= MPLS_LIST_NEXT(&i
->addr_root
, ap
, _if
)));
199 ldp_addr
*ldp_if_addr_find(ldp_if
*i
, mpls_inet_addr
*a
)
205 ap
= MPLS_LIST_HEAD(&i
->addr_root
);
208 if (!mpls_inet_addr_compare(&ap
->address
, a
)) {
211 ap
= MPLS_LIST_NEXT(&i
->addr_root
, ap
, _if
);
216 mpls_return_enum
ldp_if_startup(ldp_global
* g
, ldp_if
* i
)
218 ldp_entity
*e
= NULL
;
220 LDP_ENTER(g
->user_data
, "ldp_if_startup");
222 MPLS_ASSERT(i
!= NULL
);
224 MPLS_ASSERT(e
!= NULL
);
225 MPLS_ASSERT(e
->p
.iff
!= NULL
);
227 if (mpls_socket_multicast_if_join(g
->socket_handle
, g
->hello_socket
, i
,
228 &i
->dest
.addr
) == MPLS_FAILURE
) {
229 goto ldp_if_startup_delay
;
232 i
->dest
.port
= e
->remote_udp_port
;
233 if (ldp_hello_send(g
, e
) == MPLS_FAILURE
) {
234 ldp_if_shutdown(g
, i
);
237 i
->oper_state
= MPLS_OPER_UP
;
239 LDP_EXIT(g
->user_data
, "ldp_if_startup");
243 ldp_if_startup_delay
:
246 * when a interface update comes in, it will search the global
247 * list of interfaces, and start up the interface then
249 i
->oper_state
= MPLS_OPER_DOWN
;
251 LDP_EXIT(g
->user_data
, "ldp_if_startup-delayed");
256 mpls_return_enum
ldp_if_shutdown(ldp_global
* g
, ldp_if
* i
)
258 ldp_entity
*e
= NULL
;
260 MPLS_ASSERT(i
!= NULL
&& ((e
= i
->entity
) != NULL
));
262 LDP_ENTER(g
->user_data
, "ldp_if_shutdown");
264 i
->oper_state
= MPLS_OPER_DOWN
;
266 mpls_socket_multicast_if_drop(g
->socket_handle
, g
->hello_socket
, i
,
269 mpls_timer_stop(g
->timer_handle
, i
->hellotime_send_timer
);
270 mpls_timer_delete(g
->timer_handle
, i
->hellotime_send_timer
);
271 i
->hellotime_send_timer_duration
= 0;
272 i
->hellotime_send_timer
= 0;
274 /* the entity is held in ldp_hello_send when it creates the timer
275 * ldp_hello_send is called by ldp_if_startup
277 MPLS_ASSERT(e
!= NULL
);
278 MPLS_REFCNT_RELEASE(e
, ldp_entity_delete
);
281 ldp_mesg_delete(i
->hello
);
285 LDP_EXIT(g
->user_data
, "ldp_if_shutdown");
290 mpls_bool
ldp_if_is_active(ldp_if
* i
)
292 if (i
&& i
->entity
&& i
->entity
->admin_state
== MPLS_ADMIN_ENABLE
)
293 return MPLS_BOOL_TRUE
;
295 return MPLS_BOOL_FALSE
;
298 mpls_return_enum
_ldp_if_add_entity(ldp_if
* i
, ldp_entity
* e
)
308 ldp_entity
*ldp_if_get_entity(ldp_if
* i
)
313 mpls_return_enum
_ldp_if_del_entity(ldp_if
* i
)
315 if (i
&& i
->entity
) {
316 MPLS_REFCNT_RELEASE(i
->entity
, ldp_entity_delete
);
323 uint32_t _ldp_if_get_next_index()
325 uint32_t retval
= _ldp_sub_entity_next_index
;
327 _ldp_sub_entity_next_index
++;
328 if (retval
> _ldp_sub_entity_next_index
) {
329 _ldp_sub_entity_next_index
= 1;