Convertion to a ECMP capable infrastructure compiles (no testing
[mpls-ldp-portable.git] / ldp / ldp_addr.c
blobaa9c679787d4757da66caf7e45983649c6be9034
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_session.h"
15 #include "ldp_entity.h"
16 #include "ldp_pdu_setup.h"
17 #include "ldp_addr.h"
18 #include "ldp_nexthop.h"
19 #include "ldp_buf.h"
20 #include "ldp_mesg.h"
21 #include "mpls_list.h"
22 #include "mpls_ifmgr_impl.h"
23 #include "mpls_mm_impl.h"
24 #include "mpls_trace_impl.h"
25 #include "mpls_tree_impl.h"
27 static uint32_t _ldp_addr_next_index = 1;
29 ldp_addr *ldp_addr_find(ldp_global *g, mpls_inet_addr * address)
31 ldp_addr *addr = NULL;
33 if (mpls_tree_get(g->addr_tree, address->u.ipv4, 32, (void **)&addr) !=
34 MPLS_SUCCESS) {
35 return NULL;
37 return addr;
40 ldp_addr *ldp_addr_insert(ldp_global *g, mpls_inet_addr * address)
42 ldp_addr *addr = NULL;
44 if ((addr = ldp_addr_create(address)) == NULL) {
45 LDP_PRINT(g->user_data, "ldp_addr_insert: error creating address\n");
46 return NULL;
48 MPLS_REFCNT_HOLD(addr);
49 if (mpls_tree_insert(g->addr_tree, address->u.ipv4, 32, (void *)addr) !=
50 MPLS_SUCCESS) {
51 LDP_PRINT(g->user_data, "ldp_addr_insert: error adding addr\n");
52 return NULL;
54 return addr;
57 void ldp_addr_remove(ldp_global *g, mpls_inet_addr * address)
59 ldp_addr *addr = NULL;
61 if (mpls_tree_remove(g->addr_tree, address->u.ipv4, 32, (void **)&addr) ==
62 MPLS_SUCCESS) {
63 MPLS_REFCNT_RELEASE(addr, ldp_addr_delete);
67 ldp_addr *ldp_addr_create(mpls_inet_addr * address)
69 ldp_addr *a = (ldp_addr *) mpls_malloc(sizeof(ldp_addr));
71 if (a) {
72 MPLS_REFCNT_INIT(a, 0);
73 mpls_link_list_init(&a->session_root);
74 MPLS_LIST_INIT(&a->nh_root, ldp_nexthop);
75 memcpy(&a->address, address, sizeof(mpls_inet_addr));
76 a->index = _ldp_addr_get_next_index();
78 return a;
81 void ldp_addr_delete(ldp_addr * a)
83 LDP_PRINT(g->user_data,"addr delete\n");
84 mpls_free(a);
87 mpls_return_enum _ldp_addr_add_session(ldp_addr * a, ldp_session * s)
89 MPLS_ASSERT(a && s);
90 MPLS_REFCNT_HOLD(s);
91 if (mpls_link_list_add_tail(&a->session_root, s) == MPLS_SUCCESS) {
92 return MPLS_SUCCESS;
94 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
95 return MPLS_FAILURE;
98 void _ldp_addr_del_session(ldp_addr * a, ldp_session * s)
100 MPLS_ASSERT(a && s);
101 mpls_link_list_remove_data(&a->session_root, s);
102 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
105 void ldp_addr_add_nexthop(ldp_addr * a, ldp_nexthop * nh)
107 ldp_nexthop *np = NULL;
109 MPLS_ASSERT(a && nh);
110 MPLS_REFCNT_HOLD(nh);
112 ldp_nexthop_add_addr(nh,a);
114 np = MPLS_LIST_HEAD(&a->nh_root);
115 while (np != NULL) {
116 if (np->index > nh->index) {
117 MPLS_LIST_INSERT_BEFORE(&a->nh_root, np, nh, _addr);
118 return;
120 np = MPLS_LIST_NEXT(&a->nh_root, np, _addr);
122 MPLS_LIST_ADD_TAIL(&a->nh_root, nh, _addr, ldp_nexthop);
125 void ldp_addr_del_nexthop(ldp_addr * a, ldp_nexthop * nh)
127 MPLS_ASSERT(a && nh);
128 MPLS_LIST_REMOVE(&a->nh_root, nh, _addr);
129 ldp_nexthop_del_addr(nh);
130 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);
133 uint32_t _ldp_addr_get_next_index()
135 uint32_t retval = _ldp_addr_next_index;
137 _ldp_addr_next_index++;
138 if (retval > _ldp_addr_next_index) {
139 _ldp_addr_next_index = 1;
141 return retval;
144 void ldp_addr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
145 mpls_inet_addr * addr)
147 MPLS_MSGPTR(Adr);
149 LDP_ENTER(g->user_data, "ldp_addr_mesg_prepare");
151 ldp_mesg_prepare(msg, MPLS_ADDR_MSGTYPE, msgid);
152 MPLS_MSGPARAM(Adr) = &msg->u.addr;
154 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
155 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
156 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
158 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
159 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
161 LDP_EXIT(g->user_data, "ldp_addr_mesg_prepare");
164 void ldp_waddr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
165 mpls_inet_addr * addr)
167 MPLS_MSGPTR(Adr);
169 LDP_ENTER(g->user_data, "ldp_waddr_mesg_prepare");
171 ldp_mesg_prepare(msg, MPLS_ADDRWITH_MSGTYPE, msgid);
172 MPLS_MSGPARAM(Adr) = &msg->u.addr;
174 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
175 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
176 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
178 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
179 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
181 LDP_EXIT(g->user_data, "ldp_waddr_mesg_prepare");
184 mpls_return_enum ldp_addr_send(ldp_global * g, ldp_session * s,
185 mpls_inet_addr * a)
187 mpls_return_enum result = MPLS_FAILURE;
189 MPLS_ASSERT(s && a);
191 LDP_ENTER(g->user_data, "ldp_addr_send");
193 ldp_addr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
195 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
196 "Addr Send: session(%d)\n", s->index);
198 result = ldp_mesg_send_tcp(g, s, s->tx_message);
200 LDP_EXIT(g->user_data, "ldp_addr_send");
202 return result;
205 mpls_return_enum ldp_waddr_send(ldp_global * g, ldp_session * s,
206 mpls_inet_addr * a)
208 mpls_return_enum result = MPLS_FAILURE;
210 MPLS_ASSERT(s && a);
212 LDP_ENTER(g->user_data, "ldp_waddr_send");
214 ldp_waddr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
216 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
217 "Addr Withdraw Send: session(%d)\n", s->index);
219 result = ldp_mesg_send_tcp(g, s, s->tx_message);
221 LDP_EXIT(g->user_data, "ldp_waddr_send");
223 return result;
226 mpls_return_enum ldp_addr_process(ldp_global * g, ldp_session * s,
227 ldp_entity * e, ldp_mesg * msg)
229 mplsLdpAdrMsg_t *body = &msg->u.addr;
230 mpls_inet_addr inet;
231 ldp_addr *addr = NULL;
232 ldp_nexthop *nh = NULL;
233 ldp_fec *fec = NULL;
234 int len = (body->addressList.baseTlv.length - MPLS_ADDFAMFIXLEN) /
235 MPLS_IPv4LEN;
236 int i;
238 LDP_ENTER(g->user_data, "ldp_addr_process");
240 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ADDRESS,
241 "Addr Recv: session(%d)\n", s->index);
243 for (i = 0; i < len; i++) {
244 inet.type = MPLS_FAMILY_IPV4;
245 inet.u.ipv4 = body->addressList.address[i];
247 if (msg->u.generic.flags.flags.msgType == MPLS_ADDR_MSGTYPE) {
248 if (!(addr == ldp_addr_find(g, &inet))) {
249 /* it's not in the tree, put it there! */
250 if (ldp_addr_insert(g, &inet) == NULL) {
251 LDP_PRINT(g->user_data, "ldp_addr_process: error adding addr\n");
252 goto ldp_addr_process_end;
256 /* the addr is in the tree */
257 if (ldp_session_add_addr(s, addr) == MPLS_FAILURE) {
258 LDP_PRINT(g->user_data,
259 "ldp_addr_process: error adding address to session\n");
260 return MPLS_FAILURE;
263 nh = MPLS_LIST_HEAD(&addr->nh_root);
264 while (nh != NULL) {
265 fec = nh->fec;
266 /* create cross connect */
267 /* send label mapping */
268 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
270 } else {
271 /* addr withdrawl */
272 if ((addr = ldp_addr_find(g, &inet))) {
273 nh = MPLS_LIST_HEAD(&addr->nh_root);
274 while (fec != NULL) {
275 /* send label withdrawl */
276 /* delete cross connect */
277 nh = MPLS_LIST_NEXT(&addr->nh_root, nh, _addr);
280 ldp_session_del_addr(s, addr);
281 if (MPLS_REFCNT_VALUE(addr) == 1) {
282 /* the tree is the last one holding a ref to this addr */
283 ldp_addr_remove(g, &inet);
289 LDP_EXIT(g->user_data, "ldp_addr_process");
291 return MPLS_SUCCESS;
293 ldp_addr_process_end:
294 if (addr != NULL)
295 ldp_addr_delete(addr);
297 LDP_EXIT(g->user_data, "ldp_addr_process-error");
299 return MPLS_FAILURE;