Change inlabel outlabel/nexthop, and attr accounting. Specically
[mpls-ldp-portable.git] / ldp / ldp_if.c
blob333e05c9f2477be180455c58f2e66a83e721f834
2 /*
3 * Copyright (C) James R. Leu 2000
4 * jleu@mindspring.com
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
8 */
10 #include <stdlib.h>
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"
18 #include "ldp_addr.h"
19 #include "ldp_if.h"
20 #include "ldp_fec.h"
21 #include "ldp_mesg.h"
22 #include "ldp_buf.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));
39 if (i) {
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);
57 i->label_space = -1;
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);
67 return 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);
76 i->tx_buffer = NULL;
77 i->tx_message = NULL;
78 _ldp_global_del_if(g, i);
79 mpls_free(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)
89 ldp_if *iff = NULL;
91 MPLS_ASSERT(g);
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");
96 return NULL;
98 iff->handle = handle;
99 return iff;
102 #if 0
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);
108 #endif
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;
120 MPLS_ASSERT(i && n);
122 ldp_nexthop_add_if(n,i);
124 np = MPLS_LIST_HEAD(&i->nh_root);
125 while (np != NULL) {
126 if (np->index > n->index) {
127 MPLS_LIST_INSERT_BEFORE(&i->nh_root, np, n, _if);
128 return;
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)
137 MPLS_ASSERT(i && 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)
144 ldp_addr *ap = NULL;
146 MPLS_ASSERT(i && a);
147 MPLS_REFCNT_HOLD(a);
149 ldp_addr_add_if(a,i);
151 ap = MPLS_LIST_HEAD(&i->addr_root);
152 while (ap != NULL) {
153 if (ap->index > a->index) {
154 MPLS_LIST_INSERT_BEFORE(&i->addr_root, ap, a, _if);
155 return;
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)
164 MPLS_ASSERT(i && 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)
172 ldp_addr *ap = NULL;
174 MPLS_ASSERT(i);
176 if (index > 0) {
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) {
183 *a = NULL;
184 return MPLS_END_OF_LIST;
187 ap = MPLS_LIST_HEAD(&i->addr_root);
188 do {
189 if (ap->index == index) {
190 *a = ap;
191 return MPLS_SUCCESS;
193 } while((ap = MPLS_LIST_NEXT(&i->addr_root, ap, _if)));
195 *a = NULL;
196 return MPLS_FAILURE;
199 ldp_addr *ldp_if_addr_find(ldp_if *i, mpls_inet_addr *a)
201 ldp_addr *ap = NULL;
203 MPLS_ASSERT(i && a);
205 ap = MPLS_LIST_HEAD(&i->addr_root);
207 while(ap) {
208 if (!mpls_inet_addr_compare(&ap->address, a)) {
209 return ap;
211 ap = MPLS_LIST_NEXT(&i->addr_root, ap, _if);
213 return NULL;
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);
223 e = i->entity;
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);
235 return MPLS_FAILURE;
237 i->oper_state = MPLS_OPER_UP;
239 LDP_EXIT(g->user_data, "ldp_if_startup");
241 return MPLS_SUCCESS;
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");
253 return MPLS_SUCCESS;
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,
267 &i->dest.addr);
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);
280 if (i->hello) {
281 ldp_mesg_delete(i->hello);
282 i->hello = NULL;
285 LDP_EXIT(g->user_data, "ldp_if_shutdown");
287 return MPLS_SUCCESS;
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)
300 if (i && e) {
301 MPLS_REFCNT_HOLD(e);
302 i->entity = e;
303 return MPLS_SUCCESS;
305 return MPLS_FAILURE;
308 ldp_entity *ldp_if_get_entity(ldp_if * i)
310 return i->entity;
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);
317 i->entity = NULL;
318 return MPLS_SUCCESS;
320 return MPLS_FAILURE;
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;
331 return retval;