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
10 #include "ldp_struct.h"
14 #include "ldp_pdu_setup.h"
15 #include "ldp_notif.h"
16 #include "ldp_session.h"
17 #include "ldp_entity.h"
18 #include "ldp_label_mapping.h"
19 #include "ldp_label_request.h"
21 #include "mpls_timer_impl.h"
22 #include "mpls_policy_impl.h"
23 #include "mpls_tree_impl.h"
24 #include "mpls_trace_impl.h"
25 #include "mpls_fib_impl.h"
26 #include "mpls_lock_impl.h"
28 mpls_return_enum
ldp_label_request_for_xc(ldp_global
* g
, ldp_session
* s
,
29 mpls_fec
* fec
, ldp_attr
* us_attr
, ldp_attr
** ds_attr
)
32 LDP_ENTER(g
->user_data
, "ldp_label_request_for_xc");
35 if (!((*ds_attr
) = ldp_attr_create(g
, fec
))) {
38 MPLS_REFCNT_HOLD((*ds_attr
));
40 Prepare_Label_Request_Attributes(g
, s
, fec
, (*ds_attr
), us_attr
);
41 (*ds_attr
)->state
= LDP_LSP_STATE_REQ_SENT
;
42 if (ldp_label_request_send(g
, s
, us_attr
, ds_attr
) != MPLS_SUCCESS
) {
46 LDP_EXIT(g
->user_data
, "ldp_label_request_for_xc");
51 void ldp_label_request_prepare_msg(ldp_mesg
* msg
, uint32_t msgid
,
54 mplsLdpLblReqMsg_t
*req
= NULL
;
57 ldp_mesg_prepare(msg
, MPLS_LBLREQ_MSGTYPE
, msgid
);
58 req
= &msg
->u
.request
;
60 if (s_attr
->fecTlvExists
) {
61 req
->fecTlvExists
= 1;
62 req
->baseMsg
.msgLength
+= setupFecTlv(&req
->fecTlv
);
63 req
->baseMsg
.msgLength
+= addFecElem2FecTlv(&req
->fecTlv
,
64 &s_attr
->fecTlv
.fecElArray
[0]);
66 if (s_attr
->hopCountTlvExists
) {
67 req
->hopCountTlvExists
= 1;
68 req
->baseMsg
.msgLength
+= setupHopCountTlv(&req
->hopCountTlv
,
69 s_attr
->hopCountTlv
.hcValue
);
71 if (s_attr
->pathVecTlvExists
) {
72 req
->pathVecTlvExists
= 1;
73 req
->baseMsg
.msgLength
+= setupPathTlv(&req
->pathVecTlv
);
74 for (i
= 0; i
< MPLS_MAXHOPSNUMBER
; i
++) {
75 if (s_attr
->pathVecTlv
.lsrId
[i
]) {
76 req
->baseMsg
.msgLength
+= addLsrId2PathTlv(&req
->pathVecTlv
,
77 s_attr
->pathVecTlv
.lsrId
[i
]);
83 mpls_return_enum
ldp_label_request_send(ldp_global
* g
, ldp_session
* s
,
84 ldp_attr
* us_attr
, ldp_attr
** ds_attr
)
89 LDP_ENTER(g
->user_data
, "ldp_label_request_send");
90 MPLS_ASSERT(ds_attr
&& *ds_attr
);
92 fec_tlv2mpls_fec(&((*ds_attr
)->fecTlv
), 0, &fec
);
94 if ((ds_temp
= ldp_attr_find_downstream_state(g
, s
, &fec
,
95 LDP_LSP_STATE_REQ_SENT
)) != NULL
) { /* SLRq.1 */
97 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
98 "Label Request Send: request already pending(%d)\n", ds_temp
->index
);
100 ldp_attr_add_us2ds(us_attr
, ds_temp
);
102 /* we do not need the one passed in, but make sure that the caller
103 is using this one from here forth */
104 ldp_attr_remove_complete(g
, *ds_attr
, MPLS_BOOL_TRUE
);
109 if (s
->no_label_resource_recv
== MPLS_BOOL_TRUE
) { /* SLRq.2 */
110 goto ldp_label_request_send_error
;
113 (*ds_attr
)->msg_id
= g
->message_identifier
++;
114 ldp_label_request_prepare_msg(s
->tx_message
, (*ds_attr
)->msg_id
, *ds_attr
);
116 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
117 "Label Request Sent: session(%d)\n", s
->index
);
119 if (ldp_mesg_send_tcp(g
, s
, s
->tx_message
) == MPLS_FAILURE
) { /* SLRq.3 */
120 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ERROR
,
121 "Label Request send failed\n");
122 goto ldp_label_request_send_error
;
125 (*ds_attr
)->state
= LDP_LSP_STATE_REQ_SENT
;
126 if (ldp_attr_insert_downstream(g
, s
, (*ds_attr
)) == MPLS_FAILURE
) { /* SLRq.4 */
127 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ERROR
,
128 "Couldn't insert sent attributes in tree\n");
129 goto ldp_label_request_send_error
;
132 ldp_attr_add_us2ds(us_attr
, *ds_attr
);
135 LDP_EXIT(g
->user_data
, "ldp_label_request_send");
137 return MPLS_SUCCESS
; /* SLRq.5 */
139 ldp_label_request_send_error
:
141 LDP_PRINT(g
->user_data
, "SLRq.6\n");
142 (*ds_attr
)->state
= LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT
;
143 ldp_attr_insert_downstream(g
, s
, (*ds_attr
)); /* SLRq.6 */
145 LDP_EXIT(g
->user_data
, "ldp_label_request_send-error");
147 return MPLS_FAILURE
; /* SLRq.7 */
150 void req2attr(mplsLdpLblReqMsg_t
* req
, ldp_attr
* attr
, uint32_t flag
)
152 attr
->msg_id
= req
->baseMsg
.msgId
;
154 if (req
->fecTlvExists
&& flag
& LDP_ATTR_FEC
) {
155 memcpy(&attr
->fecTlv
, &req
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
156 attr
->fecTlvExists
= 1;
158 if (req
->hopCountTlvExists
&& flag
& LDP_ATTR_HOPCOUNT
) {
159 memcpy(&attr
->hopCountTlv
, &req
->hopCountTlv
, sizeof(mplsLdpHopTlv_t
));
160 attr
->hopCountTlvExists
= 1;
162 if (req
->pathVecTlvExists
&& flag
& LDP_ATTR_PATH
) {
163 memcpy(&attr
->pathVecTlv
, &req
->pathVecTlv
, sizeof(mplsLdpPathTlv_t
));
164 attr
->pathVecTlvExists
= 1;
166 if (req
->lblMsgIdTlvExists
&& flag
& LDP_ATTR_MSGID
) {
167 memcpy(&attr
->lblMsgIdTlv
, &req
->lblMsgIdTlv
, sizeof(mplsLdpLblMsgIdTlv_t
));
168 attr
->lblMsgIdTlvExists
= 1;
170 if (req
->lspidTlvExists
&& flag
& LDP_ATTR_LSPID
) {
171 memcpy(&attr
->lspidTlv
, &req
->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
172 attr
->lspidTlvExists
= 1;
174 if (req
->trafficTlvExists
&& flag
& LDP_ATTR_TRAFFIC
) {
175 memcpy(&attr
->trafficTlv
, &req
->trafficTlv
, sizeof(mplsLdpTrafficTlv_t
));
176 attr
->trafficTlvExists
= 1;
180 void ldp_label_request_initial_callback(mpls_timer_handle timer
, void *extra
,
181 mpls_cfg_handle handle
)
183 ldp_session
*s
= (ldp_session
*)extra
;
184 ldp_global
*g
= (ldp_global
*)handle
;
185 ldp_nexthop
*nh
= NULL
;
188 ldp_session
*nh_session
= NULL
;
189 mpls_bool done
= MPLS_BOOL_FALSE
;
191 ldp_attr
*attr
= NULL
;
193 ldp_attr
*ds_attr
= NULL
;
195 LDP_ENTER(g
->user_data
, "ldp_label_request_initial_callback");
197 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_TIMER
,
198 "Initial Label Request Callback fired: session(%d)\n", s
->index
);
200 mpls_lock_get(g
->global_lock
);
202 mpls_timer_stop(g
->timer_handle
, timer
);
204 if ((f
= MPLS_LIST_HEAD(&g
->fec
))) {
206 if ((nh
= MPLS_LIST_HEAD(&f
->nh_root
))) {
208 switch (f
->info
.type
) {
209 case MPLS_FEC_PREFIX
:
210 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
211 LDP_TRACE_FLAG_ROUTE
, "Processing prefix FEC: %08x/%d ",
212 f
->info
.u
.prefix
.network
.u
.ipv4
, f
->info
.u
.prefix
.length
);
215 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
216 LDP_TRACE_FLAG_ROUTE
, "Processing host FEC: %08x ",
217 f
->info
.u
.host
.u
.ipv4
);
220 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
221 LDP_TRACE_FLAG_ROUTE
, "Processing L2CC FEC: %d %d %d ",
222 f
->info
.u
.l2cc
.connection_id
, f
->info
.u
.l2cc
.group_id
,
223 f
->info
.u
.l2cc
.type
);
229 if (nh
->info
.type
& MPLS_NH_IP
) {
230 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
231 LDP_TRACE_FLAG_ROUTE
, "via %08x\n", nh
->addr
->address
.u
.ipv4
);
233 if (nh
->info
.type
& MPLS_NH_IF
) {
234 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
235 LDP_TRACE_FLAG_ROUTE
, "via %p\n", nh
->iff
->handle
);
238 /* check to see if export policy allows us to 'see' this route */
239 if (mpls_policy_export_check(g
->user_data
, &f
->info
, &nh
->info
)
240 == MPLS_BOOL_FALSE
) {
241 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
242 LDP_TRACE_FLAG_DEBUG
, "Rejected by export policy\n");
246 /* find the next hop session corresponding to this FEC */
247 nh_session
= ldp_session_for_nexthop(nh
);
249 /* do we have a valid next hop session, and is the nexp hop session
251 if ((!nh_session
) || (nh_session
->index
!= s
->index
)) {
255 /* have we already sent a label request to this peer for this FEC? */
256 if (ldp_attr_find_downstream_state(g
, s
, &f
->info
,
257 LDP_LSP_STATE_REQ_SENT
)) {
261 /* clear out info from the last FEC */
264 /* jleu: duplicate code from ldp_attr_find_upstream_state_any */
265 fs
= MPLS_LIST_HEAD(&f
->fs_root_us
);
267 attr
= MPLS_LIST_HEAD(&fs
->attr_root
);
269 if (attr
->state
== LDP_LSP_STATE_REQ_RECV
||
270 attr
->state
== LDP_LSP_STATE_MAP_SENT
) {
272 /* this is not neccessarily going to be XC'd to something */
273 ldp_label_request_for_xc(g
, s
, &f
->info
, attr
, &ds_attr
);
276 attr
= MPLS_LIST_NEXT(&fs
->attr_root
, attr
, _fs
);
278 fs
= MPLS_LIST_NEXT(&f
->fs_root_us
, fs
, _fec
);
283 * we did not find any received requests or sent mappings so
284 * send a request and xc it to nothing
286 ldp_label_request_for_xc(g
, s
, &f
->info
, NULL
, &ds_attr
);
288 } while ((nh
= MPLS_LIST_NEXT(&f
->nh_root
, nh
, _fec
)));
290 } while ((f
= MPLS_LIST_NEXT(&g
->fec
, f
, _global
)));
291 done
= MPLS_BOOL_TRUE
;
294 if (done
== MPLS_BOOL_TRUE
) {
295 mpls_timer_delete(g
->timer_handle
, timer
);
296 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
297 s
->initial_distribution_timer
= (mpls_timer_handle
) 0;
299 mpls_timer_start(g
->timer_handle
, timer
, MPLS_TIMER_ONESHOT
);
300 /* need to mark the session with where it left off */
303 mpls_lock_release(g
->global_lock
);
305 LDP_EXIT(g
->user_data
, "ldp_label_request_initial_callback");
308 void Prepare_Label_Request_Attributes(ldp_global
* g
, ldp_session
* s
,
309 mpls_fec
* fec
, ldp_attr
* r_attr
, ldp_attr
* s_attr
)
313 MPLS_ASSERT(s
&& r_attr
);
315 if (!(s
->oper_loop_detection
== LDP_LOOP_HOPCOUNT
||
316 s
->oper_loop_detection
== LDP_LOOP_HOPCOUNT_PATHVECTOR
||
317 r_attr
->hopCountTlvExists
)) { /* PRqA.1 */
321 /* is this LSR allowed to be an LER for FEC? *//* PRqA.2 */
322 /* some policy gunk needs to be checked here */
323 /* if not goto PRqA.6 */
325 s_attr
->hopCountTlvExists
= 1; /* PRqA.3 */
326 s_attr
->hopCountTlv
.hcValue
= 1;
328 if (s
->oper_loop_detection
== LDP_LOOP_NONE
) { /* PRqA.4 */
332 if (g
->label_merge
== MPLS_BOOL_TRUE
) { /* PRqA.5 */
335 goto Prepare_Label_Request_Attributes_13
;
337 if (r_attr
&& r_attr
->hopCountTlvExists
) { /* PRqA.6 */
338 s_attr
->hopCountTlvExists
= 1; /* PRqA.7 */
339 s_attr
->hopCountTlv
.hcValue
= (r_attr
->hopCountTlv
.hcValue
) ?
340 (r_attr
->hopCountTlv
.hcValue
+ 1) : 0;
342 s_attr
->hopCountTlvExists
= 1; /* PRqA.8 */
343 s_attr
->hopCountTlv
.hcValue
= 0;
346 if (s
->oper_loop_detection
== LDP_LOOP_NONE
) { /* PRqA.9 */
350 if (r_attr
&& r_attr
->pathVecTlvExists
) { /* PRqA.10 */
351 goto Prepare_Label_Request_Attributes_12
;
354 if (g
->label_merge
== MPLS_BOOL_TRUE
) { /* PRqA.11 */
357 goto Prepare_Label_Request_Attributes_13
;
359 Prepare_Label_Request_Attributes_12
:
360 /* we only get to PRqA.12 if we have verified we have a r_attr */
361 s_attr
->pathVecTlvExists
= 1;
362 s_attr
->pathVecTlv
.lsrId
[0] = g
->lsr_identifier
.u
.ipv4
;
363 for (i
= 1; i
< (MPLS_MAXHOPSNUMBER
- 1); i
++) {
364 if (r_attr
->pathVecTlv
.lsrId
[i
- 1]) {
365 s_attr
->pathVecTlv
.lsrId
[i
] = r_attr
->pathVecTlv
.lsrId
[i
- 1];
370 Prepare_Label_Request_Attributes_13
:
371 s_attr
->pathVecTlvExists
= 1;
372 s_attr
->pathVecTlv
.lsrId
[0] = g
->lsr_identifier
.u
.ipv4
;
375 mpls_return_enum
ldp_label_request_process(ldp_global
* g
, ldp_session
* s
,
376 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* us_attr
, ldp_fec
* f
)
378 ldp_session
*nh_session
= NULL
;
379 ldp_nexthop
*nh
= NULL
;
380 ldp_attr_list
*us_list
= NULL
;
381 mpls_bool egress
= MPLS_BOOL_FALSE
;
382 mpls_bool egress_flag
= MPLS_BOOL_FALSE
;
383 ldp_attr
*ds_attr
= NULL
;
384 ldp_attr
*us_temp
= NULL
;
386 if (Check_Received_Attributes(g
, s
, us_attr
, MPLS_LBLREQ_MSGTYPE
) !=
387 MPLS_SUCCESS
) { /* LRp.1 */
392 ldp_notif_send(g
, s
, us_attr
, LDP_NOTIF_NO_ROUTE
); /* LRq.5 */
396 /* just find one valid nexthop session for now */
397 nh
= MPLS_LIST_HEAD(&f
->nh_root
);
400 nh_session
= ldp_session_for_nexthop(nh
);
402 if (egress_flag
== MPLS_BOOL_FALSE
) {
403 egress_flag
= mpls_policy_egress_check(g
->user_data
, &f
->info
, &nh
->info
);
405 nh
= MPLS_LIST_NEXT(&f
->nh_root
, nh
, _fec
);
408 if ((!nh_session
) && (egress_flag
== MPLS_BOOL_TRUE
)) {
409 egress
= MPLS_BOOL_TRUE
;
411 if (nh_session
!= NULL
&& s
->index
== nh_session
->index
) { /* LRq.3 */
412 ldp_notif_send(g
, s
, us_attr
, LDP_NOTIF_LOOP_DETECTED
); /* LRq.4 */
416 if ((us_list
= ldp_attr_find_upstream_all2(g
, s
, f
)) != NULL
) {
417 us_temp
= MPLS_LIST_HEAD(us_list
);
418 while (us_temp
!= NULL
) {
419 if (us_temp
->state
== LDP_LSP_STATE_REQ_RECV
&& /* LRq.6 */
420 us_temp
->msg_id
== us_attr
->msg_id
) { /* LRq.7 */
423 us_temp
= MPLS_LIST_NEXT(us_list
, us_temp
, _fs
);
427 us_attr
->state
= LDP_LSP_STATE_REQ_RECV
; /* LRq.8 */
429 if (ldp_attr_insert_upstream2(g
, s
, us_attr
, f
) != MPLS_SUCCESS
) {
430 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_ERROR
,
431 "Couldn't insert recv attributes in tree\n");
432 goto ldp_label_request_process_error
;
436 ds_attr
= ldp_attr_find_downstream_state2(g
, nh_session
, f
,
437 LDP_LSP_STATE_MAP_RECV
);
442 if (g
->lsp_control_mode
== LDP_CONTROL_INDEPENDENT
) { /* LRq.9 */
443 if (ldp_label_mapping_with_xc(g
, s
, f
, &us_attr
, ds_attr
) != MPLS_SUCCESS
) {
444 goto ldp_label_request_process_error
;
447 if (egress
== MPLS_BOOL_TRUE
|| ds_attr
) {
451 if ((!(egress
== MPLS_BOOL_TRUE
|| ds_attr
)) ||
452 (g
->label_merge
== MPLS_BOOL_FALSE
)) {
456 if (ldp_label_mapping_with_xc(g
, s
, f
, &us_attr
, ds_attr
) != MPLS_SUCCESS
) {
457 goto ldp_label_request_process_error
;
464 if (ldp_label_request_for_xc(g
, nh_session
, &f
->info
, us_attr
, &ds_attr
) !=
466 goto ldp_label_request_process_error
;
470 /* the work done by LRq_11 is handled in ldp_label_mapping_with_xc() */
472 if (ds_attr
!= NULL
&& ds_attr
->in_tree
== MPLS_BOOL_FALSE
) {
473 ldp_attr_remove_complete(g
, ds_attr
, MPLS_BOOL_FALSE
);
477 ldp_label_request_process_error
: