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"
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
));
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
);
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
);
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
) !=
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");
78 MPLS_REFCNT_HOLD(addr
);
79 if (mpls_tree_insert(g
->addr_tree
, address
->u
.ipv4
, 32, (void *)addr
) !=
81 LDP_PRINT(g
->user_data
, "ldp_addr_insert: error adding addr\n");
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
) ==
93 MPLS_REFCNT_RELEASE2(g
, addr
, ldp_addr_delete
);
97 mpls_return_enum
_ldp_addr_add_session(ldp_addr
* a
, ldp_session
* s
)
101 if (mpls_link_list_add_tail(&a
->session_root
, s
) == MPLS_SUCCESS
) {
104 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
108 void _ldp_addr_del_session(ldp_addr
* a
, ldp_session
* 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
);
126 if (np
->index
> nh
->index
) {
127 MPLS_LIST_INSERT_BEFORE(&a
->nh_root
, np
, nh
, _addr
);
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;
154 void ldp_addr_mesg_prepare(ldp_mesg
* msg
, ldp_global
* g
, uint32_t msgid
,
155 mpls_inet_addr
* addr
)
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
)
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
,
197 mpls_return_enum result
= MPLS_FAILURE
;
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");
215 mpls_return_enum
ldp_waddr_send(ldp_global
* g
, ldp_session
* s
,
218 mpls_return_enum result
= MPLS_FAILURE
;
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");
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
;
241 ldp_addr
*addr
= NULL
;
242 ldp_nexthop
*nh
= NULL
;
244 int len
= (body
->addressList
.baseTlv
.length
- MPLS_ADDFAMFIXLEN
) /
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");
273 nh
= MPLS_LIST_HEAD(&addr
->nh_root
);
276 /* create cross connect */
277 /* send label mapping */
278 nh
= MPLS_LIST_NEXT(&addr
->nh_root
, nh
, _addr
);
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");
303 ldp_addr_process_end
:
305 LDP_EXIT(g
->user_data
, "ldp_addr_process-error");