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"
11 #include "ldp_session.h"
15 #include "ldp_notif.h"
16 #include "ldp_entity.h"
17 #include "ldp_inlabel.h"
18 #include "ldp_outlabel.h"
19 #include "ldp_global.h"
20 #include "ldp_pdu_setup.h"
21 #include "ldp_label_rel_with.h"
22 #include "ldp_label_mapping.h"
23 #include "ldp_label_request.h"
25 #include "mpls_timer_impl.h"
26 #include "mpls_fib_impl.h"
27 #include "mpls_lock_impl.h"
28 #include "mpls_tree_impl.h"
29 #include "mpls_trace_impl.h"
30 #include "mpls_mm_impl.h"
31 #include "mpls_policy_impl.h"
36 #include "mpls_mpls_impl.h"
39 mpls_return_enum
ldp_label_mapping_with_xc(ldp_global
* g
, ldp_session
* s
,
40 mpls_fec
* fec
, ldp_attr
** us_attr
, ldp_attr
* ds_attr
)
42 mpls_return_enum result
;
43 mpls_bool propogating
= MPLS_BOOL_TRUE
;
49 if (!((*us_attr
) = ldp_attr_create(fec
))) {
54 propogating
= MPLS_BOOL_FALSE
;
57 Prepare_Label_Mapping_Attributes(g
, s
, fec
, ds_attr
, (*us_attr
), propogating
,
59 if (ldp_label_mapping_send(g
, s
, (*us_attr
), ds_attr
) != MPLS_SUCCESS
) {
60 if ((*us_attr
)->in_tree
!= MPLS_BOOL_TRUE
) {
61 ldp_attr_delete(*us_attr
);
66 if (ds_attr
&& ds_attr
->outlabel
) {
68 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
69 LDP_TRACE_FLAG_BINDING
, "Cross Connect Added\n");
71 result
= ldp_inlabel_add_outlabel(g
,(*us_attr
)->inlabel
,ds_attr
->outlabel
);
72 if (result
!= MPLS_SUCCESS
) {
73 ldp_label_withdraw_send(g
, s
, (*us_attr
), LDP_NOTIF_NONE
);
80 ldp_session
*ldp_get_session_by_next_hop(ldp_global
* g
, mpls_nexthop
* a
,
83 ldp_addr
*addr
= NULL
;
86 if (a
->type
& MPLS_NH_IP
) {
88 } else if (a
->type
& MPLS_NH_IF
) {
89 ldp_if
*iff
= ldp_global_find_if_handle(g
, a
->if_handle
);
93 /* JLEU if there is more then one session on this interface
94 then we're in trouble, just choose the first for now */
98 a
= MPLS_LIST_HEAD(&iff
->entity
->adj_root
);
105 if (mpls_tree_get(g
->addr_tree
, key
, 32, (void **)&addr
) == MPLS_SUCCESS
) {
106 ldp_session
*ses
= NULL
;
108 /* JLEU if there is more then one session that has given this address
109 then we're in trouble, just choose the first for now */
110 if ((ses
= (ldp_session
*)mpls_link_list_head_data(&addr
->session_root
))) {
120 mpls_return_enum
ldp_get_next_hop_session_for_fec(ldp_global
* g
,
121 mpls_fec
* fec
, ldp_addr
** next_hop
, ldp_session
** next_hop_session
)
123 ldp_session
*session
= NULL
;
124 ldp_addr
*addr
= NULL
;
127 if (next_hop_session
) {
128 *next_hop_session
= NULL
;
134 if (mpls_fib_get_route(g
->fib_handle
, 1, fec
, &route
) != 1) {
135 /* JLEU: how to handle the multipath case */
136 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_NORMAL
,
137 "No route to FEC (%08x/%d)\n", fec
->u
.prefix
.network
.u
.ipv4
,
138 fec
->u
.prefix
.length
);
139 return MPLS_NO_ROUTE
;
142 if (route
.nh
.attached
== MPLS_BOOL_TRUE
) {
146 if (!(session
= ldp_get_session_by_next_hop(g
, &route
.nh
, &addr
))) {
150 if (next_hop_session
) {
151 *next_hop_session
= session
;
159 mpls_return_enum
Check_Received_Attributes(ldp_global
* g
, ldp_session
* s
,
160 ldp_attr
* r_attr
, uint16_t type
)
165 if (!r_attr
->hopCountTlvExists
) { /* CRa.1 */
166 goto Check_Received_Attributes_5
;
169 if (r_attr
->hopCountTlv
.hcValue
>= s
->cfg_hop_count_limit
) { /* CRa.2 */
170 LDP_PRINT(g
->user_data
, "CRa.2\n");
171 goto Check_Received_Attributes_6
;
174 if (!r_attr
->pathVecTlvExists
) { /* CRa.3 */
175 goto Check_Received_Attributes_5
;
178 for (i
= 0; i
< MPLS_MAXHOPSNUMBER
; i
++) { /* CRa.4 */
179 if (r_attr
->pathVecTlv
.lsrId
[i
]) {
181 if (r_attr
->pathVecTlv
.lsrId
[i
] == g
->lsr_identifier
.u
.ipv4
) {
182 goto Check_Received_Attributes_6
;
183 LDP_PRINT(g
->user_data
, "CRa.4a\n");
185 if (count
> s
->oper_path_vector_limit
) {
186 goto Check_Received_Attributes_6
;
187 LDP_PRINT(g
->user_data
, "CRa.4b\n");
192 Check_Received_Attributes_5
:
195 Check_Received_Attributes_6
:
196 if (type
!= MPLS_LBLMAP_MSGTYPE
) {
197 ldp_notif_send(g
, s
, r_attr
, LDP_NOTIF_LOOP_DETECTED
); /* CRa.7 */
199 return MPLS_FAILURE
; /* CRa.8 */
202 void Prepare_Label_Mapping_Attributes(ldp_global
* g
, ldp_session
* s
,
203 mpls_fec
* fec
, ldp_attr
* r_attr
, ldp_attr
* s_attr
, mpls_bool propogating
,
209 /* NOTE: PMpA.21 is the end of the procedure (ie return) */
210 /* this function uses goto quite extensivly for a REASON!! */
211 /* Check Appedix A of the LDP draft */
213 LDP_ENTER(g
->user_data
, "Prepare_Label_Mapping_Attributes");
215 if (r_attr
== NULL
) {
216 memset(&dummy
, 0, sizeof(ldp_attr
));
217 mpls_fec2fec_tlv(fec
, &dummy
.fecTlv
, 0);
218 dummy
.fecTlvExists
= 1;
219 dummy
.fecTlv
.numberFecElements
= 1;
223 if (!(s
->oper_loop_detection
== LDP_LOOP_HOPCOUNT
||
224 s
->oper_loop_detection
== LDP_LOOP_HOPCOUNT_PATHVECTOR
||
225 r_attr
->hopCountTlvExists
)) { /* PMpA.1 */
226 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
230 switch (ldp_get_next_hop_session_for_fec(g
, fec
, NULL
, NULL
)) { /* PMpA.2 */
237 /* I'm egress (for now) */
238 s_attr
->hopCountTlvExists
= 1;
239 s_attr
->hopCountTlv
.hcValue
= 1; /* PMpA.3 */
240 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
250 if (!(r_attr
->hopCountTlvExists
)) { /* PMpA.4 */
251 goto Prepare_Label_Mapping_Attributes_8
;
254 if (!(g
->ttl_less_domain
== MPLS_BOOL_TRUE
&&
255 s
->cfg_remote_in_ttl_less_domain
== MPLS_BOOL_TRUE
)) { /* PMpA.5 */
256 goto Prepare_Label_Mapping_Attributes_7
;
259 s_attr
->hopCountTlvExists
= 1;
260 s_attr
->hopCountTlv
.hcValue
= 1; /* PMpA.6 */
261 goto Prepare_Label_Mapping_Attributes_9
;
263 Prepare_Label_Mapping_Attributes_7
:
264 s_attr
->hopCountTlvExists
= 1;
265 s_attr
->hopCountTlv
.hcValue
= (r_attr
->hopCountTlv
.hcValue
) ?
266 (r_attr
->hopCountTlv
.hcValue
+ 1) : 0;
267 goto Prepare_Label_Mapping_Attributes_9
;
269 Prepare_Label_Mapping_Attributes_8
:
270 s_attr
->hopCountTlvExists
= 1;
271 s_attr
->hopCountTlv
.hcValue
= 0;
273 Prepare_Label_Mapping_Attributes_9
:
274 if (s
->oper_loop_detection
== LDP_LOOP_NONE
) {
275 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
279 if (r_attr
->pathVecTlvExists
) { /* PMpA.10 */
280 goto Prepare_Label_Mapping_Attributes_19
;
283 if (propogating
== MPLS_BOOL_FALSE
) { /* PMpA.11 */
284 goto Prepare_Label_Mapping_Attributes_20
;
287 if (g
->label_merge
!= MPLS_BOOL_TRUE
) { /* PMpA.12 */
288 goto Prepare_Label_Mapping_Attributes_14
;
291 if (already
== MPLS_BOOL_FALSE
) { /* PMpA.13 */
292 goto Prepare_Label_Mapping_Attributes_20
;
295 Prepare_Label_Mapping_Attributes_14
:
296 if (!r_attr
->hopCountTlvExists
) {
297 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
301 if (r_attr
->hopCountTlv
.hcValue
== 0) { /* PMpA.15 */
302 goto Prepare_Label_Mapping_Attributes_20
;
305 if (already
== MPLS_BOOL_FALSE
) { /* PMpA.16 */
306 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
310 /* r_attr contain PrevHopCount _IF_ we had one */
311 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
312 return; /* PMpA.17 */
314 if (r_attr
->hopCountTlv
.hcValue
!= 0) { /* PMpA.18 */
315 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
319 Prepare_Label_Mapping_Attributes_19
:
320 s_attr
->pathVecTlvExists
= 1;
321 s_attr
->pathVecTlv
.lsrId
[0] = g
->lsr_identifier
.u
.ipv4
;
322 for (i
= 1; i
< (MPLS_MAXHOPSNUMBER
- 1); i
++) {
323 if (r_attr
->pathVecTlv
.lsrId
[i
- 1]) {
324 s_attr
->pathVecTlv
.lsrId
[0] = r_attr
->pathVecTlv
.lsrId
[i
- 1];
328 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
331 Prepare_Label_Mapping_Attributes_20
:
332 s_attr
->pathVecTlvExists
= 1;
333 s_attr
->pathVecTlv
.lsrId
[0] = g
->lsr_identifier
.u
.ipv4
;
335 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
339 void map2attr(mplsLdpLblMapMsg_t
* map
, ldp_attr
* attr
, uint32_t flag
)
341 attr
->msg_id
= map
->baseMsg
.msgId
;
343 if (map
->fecTlvExists
&& flag
& LDP_ATTR_FEC
) {
344 memcpy(&attr
->fecTlv
, &map
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
345 attr
->fecTlvExists
= 1;
347 if (map
->genLblTlvExists
&& flag
& LDP_ATTR_LABEL
) {
348 memcpy(&attr
->genLblTlv
, &map
->genLblTlv
, sizeof(mplsLdpGenLblTlv_t
));
349 attr
->genLblTlvExists
= 1;
350 } else if (map
->atmLblTlvExists
&& flag
& LDP_ATTR_LABEL
) {
351 memcpy(&attr
->atmLblTlv
, &map
->atmLblTlv
, sizeof(mplsLdpAtmLblTlv_t
));
352 attr
->atmLblTlvExists
= 1;
353 } else if (map
->frLblTlvExists
&& flag
& LDP_ATTR_LABEL
) {
354 memcpy(&attr
->frLblTlv
, &map
->frLblTlv
, sizeof(mplsLdpFrLblTlv_t
));
355 attr
->frLblTlvExists
= 1;
357 if (map
->hopCountTlvExists
&& flag
& LDP_ATTR_HOPCOUNT
) {
358 memcpy(&attr
->hopCountTlv
, &map
->hopCountTlv
, sizeof(mplsLdpHopTlv_t
));
359 attr
->hopCountTlvExists
= 1;
361 if (map
->pathVecTlvExists
&& flag
& LDP_ATTR_PATH
) {
362 memcpy(&attr
->pathVecTlv
, &map
->pathVecTlv
, sizeof(mplsLdpPathTlv_t
));
363 attr
->pathVecTlvExists
= 1;
365 if (map
->lblMsgIdTlvExists
&& flag
& LDP_ATTR_MSGID
) {
366 memcpy(&attr
->lblMsgIdTlv
, &map
->lblMsgIdTlv
, sizeof(mplsLdpLblMsgIdTlv_t
));
367 attr
->lblMsgIdTlvExists
= 1;
369 if (map
->lspidTlvExists
&& flag
& LDP_ATTR_LSPID
) {
370 memcpy(&attr
->lspidTlv
, &map
->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
371 attr
->lspidTlvExists
= 1;
373 if (map
->trafficTlvExists
&& flag
& LDP_ATTR_TRAFFIC
) {
374 memcpy(&attr
->trafficTlv
, &map
->trafficTlv
, sizeof(mplsLdpTrafficTlv_t
));
375 attr
->trafficTlvExists
= 1;
379 void attr2map(ldp_attr
* attr
, mplsLdpLblMapMsg_t
* map
)
381 if (attr
->fecTlvExists
) {
382 memcpy(&map
->fecTlv
, &attr
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
383 map
->fecTlvExists
= 1;
385 if (attr
->genLblTlvExists
) {
386 memcpy(&map
->genLblTlv
, &attr
->genLblTlv
, sizeof(mplsLdpGenLblTlv_t
));
387 map
->genLblTlvExists
= 1;
389 if (attr
->atmLblTlvExists
) {
390 memcpy(&map
->atmLblTlv
, &attr
->atmLblTlv
, sizeof(mplsLdpAtmLblTlv_t
));
391 map
->atmLblTlvExists
= 1;
393 if (attr
->frLblTlvExists
) {
394 memcpy(&map
->frLblTlv
, &attr
->frLblTlv
, sizeof(mplsLdpFrLblTlv_t
));
395 map
->frLblTlvExists
= 1;
397 if (attr
->hopCountTlvExists
) {
398 memcpy(&map
->hopCountTlv
, &attr
->hopCountTlv
, sizeof(mplsLdpHopTlv_t
));
399 map
->hopCountTlvExists
= 1;
401 if (attr
->pathVecTlvExists
) {
402 memcpy(&map
->pathVecTlv
, &attr
->pathVecTlv
, sizeof(mplsLdpPathTlv_t
));
403 map
->pathVecTlvExists
= 1;
405 if (attr
->lblMsgIdTlvExists
) {
406 memcpy(&map
->lblMsgIdTlv
, &attr
->lblMsgIdTlv
, sizeof(mplsLdpLblMsgIdTlv_t
));
407 map
->lblMsgIdTlvExists
= 1;
409 if (attr
->lspidTlvExists
) {
410 memcpy(&map
->lspidTlv
, &attr
->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
411 map
->lspidTlvExists
= 1;
413 if (attr
->trafficTlvExists
) {
414 memcpy(&map
->trafficTlv
, &attr
->trafficTlv
, sizeof(mplsLdpTrafficTlv_t
));
415 map
->trafficTlvExists
= 1;
419 void ldp_label_mapping_initial_callback(mpls_timer_handle timer
, void *extra
,
420 mpls_cfg_handle handle
)
422 ldp_session
*s
= (ldp_session
*) extra
;
423 ldp_global
*g
= (ldp_global
*)handle
;
424 ldp_attr
*ds_attr
= NULL
;
425 ldp_attr
*us_attr
= NULL
;
426 ldp_addr
*nh_addr
= NULL
;
427 ldp_session
*nh_session
= NULL
;
428 mpls_bool done
= MPLS_BOOL_FALSE
;
430 mpls_return_enum result
;
432 LDP_ENTER(g
->user_data
, "ldp_label_mapping_initial_callback");
434 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_TIMER
,
435 "Initial Label Mapping fired: session(%d)\n", s
->index
);
437 mpls_lock_get(g
->global_lock
);
439 mpls_timer_stop(g
->timer_handle
, timer
);
441 if (mpls_fib_getfirst_route(g
->fib_handle
, &dest
) == MPLS_SUCCESS
) {
444 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_ROUTE
,
445 "Processing: %08x/%d ", dest
.u
.prefix
.network
.u
.ipv4
,
446 dest
.u
.prefix
.length
);
448 if (dest
.nh
.type
& MPLS_NH_IP
) {
449 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
450 LDP_TRACE_FLAG_ROUTE
, "via %08x\n", dest
.nh
.ip
.u
.ipv4
);
451 } else if (dest
.nh
.type
& MPLS_NH_IF
) {
452 struct ldp_if
*iff
= ldp_global_find_if_handle(g
,dest
.nh
.if_handle
);
453 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
454 LDP_TRACE_FLAG_ROUTE
, "via %s\n",
455 iff
? iff
->name
: "(not an LDP interface)\n");
460 /* are we allowed to export this route from the rib */
461 if (mpls_policy_export_check(g
->user_data
, &dest
, &dest
.nh
) ==
463 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_POLICY
,
464 "Rejected by export policy\n");
468 /* have we already sent a mapping for this fec to the new session? */
469 if ((us_attr
= ldp_attr_find_upstream_state(g
, s
, &dest
,
470 LDP_LSP_STATE_MAP_SENT
))) {
471 /* no need to sent another mapping */
472 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_ROUTE
,
473 "Already sent this FEC to session %d\n", s
->index
);
477 result
= ldp_get_next_hop_session_for_fec(g
,&dest
,&nh_addr
,&nh_session
);
478 if (result
!= MPLS_SUCCESS
|| !nh_session
) {
481 if (nh_session
->index
== s
->index
) {
482 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
483 LDP_TRACE_FLAG_ROUTE
, "Nexthop session(%d) == session(%d)\n",
484 nh_session
->index
, s
->index
);
487 ds_attr
= ldp_attr_find_downstream_state(g
, nh_session
, &dest
,
488 LDP_LSP_STATE_MAP_RECV
);
491 if ((g
->label_merge
!= MPLS_BOOL_TRUE
) && ldp_attr_num_us2ds(ds_attr
)) {
492 /* we have a ds label, but can't use it */
498 /* we can use it, merge on baby */
499 ldp_label_mapping_with_xc(g
, s
, &dest
, &us_attr
, ds_attr
);
501 /* we don't have a ds label */
503 /* we will be egress? */
504 if (g
->lsp_control_mode
== LDP_CONTROL_ORDERED
) {
505 if (mpls_policy_egress_check(g
->user_data
, &dest
, &dest
.nh
) ==
507 ldp_label_mapping_with_xc(g
, s
, &dest
, &us_attr
, NULL
);
510 ldp_label_mapping_with_xc(g
, s
, &dest
, &us_attr
, NULL
);
514 /* why the hell are we requesting labels? this callback is only
517 if (nh_session
&& nh_session
->oper_distribution_mode
==
518 LDP_DISTRIBUTION_ONDEMAND
) {
519 ldp_label_request_for_xc(g
, nh_session
, &dest
, us_attr
, &ds_attr
);
523 } while (mpls_fib_getnext_route(g
->fib_handle
, &dest
) == MPLS_SUCCESS
);
524 done
= MPLS_BOOL_TRUE
;
527 done
= MPLS_BOOL_TRUE
;
529 if (done
== MPLS_BOOL_TRUE
) {
530 mpls_timer_delete(g
->timer_handle
, timer
);
531 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
532 s
->initial_distribution_timer
= (mpls_timer_handle
) 0;
534 mpls_timer_start(g
->timer_handle
, timer
, MPLS_TIMER_ONESHOT
);
535 /* need to mark the session with where it left off */
538 mpls_lock_release(g
->global_lock
);
540 LDP_EXIT(g
->user_data
, "ldp_label_mapping_initial_callback");
543 mpls_return_enum
ldp_label_mapping_send(ldp_global
* g
, ldp_session
* s
,
544 ldp_attr
* us_attr
, ldp_attr
* ds_attr
)
546 ldp_inlabel
*in
= NULL
;
550 LDP_ENTER(g
->user_data
, "ldp_label_mapping_send");
551 MPLS_ASSERT(us_attr
);
553 fec_tlv2mpls_fec(&us_attr
->fecTlv
, 0, &fec
);
555 if ((in
= ldp_inlabel_create_complete(g
, s
, us_attr
)) == NULL
) { /* SL.1-3 */
559 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_BINDING
,
562 us_attr
->state
= LDP_LSP_STATE_MAP_SENT
;
564 us_attr
->msg_id
= g
->message_identifier
;
565 ldp_label_mapping_prepare_msg(s
->tx_message
, g
->message_identifier
++,
568 if (us_attr
->in_tree
== MPLS_BOOL_FALSE
&&
569 ldp_attr_insert_upstream(g
, s
, us_attr
) != MPLS_SUCCESS
) { /* SL.5 */
570 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ERROR
,
571 "Couldn't insert sent attributes in tree\n");
572 goto ldp_label_mapping_send_error
;
575 if (ldp_mesg_send_tcp(g
, s
, s
->tx_message
) != MPLS_SUCCESS
) { /* SL.4 */
576 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ERROR
,
577 "Failed sending Label Mapping to %s\n",
579 goto ldp_label_mapping_send_error
;
582 ldp_attr_add_us2ds(us_attr
, ds_attr
);
584 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
585 "Label Mapping Sent to %s for %08x/%d\n",
587 us_attr
->fecTlv
.fecElArray
[0].addressEl
.address
,
588 us_attr
->fecTlv
.fecElArray
[0].addressEl
.preLen
);
590 us_attr
->state
= LDP_LSP_STATE_MAP_SENT
; /* SL.6,7 */
592 LDP_EXIT(g
->user_data
, "ldp_label_mapping_send");
593 return MPLS_SUCCESS
; /* SL.8 */
596 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_STATE
,
597 "No Label Resources\n");
599 while ((us_temp
= ldp_attr_find_upstream_state(g
, s
, &fec
,
600 LDP_LSP_STATE_REQ_RECV
)) != NULL
) { /* SL.9 */
601 ldp_notif_send(g
, s
, us_temp
, LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE
);
603 s
->no_label_resource_sent
= MPLS_BOOL_TRUE
; /* SL.12 */
604 us_temp
->state
= LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT
; /* SL.13 */
607 LDP_EXIT(g
->user_data
, "ldp_label_mapping_send");
611 ldp_label_mapping_send_error
:
613 LDP_EXIT(g
->user_data
, "ldp_label_mapping_send-error");
617 void ldp_label_mapping_prepare_msg(ldp_mesg
* msg
, uint32_t msgid
,
620 mplsLdpLblMapMsg_t
*map
= NULL
;
625 ldp_mesg_prepare(msg
, MPLS_LBLMAP_MSGTYPE
, msgid
);
628 if (s_attr
->fecTlvExists
) {
629 /* JLEU: only 1 FEC is allowed!! */
630 map
->fecTlvExists
= 1;
631 map
->baseMsg
.msgLength
+= setupFecTlv(&map
->fecTlv
);
632 map
->baseMsg
.msgLength
+= addFecElem2FecTlv(&map
->fecTlv
,
633 &s_attr
->fecTlv
.fecElArray
[0]);
635 if (s_attr
->genLblTlvExists
) {
636 map
->genLblTlvExists
= 1;
637 map
->baseMsg
.msgLength
+= setupGenLblTlv(&map
->genLblTlv
,
638 s_attr
->genLblTlv
.label
);
640 if (s_attr
->atmLblTlvExists
) {
641 map
->atmLblTlvExists
= 1;
642 map
->baseMsg
.msgLength
+= setupAtmLblTlv(&map
->atmLblTlv
, 0, 0,
643 s_attr
->atmLblTlv
.flags
.flags
.vpi
, s_attr
->atmLblTlv
.vci
);
645 if (s_attr
->frLblTlvExists
) {
646 map
->frLblTlvExists
= 1;
647 map
->baseMsg
.msgLength
+= setupFrLblTlv(&map
->frLblTlv
, 0,
648 s_attr
->frLblTlv
.flags
.flags
.len
, s_attr
->frLblTlv
.flags
.flags
.dlci
);
650 if (s_attr
->hopCountTlvExists
) {
651 map
->hopCountTlvExists
= 1;
652 map
->baseMsg
.msgLength
+= setupHopCountTlv(&map
->hopCountTlv
,
653 s_attr
->hopCountTlv
.hcValue
);
655 if (s_attr
->pathVecTlvExists
) {
656 map
->pathVecTlvExists
= 1;
657 map
->baseMsg
.msgLength
+= setupPathTlv(&map
->pathVecTlv
);
658 for (i
= 0; i
< MPLS_MAXHOPSNUMBER
; i
++) {
659 if (s_attr
->pathVecTlv
.lsrId
[i
]) {
660 map
->baseMsg
.msgLength
+= addLsrId2PathTlv(&map
->pathVecTlv
,
661 s_attr
->pathVecTlv
.lsrId
[i
]);
666 if (s_attr
->lblMsgIdTlvExists
) {
668 if (s_attr
->lspidTlvExists
) {
670 if (s_attr
->trafficTlvExists
) {
675 mpls_return_enum
ldp_label_mapping_process(ldp_global
* g
, ldp_session
* s
,
676 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
, mpls_fec
* fec
)
678 mpls_return_enum retval
= MPLS_SUCCESS
;
679 ldp_session
*nh_session
= NULL
;
680 ldp_session
*peer
= NULL
;
681 ldp_attr_list
*us_list
= NULL
;
682 ldp_attr_list
*ds_list
= NULL
;
683 ldp_attr
*ds_attr
= NULL
;
684 ldp_attr
*ds_temp
= NULL
;
685 ldp_attr
*us_attr
= NULL
;
686 ldp_attr
*us_temp
= NULL
;
689 ldp_outlabel
*out
= NULL
;
690 ldp_addr
*nh_addr
= NULL
;
691 mpls_bool requested
= MPLS_BOOL_FALSE
;
692 ldp_attr
*update
= NULL
;
693 mpls_bool need_request
= MPLS_BOOL_FALSE
;
694 mpls_return_enum result
;
696 LDP_ENTER(g
->user_data
, "ldp_label_mapping_process");
698 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
699 "Label Mapping Recv from %s for %08x/%d\n",
701 r_attr
->fecTlv
.fecElArray
[0].addressEl
.address
,
702 r_attr
->fecTlv
.fecElArray
[0].addressEl
.preLen
);
704 if ((ds_attr
= ldp_attr_find_downstream_state(g
, s
, fec
,
705 LDP_LSP_STATE_REQ_SENT
)) != NULL
) { /* LMp.1 */
706 /* just remove the req from the tree, we will use the r_attr sent to us */
707 ldp_attr_delete_downstream(g
, s
, ds_attr
);
708 requested
= MPLS_BOOL_TRUE
;
710 requested
= MPLS_BOOL_FALSE
;
714 ds_attr
->state
= LDP_LSP_STATE_MAP_RECV
; /* LMp.2 */
717 * ds_attr is the mapping we will keep and is NOT in the tree, unless
718 * it is an update mapping ...
720 if (Check_Received_Attributes(g
, s
, ds_attr
, MPLS_LBLMAP_MSGTYPE
) ==
721 MPLS_SUCCESS
) { /* LMp.3 */
726 * A loop was detected
728 if ((ds_list
= ldp_attr_find_downstream_all(g
, s
, fec
))) {
729 ds_temp
= MPLS_LIST_HEAD(ds_list
);
731 * check all the labels this session has received from "s" for "fec"
732 * do we have a duplicat?
735 if ((ds_temp
->state
== LDP_LSP_STATE_MAP_RECV
) && /* LMp.4 */
736 ldp_attr_is_equal(ds_temp
, ds_attr
, LDP_ATTR_LABEL
) == /* LMp.5 */
738 /* remove record of the label and remove it switching */
739 ldp_attr_remove_complete(g
, ds_temp
, MPLS_BOOL_TRUE
); /* LMp.6,7 */
741 * I think this is supposed to be 32 NOT 33, we need to release
746 ds_temp
= MPLS_LIST_NEXT(ds_list
, ds_temp
, _fs
);
750 LDP_PRINT(g
->user_data
, "Receive_Label_Map_8: send release");
751 if (ldp_label_release_send(g
, s
, ds_attr
, LDP_NOTIF_LOOP_DETECTED
) !=
752 MPLS_SUCCESS
) { /* LMp.8 */
753 retval
= MPLS_FAILURE
;
761 ds_temp
= ldp_attr_find_downstream_state(g
, s
, fec
, LDP_LSP_STATE_MAP_RECV
);
762 if (requested
== MPLS_BOOL_TRUE
||
763 g
->label_merge
== MPLS_BOOL_FALSE
|| !ds_temp
) {
764 /* !merging then this is always a new LSP
765 * merging w/o a recv'd mapping is a new LSP
766 * this check comes from Note 6
771 /* searching all recv'd attrs for matched mappings,
772 * stop after finding 1st match
774 if ((ds_list
= ldp_attr_find_downstream_all(g
, s
, fec
))) {
775 ds_temp
= MPLS_LIST_HEAD(ds_list
);
777 if (ds_temp
->state
== LDP_LSP_STATE_MAP_RECV
) { /* LMp.9 */
778 if (ldp_attr_is_equal(ds_attr
, ds_temp
, LDP_ATTR_LABEL
) ==
779 MPLS_BOOL_TRUE
) { /* LMp.10 */
781 * this mapping matches an existing mapping, but it
782 * could contain updated attributes
788 * we have been given another label for the same FEC and we
789 * didn't request it, release it
791 LDP_PRINT(g
->user_data
, "LMp.10 dup without req\n");
795 ds_temp
= MPLS_LIST_NEXT(ds_list
, ds_temp
, _fs
);
801 * update ONLY has a value for updated label mapping
804 result
= ldp_get_next_hop_session_for_fec(g
, fec
, &nh_addr
, &nh_session
);
807 * the following departs from the procedure, it allows for filtering
810 * Are we configured to accept and INSTALL this mapping?
812 if (mpls_policy_import_check(g
->user_data
, fec
, &fec
->nh
) ==
815 * policy has rejected it, store it away
818 ldp_attr2ldp_attr(ds_attr
, update
, LDP_ATTR_HOPCOUNT
| LDP_ATTR_PATH
|
819 LDP_ATTR_MSGID
| LDP_ATTR_LSPID
| LDP_ATTR_TRAFFIC
);
820 /* JLEU free ds_attr? */
821 update
->filtered
= MPLS_BOOL_TRUE
;
822 if (update
->outlabel
&& update
->outlabel
->switching
== MPLS_BOOL_TRUE
) {
823 /* the mapping has been filtered, but the original wasn't? */
827 ds_attr
->filtered
= MPLS_BOOL_TRUE
;
828 if (ldp_attr_insert_downstream(g
, s
, ds_attr
) != MPLS_SUCCESS
) {
829 retval
= MPLS_FAILURE
;
836 if (result
!= MPLS_SUCCESS
|| !nh_session
|| nh_session
->index
!= s
->index
) {
838 * if we don't know about the route, or the next hop isn't a peer,
839 * or if the next hop isn't the one who sent us the mapping ....
841 if (g
->label_retention_mode
== LDP_RETENTION_CONSERVATIVE
) { /* LMp.13C */
842 LDP_PRINT(g
->user_data
, "LMp.13C conservative\n");
849 LDP_PRINT(g
->user_data
, "index: %3d %08x/%d %d\n", ds_attr
->index
,
850 ds_attr
->fecTlv
.fecElArray
[0].addressEl
.address
,
851 ds_attr
->fecTlv
.fecElArray
[0].addressEl
.preLen
, ds_attr
->state
);
854 ldp_attr2ldp_attr(ds_attr
, update
, LDP_ATTR_HOPCOUNT
| LDP_ATTR_PATH
|
855 LDP_ATTR_MSGID
| LDP_ATTR_LSPID
| LDP_ATTR_TRAFFIC
);
856 /* JLEU free ds_attr? */
859 if (ldp_attr_insert_downstream(g
, s
, ds_attr
) != MPLS_SUCCESS
) {
860 retval
= MPLS_FAILURE
;
867 * this is slightly different form the procedure, we can still be
868 * transit for a FEC we are not configured to be ingress for.
869 * Either way we only need to do the "install for fwd/switching"
870 * only once. We could arrive here multiple times due to updates,
871 * only install it the first time
873 if ((!update
) || (!update
->outlabel
)) {
875 * we haven't installed it yet.
876 * Either new (!update), or a result of a "Detect FEC Nexthop Change"
877 * and we had this mapping in our database (!update->outlabel))
880 if (!(out
= ldp_outlabel_create_complete(g
, s
, nh_addr
, ds_attr
))) {
881 LDP_PRINT(g
->user_data
, "LMp.15 failure creating outlabel\n");
885 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_BINDING
,
886 "Out Label Added\n");
890 * are we configured to act as ingress for this FEC?
892 if (mpls_policy_ingress_check(g
->user_data
, fec
, &fec
->nh
) ==
893 MPLS_BOOL_TRUE
) { /* LMp.14 */
895 * yep, bind the label to the FEC
897 if (ds_attr
->ingress
!= MPLS_BOOL_TRUE
) {
900 ftn
.outsegment_index
= ds_attr
->outlabel
->info
.handle
;
901 memcpy(&ftn
.fec
, fec
, sizeof(mpls_fec
));
902 lsr_cfg_ftn_set2(g
->lsr_handle
, &ftn
, LSR_CFG_ADD
|LSR_FTN_CFG_FEC
|
903 LSR_FTN_CFG_OUTSEGMENT
);
905 mpls_mpls_fec2out_add(g
->mpls_handle
, fec
, &ds_attr
->outlabel
->info
);
907 ds_attr
->ingress
= MPLS_BOOL_TRUE
;
908 ds_attr
->outlabel
->merge_count
++;
909 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_BINDING
,
910 "FEC Binding Added\n");
914 /* create a set of attrs that we will fill and compare against
915 * if this mapping were to be propogate these are the attrs it would have
916 * by comparing what we did sent in the past to these, we con figure out
917 * if we need to send an updated mapping
919 memset(&dumb_attr
, 0, sizeof(ldp_attr
));
920 mpls_fec2fec_tlv(fec
, &dumb_attr
.fecTlv
, 0);
921 dumb_attr
.fecTlvExists
= 1;
922 dumb_attr
.fecTlv
.numberFecElements
= 1;
924 Prepare_Label_Mapping_Attributes(g
, s
, fec
, ds_attr
, &dumb_attr
,
925 MPLS_BOOL_TRUE
, MPLS_BOOL_TRUE
);
929 * this is the first time we've seen this mapping, add it to the database.
930 * all future updates will modify this entry in place
933 if (ldp_attr_insert_downstream(g
, s
, ds_attr
) != MPLS_SUCCESS
) {
934 retval
= MPLS_FAILURE
;
942 * this is an update, propogate update to all member of this LSP
944 us_temp
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
946 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_temp
, _ds_attr
);
951 peer
= MPLS_LIST_HEAD(&g
->session
);
952 while (peer
) { /* LMp.17 */
954 if (peer
->state
!= LDP_STATE_OPERATIONAL
||
955 peer
->index
== s
->index
) {
956 /* peer equals msg source */
960 /* check to see if a upstream mapping has been xc'd to this
961 * downstream mapping for this session. If so we need to propogate
962 * the attr changes (if any)
964 us_temp
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
966 if (us_temp
->session
->index
== peer
->index
) {
969 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_temp
, _ds_attr
);
972 if (us_temp
) { /* LMp.18 */
974 if ((us_list
= ldp_attr_find_upstream_all(g
, peer
, fec
))) {
975 us_temp
= MPLS_LIST_HEAD(us_list
);
977 if (us_temp
->state
== LDP_LSP_STATE_MAP_SENT
) {
979 if (ldp_attr_is_equal(us_temp
, &dumb_attr
,
980 LDP_ATTR_HOPCOUNT
| LDP_ATTR_PATH
) != MPLS_BOOL_TRUE
) {
981 if (ldp_label_mapping_with_xc(g
, us_temp
->session
, fec
, &us_temp
,
982 ds_attr
) != MPLS_SUCCESS
) { /* LMp.24-26 */
983 retval
= MPLS_FAILURE
;
988 us_temp
= MPLS_LIST_NEXT(us_list
, us_temp
, _fs
);
993 if ((peer
->oper_distribution_mode
== LDP_DISTRIBUTION_UNSOLICITED
) &&
994 (g
->lsp_control_mode
== LDP_CONTROL_ORDERED
)) { /* LMp.19 */
997 * if we're not merging and we have multiple ORDERED DU sessions,
998 * we will to start requesting labels after we propogate the mapping to
1001 if (need_request
== MPLS_BOOL_TRUE
) {
1002 if (ldp_attr_find_downstream_state(g
, peer
, fec
,
1003 LDP_LSP_STATE_REQ_SENT
) == NULL
) {
1005 * we don't have a request for FEC to peer outstanding, make one
1008 if (ldp_label_request_for_xc(g
, peer
, fec
, NULL
, &ds_temp
) !=
1010 retval
= MPLS_FAILURE
;
1016 * We're in DU more, either we're merging, or we're not merging and
1017 * this is the first peer we're propogating this mapping to
1021 if (ldp_label_mapping_with_xc(g
, peer
, fec
, &us_attr
, ds_attr
) !=
1023 retval
= MPLS_FAILURE
;
1027 * if we're not merging, we will need to request a label for
1030 if (g
->label_merge
== MPLS_BOOL_FALSE
) {
1031 need_request
= MPLS_BOOL_TRUE
;
1037 while ((us_temp
= ldp_attr_find_upstream_state(g
, peer
, fec
,
1038 LDP_LSP_STATE_REQ_RECV
))) {
1040 if (peer
->oper_distribution_mode
== LDP_DISTRIBUTION_UNSOLICITED
) {
1041 if (need_request
== MPLS_BOOL_TRUE
) {
1042 if (ldp_attr_find_downstream_state(g
, peer
, fec
,
1043 LDP_LSP_STATE_REQ_SENT
) == NULL
) {
1045 * we don't have a request for FEC to peer outstanding
1048 if (ldp_label_request_for_xc(g
, peer
, fec
, us_temp
,
1049 &ds_temp
) != MPLS_SUCCESS
) {
1050 retval
= MPLS_FAILURE
;
1055 if (ldp_label_mapping_with_xc(g
, peer
, fec
, &us_temp
,
1056 ds_attr
) != MPLS_SUCCESS
) {
1057 retval
= MPLS_FAILURE
;
1062 if ((us_list
= ldp_attr_find_upstream_all(g
, peer
, fec
))) {
1063 us_temp
= MPLS_LIST_HEAD(ds_list
);
1065 if (us_temp
->state
== LDP_LSP_STATE_REQ_RECV
) {
1066 if (need_request
== MPLS_BOOL_TRUE
) {
1067 if (ldp_attr_find_downstream_state(g
, peer
, fec
,
1068 LDP_LSP_STATE_REQ_SENT
) == NULL
) {
1070 * we don't have a request for FEC to peer outstanding
1073 if (ldp_label_request_for_xc(g
, peer
, fec
, us_temp
,
1074 &ds_temp
) != MPLS_SUCCESS
) {
1075 retval
= MPLS_FAILURE
;
1080 if (ldp_label_mapping_with_xc(g
, peer
, fec
, &us_temp
,
1081 ds_attr
) != MPLS_SUCCESS
) {
1082 retval
= MPLS_FAILURE
;
1086 * if we're not merging, we will need to request a label for
1089 if (g
->label_merge
== MPLS_BOOL_FALSE
) {
1090 need_request
= MPLS_BOOL_TRUE
;
1094 us_temp
= MPLS_LIST_NEXT(us_list
, us_temp
, _fs
);
1101 peer
= MPLS_LIST_NEXT(&g
->session
, peer
, _global
);
1105 LDP_EXIT(g
->user_data
, "ldp_label_mapping_process");
1109 LDP_PRINT(g
->user_data
, "Receive_Label_Map_32: send release");
1110 if (ldp_label_release_send(g
, s
, ds_attr
, LDP_NOTIF_NONE
) != MPLS_SUCCESS
) {
1111 retval
= MPLS_FAILURE
;
1113 LDP_EXIT(g
->user_data
, "ldp_label_mapping_process");