Refcnt fixes introduced when I converted addr and fec to
[mpls-ldp-portable.git] / ldp / ldp_addr.c
blobe5fc011c2ac62bfe86d187e3674369c113f90350
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 <string.h>
12 #include <sys/socket.h>
13 #include "ldp_struct.h"
14 #include "ldp_global.h"
15 #include "ldp_session.h"
16 #include "ldp_entity.h"
17 #include "ldp_pdu_setup.h"
18 #include "ldp_addr.h"
19 #include "ldp_nexthop.h"
20 #include "ldp_if.h"
21 #include "ldp_buf.h"
22 #include "ldp_mesg.h"
23 #include "mpls_list.h"
24 #include "mpls_ifmgr_impl.h"
25 #include "mpls_mm_impl.h"
26 #include "mpls_trace_impl.h"
27 #include "mpls_tree_impl.h"
29 static uint32_t _ldp_addr_next_index = 1;
31 ldp_addr *ldp_addr_create(ldp_global *g, mpls_inet_addr * address)
33 ldp_addr *a = (ldp_addr *) mpls_malloc(sizeof(ldp_addr));
35 if (a) {
37 * note: this is init to 1 for a reason!
38 * We're placing it in the global list, so this is our refcnt
39 * when this refcnt gets to zero, it will be removed from the
40 * global list and deleted
43 * TESTING: jleu 6/7/2004, since I want the addr to be cleaned up
44 * when it no longer has a nexthop, fec, or label, the only things that
45 * should increment the ref are those (nh, fec, label etc), not global
46 * nor inserting into the tree.
47 MPLS_REFCNT_INIT(a, 1);
49 MPLS_REFCNT_INIT(a, 0);
50 mpls_link_list_init(&a->session_root);
51 MPLS_LIST_INIT(&a->nh_root, ldp_nexthop);
52 MPLS_LIST_ELEM_INIT(a, _global);
53 MPLS_LIST_ELEM_INIT(a, _if);
54 memcpy(&a->address, address, sizeof(mpls_inet_addr));
55 a->index = _ldp_addr_get_next_index();
56 _ldp_global_add_addr(g, a);
57 ldp_addr_insert2(g, a);
59 return a;
62 void ldp_addr_delete(ldp_global *g, ldp_addr * a)
64 fprintf(stderr, "addr delete: %p\n", a);
65 MPLS_REFCNT_ASSERT(a, 0);
66 ldp_addr_remove(g, &a->address);
67 _ldp_global_del_addr(g, a);
68 mpls_free(a);
71 ldp_addr *ldp_addr_find(ldp_global *g, mpls_inet_addr * address)
73 ldp_addr *addr = NULL;
75 if (mpls_tree_get(g->addr_tree, address->u.ipv4, 32, (void **)&addr) !=
76 MPLS_SUCCESS) {
77 return NULL;
79 return addr;
82 ldp_addr *ldp_addr_insert(ldp_global *g, mpls_inet_addr * address)
84 ldp_addr *addr = NULL;
86 if ((addr = ldp_addr_create(g, address)) == NULL) {
87 LDP_PRINT(g->user_data, "ldp_addr_insert: error creating address\n");
88 return NULL;
90 return addr;
93 mpls_return_enum ldp_addr_insert2(ldp_global *g, ldp_addr *addr)
95 if (mpls_tree_insert(g->addr_tree, addr->address.u.ipv4, 32, (void *)addr) !=
96 MPLS_SUCCESS) {
97 LDP_PRINT(g->user_data, "ldp_addr_insert2: error adding addr\n");
98 MPLS_REFCNT_RELEASE2(g, addr, ldp_addr_delete);
99 return MPLS_FATAL;
101 return MPLS_SUCCESS;
104 void ldp_addr_remove(ldp_global *g, mpls_inet_addr * address)
106 ldp_addr *addr = NULL;
107 mpls_tree_remove(g->addr_tree, address->u.ipv4, 32, (void **)&addr);
110 void ldp_addr_add_if(ldp_addr * a, ldp_if * i)
112 MPLS_ASSERT(a && i);
113 MPLS_REFCNT_HOLD(i);
114 a->iff = i;
117 void ldp_addr_del_if(ldp_global *g, ldp_addr * a)
119 MPLS_ASSERT(a);
120 MPLS_REFCNT_RELEASE2(g, a->iff, ldp_if_delete);
121 a->iff = NULL;
124 mpls_bool ldp_addr_is_empty(ldp_addr *a)
126 if (a->iff == NULL && MPLS_LIST_EMPTY(&a->nh_root) &&
127 MPLS_LIST_EMPTY(&a->session_root)) {
128 return MPLS_BOOL_TRUE;
130 return MPLS_BOOL_FALSE;
133 mpls_return_enum _ldp_addr_add_session(ldp_addr * a, ldp_session * s)
135 MPLS_ASSERT(a && s);
136 MPLS_REFCNT_HOLD(s);
137 if (mpls_link_list_add_tail(&a->session_root, s) == MPLS_SUCCESS) {
138 return MPLS_SUCCESS;
140 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
141 return MPLS_FAILURE;
144 void _ldp_addr_del_session(ldp_addr * a, ldp_session * s)
146 MPLS_ASSERT(a && s);
147 mpls_link_list_remove_data(&a->session_root, s);
148 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
151 void ldp_addr_add_nexthop(ldp_addr * a, ldp_nexthop * nh)
153 ldp_nexthop *np = NULL;
155 MPLS_ASSERT(a && nh);
156 MPLS_REFCNT_HOLD(nh);
158 ldp_nexthop_add_addr(nh,a);
160 np = MPLS_LIST_HEAD(&a->nh_root);
161 while (np != NULL) {
162 if (np->index > nh->index) {
163 MPLS_LIST_INSERT_BEFORE(&a->nh_root, np, nh, _addr);
164 return;
166 np = MPLS_LIST_NEXT(&a->nh_root, np, _addr);
168 MPLS_LIST_ADD_TAIL(&a->nh_root, nh, _addr, ldp_nexthop);
171 void ldp_addr_del_nexthop(ldp_global *g, ldp_addr * a, ldp_nexthop * nh)
173 MPLS_ASSERT(a && nh);
174 MPLS_LIST_REMOVE(&a->nh_root, nh, _addr);
175 ldp_nexthop_del_addr(g, nh);
176 MPLS_REFCNT_RELEASE2(g, nh, ldp_nexthop_delete);
179 uint32_t _ldp_addr_get_next_index()
181 uint32_t retval = _ldp_addr_next_index;
183 _ldp_addr_next_index++;
184 if (retval > _ldp_addr_next_index) {
185 _ldp_addr_next_index = 1;
187 return retval;
190 void ldp_addr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
191 mpls_inet_addr * addr)
193 MPLS_MSGPTR(Adr);
195 LDP_ENTER(g->user_data, "ldp_addr_mesg_prepare");
197 ldp_mesg_prepare(msg, MPLS_ADDR_MSGTYPE, msgid);
198 MPLS_MSGPARAM(Adr) = &msg->u.addr;
200 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
201 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
202 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
204 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
205 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
207 LDP_EXIT(g->user_data, "ldp_addr_mesg_prepare");
210 void ldp_waddr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
211 mpls_inet_addr * addr)
213 MPLS_MSGPTR(Adr);
215 LDP_ENTER(g->user_data, "ldp_waddr_mesg_prepare");
217 ldp_mesg_prepare(msg, MPLS_ADDRWITH_MSGTYPE, msgid);
218 MPLS_MSGPARAM(Adr) = &msg->u.addr;
220 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
221 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
222 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
224 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
225 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
227 LDP_EXIT(g->user_data, "ldp_waddr_mesg_prepare");
230 mpls_return_enum ldp_addr_send(ldp_global * g, ldp_session * s,
231 mpls_inet_addr * a)
233 mpls_return_enum result = MPLS_FAILURE;
235 MPLS_ASSERT(s && a);
237 LDP_ENTER(g->user_data, "ldp_addr_send");
239 ldp_addr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
241 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
242 "Addr Send: session(%d)\n", s->index);
244 result = ldp_mesg_send_tcp(g, s, s->tx_message);
246 LDP_EXIT(g->user_data, "ldp_addr_send");
248 return result;
251 mpls_return_enum ldp_waddr_send(ldp_global * g, ldp_session * s,
252 mpls_inet_addr * a)
254 mpls_return_enum result = MPLS_FAILURE;
256 MPLS_ASSERT(s && a);
258 LDP_ENTER(g->user_data, "ldp_waddr_send");
260 ldp_waddr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
262 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
263 "Addr Withdraw Send: session(%d)\n", s->index);
265 result = ldp_mesg_send_tcp(g, s, s->tx_message);
267 LDP_EXIT(g->user_data, "ldp_waddr_send");
269 return result;
272 mpls_return_enum ldp_addr_process(ldp_global * g, ldp_session * s,
273 ldp_entity * e, ldp_mesg * msg)
275 mplsLdpAdrMsg_t *body = &msg->u.addr;
276 mpls_inet_addr inet;
277 ldp_addr *addr = NULL;
278 ldp_nexthop *nh = NULL;
279 ldp_fec *fec = NULL;
280 int len = (body->addressList.baseTlv.length - MPLS_ADDFAMFIXLEN) /
281 MPLS_IPv4LEN;
282 int i;
284 LDP_ENTER(g->user_data, "ldp_addr_process");
286 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ADDRESS,
287 "Addr Recv: session(%d)\n", s->index);
289 for (i = 0; i < len; i++) {
290 inet.type = MPLS_FAMILY_IPV4;
291 inet.u.ipv4 = body->addressList.address[i];
293 if (msg->u.generic.flags.flags.msgType == MPLS_ADDR_MSGTYPE) {
294 if (!(addr = ldp_addr_find(g, &inet))) {
295 /* it's not in the tree, put it there! */
296 if ((addr = ldp_addr_insert(g, &inet)) == NULL) {
297 LDP_PRINT(g->user_data, "ldp_addr_process: error adding addr\n");
298 goto ldp_addr_process_end;
302 /* the addr is in the tree */
303 if (ldp_session_add_addr(g, s, addr) == MPLS_FAILURE) {
304 LDP_PRINT(g->user_data,
305 "ldp_addr_process: error adding address to session\n");
306 return MPLS_FAILURE;
309 nh = MPLS_LIST_HEAD(&addr->nh_root);
310 while (nh != NULL) {
311 fec = nh->fec;
312 /* create cross connect */
313 /* send label mapping */
314 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
316 } else {
317 /* addr withdrawl */
318 if ((addr = ldp_addr_find(g, &inet))) {
319 nh = MPLS_LIST_HEAD(&addr->nh_root);
320 while (fec != NULL) {
321 /* send label withdrawl */
322 /* delete cross connect */
323 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
326 ldp_session_del_addr(g, s, addr);
331 LDP_EXIT(g->user_data, "ldp_addr_process");
333 return MPLS_SUCCESS;
335 ldp_addr_process_end:
337 LDP_EXIT(g->user_data, "ldp_addr_process-error");
339 return MPLS_FAILURE;