Convert to a generic FEC handling architecture. Part of this change
[mpls-ldp-portable.git] / ldp / ldp_addr.c
blob1144cf38b9852e0048ae265fb1e5e7472187f263
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_fec.h"
19 #include "ldp_buf.h"
20 #include "ldp_mesg.h"
21 #include "mpls_ifmgr_impl.h"
22 #include "mpls_mm_impl.h"
23 #include "mpls_trace_impl.h"
24 #include "mpls_tree_impl.h"
26 static uint32_t _ldp_addr_next_index = 1;
28 ldp_addr *ldp_addr_find(ldp_global *g, mpls_inet_addr * address)
30 ldp_addr *addr = NULL;
32 if (mpls_tree_get(g->addr_tree, address->u.ipv4, 32, (void **)&addr) !=
33 MPLS_SUCCESS) {
34 return NULL;
36 return addr;
39 ldp_addr *ldp_addr_insert(ldp_global *g, mpls_inet_addr * address)
41 ldp_addr *addr = NULL;
43 if ((addr = ldp_addr_create(address)) == NULL) {
44 LDP_PRINT(g->user_data, "ldp_addr_insert: error creating address\n");
45 return NULL;
47 MPLS_REFCNT_HOLD(addr);
48 if (mpls_tree_insert(g->addr_tree, address->u.ipv4, 32, (void *)addr) !=
49 MPLS_SUCCESS) {
50 LDP_PRINT(g->user_data, "ldp_addr_insert: error adding addr\n");
51 return NULL;
53 return addr;
56 void ldp_addr_remove(ldp_global *g, mpls_inet_addr * address)
58 ldp_addr *addr = NULL;
60 if (mpls_tree_remove(g->addr_tree, address->u.ipv4, 32, (void **)&addr) ==
61 MPLS_SUCCESS) {
62 MPLS_REFCNT_RELEASE(addr, ldp_addr_delete);
66 ldp_addr *ldp_addr_create(mpls_inet_addr * address)
68 ldp_addr *a = (ldp_addr *) mpls_malloc(sizeof(ldp_addr));
70 if (a) {
71 MPLS_REFCNT_INIT(a, 0);
72 mpls_link_list_init(&a->session_root);
73 MPLS_LIST_INIT(&a->fec_addr_root, ldp_fec);
74 memcpy(&a->address, address, sizeof(mpls_inet_addr));
75 a->index = _ldp_addr_get_next_index();
77 return a;
80 void ldp_addr_delete(ldp_addr * a)
82 LDP_PRINT(g->user_data,"addr delete\n");
83 mpls_free(a);
86 mpls_return_enum _ldp_addr_add_session(ldp_addr * a, ldp_session * s)
88 MPLS_ASSERT(a && s);
89 MPLS_REFCNT_HOLD(s);
90 if (mpls_link_list_add_tail(&a->session_root, s) == MPLS_SUCCESS) {
91 return MPLS_SUCCESS;
93 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
94 return MPLS_FAILURE;
97 void _ldp_addr_del_session(ldp_addr * a, ldp_session * s)
99 MPLS_ASSERT(a && s);
100 mpls_link_list_remove_data(&a->session_root, s);
101 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
104 void ldp_addr_add_fec(ldp_addr * a, ldp_fec * f)
106 ldp_fec *fp = NULL;
108 MPLS_ASSERT(a && f);
109 MPLS_REFCNT_HOLD(f);
111 ldp_fec_add_addr(f,a);
113 fp = MPLS_LIST_HEAD(&a->fec_addr_root);
114 while (fp != NULL) {
115 if (fp->index > f->index) {
116 MPLS_LIST_INSERT_BEFORE(&a->fec_addr_root, fp, f, _addr);
117 return;
119 fp = MPLS_LIST_NEXT(&a->fec_addr_root, fp, _addr);
121 MPLS_LIST_ADD_TAIL(&a->fec_addr_root, f, _addr, ldp_fec);
124 void ldp_addr_del_fec(ldp_addr * a, ldp_fec * f)
126 MPLS_ASSERT(a && f);
127 MPLS_LIST_REMOVE(&a->fec_addr_root, f, _addr);
128 ldp_fec_del_addr(f);
129 MPLS_REFCNT_RELEASE(f, ldp_fec_delete);
132 uint32_t _ldp_addr_get_next_index()
134 uint32_t retval = _ldp_addr_next_index;
136 _ldp_addr_next_index++;
137 if (retval > _ldp_addr_next_index) {
138 _ldp_addr_next_index = 1;
140 return retval;
143 void ldp_addr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
144 mpls_inet_addr * addr)
146 MPLS_MSGPTR(Adr);
148 LDP_ENTER(g->user_data, "ldp_addr_mesg_prepare");
150 ldp_mesg_prepare(msg, MPLS_ADDR_MSGTYPE, msgid);
151 MPLS_MSGPARAM(Adr) = &msg->u.addr;
153 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
154 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
155 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
157 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
158 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
160 LDP_EXIT(g->user_data, "ldp_addr_mesg_prepare");
163 void ldp_waddr_mesg_prepare(ldp_mesg * msg, ldp_global * g, uint32_t msgid,
164 mpls_inet_addr * addr)
166 MPLS_MSGPTR(Adr);
168 LDP_ENTER(g->user_data, "ldp_waddr_mesg_prepare");
170 ldp_mesg_prepare(msg, MPLS_ADDRWITH_MSGTYPE, msgid);
171 MPLS_MSGPARAM(Adr) = &msg->u.addr;
173 MPLS_MSGPARAM(Adr)->adrListTlvExists = 1;
174 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
175 setupAddrTlv(&(MPLS_MSGPARAM(Adr)->addressList));
177 MPLS_MSGPARAM(Adr)->baseMsg.msgLength +=
178 addAddrElem2AddrTlv(&(MPLS_MSGPARAM(Adr)->addressList), addr->u.ipv4);
180 LDP_EXIT(g->user_data, "ldp_waddr_mesg_prepare");
183 mpls_return_enum ldp_addr_send(ldp_global * g, ldp_session * s,
184 mpls_inet_addr * a)
186 mpls_return_enum result = MPLS_FAILURE;
188 MPLS_ASSERT(s && a);
190 LDP_ENTER(g->user_data, "ldp_addr_send");
192 ldp_addr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
194 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
195 "Addr Send: session(%d)\n", s->index);
197 result = ldp_mesg_send_tcp(g, s, s->tx_message);
199 LDP_EXIT(g->user_data, "ldp_addr_send");
201 return result;
204 mpls_return_enum ldp_waddr_send(ldp_global * g, ldp_session * s,
205 mpls_inet_addr * a)
207 mpls_return_enum result = MPLS_FAILURE;
209 MPLS_ASSERT(s && a);
211 LDP_ENTER(g->user_data, "ldp_waddr_send");
213 ldp_waddr_mesg_prepare(s->tx_message, g, g->message_identifier++, a);
215 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ADDRESS,
216 "Addr Withdraw Send: session(%d)\n", s->index);
218 result = ldp_mesg_send_tcp(g, s, s->tx_message);
220 LDP_EXIT(g->user_data, "ldp_waddr_send");
222 return result;
225 mpls_return_enum ldp_addr_process(ldp_global * g, ldp_session * s,
226 ldp_entity * e, ldp_mesg * msg)
228 mplsLdpAdrMsg_t *body = &msg->u.addr;
229 mpls_inet_addr inet;
230 ldp_addr *addr = NULL;
231 ldp_fec *fec = NULL;
232 int len = (body->addressList.baseTlv.length - MPLS_ADDFAMFIXLEN) /
233 MPLS_IPv4LEN;
234 int i;
236 LDP_ENTER(g->user_data, "ldp_addr_process");
238 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ADDRESS,
239 "Addr Recv: session(%d)\n", s->index);
241 for (i = 0; i < len; i++) {
242 inet.type = MPLS_FAMILY_IPV4;
243 inet.u.ipv4 = body->addressList.address[i];
245 if (msg->u.generic.flags.flags.msgType == MPLS_ADDR_MSGTYPE) {
246 if (!(addr == ldp_addr_find(g, &inet))) {
247 /* it's not in the tree, put it there! */
248 if (ldp_addr_insert(g, &inet) == NULL) {
249 LDP_PRINT(g->user_data, "ldp_addr_process: error adding addr\n");
250 goto ldp_addr_process_end;
254 /* the addr is in the tree */
255 if (ldp_session_add_addr(s, addr) == MPLS_FAILURE) {
256 LDP_PRINT(g->user_data,
257 "ldp_addr_process: error adding address to session\n");
258 return MPLS_FAILURE;
261 fec = MPLS_LIST_HEAD(&addr->fec_addr_root);
262 while (fec != NULL) {
263 /* create cross connect */
264 /* send label mapping */
265 fec = MPLS_LIST_NEXT(&addr->fec_addr_root, fec, _addr);
267 } else {
268 /* addr withdrawl */
269 if ((addr = ldp_addr_find(g, &inet))) {
270 fec = MPLS_LIST_HEAD(&addr->fec_addr_root);
271 while (fec != NULL) {
272 /* send label withdrawl */
273 /* delete cross connect */
274 fec = MPLS_LIST_NEXT(&addr->fec_addr_root, fec, _addr);
277 ldp_session_del_addr(s, addr);
278 if (MPLS_REFCNT_VALUE(addr) == 1) {
279 /* the tree is the last one holding a ref to this addr */
280 ldp_addr_remove(g, &inet);
286 LDP_EXIT(g->user_data, "ldp_addr_process");
288 return MPLS_SUCCESS;
290 ldp_addr_process_end:
291 if (addr != NULL)
292 ldp_addr_delete(addr);
294 LDP_EXIT(g->user_data, "ldp_addr_process-error");
296 return MPLS_FAILURE;