Print standard delete message
[mpls-ldp-portable.git] / ldp / ldp_addr.c
blob9e4608e32c8b5a71af54e3bb29d8d4152e2c3512
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 LDP_ENTER(g->user_data, "ldp_addr_create: 0x%08x", address->u.ipv4);
36 if (a) {
38 * note: this is init to 1 for a reason!
39 * We're placing it in the global list, so this is our refcnt
40 * when this refcnt gets to zero, it will be removed from the
41 * global list and deleted
44 * TESTING: jleu 6/7/2004, since I want the addr to be cleaned up
45 * when it no longer has a nexthop, fec, or label, the only things that
46 * should increment the ref are those (nh, fec, label etc), not global
47 * nor inserting into the tree.
48 MPLS_REFCNT_INIT(a, 1);
50 MPLS_REFCNT_INIT(a, 0);
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 a->session = NULL;
57 _ldp_global_add_addr(g, a);
58 ldp_addr_insert2(g, a);
60 LDP_EXIT(g->user_data, "ldp_addr_create: %p", a);
61 return a;
64 void ldp_addr_delete(ldp_global *g, ldp_addr * a)
66 fprintf(stderr, "addr delete: %p\n", a);
67 MPLS_REFCNT_ASSERT(a, 0);
68 ldp_addr_remove(g, &a->address);
69 _ldp_global_del_addr(g, a);
70 mpls_free(a);
73 ldp_addr *ldp_addr_find(ldp_global *g, mpls_inet_addr * address)
75 ldp_addr *addr = NULL;
77 LDP_ENTER(g->user_data, "ldp_addr_find: 0x%08x", address->u.ipv4);
78 if (mpls_tree_get(g->addr_tree, address->u.ipv4, 32, (void **)&addr) !=
79 MPLS_SUCCESS) {
80 LDP_EXIT(g->user_data, "ldp_addr_find: NULL");
81 return NULL;
83 LDP_EXIT(g->user_data, "ldp_addr_find: %p", addr);
84 return addr;
87 ldp_addr *ldp_addr_insert(ldp_global *g, mpls_inet_addr * address)
89 ldp_addr *addr = NULL;
91 if ((addr = ldp_addr_create(g, address)) == NULL) {
92 LDP_PRINT(g->user_data, "ldp_addr_insert: error creating address\n");
93 return NULL;
95 return addr;
98 mpls_return_enum ldp_addr_insert2(ldp_global *g, ldp_addr *addr)
100 LDP_ENTER(g->user_data, "ldp_addr_insert2: 0x%08", addr->address.u.ipv4);
101 if (mpls_tree_insert(g->addr_tree, addr->address.u.ipv4, 32, (void *)addr) !=
102 MPLS_SUCCESS) {
103 LDP_EXIT(g->user_data, "ldp_addr_insert2-error");
104 MPLS_REFCNT_RELEASE2(g, addr, ldp_addr_delete);
105 return MPLS_FATAL;
107 LDP_EXIT(g->user_data, "ldp_addr_insert2");
108 return MPLS_SUCCESS;
111 void ldp_addr_remove(ldp_global *g, mpls_inet_addr * address)
113 ldp_addr *addr = NULL;
114 mpls_tree_remove(g->addr_tree, address->u.ipv4, 32, (void **)&addr);
117 void ldp_addr_add_if(ldp_addr * a, ldp_if * i)
119 MPLS_ASSERT(a && i);
120 MPLS_REFCNT_HOLD(i);
121 a->iff = i;
124 void ldp_addr_del_if(ldp_global *g, ldp_addr * a)
126 MPLS_ASSERT(a);
127 MPLS_REFCNT_RELEASE2(g, a->iff, ldp_if_delete);
128 a->iff = NULL;
131 mpls_bool ldp_addr_is_empty(ldp_addr *a)
133 if ((a->iff == NULL) && MPLS_LIST_EMPTY(&a->nh_root) &&
134 (a->session == NULL)) {
135 return MPLS_BOOL_TRUE;
137 return MPLS_BOOL_FALSE;
140 mpls_return_enum _ldp_addr_add_session(ldp_addr * a, ldp_session * s)
142 MPLS_ASSERT(a && s);
143 MPLS_REFCNT_HOLD(s);
144 a->session = s;
145 return MPLS_SUCCESS;
148 void _ldp_addr_del_session(ldp_addr * a, ldp_session * s)
150 MPLS_ASSERT(a && s);
151 a->session = NULL;
152 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
156 * We do not hold a ref to the nexthop. The nexthop holds a ref to the
157 * addr. Nexthop creation calls ldp_addr_add_nexthop, nexthop deletion
158 * calls ldp_addr_del_nexthop. There is no way a nexthop can be deleted
159 * without removing the addrs ref to the nexthop.
161 void ldp_addr_add_nexthop(ldp_addr * a, ldp_nexthop * nh)
163 ldp_nexthop *np = NULL;
165 MPLS_ASSERT(a && nh);
167 ldp_nexthop_add_addr(nh,a);
169 np = MPLS_LIST_HEAD(&a->nh_root);
170 while (np != NULL) {
171 if (np->index > nh->index) {
172 MPLS_LIST_INSERT_BEFORE(&a->nh_root, np, nh, _addr);
173 return;
175 np = MPLS_LIST_NEXT(&a->nh_root, np, _addr);
177 MPLS_LIST_ADD_TAIL(&a->nh_root, nh, _addr, ldp_nexthop);
180 void ldp_addr_del_nexthop(ldp_global *g, ldp_addr * a, ldp_nexthop * nh)
182 MPLS_ASSERT(a && nh);
183 MPLS_LIST_REMOVE(&a->nh_root, nh, _addr);
184 ldp_nexthop_del_addr(g, nh);
187 uint32_t _ldp_addr_get_next_index()
189 uint32_t retval = _ldp_addr_next_index;
191 _ldp_addr_next_index++;
192 if (retval > _ldp_addr_next_index) {
193 _ldp_addr_next_index = 1;
195 return retval;
198 void ldp_addr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
199 mpls_inet_addr * addr)
201 MPLS_MSGPTR(Adr);
203 LDP_ENTER(g->user_data, "ldp_addr_mesg_prepare");
205 ldp_mesg_prepare(msg, MPLS_ADDR_MSGTYPE, msgid);
206 MPLS_MSGPARAM(Adr) = &msg->u.addr;
208 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
209 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
210 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
212 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
213 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
215 LDP_EXIT(g->user_data, "ldp_addr_mesg_prepare");
218 void ldp_waddr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
219 mpls_inet_addr * addr)
221 MPLS_MSGPTR(Adr);
223 LDP_ENTER(g->user_data, "ldp_waddr_mesg_prepare");
225 ldp_mesg_prepare(msg, MPLS_ADDRWITH_MSGTYPE, msgid);
226 MPLS_MSGPARAM(Adr) = &msg->u.addr;
228 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
229 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
230 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
232 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
233 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
235 LDP_EXIT(g->user_data, "ldp_waddr_mesg_prepare");
238 mpls_return_enum ldp_addr_send(ldp_global * g, ldp_session * s,
239 mpls_inet_addr * a)
241 mpls_return_enum result = MPLS_FAILURE;
243 MPLS_ASSERT(s && a);
245 LDP_ENTER(g->user_data, "ldp_addr_send");
247 ldp_addr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
249 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
250 "Addr Send: session(%d)\n", s->index);
252 result = ldp_mesg_send_tcp(g, s, s->tx_message);
254 LDP_EXIT(g->user_data, "ldp_addr_send");
256 return result;
259 mpls_return_enum ldp_waddr_send(ldp_global * g, ldp_session * s,
260 mpls_inet_addr * a)
262 mpls_return_enum result = MPLS_FAILURE;
264 MPLS_ASSERT(s && a);
266 LDP_ENTER(g->user_data, "ldp_waddr_send");
268 ldp_waddr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
270 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
271 "Addr Withdraw Send: session(%d)\n", s->index);
273 result = ldp_mesg_send_tcp(g, s, s->tx_message);
275 LDP_EXIT(g->user_data, "ldp_waddr_send");
277 return result;
280 mpls_return_enum ldp_addr_process(ldp_global * g, ldp_session * s,
281 ldp_entity * e, ldp_mesg * msg)
283 mplsLdpAdrMsg_t *body = &msg->u.addr;
284 mpls_inet_addr inet;
285 ldp_addr *addr = NULL;
286 ldp_nexthop *nh = NULL;
287 ldp_fec *fec = NULL;
288 int len = (body->addressList.baseTlv.length - MPLS_ADDFAMFIXLEN) /
289 MPLS_IPv4LEN;
290 int i;
292 LDP_ENTER(g->user_data, "ldp_addr_process");
294 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ADDRESS,
295 "Addr Recv: session(%d)\n", s->index);
297 for (i = 0; i < len; i++) {
298 inet.type = MPLS_FAMILY_IPV4;
299 inet.u.ipv4 = body->addressList.address[i];
301 if (msg->u.generic.flags.flags.msgType == MPLS_ADDR_MSGTYPE) {
302 if (!(addr = ldp_addr_find(g, &inet))) {
303 /* it's not in the tree, put it there! */
304 if ((addr = ldp_addr_insert(g, &inet)) == NULL) {
305 LDP_PRINT(g->user_data, "ldp_addr_process: error adding addr\n");
306 goto ldp_addr_process_end;
310 /* the addr is in the tree */
311 if (addr->session) {
312 LDP_PRINT(g->user_data,
313 "ldp_addr_process: session (%d) already advertised this address\n",
314 addr->session->index);
315 return MPLS_FAILURE;
318 if (ldp_session_add_addr(g, s, addr) == MPLS_FAILURE) {
319 LDP_PRINT(g->user_data,
320 "ldp_addr_process: error adding address to session\n");
321 return MPLS_FAILURE;
324 nh = MPLS_LIST_HEAD(&addr->nh_root);
325 while (nh != NULL) {
326 fec = nh->fec;
327 /* create cross connect */
328 /* send label mapping */
329 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
331 } else {
332 /* addr withdrawl */
333 if ((addr = ldp_addr_find(g, &inet))) {
334 nh = MPLS_LIST_HEAD(&addr->nh_root);
335 while (fec != NULL) {
336 /* send label withdrawl */
337 /* delete cross connect */
338 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
341 ldp_session_del_addr(g, s, addr);
346 LDP_EXIT(g->user_data, "ldp_addr_process");
348 return MPLS_SUCCESS;
350 ldp_addr_process_end:
352 LDP_EXIT(g->user_data, "ldp_addr_process-error");
354 return MPLS_FAILURE;
357 void ldp_addr_process_add(ldp_global *g, struct ldp_addr *a)
359 ldp_session* sp = MPLS_LIST_HEAD(&g->session);
360 while (sp != NULL) {
361 if (sp->state == LDP_STATE_OPERATIONAL) {
362 ldp_addr_send(g, sp, &a->address);
364 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
368 void ldp_addr_process_remove(ldp_global *g, struct ldp_addr *a)
370 ldp_session* sp = MPLS_LIST_HEAD(&g->session);
371 while (sp != NULL) {
372 if (sp->state == LDP_STATE_OPERATIONAL) {
373 ldp_waddr_send(g, sp, &a->address);
375 sp = MPLS_LIST_NEXT(&g->session, sp, _global);