Re-work the adding/removing of ldp_if and ldp_addr.
[mpls-ldp-portable.git] / ldp / ldp_label_mapping.c
blob25f3393f48663c2ad2bb45fb05934a91e736d9d4
2 /*
3 * Copyright (C) James R. Leu 2000
4 * jleu@mindspring.com
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
8 */
10 #include "ldp_struct.h"
11 #include "ldp_session.h"
12 #include "ldp_attr.h"
13 #include "ldp_fec.h"
14 #include "ldp_mesg.h"
15 #include "ldp_notif.h"
16 #include "ldp_entity.h"
17 #include "ldp_inlabel.h"
18 #include "ldp_outlabel.h"
19 #include "ldp_nexthop.h"
20 #include "ldp_global.h"
21 #include "ldp_pdu_setup.h"
22 #include "ldp_label_rel_with.h"
23 #include "ldp_label_mapping.h"
24 #include "ldp_label_request.h"
26 #include "mpls_timer_impl.h"
27 #include "mpls_fib_impl.h"
28 #include "mpls_lock_impl.h"
29 #include "mpls_tree_impl.h"
30 #include "mpls_trace_impl.h"
31 #include "mpls_mm_impl.h"
32 #include "mpls_policy_impl.h"
34 #if MPLS_USE_LSR
35 #include "lsr_cfg.h"
36 #else
37 #include "mpls_mpls_impl.h"
38 #endif
40 mpls_return_enum ldp_label_mapping_with_xc(ldp_global * g, ldp_session * s,
41 ldp_fec * f, ldp_attr ** us_attr, ldp_attr * ds_attr)
43 mpls_return_enum result;
44 mpls_bool propogating = MPLS_BOOL_TRUE;
45 mpls_bool egress = MPLS_BOOL_TRUE;
47 MPLS_ASSERT(us_attr);
49 if (!(*us_attr)) {
50 if (!((*us_attr) = ldp_attr_create(&f->info))) {
51 return MPLS_FAILURE;
54 if (!ds_attr) {
55 propogating = MPLS_BOOL_FALSE;
56 egress = MPLS_BOOL_TRUE;
59 Prepare_Label_Mapping_Attributes(g, s, &f->info, ds_attr, (*us_attr),
60 propogating, MPLS_BOOL_TRUE, egress);
62 if (ldp_attr_insert_upstream2(g, s, (*us_attr), f) != MPLS_SUCCESS) {
63 ldp_attr_delete(*us_attr);
64 return MPLS_FATAL;
67 if (ldp_label_mapping_send(g, s, (*us_attr), ds_attr) != MPLS_SUCCESS) {
68 ldp_attr_delete(*us_attr);
69 return MPLS_FATAL;
72 if (ds_attr && ds_attr->outlabel) {
74 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
75 LDP_TRACE_FLAG_BINDING, "Cross Connect Added\n");
77 result = ldp_inlabel_add_outlabel(g,(*us_attr)->inlabel,ds_attr->outlabel);
78 if (result != MPLS_SUCCESS) {
79 ldp_label_withdraw_send(g, s, (*us_attr), LDP_NOTIF_NONE);
80 return MPLS_FATAL;
83 return MPLS_SUCCESS;
86 ldp_session *ldp_get_next_hop_session_for_fec2(ldp_fec * f, ldp_nexthop *nh) {
87 ldp_session *session = NULL;
89 * find the info about the next hop for this FEC
91 if (nh->addr && nh->addr->session_root.count > 0) {
92 session = mpls_link_list_head_data(&nh->addr->session_root);
93 } else if (nh->iff && nh->iff->is_p2p == MPLS_BOOL_TRUE &&
94 &nh->iff->entity) {
95 ldp_adj *adj = MPLS_LIST_HEAD(&nh->iff->entity->adj_root);
96 session = adj ? adj->session : NULL;
98 return session;
101 mpls_return_enum ldp_get_next_hop_session_for_fec(ldp_global * g,
102 mpls_fec * fec, mpls_nexthop *nh, ldp_session ** next_hop_session)
104 ldp_fec *f = NULL;
105 ldp_nexthop *n = NULL;
107 MPLS_ASSERT(next_hop_session);
109 if (!(f = ldp_fec_find(g, fec))) {
110 return MPLS_NO_ROUTE;
113 if (!(n = ldp_fec_nexthop_find(f, nh))) {
114 return MPLS_NO_ROUTE;
117 *next_hop_session = ldp_get_next_hop_session_for_fec2(f,n);
118 return (*next_hop_session) ? MPLS_SUCCESS : MPLS_FAILURE;
121 mpls_return_enum Check_Received_Attributes(ldp_global * g, ldp_session * s,
122 ldp_attr * r_attr, uint16_t type)
124 int count = 0;
125 int i;
127 if (!r_attr->hopCountTlvExists) { /* CRa.1 */
128 goto Check_Received_Attributes_5;
131 if (r_attr->hopCountTlv.hcValue >= s->cfg_hop_count_limit) { /* CRa.2 */
132 LDP_PRINT(g->user_data, "CRa.2\n");
133 goto Check_Received_Attributes_6;
136 if (!r_attr->pathVecTlvExists) { /* CRa.3 */
137 goto Check_Received_Attributes_5;
140 for (i = 0; i < MPLS_MAXHOPSNUMBER; i++) { /* CRa.4 */
141 if (r_attr->pathVecTlv.lsrId[i]) {
142 count++;
143 if (r_attr->pathVecTlv.lsrId[i] == g->lsr_identifier.u.ipv4) {
144 goto Check_Received_Attributes_6;
145 LDP_PRINT(g->user_data, "CRa.4a\n");
147 if (count > s->oper_path_vector_limit) {
148 goto Check_Received_Attributes_6;
149 LDP_PRINT(g->user_data, "CRa.4b\n");
154 Check_Received_Attributes_5:
155 return MPLS_SUCCESS;
157 Check_Received_Attributes_6:
158 if (type != MPLS_LBLMAP_MSGTYPE) {
159 ldp_notif_send(g, s, r_attr, LDP_NOTIF_LOOP_DETECTED); /* CRa.7 */
161 return MPLS_FAILURE; /* CRa.8 */
164 void Prepare_Label_Mapping_Attributes(ldp_global * g, ldp_session * s,
165 mpls_fec * fec, ldp_attr * r_attr, ldp_attr * s_attr, mpls_bool propogating,
166 mpls_bool already, mpls_bool egress)
168 ldp_attr dummy;
169 int i;
171 /* NOTE: PMpA.21 is the end of the procedure (ie return) */
172 /* this function uses goto quite extensivly for a REASON!! */
173 /* Check Appedix A of the LDP draft */
175 LDP_ENTER(g->user_data, "Prepare_Label_Mapping_Attributes");
177 if (!r_attr) {
178 memset(&dummy, 0, sizeof(ldp_attr));
179 mpls_fec2fec_tlv(fec, &dummy.fecTlv, 0);
180 dummy.fecTlvExists = 1;
181 dummy.fecTlv.numberFecElements = 1;
182 r_attr = &dummy;
185 if (!(s->oper_loop_detection == LDP_LOOP_HOPCOUNT ||
186 s->oper_loop_detection == LDP_LOOP_HOPCOUNT_PATHVECTOR ||
187 r_attr->hopCountTlvExists)) { /* PMpA.1 */
188 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
189 return;
192 if (egress) {/* PMpA.2 */
193 /* I'm egress (for now) */
194 s_attr->hopCountTlvExists = 1;
195 s_attr->hopCountTlv.hcValue = 1; /* PMpA.3 */
196 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
197 return;
200 if (!(r_attr->hopCountTlvExists)) { /* PMpA.4 */
201 goto Prepare_Label_Mapping_Attributes_8;
204 if (!(g->ttl_less_domain == MPLS_BOOL_TRUE &&
205 s->cfg_remote_in_ttl_less_domain == MPLS_BOOL_TRUE)) { /* PMpA.5 */
206 goto Prepare_Label_Mapping_Attributes_7;
209 s_attr->hopCountTlvExists = 1;
210 s_attr->hopCountTlv.hcValue = 1; /* PMpA.6 */
211 goto Prepare_Label_Mapping_Attributes_9;
213 Prepare_Label_Mapping_Attributes_7:
214 s_attr->hopCountTlvExists = 1;
215 s_attr->hopCountTlv.hcValue = (r_attr->hopCountTlv.hcValue) ?
216 (r_attr->hopCountTlv.hcValue + 1) : 0;
217 goto Prepare_Label_Mapping_Attributes_9;
219 Prepare_Label_Mapping_Attributes_8:
220 s_attr->hopCountTlvExists = 1;
221 s_attr->hopCountTlv.hcValue = 0;
223 Prepare_Label_Mapping_Attributes_9:
224 if (s->oper_loop_detection == LDP_LOOP_NONE) {
225 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
226 return;
229 if (r_attr->pathVecTlvExists) { /* PMpA.10 */
230 goto Prepare_Label_Mapping_Attributes_19;
233 if (propogating == MPLS_BOOL_FALSE) { /* PMpA.11 */
234 goto Prepare_Label_Mapping_Attributes_20;
237 if (g->label_merge != MPLS_BOOL_TRUE) { /* PMpA.12 */
238 goto Prepare_Label_Mapping_Attributes_14;
241 if (already == MPLS_BOOL_FALSE) { /* PMpA.13 */
242 goto Prepare_Label_Mapping_Attributes_20;
245 Prepare_Label_Mapping_Attributes_14:
246 if (!r_attr->hopCountTlvExists) {
247 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
248 return;
251 if (r_attr->hopCountTlv.hcValue == 0) { /* PMpA.15 */
252 goto Prepare_Label_Mapping_Attributes_20;
255 if (already == MPLS_BOOL_FALSE) { /* PMpA.16 */
256 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
257 return;
260 /* r_attr contain PrevHopCount _IF_ we had one */
261 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
262 return; /* PMpA.17 */
264 if (r_attr->hopCountTlv.hcValue != 0) { /* PMpA.18 */
265 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
266 return;
269 Prepare_Label_Mapping_Attributes_19:
270 s_attr->pathVecTlvExists = 1;
271 s_attr->pathVecTlv.lsrId[0] = g->lsr_identifier.u.ipv4;
272 for (i = 1; i < (MPLS_MAXHOPSNUMBER - 1); i++) {
273 if (r_attr->pathVecTlv.lsrId[i - 1]) {
274 s_attr->pathVecTlv.lsrId[0] = r_attr->pathVecTlv.lsrId[i - 1];
278 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
279 return;
281 Prepare_Label_Mapping_Attributes_20:
282 s_attr->pathVecTlvExists = 1;
283 s_attr->pathVecTlv.lsrId[0] = g->lsr_identifier.u.ipv4;
285 LDP_EXIT(g->user_data, "Prepare_Label_Mapping_Attributes");
286 return;
289 void map2attr(mplsLdpLblMapMsg_t * map, ldp_attr * attr, uint32_t flag)
291 attr->msg_id = map->baseMsg.msgId;
293 if (map->fecTlvExists && flag & LDP_ATTR_FEC) {
294 memcpy(&attr->fecTlv, &map->fecTlv, sizeof(mplsLdpFecTlv_t));
295 attr->fecTlvExists = 1;
297 if (map->genLblTlvExists && flag & LDP_ATTR_LABEL) {
298 memcpy(&attr->genLblTlv, &map->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
299 attr->genLblTlvExists = 1;
300 } else if (map->atmLblTlvExists && flag & LDP_ATTR_LABEL) {
301 memcpy(&attr->atmLblTlv, &map->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
302 attr->atmLblTlvExists = 1;
303 } else if (map->frLblTlvExists && flag & LDP_ATTR_LABEL) {
304 memcpy(&attr->frLblTlv, &map->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
305 attr->frLblTlvExists = 1;
307 if (map->hopCountTlvExists && flag & LDP_ATTR_HOPCOUNT) {
308 memcpy(&attr->hopCountTlv, &map->hopCountTlv, sizeof(mplsLdpHopTlv_t));
309 attr->hopCountTlvExists = 1;
311 if (map->pathVecTlvExists && flag & LDP_ATTR_PATH) {
312 memcpy(&attr->pathVecTlv, &map->pathVecTlv, sizeof(mplsLdpPathTlv_t));
313 attr->pathVecTlvExists = 1;
315 if (map->lblMsgIdTlvExists && flag & LDP_ATTR_MSGID) {
316 memcpy(&attr->lblMsgIdTlv, &map->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
317 attr->lblMsgIdTlvExists = 1;
319 if (map->lspidTlvExists && flag & LDP_ATTR_LSPID) {
320 memcpy(&attr->lspidTlv, &map->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
321 attr->lspidTlvExists = 1;
323 if (map->trafficTlvExists && flag & LDP_ATTR_TRAFFIC) {
324 memcpy(&attr->trafficTlv, &map->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
325 attr->trafficTlvExists = 1;
329 void attr2map(ldp_attr * attr, mplsLdpLblMapMsg_t * map)
331 if (attr->fecTlvExists) {
332 memcpy(&map->fecTlv, &attr->fecTlv, sizeof(mplsLdpFecTlv_t));
333 map->fecTlvExists = 1;
335 if (attr->genLblTlvExists) {
336 memcpy(&map->genLblTlv, &attr->genLblTlv, sizeof(mplsLdpGenLblTlv_t));
337 map->genLblTlvExists = 1;
339 if (attr->atmLblTlvExists) {
340 memcpy(&map->atmLblTlv, &attr->atmLblTlv, sizeof(mplsLdpAtmLblTlv_t));
341 map->atmLblTlvExists = 1;
343 if (attr->frLblTlvExists) {
344 memcpy(&map->frLblTlv, &attr->frLblTlv, sizeof(mplsLdpFrLblTlv_t));
345 map->frLblTlvExists = 1;
347 if (attr->hopCountTlvExists) {
348 memcpy(&map->hopCountTlv, &attr->hopCountTlv, sizeof(mplsLdpHopTlv_t));
349 map->hopCountTlvExists = 1;
351 if (attr->pathVecTlvExists) {
352 memcpy(&map->pathVecTlv, &attr->pathVecTlv, sizeof(mplsLdpPathTlv_t));
353 map->pathVecTlvExists = 1;
355 if (attr->lblMsgIdTlvExists) {
356 memcpy(&map->lblMsgIdTlv, &attr->lblMsgIdTlv, sizeof(mplsLdpLblMsgIdTlv_t));
357 map->lblMsgIdTlvExists = 1;
359 if (attr->lspidTlvExists) {
360 memcpy(&map->lspidTlv, &attr->lspidTlv, sizeof(mplsLdpLspIdTlv_t));
361 map->lspidTlvExists = 1;
363 if (attr->trafficTlvExists) {
364 memcpy(&map->trafficTlv, &attr->trafficTlv, sizeof(mplsLdpTrafficTlv_t));
365 map->trafficTlvExists = 1;
369 void ldp_label_mapping_initial_callback(mpls_timer_handle timer, void *extra,
370 mpls_cfg_handle handle)
372 ldp_session *s = (ldp_session *) extra;
373 ldp_global *g = (ldp_global*)handle;
374 ldp_attr *ds_attr = NULL;
375 ldp_attr *us_attr = NULL;
376 ldp_session *nh_session = NULL;
377 mpls_bool done = MPLS_BOOL_FALSE;
378 ldp_fec *f;
379 ldp_nexthop *nh;
381 LDP_ENTER(g->user_data, "ldp_label_mapping_initial_callback");
383 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_TIMER,
384 "Initial Label Mapping fired: session(%d)\n", s->index);
386 mpls_lock_get(g->global_lock);
388 mpls_timer_stop(g->timer_handle, timer);
390 if ((f = MPLS_LIST_HEAD(&g->fec))) {
391 do {
392 if ((nh = MPLS_LIST_HEAD(&f->nh_root))) {
393 do {
394 switch (f->info.type) {
395 case MPLS_FEC_PREFIX:
396 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
397 LDP_TRACE_FLAG_ROUTE, "Processing prefix FEC: %08x/%d ",
398 f->info.u.prefix.network.u.ipv4, f->info.u.prefix.length);
399 break;
400 case MPLS_FEC_HOST:
401 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
402 LDP_TRACE_FLAG_ROUTE, "Processing host FEC: %08x ",
403 f->info.u.host.u.ipv4);
404 break;
405 case MPLS_FEC_L2CC:
406 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
407 LDP_TRACE_FLAG_ROUTE, "Processingu L2CC FEC: %d %d %d ",
408 f->info.u.l2cc.connection_id, f->info.u.l2cc.group_id,
409 f->info.u.l2cc.type);
410 break;
411 default:
412 MPLS_ASSERT(0);
415 if (nh->type & MPLS_NH_IP) {
416 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
417 LDP_TRACE_FLAG_ROUTE, "via %08x\n", nh->addr->address.u.ipv4);
419 if (nh->type & MPLS_NH_IF) {
420 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
421 LDP_TRACE_FLAG_ROUTE, "via %s\n", nh->iff->name);
424 /* are we allowed to export this route from the rib */
425 if (mpls_policy_export_check(g->user_data, &f->info, &nh->info) ==
426 MPLS_BOOL_FALSE) {
427 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
428 LDP_TRACE_FLAG_POLICY, "Rejected by export policy\n");
429 continue;
432 /* have we already sent a mapping for this fec to the new session? */
433 if ((us_attr = ldp_attr_find_upstream_state2(g, s, f,
434 LDP_LSP_STATE_MAP_SENT))) {
435 /* no need to sent another mapping */
436 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
437 LDP_TRACE_FLAG_ROUTE, "Already sent this FEC to session %d\n",
438 s->index);
439 continue;
442 if (!(nh_session = ldp_get_next_hop_session_for_fec2(f,nh))) {
443 ds_attr = NULL;
444 } else {
445 if (nh_session->index == s->index) {
446 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL,
447 LDP_TRACE_FLAG_ROUTE, "Nexthop session(%d) == session(%d)\n",
448 nh_session->index, s->index);
449 continue;
451 ds_attr = ldp_attr_find_downstream_state2(g, nh_session, f,
452 LDP_LSP_STATE_MAP_RECV);
455 if ((g->label_merge != MPLS_BOOL_TRUE) &&
456 ldp_attr_num_us2ds(ds_attr)) {
457 /* we have a ds label, but can't use it */
458 ds_attr = NULL;
461 us_attr = NULL;
462 if (ds_attr) {
463 /* we can use it, merge on baby */
464 ldp_label_mapping_with_xc(g, s, f, &us_attr, ds_attr);
465 } else {
466 /* we don't have a ds label */
468 /* we will be egress? */
469 if (g->lsp_control_mode == LDP_CONTROL_ORDERED) {
470 if (mpls_policy_egress_check(g->user_data, &f->info,
471 &nh->info) == MPLS_BOOL_TRUE) {
472 ldp_label_mapping_with_xc(g, s, f, &us_attr, NULL);
474 } else {
475 ldp_label_mapping_with_xc(g, s, f, &us_attr, NULL);
478 } while ((nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec)));
480 } while ((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
481 done = MPLS_BOOL_TRUE;
484 done = MPLS_BOOL_TRUE;
486 if (done == MPLS_BOOL_TRUE) {
487 mpls_timer_delete(g->timer_handle, timer);
488 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
489 s->initial_distribution_timer = (mpls_timer_handle) 0;
490 } else {
491 mpls_timer_start(g->timer_handle, timer, MPLS_TIMER_ONESHOT);
492 /* need to mark the session with where it left off */
495 mpls_lock_release(g->global_lock);
497 LDP_EXIT(g->user_data, "ldp_label_mapping_initial_callback");
500 mpls_return_enum ldp_label_mapping_send(ldp_global * g, ldp_session * s,
501 ldp_attr * us_attr, ldp_attr * ds_attr)
503 ldp_inlabel *in = NULL;
504 ldp_attr *us_temp;
506 LDP_ENTER(g->user_data, "ldp_label_mapping_send");
507 MPLS_ASSERT(us_attr);
509 if ((in = ldp_inlabel_create_complete(g, s, us_attr)) == NULL) { /* SL.1-3 */
510 goto Send_Label_9;
513 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_BINDING,
514 "In Label Added\n");
516 us_attr->state = LDP_LSP_STATE_MAP_SENT;
518 us_attr->msg_id = g->message_identifier;
519 ldp_label_mapping_prepare_msg(s->tx_message, g->message_identifier++,
520 us_attr);
522 if (ldp_mesg_send_tcp(g, s, s->tx_message) != MPLS_SUCCESS) { /* SL.4 */
523 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_ERROR,
524 "Failed sending Label Mapping to %s\n",
525 s->session_name);
526 goto ldp_label_mapping_send_error;
529 ldp_attr_add_us2ds(us_attr, ds_attr);
531 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_LABEL,
532 "Label Mapping Sent to %s for %08x/%d\n",
533 s->session_name,
534 us_attr->fecTlv.fecElArray[0].addressEl.address,
535 us_attr->fecTlv.fecElArray[0].addressEl.preLen);
537 us_attr->state = LDP_LSP_STATE_MAP_SENT; /* SL.6,7 */
539 LDP_EXIT(g->user_data, "ldp_label_mapping_send");
540 return MPLS_SUCCESS; /* SL.8 */
542 Send_Label_9:
543 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_STATE,
544 "No Label Resources\n");
546 while ((us_temp = ldp_attr_find_upstream_state2(g, s, us_attr->fec,
547 LDP_LSP_STATE_REQ_RECV)) != NULL) { /* SL.9 */
548 ldp_notif_send(g, s, us_temp, LDP_NOTIF_NO_LABEL_RESOURCES_AVAILABLE);
549 /* SL.10 */
550 s->no_label_resource_sent = MPLS_BOOL_TRUE; /* SL.12 */
551 us_temp->state = LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT; /* SL.13 */
554 LDP_EXIT(g->user_data, "ldp_label_mapping_send");
556 return MPLS_SUCCESS;
558 ldp_label_mapping_send_error:
560 LDP_EXIT(g->user_data, "ldp_label_mapping_send-error");
561 return MPLS_FAILURE;
564 void ldp_label_mapping_prepare_msg(ldp_mesg * msg, uint32_t msgid,
565 ldp_attr * s_attr)
567 mplsLdpLblMapMsg_t *map = NULL;
568 int i;
570 MPLS_ASSERT(msg);
572 ldp_mesg_prepare(msg, MPLS_LBLMAP_MSGTYPE, msgid);
573 map = &msg->u.map;
575 if (s_attr->fecTlvExists) {
576 /* JLEU: only 1 FEC is allowed!! */
577 map->fecTlvExists = 1;
578 map->baseMsg.msgLength += setupFecTlv(&map->fecTlv);
579 map->baseMsg.msgLength += addFecElem2FecTlv(&map->fecTlv,
580 &s_attr->fecTlv.fecElArray[0]);
582 if (s_attr->genLblTlvExists) {
583 map->genLblTlvExists = 1;
584 map->baseMsg.msgLength += setupGenLblTlv(&map->genLblTlv,
585 s_attr->genLblTlv.label);
587 if (s_attr->atmLblTlvExists) {
588 map->atmLblTlvExists = 1;
589 map->baseMsg.msgLength += setupAtmLblTlv(&map->atmLblTlv, 0, 0,
590 s_attr->atmLblTlv.flags.flags.vpi, s_attr->atmLblTlv.vci);
592 if (s_attr->frLblTlvExists) {
593 map->frLblTlvExists = 1;
594 map->baseMsg.msgLength += setupFrLblTlv(&map->frLblTlv, 0,
595 s_attr->frLblTlv.flags.flags.len, s_attr->frLblTlv.flags.flags.dlci);
597 if (s_attr->hopCountTlvExists) {
598 map->hopCountTlvExists = 1;
599 map->baseMsg.msgLength += setupHopCountTlv(&map->hopCountTlv,
600 s_attr->hopCountTlv.hcValue);
602 if (s_attr->pathVecTlvExists) {
603 map->pathVecTlvExists = 1;
604 map->baseMsg.msgLength += setupPathTlv(&map->pathVecTlv);
605 for (i = 0; i < MPLS_MAXHOPSNUMBER; i++) {
606 if (s_attr->pathVecTlv.lsrId[i]) {
607 map->baseMsg.msgLength += addLsrId2PathTlv(&map->pathVecTlv,
608 s_attr->pathVecTlv.lsrId[i]);
612 #if 0
613 if (s_attr->lblMsgIdTlvExists) {
615 if (s_attr->lspidTlvExists) {
617 if (s_attr->trafficTlvExists) {
619 #endif
622 mpls_return_enum ldp_label_mapping_process(ldp_global * g, ldp_session * s,
623 ldp_adj * a, ldp_entity * e, ldp_attr * r_attr, ldp_fec * f)
625 mpls_return_enum retval = MPLS_SUCCESS;
626 ldp_session *peer = NULL;
627 ldp_attr_list *us_list = NULL;
628 ldp_attr_list *ds_list = NULL;
629 ldp_attr *ds_attr = NULL;
630 ldp_attr *ds_temp = NULL;
631 ldp_attr *us_attr = NULL;
632 ldp_attr *us_temp = NULL;
633 ldp_attr dumb_attr;
634 ldp_nexthop *nh = NULL;
636 ldp_outlabel *out = NULL;
637 mpls_bool requested = MPLS_BOOL_FALSE;
638 ldp_attr *update = NULL;
639 mpls_bool need_request = MPLS_BOOL_FALSE;
641 LDP_ENTER(g->user_data, "ldp_label_mapping_process");
643 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
644 "Label Mapping Recv from %s for %08x/%d\n",
645 s->session_name,
646 r_attr->fecTlv.fecElArray[0].addressEl.address,
647 r_attr->fecTlv.fecElArray[0].addressEl.preLen);
649 if ((ds_attr = ldp_attr_find_downstream_state2(g, s, f,
650 LDP_LSP_STATE_REQ_SENT)) != NULL) { /* LMp.1 */
651 /* just remove the req from the tree, we will use the r_attr sent to us */
652 ldp_attr_delete_downstream(g, s, ds_attr);
653 requested = MPLS_BOOL_TRUE;
654 } else {
655 requested = MPLS_BOOL_FALSE;
658 ds_attr = r_attr;
659 ds_attr->state = LDP_LSP_STATE_MAP_RECV; /* LMp.2 */
662 * ds_attr is the mapping we will keep and is NOT in the tree, unless
663 * it is an update mapping ...
665 if (Check_Received_Attributes(g, s, ds_attr, MPLS_LBLMAP_MSGTYPE) ==
666 MPLS_SUCCESS) { /* LMp.3 */
667 goto LMp_9;
671 * A loop was detected
673 if ((ds_list = ldp_attr_find_downstream_all2(g, s, f))) {
674 ds_temp = MPLS_LIST_HEAD(ds_list);
676 * check all the labels this session has received from "s" for "fec"
677 * do we have a duplicat?
679 while (ds_temp) {
680 if ((ds_temp->state == LDP_LSP_STATE_MAP_RECV) && /* LMp.4 */
681 ldp_attr_is_equal(ds_temp, ds_attr, LDP_ATTR_LABEL) == /* LMp.5 */
682 MPLS_BOOL_TRUE) {
683 /* remove record of the label and remove it switching */
684 ldp_attr_remove_complete(g, ds_temp, MPLS_BOOL_TRUE); /* LMp.6,7 */
686 * I think this is supposed to be 32 NOT 33, we need to release
687 * it don't we?
689 goto LMp_33;
691 ds_temp = MPLS_LIST_NEXT(ds_list, ds_temp, _fs);
695 LDP_PRINT(g->user_data, "Receive_Label_Map_8: send release");
696 if (ldp_label_release_send(g, s, ds_attr, LDP_NOTIF_LOOP_DETECTED) !=
697 MPLS_SUCCESS) { /* LMp.8 */
698 retval = MPLS_FAILURE;
700 goto LMp_33;
702 LMp_9:
704 * No Loop Detected
706 ds_temp = ldp_attr_find_downstream_state2(g, s, f, LDP_LSP_STATE_MAP_RECV);
707 if (requested == MPLS_BOOL_TRUE ||
708 g->label_merge == MPLS_BOOL_FALSE || !ds_temp) {
709 /* !merging then this is always a new LSP
710 * merging w/o a recv'd mapping is a new LSP
711 * this check comes from Note 6
713 goto LMp_11;
716 /* searching all recv'd attrs for matched mappings,
717 * stop after finding 1st match
719 if ((ds_list = ldp_attr_find_downstream_all2(g, s, f))) {
720 ds_temp = MPLS_LIST_HEAD(ds_list);
721 while (ds_temp) {
722 if (ds_temp->state == LDP_LSP_STATE_MAP_RECV) { /* LMp.9 */
723 if (ldp_attr_is_equal(ds_attr, ds_temp, LDP_ATTR_LABEL) ==
724 MPLS_BOOL_TRUE) { /* LMp.10 */
726 * this mapping matches an existing mapping, but it
727 * could contain updated attributes
729 update = ds_temp;
730 break;
731 } else {
733 * we have been given another label for the same FEC and we
734 * didn't request it, release it
736 LDP_PRINT(g->user_data, "LMp.10 dup without req\n");
737 goto LMp_32;
740 ds_temp = MPLS_LIST_NEXT(ds_list, ds_temp, _fs);
744 LMp_11:
746 * update ONLY has a value for updated label mapping
748 /* LMp.11 */
749 nh = ldp_nexthop_for_fec_session(f,s);
752 * the following departs from the procedure, it allows for filtering
753 * of label mappings
755 * Are we configured to accept and INSTALL this mapping?
757 if (mpls_policy_import_check(g->user_data, &f->info, &nh->info) ==
758 MPLS_BOOL_FALSE) {
760 * policy has rejected it, store it away
762 if (update) {
763 ldp_attr2ldp_attr(ds_attr, update, LDP_ATTR_HOPCOUNT | LDP_ATTR_PATH |
764 LDP_ATTR_MSGID | LDP_ATTR_LSPID | LDP_ATTR_TRAFFIC);
765 /* JLEU free ds_attr? */
766 update->filtered = MPLS_BOOL_TRUE;
767 if (update->outlabel && update->outlabel->switching == MPLS_BOOL_TRUE) {
768 /* the mapping has been filtered, but the original wasn't? */
769 MPLS_ASSERT(0);
771 } else {
772 ds_attr->filtered = MPLS_BOOL_TRUE;
773 if (ldp_attr_insert_downstream(g, s, ds_attr) != MPLS_SUCCESS) {
774 retval = MPLS_FAILURE;
777 goto LMp_33;
780 /* LMp.12 */
781 if ((!f) || (!nh)) {
783 * if we don't know about the route, or we don't have a next hop session,
784 * or the next hop session isn't the one who sent us the mapping ....
786 if (g->label_retention_mode == LDP_RETENTION_CONSERVATIVE) { /* LMp.13C */
787 LDP_PRINT(g->user_data, "LMp.13C conservative\n");
788 goto LMp_32;
792 * store it away
794 LDP_PRINT(g->user_data, "index: %3d %08x/%d %d\n", ds_attr->index,
795 ds_attr->fecTlv.fecElArray[0].addressEl.address,
796 ds_attr->fecTlv.fecElArray[0].addressEl.preLen, ds_attr->state);
798 if (update) {
799 ldp_attr2ldp_attr(ds_attr, update, LDP_ATTR_HOPCOUNT | LDP_ATTR_PATH |
800 LDP_ATTR_MSGID | LDP_ATTR_LSPID | LDP_ATTR_TRAFFIC);
801 /* JLEU free ds_attr? */
802 } else {
803 /* LMp.13L */
804 if (ldp_attr_insert_downstream(g, s, ds_attr) != MPLS_SUCCESS) {
805 retval = MPLS_FAILURE;
808 goto LMp_33;
812 * this is slightly different form the procedure, we can still be
813 * transit for a FEC we are not configured to be ingress for.
814 * Either way we only need to do the "install for fwd/switching"
815 * only once. We could arrive here multiple times due to updates,
816 * only install it the first time
818 if ((!update) || (!update->outlabel)) {
820 * we haven't installed it yet.
821 * Either new (!update), or a result of a "Detect FEC Nexthop Change"
822 * and we had this mapping in our database (!update->outlabel))
825 if (!(out = ldp_outlabel_create_complete(g, s, ds_attr, nh))) {
826 LDP_PRINT(g->user_data, "LMp.15 failure creating outlabel\n");
827 goto LMp_32;
830 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_BINDING,
831 "Out Label Added\n");
835 * are we configured to act as ingress for this FEC?
837 if (mpls_policy_ingress_check(g->user_data, &f->info, &nh->info) ==
838 MPLS_BOOL_TRUE) { /* LMp.14 */
840 * yep, bind the label to the FEC
842 if (ds_attr->ingress != MPLS_BOOL_TRUE) {
843 #if MPLS_USE_LSR
844 lsr_ftn ftn;
845 ftn.outsegment_index = ds_attr->outlabel->info.handle;
846 memcpy(&ftn.fec, &f->info, sizeof(mpls_fec));
847 lsr_cfg_ftn_set2(g->lsr_handle, &ftn, LSR_CFG_ADD|LSR_FTN_CFG_FEC|
848 LSR_FTN_CFG_OUTSEGMENT);
849 #else
850 mpls_mpls_fec2out_add(g->mpls_handle, &f->info, &ds_attr->outlabel->info);
851 #endif
852 ds_attr->ingress = MPLS_BOOL_TRUE;
853 ds_attr->outlabel->merge_count++;
854 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_BINDING,
855 "FEC Binding Added\n");
859 /* create a set of attrs that we will fill and compare against
860 * if this mapping were to be propogate these are the attrs it would have
861 * by comparing what we did sent in the past to these, we con figure out
862 * if we need to send an updated mapping
864 memset(&dumb_attr, 0, sizeof(ldp_attr));
865 mpls_fec2fec_tlv(&f->info, &dumb_attr.fecTlv, 0);
866 dumb_attr.fecTlvExists = 1;
867 dumb_attr.fecTlv.numberFecElements = 1;
870 * by definition (we received a label mapping that will be used) this
871 * LSR is _not_ the egress, so calculate a hop and path based on the
872 * mapping we received. We will compare this with mapping that have
873 * already been sent. If they differ, we will send an updated mapping
875 Prepare_Label_Mapping_Attributes(g, s, &f->info, ds_attr, &dumb_attr,
876 MPLS_BOOL_TRUE, MPLS_BOOL_TRUE, MPLS_BOOL_FALSE);
878 if (!update) {
880 * this is the first time we've seen this mapping, add it to the database.
881 * all future updates will modify this entry in place
883 /* LMp.16 */
884 if (ldp_attr_insert_downstream(g, s, ds_attr) != MPLS_SUCCESS) {
885 retval = MPLS_FAILURE;
886 goto LMp_33;
890 #if 0
891 if (update) {
893 * this is an update, propogate update to all member of this LSP
895 us_temp = MPLS_LIST_HEAD(&ds_attr->us_attr_root);
896 while (us_temp) {
897 us_temp = MPLS_LIST_NEXT(&ds_attr->us_attr_root, us_temp, _ds_attr);
900 #endif
902 peer = MPLS_LIST_HEAD(&g->session);
903 while (peer) { /* LMp.17 */
905 if (peer->state != LDP_STATE_OPERATIONAL ||
906 peer->index == s->index) {
907 /* peer equals msg source */
908 goto next_peer;
911 /* check to see if a upstream mapping has been xc'd to this
912 * downstream mapping for this session. If so we need to propogate
913 * the attr changes (if any)
915 us_temp = MPLS_LIST_HEAD(&ds_attr->us_attr_root);
916 while (us_temp) {
917 if (us_temp->session->index == peer->index) {
918 break;
920 us_temp = MPLS_LIST_NEXT(&ds_attr->us_attr_root, us_temp, _ds_attr);
923 if (us_temp) { /* LMp.18 */
924 /* LMp.22 - 27 */
925 if ((us_list = ldp_attr_find_upstream_all2(g, peer, f))) {
926 us_temp = MPLS_LIST_HEAD(us_list);
927 while (us_temp) {
928 if (us_temp->state == LDP_LSP_STATE_MAP_SENT) {
929 /* LMp.23 */
930 if (ldp_attr_is_equal(us_temp, &dumb_attr,
931 LDP_ATTR_HOPCOUNT | LDP_ATTR_PATH) != MPLS_BOOL_TRUE) {
932 if (ldp_label_mapping_with_xc(g, us_temp->session, f, &us_temp,
933 ds_attr) != MPLS_SUCCESS) { /* LMp.24-26 */
934 retval = MPLS_FAILURE;
935 goto LMp_33;
939 us_temp = MPLS_LIST_NEXT(us_list, us_temp, _fs);
944 if ((peer->oper_distribution_mode == LDP_DISTRIBUTION_UNSOLICITED) &&
945 (g->lsp_control_mode == LDP_CONTROL_ORDERED)) { /* LMp.19 */
948 * if we're not merging and we have multiple ORDERED DU sessions,
949 * we will to start requesting labels after we propogate the mapping to
950 * the first peer
952 if (need_request == MPLS_BOOL_TRUE) {
953 if (ldp_attr_find_downstream_state2(g, peer, f,
954 LDP_LSP_STATE_REQ_SENT) == NULL) {
956 * we don't have a request for FEC to peer outstanding, make one
958 ds_temp = NULL;
959 if (ldp_label_request_for_xc(g, peer, &f->info, NULL, &ds_temp) !=
960 MPLS_SUCCESS) {
961 retval = MPLS_FAILURE;
962 goto LMp_33;
965 } else {
967 * We're in DU more, either we're merging, or we're not merging and
968 * this is the first peer we're propogating this mapping to
970 /* LMp.20-21,30 */
971 us_attr = NULL;
972 if (ldp_label_mapping_with_xc(g, peer, f, &us_attr, ds_attr) !=
973 MPLS_SUCCESS) {
974 retval = MPLS_FAILURE;
975 goto LMp_33;
978 * if we're not merging, we will need to request a label for
979 * the next DU peer
981 if (g->label_merge == MPLS_BOOL_FALSE) {
982 need_request = MPLS_BOOL_TRUE;
987 /* LMp.28 */
988 while ((us_temp = ldp_attr_find_upstream_state2(g, peer, f,
989 LDP_LSP_STATE_REQ_RECV))) {
991 if (peer->oper_distribution_mode == LDP_DISTRIBUTION_UNSOLICITED) {
992 if (need_request == MPLS_BOOL_TRUE) {
993 if (ldp_attr_find_downstream_state2(g, peer, f,
994 LDP_LSP_STATE_REQ_SENT) == NULL) {
996 * we don't have a request for FEC to peer outstanding
998 ds_temp = NULL;
999 if (ldp_label_request_for_xc(g, peer, &f->info, us_temp,
1000 &ds_temp) != MPLS_SUCCESS) {
1001 retval = MPLS_FAILURE;
1002 goto LMp_33;
1005 } else {
1006 if (ldp_label_mapping_with_xc(g, peer, f, &us_temp,
1007 ds_attr) != MPLS_SUCCESS) {
1008 retval = MPLS_FAILURE;
1009 goto LMp_33;
1012 } else {
1013 if ((us_list = ldp_attr_find_upstream_all2(g, peer, f))) {
1014 us_temp = MPLS_LIST_HEAD(ds_list);
1015 while (us_temp) {
1016 if (us_temp->state == LDP_LSP_STATE_REQ_RECV) {
1017 if (need_request == MPLS_BOOL_TRUE) {
1018 if (ldp_attr_find_downstream_state2(g, peer, f,
1019 LDP_LSP_STATE_REQ_SENT) == NULL) {
1021 * we don't have a request for FEC to peer outstanding
1023 ds_temp = NULL;
1024 if (ldp_label_request_for_xc(g, peer, &f->info, us_temp,
1025 &ds_temp) != MPLS_SUCCESS) {
1026 retval = MPLS_FAILURE;
1027 goto LMp_33;
1030 } else {
1031 if (ldp_label_mapping_with_xc(g, peer, f, &us_temp,
1032 ds_attr) != MPLS_SUCCESS) {
1033 retval = MPLS_FAILURE;
1034 goto LMp_33;
1037 * if we're not merging, we will need to request a label for
1038 * the next DU peer
1040 if (g->label_merge == MPLS_BOOL_FALSE) {
1041 need_request = MPLS_BOOL_TRUE;
1045 us_temp = MPLS_LIST_NEXT(us_list, us_temp, _fs);
1051 next_peer:
1052 peer = MPLS_LIST_NEXT(&g->session, peer, _global);
1055 LMp_33:
1056 LDP_EXIT(g->user_data, "ldp_label_mapping_process");
1057 return retval;
1059 LMp_32:
1060 LDP_PRINT(g->user_data, "Receive_Label_Map_32: send release");
1061 if (ldp_label_release_send(g, s, ds_attr, LDP_NOTIF_NONE) != MPLS_SUCCESS) {
1062 retval = MPLS_FAILURE;
1064 LDP_EXIT(g->user_data, "ldp_label_mapping_process");
1065 return retval;