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 ldp_fec
* f
, ldp_attr
** us_attr
, ldp_attr
* ds_attr
)
42 mpls_return_enum result
;
43 mpls_bool propogating
= MPLS_BOOL_TRUE
;
44 mpls_bool egress
= MPLS_BOOL_TRUE
;
49 if (!((*us_attr
) = ldp_attr_create(&f
->info
))) {
54 propogating
= MPLS_BOOL_FALSE
;
55 egress
= MPLS_BOOL_TRUE
;
58 Prepare_Label_Mapping_Attributes(g
, s
, &f
->info
, ds_attr
, (*us_attr
),
59 propogating
, MPLS_BOOL_TRUE
, egress
);
61 if (ldp_attr_insert_upstream2(g
, s
, (*us_attr
), f
) != MPLS_SUCCESS
) {
62 ldp_attr_delete(*us_attr
);
66 if (ldp_label_mapping_send(g
, s
, (*us_attr
), ds_attr
) != MPLS_SUCCESS
) {
67 ldp_attr_delete(*us_attr
);
71 if (ds_attr
&& ds_attr
->outlabel
) {
73 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
74 LDP_TRACE_FLAG_BINDING
, "Cross Connect Added\n");
76 result
= ldp_inlabel_add_outlabel(g
,(*us_attr
)->inlabel
,ds_attr
->outlabel
);
77 if (result
!= MPLS_SUCCESS
) {
78 ldp_label_withdraw_send(g
, s
, (*us_attr
), LDP_NOTIF_NONE
);
85 ldp_session
*ldp_get_session_by_next_hop(ldp_global
* g
, mpls_nexthop
* a
,
89 ldp_addr
*addr
= NULL
;
91 MPLS_ASSERT(next_hop
);
93 if (a
->type
== MPLS_NH_IP
) {
94 /* possibly an indirect nexthop */
95 if (!mpls_fib_get_best_route(g
->fib_handle
, 1, &dest
, &entry
)) {
101 if (a
->type
& MPLS_NH_IP
) {
102 if (mpls_tree_get(g
->addr_tree
, a
->ip
.u
.ipv4
, 32, (void **)&addr
) ==
104 ldp_session
*ses
= NULL
;
106 /* JLEU if there is more then one session that has given this address
107 then we're in trouble, just choose the first for now */
108 if ((ses
= (ldp_session
*)mpls_link_list_head_data(&addr
->session_root
))) {
113 } else if (a
->type
& MPLS_NH_IF
) {
114 ldp_if
*iff
= ldp_global_find_if_handle(g
, a
->if_handle
);
118 /* JLEU if there is more then one session on this interface
119 then we're in trouble, just choose the first for now */
121 a
= MPLS_LIST_HEAD(&iff
->entity
->adj_root
);
131 ldp_session
*ldp_get_next_hop_session_for_fec2(ldp_fec
* f
) {
132 ldp_session
*session
= NULL
;
134 * find the info about the next hop for this FEC
136 if (f
->addr
&& f
->addr
->session_root
.count
> 0) {
137 session
= mpls_link_list_head_data(&f
->addr
->session_root
);
138 } else if (f
->iff
&& f
->iff
->is_p2p
== MPLS_BOOL_TRUE
&&
140 ldp_adj
*adj
= MPLS_LIST_HEAD(&f
->iff
->entity
->adj_root
);
141 session
= adj
? adj
->session
: NULL
;
146 mpls_return_enum
ldp_get_next_hop_session_for_fec(ldp_global
* g
,
147 mpls_fec
* fec
, ldp_session
** next_hop_session
)
151 MPLS_ASSERT(next_hop_session
);
153 if (!(f
= ldp_fec_find(g
, fec
))) {
154 return MPLS_NO_ROUTE
;
157 *next_hop_session
= ldp_get_next_hop_session_for_fec2(f
);
158 return (*next_hop_session
) ? MPLS_SUCCESS
: MPLS_FAILURE
;
161 mpls_return_enum
Check_Received_Attributes(ldp_global
* g
, ldp_session
* s
,
162 ldp_attr
* r_attr
, uint16_t type
)
167 if (!r_attr
->hopCountTlvExists
) { /* CRa.1 */
168 goto Check_Received_Attributes_5
;
171 if (r_attr
->hopCountTlv
.hcValue
>= s
->cfg_hop_count_limit
) { /* CRa.2 */
172 LDP_PRINT(g
->user_data
, "CRa.2\n");
173 goto Check_Received_Attributes_6
;
176 if (!r_attr
->pathVecTlvExists
) { /* CRa.3 */
177 goto Check_Received_Attributes_5
;
180 for (i
= 0; i
< MPLS_MAXHOPSNUMBER
; i
++) { /* CRa.4 */
181 if (r_attr
->pathVecTlv
.lsrId
[i
]) {
183 if (r_attr
->pathVecTlv
.lsrId
[i
] == g
->lsr_identifier
.u
.ipv4
) {
184 goto Check_Received_Attributes_6
;
185 LDP_PRINT(g
->user_data
, "CRa.4a\n");
187 if (count
> s
->oper_path_vector_limit
) {
188 goto Check_Received_Attributes_6
;
189 LDP_PRINT(g
->user_data
, "CRa.4b\n");
194 Check_Received_Attributes_5
:
197 Check_Received_Attributes_6
:
198 if (type
!= MPLS_LBLMAP_MSGTYPE
) {
199 ldp_notif_send(g
, s
, r_attr
, LDP_NOTIF_LOOP_DETECTED
); /* CRa.7 */
201 return MPLS_FAILURE
; /* CRa.8 */
204 void Prepare_Label_Mapping_Attributes(ldp_global
* g
, ldp_session
* s
,
205 mpls_fec
* fec
, ldp_attr
* r_attr
, ldp_attr
* s_attr
, mpls_bool propogating
,
206 mpls_bool already
, mpls_bool egress
)
211 /* NOTE: PMpA.21 is the end of the procedure (ie return) */
212 /* this function uses goto quite extensivly for a REASON!! */
213 /* Check Appedix A of the LDP draft */
215 LDP_ENTER(g
->user_data
, "Prepare_Label_Mapping_Attributes");
218 memset(&dummy
, 0, sizeof(ldp_attr
));
219 mpls_fec2fec_tlv(fec
, &dummy
.fecTlv
, 0);
220 dummy
.fecTlvExists
= 1;
221 dummy
.fecTlv
.numberFecElements
= 1;
225 if (!(s
->oper_loop_detection
== LDP_LOOP_HOPCOUNT
||
226 s
->oper_loop_detection
== LDP_LOOP_HOPCOUNT_PATHVECTOR
||
227 r_attr
->hopCountTlvExists
)) { /* PMpA.1 */
228 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
232 if (egress
) {/* PMpA.2 */
233 /* I'm egress (for now) */
234 s_attr
->hopCountTlvExists
= 1;
235 s_attr
->hopCountTlv
.hcValue
= 1; /* PMpA.3 */
236 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
240 if (!(r_attr
->hopCountTlvExists
)) { /* PMpA.4 */
241 goto Prepare_Label_Mapping_Attributes_8
;
244 if (!(g
->ttl_less_domain
== MPLS_BOOL_TRUE
&&
245 s
->cfg_remote_in_ttl_less_domain
== MPLS_BOOL_TRUE
)) { /* PMpA.5 */
246 goto Prepare_Label_Mapping_Attributes_7
;
249 s_attr
->hopCountTlvExists
= 1;
250 s_attr
->hopCountTlv
.hcValue
= 1; /* PMpA.6 */
251 goto Prepare_Label_Mapping_Attributes_9
;
253 Prepare_Label_Mapping_Attributes_7
:
254 s_attr
->hopCountTlvExists
= 1;
255 s_attr
->hopCountTlv
.hcValue
= (r_attr
->hopCountTlv
.hcValue
) ?
256 (r_attr
->hopCountTlv
.hcValue
+ 1) : 0;
257 goto Prepare_Label_Mapping_Attributes_9
;
259 Prepare_Label_Mapping_Attributes_8
:
260 s_attr
->hopCountTlvExists
= 1;
261 s_attr
->hopCountTlv
.hcValue
= 0;
263 Prepare_Label_Mapping_Attributes_9
:
264 if (s
->oper_loop_detection
== LDP_LOOP_NONE
) {
265 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
269 if (r_attr
->pathVecTlvExists
) { /* PMpA.10 */
270 goto Prepare_Label_Mapping_Attributes_19
;
273 if (propogating
== MPLS_BOOL_FALSE
) { /* PMpA.11 */
274 goto Prepare_Label_Mapping_Attributes_20
;
277 if (g
->label_merge
!= MPLS_BOOL_TRUE
) { /* PMpA.12 */
278 goto Prepare_Label_Mapping_Attributes_14
;
281 if (already
== MPLS_BOOL_FALSE
) { /* PMpA.13 */
282 goto Prepare_Label_Mapping_Attributes_20
;
285 Prepare_Label_Mapping_Attributes_14
:
286 if (!r_attr
->hopCountTlvExists
) {
287 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
291 if (r_attr
->hopCountTlv
.hcValue
== 0) { /* PMpA.15 */
292 goto Prepare_Label_Mapping_Attributes_20
;
295 if (already
== MPLS_BOOL_FALSE
) { /* PMpA.16 */
296 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
300 /* r_attr contain PrevHopCount _IF_ we had one */
301 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
302 return; /* PMpA.17 */
304 if (r_attr
->hopCountTlv
.hcValue
!= 0) { /* PMpA.18 */
305 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
309 Prepare_Label_Mapping_Attributes_19
:
310 s_attr
->pathVecTlvExists
= 1;
311 s_attr
->pathVecTlv
.lsrId
[0] = g
->lsr_identifier
.u
.ipv4
;
312 for (i
= 1; i
< (MPLS_MAXHOPSNUMBER
- 1); i
++) {
313 if (r_attr
->pathVecTlv
.lsrId
[i
- 1]) {
314 s_attr
->pathVecTlv
.lsrId
[0] = r_attr
->pathVecTlv
.lsrId
[i
- 1];
318 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
321 Prepare_Label_Mapping_Attributes_20
:
322 s_attr
->pathVecTlvExists
= 1;
323 s_attr
->pathVecTlv
.lsrId
[0] = g
->lsr_identifier
.u
.ipv4
;
325 LDP_EXIT(g
->user_data
, "Prepare_Label_Mapping_Attributes");
329 void map2attr(mplsLdpLblMapMsg_t
* map
, ldp_attr
* attr
, uint32_t flag
)
331 attr
->msg_id
= map
->baseMsg
.msgId
;
333 if (map
->fecTlvExists
&& flag
& LDP_ATTR_FEC
) {
334 memcpy(&attr
->fecTlv
, &map
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
335 attr
->fecTlvExists
= 1;
337 if (map
->genLblTlvExists
&& flag
& LDP_ATTR_LABEL
) {
338 memcpy(&attr
->genLblTlv
, &map
->genLblTlv
, sizeof(mplsLdpGenLblTlv_t
));
339 attr
->genLblTlvExists
= 1;
340 } else if (map
->atmLblTlvExists
&& flag
& LDP_ATTR_LABEL
) {
341 memcpy(&attr
->atmLblTlv
, &map
->atmLblTlv
, sizeof(mplsLdpAtmLblTlv_t
));
342 attr
->atmLblTlvExists
= 1;
343 } else if (map
->frLblTlvExists
&& flag
& LDP_ATTR_LABEL
) {
344 memcpy(&attr
->frLblTlv
, &map
->frLblTlv
, sizeof(mplsLdpFrLblTlv_t
));
345 attr
->frLblTlvExists
= 1;
347 if (map
->hopCountTlvExists
&& flag
& LDP_ATTR_HOPCOUNT
) {
348 memcpy(&attr
->hopCountTlv
, &map
->hopCountTlv
, sizeof(mplsLdpHopTlv_t
));
349 attr
->hopCountTlvExists
= 1;
351 if (map
->pathVecTlvExists
&& flag
& LDP_ATTR_PATH
) {
352 memcpy(&attr
->pathVecTlv
, &map
->pathVecTlv
, sizeof(mplsLdpPathTlv_t
));
353 attr
->pathVecTlvExists
= 1;
355 if (map
->lblMsgIdTlvExists
&& flag
& LDP_ATTR_MSGID
) {
356 memcpy(&attr
->lblMsgIdTlv
, &map
->lblMsgIdTlv
, sizeof(mplsLdpLblMsgIdTlv_t
));
357 attr
->lblMsgIdTlvExists
= 1;
359 if (map
->lspidTlvExists
&& flag
& LDP_ATTR_LSPID
) {
360 memcpy(&attr
->lspidTlv
, &map
->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
361 attr
->lspidTlvExists
= 1;
363 if (map
->trafficTlvExists
&& flag
& LDP_ATTR_TRAFFIC
) {
364 memcpy(&attr
->trafficTlv
, &map
->trafficTlv
, sizeof(mplsLdpTrafficTlv_t
));
365 attr
->trafficTlvExists
= 1;
369 void attr2map(ldp_attr
* attr
, mplsLdpLblMapMsg_t
* map
)
371 if (attr
->fecTlvExists
) {
372 memcpy(&map
->fecTlv
, &attr
->fecTlv
, sizeof(mplsLdpFecTlv_t
));
373 map
->fecTlvExists
= 1;
375 if (attr
->genLblTlvExists
) {
376 memcpy(&map
->genLblTlv
, &attr
->genLblTlv
, sizeof(mplsLdpGenLblTlv_t
));
377 map
->genLblTlvExists
= 1;
379 if (attr
->atmLblTlvExists
) {
380 memcpy(&map
->atmLblTlv
, &attr
->atmLblTlv
, sizeof(mplsLdpAtmLblTlv_t
));
381 map
->atmLblTlvExists
= 1;
383 if (attr
->frLblTlvExists
) {
384 memcpy(&map
->frLblTlv
, &attr
->frLblTlv
, sizeof(mplsLdpFrLblTlv_t
));
385 map
->frLblTlvExists
= 1;
387 if (attr
->hopCountTlvExists
) {
388 memcpy(&map
->hopCountTlv
, &attr
->hopCountTlv
, sizeof(mplsLdpHopTlv_t
));
389 map
->hopCountTlvExists
= 1;
391 if (attr
->pathVecTlvExists
) {
392 memcpy(&map
->pathVecTlv
, &attr
->pathVecTlv
, sizeof(mplsLdpPathTlv_t
));
393 map
->pathVecTlvExists
= 1;
395 if (attr
->lblMsgIdTlvExists
) {
396 memcpy(&map
->lblMsgIdTlv
, &attr
->lblMsgIdTlv
, sizeof(mplsLdpLblMsgIdTlv_t
));
397 map
->lblMsgIdTlvExists
= 1;
399 if (attr
->lspidTlvExists
) {
400 memcpy(&map
->lspidTlv
, &attr
->lspidTlv
, sizeof(mplsLdpLspIdTlv_t
));
401 map
->lspidTlvExists
= 1;
403 if (attr
->trafficTlvExists
) {
404 memcpy(&map
->trafficTlv
, &attr
->trafficTlv
, sizeof(mplsLdpTrafficTlv_t
));
405 map
->trafficTlvExists
= 1;
409 void ldp_label_mapping_initial_callback(mpls_timer_handle timer
, void *extra
,
410 mpls_cfg_handle handle
)
412 ldp_session
*s
= (ldp_session
*) extra
;
413 ldp_global
*g
= (ldp_global
*)handle
;
414 ldp_attr
*ds_attr
= NULL
;
415 ldp_attr
*us_attr
= NULL
;
416 ldp_session
*nh_session
= NULL
;
417 mpls_bool done
= MPLS_BOOL_FALSE
;
420 LDP_ENTER(g
->user_data
, "ldp_label_mapping_initial_callback");
422 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_TIMER
,
423 "Initial Label Mapping fired: session(%d)\n", s
->index
);
425 mpls_lock_get(g
->global_lock
);
427 mpls_timer_stop(g
->timer_handle
, timer
);
429 if ((f
= MPLS_LIST_HEAD(&g
->fec
))) {
431 switch (f
->info
.type
) {
432 case MPLS_FEC_PREFIX
:
433 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
434 LDP_TRACE_FLAG_ROUTE
, "Processing prefix FEC: %08x/%d ",
435 f
->info
.u
.prefix
.network
.u
.ipv4
, f
->info
.u
.prefix
.length
);
438 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
439 LDP_TRACE_FLAG_ROUTE
, "Processing host FEC: %08x ",
440 f
->info
.u
.host
.u
.ipv4
);
443 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
444 LDP_TRACE_FLAG_ROUTE
, "Processingu L2CC FEC: %d %d %d ",
445 f
->info
.u
.l2cc
.connection_id
, f
->info
.u
.l2cc
.group_id
,
446 f
->info
.u
.l2cc
.type
);
452 if (f
->nh
.type
& MPLS_NH_IP
) {
453 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
454 LDP_TRACE_FLAG_ROUTE
, "via %08x\n", f
->nh
.addr
->address
.u
.ipv4
);
456 if (f
->nh
.type
& MPLS_NH_IF
) {
457 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
,
458 LDP_TRACE_FLAG_ROUTE
, "via %s\n", f
->nh
.iff
->name
);
461 /* are we allowed to export this route from the rib */
462 if (mpls_policy_export_check(g
->user_data
, &f
->info
, &f
->info
.nh
) ==
464 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_POLICY
,
465 "Rejected by export policy\n");
469 /* have we already sent a mapping for this fec to the new session? */
470 if ((us_attr
= ldp_attr_find_upstream_state2(g
, s
, f
,
471 LDP_LSP_STATE_MAP_SENT
))) {
472 /* no need to sent another mapping */
473 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_ROUTE
,
474 "Already sent this FEC to session %d\n", s
->index
);
478 if (!(nh_session
= ldp_get_next_hop_session_for_fec2(f
))) {
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_state2(g
, nh_session
, f
,
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
, f
, &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
, &f
->info
, &f
->info
.nh
) ==
507 ldp_label_mapping_with_xc(g
, s
, f
, &us_attr
, NULL
);
510 ldp_label_mapping_with_xc(g
, s
, f
, &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
, &f
->info
, us_attr
, &ds_attr
);
523 } while ((f
= MPLS_LIST_NEXT(&g
->fec
, f
, _global
)));
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
;
549 LDP_ENTER(g
->user_data
, "ldp_label_mapping_send");
550 MPLS_ASSERT(us_attr
);
552 if ((in
= ldp_inlabel_create_complete(g
, s
, us_attr
)) == NULL
) { /* SL.1-3 */
556 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_BINDING
,
559 us_attr
->state
= LDP_LSP_STATE_MAP_SENT
;
561 us_attr
->msg_id
= g
->message_identifier
;
562 ldp_label_mapping_prepare_msg(s
->tx_message
, g
->message_identifier
++,
565 if (ldp_mesg_send_tcp(g
, s
, s
->tx_message
) != MPLS_SUCCESS
) { /* SL.4 */
566 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_ERROR
,
567 "Failed sending Label Mapping to %s\n",
569 goto ldp_label_mapping_send_error
;
572 ldp_attr_add_us2ds(us_attr
, ds_attr
);
574 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_SEND
, LDP_TRACE_FLAG_LABEL
,
575 "Label Mapping Sent to %s for %08x/%d\n",
577 us_attr
->fecTlv
.fecElArray
[0].addressEl
.address
,
578 us_attr
->fecTlv
.fecElArray
[0].addressEl
.preLen
);
580 us_attr
->state
= LDP_LSP_STATE_MAP_SENT
; /* SL.6,7 */
582 LDP_EXIT(g
->user_data
, "ldp_label_mapping_send");
583 return MPLS_SUCCESS
; /* SL.8 */
586 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_STATE
,
587 "No Label Resources\n");
589 while ((us_temp
= ldp_attr_find_upstream_state2(g
, s
, us_attr
->fec
,
590 LDP_LSP_STATE_REQ_RECV
)) != NULL
) { /* SL.9 */
591 ldp_notif_send(g
, s
, us_temp
, LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE
);
593 s
->no_label_resource_sent
= MPLS_BOOL_TRUE
; /* SL.12 */
594 us_temp
->state
= LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT
; /* SL.13 */
597 LDP_EXIT(g
->user_data
, "ldp_label_mapping_send");
601 ldp_label_mapping_send_error
:
603 LDP_EXIT(g
->user_data
, "ldp_label_mapping_send-error");
607 void ldp_label_mapping_prepare_msg(ldp_mesg
* msg
, uint32_t msgid
,
610 mplsLdpLblMapMsg_t
*map
= NULL
;
615 ldp_mesg_prepare(msg
, MPLS_LBLMAP_MSGTYPE
, msgid
);
618 if (s_attr
->fecTlvExists
) {
619 /* JLEU: only 1 FEC is allowed!! */
620 map
->fecTlvExists
= 1;
621 map
->baseMsg
.msgLength
+= setupFecTlv(&map
->fecTlv
);
622 map
->baseMsg
.msgLength
+= addFecElem2FecTlv(&map
->fecTlv
,
623 &s_attr
->fecTlv
.fecElArray
[0]);
625 if (s_attr
->genLblTlvExists
) {
626 map
->genLblTlvExists
= 1;
627 map
->baseMsg
.msgLength
+= setupGenLblTlv(&map
->genLblTlv
,
628 s_attr
->genLblTlv
.label
);
630 if (s_attr
->atmLblTlvExists
) {
631 map
->atmLblTlvExists
= 1;
632 map
->baseMsg
.msgLength
+= setupAtmLblTlv(&map
->atmLblTlv
, 0, 0,
633 s_attr
->atmLblTlv
.flags
.flags
.vpi
, s_attr
->atmLblTlv
.vci
);
635 if (s_attr
->frLblTlvExists
) {
636 map
->frLblTlvExists
= 1;
637 map
->baseMsg
.msgLength
+= setupFrLblTlv(&map
->frLblTlv
, 0,
638 s_attr
->frLblTlv
.flags
.flags
.len
, s_attr
->frLblTlv
.flags
.flags
.dlci
);
640 if (s_attr
->hopCountTlvExists
) {
641 map
->hopCountTlvExists
= 1;
642 map
->baseMsg
.msgLength
+= setupHopCountTlv(&map
->hopCountTlv
,
643 s_attr
->hopCountTlv
.hcValue
);
645 if (s_attr
->pathVecTlvExists
) {
646 map
->pathVecTlvExists
= 1;
647 map
->baseMsg
.msgLength
+= setupPathTlv(&map
->pathVecTlv
);
648 for (i
= 0; i
< MPLS_MAXHOPSNUMBER
; i
++) {
649 if (s_attr
->pathVecTlv
.lsrId
[i
]) {
650 map
->baseMsg
.msgLength
+= addLsrId2PathTlv(&map
->pathVecTlv
,
651 s_attr
->pathVecTlv
.lsrId
[i
]);
656 if (s_attr
->lblMsgIdTlvExists
) {
658 if (s_attr
->lspidTlvExists
) {
660 if (s_attr
->trafficTlvExists
) {
665 mpls_return_enum
ldp_label_mapping_process(ldp_global
* g
, ldp_session
* s
,
666 ldp_adj
* a
, ldp_entity
* e
, ldp_attr
* r_attr
, ldp_fec
* f
)
668 mpls_return_enum retval
= MPLS_SUCCESS
;
669 ldp_session
*nh_session
= NULL
;
670 ldp_session
*peer
= NULL
;
671 ldp_attr_list
*us_list
= NULL
;
672 ldp_attr_list
*ds_list
= NULL
;
673 ldp_attr
*ds_attr
= NULL
;
674 ldp_attr
*ds_temp
= NULL
;
675 ldp_attr
*us_attr
= NULL
;
676 ldp_attr
*us_temp
= NULL
;
679 ldp_outlabel
*out
= NULL
;
680 mpls_bool requested
= MPLS_BOOL_FALSE
;
681 ldp_attr
*update
= NULL
;
682 mpls_bool need_request
= MPLS_BOOL_FALSE
;
684 LDP_ENTER(g
->user_data
, "ldp_label_mapping_process");
686 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_RECV
, LDP_TRACE_FLAG_LABEL
,
687 "Label Mapping Recv from %s for %08x/%d\n",
689 r_attr
->fecTlv
.fecElArray
[0].addressEl
.address
,
690 r_attr
->fecTlv
.fecElArray
[0].addressEl
.preLen
);
692 if ((ds_attr
= ldp_attr_find_downstream_state2(g
, s
, f
,
693 LDP_LSP_STATE_REQ_SENT
)) != NULL
) { /* LMp.1 */
694 /* just remove the req from the tree, we will use the r_attr sent to us */
695 ldp_attr_delete_downstream(g
, s
, ds_attr
);
696 requested
= MPLS_BOOL_TRUE
;
698 requested
= MPLS_BOOL_FALSE
;
702 ds_attr
->state
= LDP_LSP_STATE_MAP_RECV
; /* LMp.2 */
705 * ds_attr is the mapping we will keep and is NOT in the tree, unless
706 * it is an update mapping ...
708 if (Check_Received_Attributes(g
, s
, ds_attr
, MPLS_LBLMAP_MSGTYPE
) ==
709 MPLS_SUCCESS
) { /* LMp.3 */
714 * A loop was detected
716 if ((ds_list
= ldp_attr_find_downstream_all2(g
, s
, f
))) {
717 ds_temp
= MPLS_LIST_HEAD(ds_list
);
719 * check all the labels this session has received from "s" for "fec"
720 * do we have a duplicat?
723 if ((ds_temp
->state
== LDP_LSP_STATE_MAP_RECV
) && /* LMp.4 */
724 ldp_attr_is_equal(ds_temp
, ds_attr
, LDP_ATTR_LABEL
) == /* LMp.5 */
726 /* remove record of the label and remove it switching */
727 ldp_attr_remove_complete(g
, ds_temp
, MPLS_BOOL_TRUE
); /* LMp.6,7 */
729 * I think this is supposed to be 32 NOT 33, we need to release
734 ds_temp
= MPLS_LIST_NEXT(ds_list
, ds_temp
, _fs
);
738 LDP_PRINT(g
->user_data
, "Receive_Label_Map_8: send release");
739 if (ldp_label_release_send(g
, s
, ds_attr
, LDP_NOTIF_LOOP_DETECTED
) !=
740 MPLS_SUCCESS
) { /* LMp.8 */
741 retval
= MPLS_FAILURE
;
749 ds_temp
= ldp_attr_find_downstream_state2(g
, s
, f
, LDP_LSP_STATE_MAP_RECV
);
750 if (requested
== MPLS_BOOL_TRUE
||
751 g
->label_merge
== MPLS_BOOL_FALSE
|| !ds_temp
) {
752 /* !merging then this is always a new LSP
753 * merging w/o a recv'd mapping is a new LSP
754 * this check comes from Note 6
759 /* searching all recv'd attrs for matched mappings,
760 * stop after finding 1st match
762 if ((ds_list
= ldp_attr_find_downstream_all2(g
, s
, f
))) {
763 ds_temp
= MPLS_LIST_HEAD(ds_list
);
765 if (ds_temp
->state
== LDP_LSP_STATE_MAP_RECV
) { /* LMp.9 */
766 if (ldp_attr_is_equal(ds_attr
, ds_temp
, LDP_ATTR_LABEL
) ==
767 MPLS_BOOL_TRUE
) { /* LMp.10 */
769 * this mapping matches an existing mapping, but it
770 * could contain updated attributes
776 * we have been given another label for the same FEC and we
777 * didn't request it, release it
779 LDP_PRINT(g
->user_data
, "LMp.10 dup without req\n");
783 ds_temp
= MPLS_LIST_NEXT(ds_list
, ds_temp
, _fs
);
789 * update ONLY has a value for updated label mapping
792 nh_session
= ldp_get_next_hop_session_for_fec2(f
);
795 * the following departs from the procedure, it allows for filtering
798 * Are we configured to accept and INSTALL this mapping?
800 if (mpls_policy_import_check(g
->user_data
, &f
->info
, &f
->info
.nh
) ==
803 * policy has rejected it, store it away
806 ldp_attr2ldp_attr(ds_attr
, update
, LDP_ATTR_HOPCOUNT
| LDP_ATTR_PATH
|
807 LDP_ATTR_MSGID
| LDP_ATTR_LSPID
| LDP_ATTR_TRAFFIC
);
808 /* JLEU free ds_attr? */
809 update
->filtered
= MPLS_BOOL_TRUE
;
810 if (update
->outlabel
&& update
->outlabel
->switching
== MPLS_BOOL_TRUE
) {
811 /* the mapping has been filtered, but the original wasn't? */
815 ds_attr
->filtered
= MPLS_BOOL_TRUE
;
816 if (ldp_attr_insert_downstream(g
, s
, ds_attr
) != MPLS_SUCCESS
) {
817 retval
= MPLS_FAILURE
;
824 if ((!f
) || (!nh_session
) || (nh_session
->index
!= s
->index
)) {
826 * if we don't know about the route, or we don't have a next hop session,
827 * or the next hop session isn't the one who sent us the mapping ....
829 if (g
->label_retention_mode
== LDP_RETENTION_CONSERVATIVE
) { /* LMp.13C */
830 LDP_PRINT(g
->user_data
, "LMp.13C conservative\n");
837 LDP_PRINT(g
->user_data
, "index: %3d %08x/%d %d\n", ds_attr
->index
,
838 ds_attr
->fecTlv
.fecElArray
[0].addressEl
.address
,
839 ds_attr
->fecTlv
.fecElArray
[0].addressEl
.preLen
, ds_attr
->state
);
842 ldp_attr2ldp_attr(ds_attr
, update
, LDP_ATTR_HOPCOUNT
| LDP_ATTR_PATH
|
843 LDP_ATTR_MSGID
| LDP_ATTR_LSPID
| LDP_ATTR_TRAFFIC
);
844 /* JLEU free ds_attr? */
847 if (ldp_attr_insert_downstream(g
, s
, ds_attr
) != MPLS_SUCCESS
) {
848 retval
= MPLS_FAILURE
;
855 * this is slightly different form the procedure, we can still be
856 * transit for a FEC we are not configured to be ingress for.
857 * Either way we only need to do the "install for fwd/switching"
858 * only once. We could arrive here multiple times due to updates,
859 * only install it the first time
861 if ((!update
) || (!update
->outlabel
)) {
863 * we haven't installed it yet.
864 * Either new (!update), or a result of a "Detect FEC Nexthop Change"
865 * and we had this mapping in our database (!update->outlabel))
868 if (!(out
= ldp_outlabel_create_complete(g
, s
, ds_attr
))) {
869 LDP_PRINT(g
->user_data
, "LMp.15 failure creating outlabel\n");
873 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_BINDING
,
874 "Out Label Added\n");
878 * are we configured to act as ingress for this FEC?
880 if (mpls_policy_ingress_check(g
->user_data
, &f
->info
, &f
->info
.nh
) ==
881 MPLS_BOOL_TRUE
) { /* LMp.14 */
883 * yep, bind the label to the FEC
885 if (ds_attr
->ingress
!= MPLS_BOOL_TRUE
) {
888 ftn
.outsegment_index
= ds_attr
->outlabel
->info
.handle
;
889 memcpy(&ftn
.fec
, &f
->info
, sizeof(mpls_fec
));
890 lsr_cfg_ftn_set2(g
->lsr_handle
, &ftn
, LSR_CFG_ADD
|LSR_FTN_CFG_FEC
|
891 LSR_FTN_CFG_OUTSEGMENT
);
893 mpls_mpls_fec2out_add(g
->mpls_handle
, &f
->info
, &ds_attr
->outlabel
->info
);
895 ds_attr
->ingress
= MPLS_BOOL_TRUE
;
896 ds_attr
->outlabel
->merge_count
++;
897 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_BINDING
,
898 "FEC Binding Added\n");
902 /* create a set of attrs that we will fill and compare against
903 * if this mapping were to be propogate these are the attrs it would have
904 * by comparing what we did sent in the past to these, we con figure out
905 * if we need to send an updated mapping
907 memset(&dumb_attr
, 0, sizeof(ldp_attr
));
908 mpls_fec2fec_tlv(&f
->info
, &dumb_attr
.fecTlv
, 0);
909 dumb_attr
.fecTlvExists
= 1;
910 dumb_attr
.fecTlv
.numberFecElements
= 1;
913 * by definition (we received a label mapping that will be used) this
914 * LSR is _not_ the egress, so calculate a hop and path based on the
915 * mapping we received. We will compare this with mapping that have
916 * already been sent. If they differ, we will send an updated mapping
918 Prepare_Label_Mapping_Attributes(g
, s
, &f
->info
, ds_attr
, &dumb_attr
,
919 MPLS_BOOL_TRUE
, MPLS_BOOL_TRUE
, MPLS_BOOL_FALSE
);
923 * this is the first time we've seen this mapping, add it to the database.
924 * all future updates will modify this entry in place
927 if (ldp_attr_insert_downstream(g
, s
, ds_attr
) != MPLS_SUCCESS
) {
928 retval
= MPLS_FAILURE
;
936 * this is an update, propogate update to all member of this LSP
938 us_temp
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
940 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_temp
, _ds_attr
);
945 peer
= MPLS_LIST_HEAD(&g
->session
);
946 while (peer
) { /* LMp.17 */
948 if (peer
->state
!= LDP_STATE_OPERATIONAL
||
949 peer
->index
== s
->index
) {
950 /* peer equals msg source */
954 /* check to see if a upstream mapping has been xc'd to this
955 * downstream mapping for this session. If so we need to propogate
956 * the attr changes (if any)
958 us_temp
= MPLS_LIST_HEAD(&ds_attr
->us_attr_root
);
960 if (us_temp
->session
->index
== peer
->index
) {
963 us_temp
= MPLS_LIST_NEXT(&ds_attr
->us_attr_root
, us_temp
, _ds_attr
);
966 if (us_temp
) { /* LMp.18 */
968 if ((us_list
= ldp_attr_find_upstream_all2(g
, peer
, f
))) {
969 us_temp
= MPLS_LIST_HEAD(us_list
);
971 if (us_temp
->state
== LDP_LSP_STATE_MAP_SENT
) {
973 if (ldp_attr_is_equal(us_temp
, &dumb_attr
,
974 LDP_ATTR_HOPCOUNT
| LDP_ATTR_PATH
) != MPLS_BOOL_TRUE
) {
975 if (ldp_label_mapping_with_xc(g
, us_temp
->session
, f
, &us_temp
,
976 ds_attr
) != MPLS_SUCCESS
) { /* LMp.24-26 */
977 retval
= MPLS_FAILURE
;
982 us_temp
= MPLS_LIST_NEXT(us_list
, us_temp
, _fs
);
987 if ((peer
->oper_distribution_mode
== LDP_DISTRIBUTION_UNSOLICITED
) &&
988 (g
->lsp_control_mode
== LDP_CONTROL_ORDERED
)) { /* LMp.19 */
991 * if we're not merging and we have multiple ORDERED DU sessions,
992 * we will to start requesting labels after we propogate the mapping to
995 if (need_request
== MPLS_BOOL_TRUE
) {
996 if (ldp_attr_find_downstream_state2(g
, peer
, f
,
997 LDP_LSP_STATE_REQ_SENT
) == NULL
) {
999 * we don't have a request for FEC to peer outstanding, make one
1002 if (ldp_label_request_for_xc(g
, peer
, &f
->info
, NULL
, &ds_temp
) !=
1004 retval
= MPLS_FAILURE
;
1010 * We're in DU more, either we're merging, or we're not merging and
1011 * this is the first peer we're propogating this mapping to
1015 if (ldp_label_mapping_with_xc(g
, peer
, f
, &us_attr
, ds_attr
) !=
1017 retval
= MPLS_FAILURE
;
1021 * if we're not merging, we will need to request a label for
1024 if (g
->label_merge
== MPLS_BOOL_FALSE
) {
1025 need_request
= MPLS_BOOL_TRUE
;
1031 while ((us_temp
= ldp_attr_find_upstream_state2(g
, peer
, f
,
1032 LDP_LSP_STATE_REQ_RECV
))) {
1034 if (peer
->oper_distribution_mode
== LDP_DISTRIBUTION_UNSOLICITED
) {
1035 if (need_request
== MPLS_BOOL_TRUE
) {
1036 if (ldp_attr_find_downstream_state2(g
, peer
, f
,
1037 LDP_LSP_STATE_REQ_SENT
) == NULL
) {
1039 * we don't have a request for FEC to peer outstanding
1042 if (ldp_label_request_for_xc(g
, peer
, &f
->info
, us_temp
,
1043 &ds_temp
) != MPLS_SUCCESS
) {
1044 retval
= MPLS_FAILURE
;
1049 if (ldp_label_mapping_with_xc(g
, peer
, f
, &us_temp
,
1050 ds_attr
) != MPLS_SUCCESS
) {
1051 retval
= MPLS_FAILURE
;
1056 if ((us_list
= ldp_attr_find_upstream_all2(g
, peer
, f
))) {
1057 us_temp
= MPLS_LIST_HEAD(ds_list
);
1059 if (us_temp
->state
== LDP_LSP_STATE_REQ_RECV
) {
1060 if (need_request
== MPLS_BOOL_TRUE
) {
1061 if (ldp_attr_find_downstream_state2(g
, peer
, f
,
1062 LDP_LSP_STATE_REQ_SENT
) == NULL
) {
1064 * we don't have a request for FEC to peer outstanding
1067 if (ldp_label_request_for_xc(g
, peer
, &f
->info
, us_temp
,
1068 &ds_temp
) != MPLS_SUCCESS
) {
1069 retval
= MPLS_FAILURE
;
1074 if (ldp_label_mapping_with_xc(g
, peer
, f
, &us_temp
,
1075 ds_attr
) != MPLS_SUCCESS
) {
1076 retval
= MPLS_FAILURE
;
1080 * if we're not merging, we will need to request a label for
1083 if (g
->label_merge
== MPLS_BOOL_FALSE
) {
1084 need_request
= MPLS_BOOL_TRUE
;
1088 us_temp
= MPLS_LIST_NEXT(us_list
, us_temp
, _fs
);
1095 peer
= MPLS_LIST_NEXT(&g
->session
, peer
, _global
);
1099 LDP_EXIT(g
->user_data
, "ldp_label_mapping_process");
1103 LDP_PRINT(g
->user_data
, "Receive_Label_Map_32: send release");
1104 if (ldp_label_release_send(g
, s
, ds_attr
, LDP_NOTIF_NONE
) != MPLS_SUCCESS
) {
1105 retval
= MPLS_FAILURE
;
1107 LDP_EXIT(g
->user_data
, "ldp_label_mapping_process");