Re-work the adding/removing of ldp_if and ldp_addr.
[mpls-ldp-portable.git] / ldp / ldp_addr.c
blob221b82fe9410ed363c0a584f4f64f164446fc3dd
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_buf.h"
21 #include "ldp_mesg.h"
22 #include "mpls_list.h"
23 #include "mpls_ifmgr_impl.h"
24 #include "mpls_mm_impl.h"
25 #include "mpls_trace_impl.h"
26 #include "mpls_tree_impl.h"
28 static uint32_t _ldp_addr_next_index = 1;
30 ldp_addr *ldp_addr_create(ldp_global *g, mpls_inet_addr * address)
32 ldp_addr *a = (ldp_addr *) mpls_malloc(sizeof(ldp_addr));
34 if (a) {
36 * note: this is init to 1 for a reason!
37 * We're placing it in the global list, so this is our refcnt
38 * when this refcnt gets to zero, it will be removed from the
39 * global list and deleted
41 MPLS_REFCNT_INIT(a, 1);
42 mpls_link_list_init(&a->session_root);
43 MPLS_LIST_INIT(&a->nh_root, ldp_nexthop);
44 memcpy(&a->address, address, sizeof(mpls_inet_addr));
45 a->index = _ldp_addr_get_next_index();
46 _ldp_global_add_addr(g, a);
48 return a;
51 void ldp_addr_delete(ldp_global *g, ldp_addr * a)
53 LDP_PRINT(g->user_data,"addr delete\n");
54 MPLS_REFCNT_ASSERT(a, 0);
55 _ldp_global_del_addr(g, a);
56 mpls_free(a);
59 ldp_addr *ldp_addr_find(ldp_global *g, mpls_inet_addr * address)
61 ldp_addr *addr = NULL;
63 if (mpls_tree_get(g->addr_tree, address->u.ipv4, 32, (void **)&addr) !=
64 MPLS_SUCCESS) {
65 return NULL;
67 return addr;
70 ldp_addr *ldp_addr_insert(ldp_global *g, mpls_inet_addr * address)
72 ldp_addr *addr = NULL;
74 if ((addr = ldp_addr_create(g, address)) == NULL) {
75 LDP_PRINT(g->user_data, "ldp_addr_insert: error creating address\n");
76 return NULL;
78 MPLS_REFCNT_HOLD(addr);
79 if (mpls_tree_insert(g->addr_tree, address->u.ipv4, 32, (void *)addr) !=
80 MPLS_SUCCESS) {
81 LDP_PRINT(g->user_data, "ldp_addr_insert: error adding addr\n");
82 return NULL;
84 return addr;
87 void ldp_addr_remove(ldp_global *g, mpls_inet_addr * address)
89 ldp_addr *addr = NULL;
91 if (mpls_tree_remove(g->addr_tree, address->u.ipv4, 32, (void **)&addr) ==
92 MPLS_SUCCESS) {
93 MPLS_REFCNT_RELEASE2(g, addr, ldp_addr_delete);
97 mpls_return_enum _ldp_addr_add_session(ldp_addr * a, ldp_session * s)
99 MPLS_ASSERT(a && s);
100 MPLS_REFCNT_HOLD(s);
101 if (mpls_link_list_add_tail(&a->session_root, s) == MPLS_SUCCESS) {
102 return MPLS_SUCCESS;
104 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
105 return MPLS_FAILURE;
108 void _ldp_addr_del_session(ldp_addr * a, ldp_session * s)
110 MPLS_ASSERT(a && s);
111 mpls_link_list_remove_data(&a->session_root, s);
112 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
115 void ldp_addr_add_nexthop(ldp_addr * a, ldp_nexthop * nh)
117 ldp_nexthop *np = NULL;
119 MPLS_ASSERT(a && nh);
120 MPLS_REFCNT_HOLD(nh);
122 ldp_nexthop_add_addr(nh,a);
124 np = MPLS_LIST_HEAD(&a->nh_root);
125 while (np != NULL) {
126 if (np->index > nh->index) {
127 MPLS_LIST_INSERT_BEFORE(&a->nh_root, np, nh, _addr);
128 return;
130 np = MPLS_LIST_NEXT(&a->nh_root, np, _addr);
132 MPLS_LIST_ADD_TAIL(&a->nh_root, nh, _addr, ldp_nexthop);
135 void ldp_addr_del_nexthop(ldp_global *g, ldp_addr * a, ldp_nexthop * nh)
137 MPLS_ASSERT(a && nh);
138 MPLS_LIST_REMOVE(&a->nh_root, nh, _addr);
139 ldp_nexthop_del_addr(g, nh);
140 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);
143 uint32_t _ldp_addr_get_next_index()
145 uint32_t retval = _ldp_addr_next_index;
147 _ldp_addr_next_index++;
148 if (retval > _ldp_addr_next_index) {
149 _ldp_addr_next_index = 1;
151 return retval;
154 void ldp_addr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
155 mpls_inet_addr * addr)
157 MPLS_MSGPTR(Adr);
159 LDP_ENTER(g->user_data, "ldp_addr_mesg_prepare");
161 ldp_mesg_prepare(msg, MPLS_ADDR_MSGTYPE, msgid);
162 MPLS_MSGPARAM(Adr) = &msg->u.addr;
164 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
165 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
166 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
168 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
169 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
171 LDP_EXIT(g->user_data, "ldp_addr_mesg_prepare");
174 void ldp_waddr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
175 mpls_inet_addr * addr)
177 MPLS_MSGPTR(Adr);
179 LDP_ENTER(g->user_data, "ldp_waddr_mesg_prepare");
181 ldp_mesg_prepare(msg, MPLS_ADDRWITH_MSGTYPE, msgid);
182 MPLS_MSGPARAM(Adr) = &msg->u.addr;
184 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
185 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
186 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
188 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
189 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
191 LDP_EXIT(g->user_data, "ldp_waddr_mesg_prepare");
194 mpls_return_enum ldp_addr_send(ldp_global * g, ldp_session * s,
195 mpls_inet_addr * a)
197 mpls_return_enum result = MPLS_FAILURE;
199 MPLS_ASSERT(s && a);
201 LDP_ENTER(g->user_data, "ldp_addr_send");
203 ldp_addr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
205 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
206 "Addr Send: session(%d)\n", s->index);
208 result = ldp_mesg_send_tcp(g, s, s->tx_message);
210 LDP_EXIT(g->user_data, "ldp_addr_send");
212 return result;
215 mpls_return_enum ldp_waddr_send(ldp_global * g, ldp_session * s,
216 mpls_inet_addr * a)
218 mpls_return_enum result = MPLS_FAILURE;
220 MPLS_ASSERT(s && a);
222 LDP_ENTER(g->user_data, "ldp_waddr_send");
224 ldp_waddr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
226 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
227 "Addr Withdraw Send: session(%d)\n", s->index);
229 result = ldp_mesg_send_tcp(g, s, s->tx_message);
231 LDP_EXIT(g->user_data, "ldp_waddr_send");
233 return result;
236 mpls_return_enum ldp_addr_process(ldp_global * g, ldp_session * s,
237 ldp_entity * e, ldp_mesg * msg)
239 mplsLdpAdrMsg_t *body = &msg->u.addr;
240 mpls_inet_addr inet;
241 ldp_addr *addr = NULL;
242 ldp_nexthop *nh = NULL;
243 ldp_fec *fec = NULL;
244 int len = (body->addressList.baseTlv.length - MPLS_ADDFAMFIXLEN) /
245 MPLS_IPv4LEN;
246 int i;
248 LDP_ENTER(g->user_data, "ldp_addr_process");
250 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ADDRESS,
251 "Addr Recv: session(%d)\n", s->index);
253 for (i = 0; i < len; i++) {
254 inet.type = MPLS_FAMILY_IPV4;
255 inet.u.ipv4 = body->addressList.address[i];
257 if (msg->u.generic.flags.flags.msgType == MPLS_ADDR_MSGTYPE) {
258 if (!(addr == ldp_addr_find(g, &inet))) {
259 /* it's not in the tree, put it there! */
260 if ((addr = ldp_addr_insert(g, &inet)) == NULL) {
261 LDP_PRINT(g->user_data, "ldp_addr_process: error adding addr\n");
262 goto ldp_addr_process_end;
266 /* the addr is in the tree */
267 if (ldp_session_add_addr(g, s, addr) == MPLS_FAILURE) {
268 LDP_PRINT(g->user_data,
269 "ldp_addr_process: error adding address to session\n");
270 return MPLS_FAILURE;
273 nh = MPLS_LIST_HEAD(&addr->nh_root);
274 while (nh != NULL) {
275 fec = nh->fec;
276 /* create cross connect */
277 /* send label mapping */
278 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
280 } else {
281 /* addr withdrawl */
282 if ((addr = ldp_addr_find(g, &inet))) {
283 nh = MPLS_LIST_HEAD(&addr->nh_root);
284 while (fec != NULL) {
285 /* send label withdrawl */
286 /* delete cross connect */
287 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
290 ldp_session_del_addr(g, s, addr);
291 if (MPLS_REFCNT_VALUE(addr) == 1) {
292 /* the tree is the last one holding a ref to this addr */
293 ldp_addr_remove(g, &inet);
299 LDP_EXIT(g->user_data, "ldp_addr_process");
301 return MPLS_SUCCESS;
303 ldp_addr_process_end:
305 LDP_EXIT(g->user_data, "ldp_addr_process-error");
307 return MPLS_FAILURE;