3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
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"
19 #include "ldp_nexthop.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
);
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();
57 _ldp_global_add_addr(g
, a
);
58 ldp_addr_insert2(g
, a
);
60 LDP_EXIT(g
->user_data
, "ldp_addr_create: %p", 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
);
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
) !=
80 LDP_EXIT(g
->user_data
, "ldp_addr_find: NULL");
83 LDP_EXIT(g
->user_data
, "ldp_addr_find: %p", 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");
98 mpls_return_enum
ldp_addr_insert2(ldp_global
*g
, ldp_addr
*addr
)
100 LDP_ENTER(g
->user_data
, "ldp_addr_insert2: 0x%08x", addr
->address
.u
.ipv4
);
101 if (mpls_tree_insert(g
->addr_tree
, addr
->address
.u
.ipv4
, 32, (void *)addr
) !=
103 LDP_EXIT(g
->user_data
, "ldp_addr_insert2-error");
104 MPLS_REFCNT_RELEASE2(g
, addr
, ldp_addr_delete
);
107 LDP_EXIT(g
->user_data
, "ldp_addr_insert2");
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
)
124 void ldp_addr_del_if(ldp_global
*g
, ldp_addr
* a
)
127 MPLS_REFCNT_RELEASE2(g
, a
->iff
, ldp_if_delete
);
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
)
148 void _ldp_addr_del_session(ldp_addr
* a
, ldp_session
* s
)
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
);
171 if (np
->index
> nh
->index
) {
172 MPLS_LIST_INSERT_BEFORE(&a
->nh_root
, np
, nh
, _addr
);
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;
198 void ldp_addr_mesg_prepare(ldp_mesg
* msg
, ldp_global
* g
, uint32_t msgid
,
199 mpls_inet_addr
* addr
)
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
)
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
,
241 mpls_return_enum result
= MPLS_FAILURE
;
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");
259 mpls_return_enum
ldp_waddr_send(ldp_global
* g
, ldp_session
* s
,
262 mpls_return_enum result
= MPLS_FAILURE
;
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");
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
;
285 ldp_addr
*addr
= NULL
;
286 ldp_nexthop
*nh
= NULL
;
288 int len
= (body
->addressList
.baseTlv
.length
- MPLS_ADDFAMFIXLEN
) /
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 */
312 LDP_PRINT(g
->user_data
,
313 "ldp_addr_process: session (%d) already advertised this address\n",
314 addr
->session
->index
);
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");
324 nh
= MPLS_LIST_HEAD(&addr
->nh_root
);
327 /* create cross connect */
328 /* send label mapping */
329 nh
= MPLS_LIST_NEXT(&addr
->nh_root
, nh
, _addr
);
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");
350 ldp_addr_process_end
:
352 LDP_EXIT(g
->user_data
, "ldp_addr_process-error");
357 void ldp_addr_process_add(ldp_global
*g
, struct ldp_addr
*a
)
359 ldp_session
* sp
= MPLS_LIST_HEAD(&g
->session
);
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
);
372 if (sp
->state
== LDP_STATE_OPERATIONAL
) {
373 ldp_waddr_send(g
, sp
, &a
->address
);
375 sp
= MPLS_LIST_NEXT(&g
->session
, sp
, _global
);