mpls_return_enum ldp_attr_insert_upstream(ldp_global * g, ldp_session * s, ldp_attr * a) { ldp_fec *fnode = NULL; MPLS_ASSERT(g && s && a && (a->in_tree == MPLS_BOOL_FALSE)); if ((fnode = _ldp_attr_get_fec(g, a, MPLS_BOOL_TRUE)) == NULL) { /* we couldn't get/add a node from/to the tree! */ return MPLS_FAILURE; } return ldp_attr_insert_upstream2(g, s, a, fnode); }
mpls_return_enum ldp_label_request_process(ldp_global * g, ldp_session * s, ldp_adj * a, ldp_entity * e, ldp_attr * us_attr, ldp_fec * f) { ldp_session *nh_session = NULL; ldp_nexthop *nh = NULL; ldp_attr_list *us_list = NULL; mpls_bool egress = MPLS_BOOL_FALSE; ldp_attr *ds_attr = NULL; ldp_attr *us_temp = NULL; if (Check_Received_Attributes(g, s, us_attr, MPLS_LBLREQ_MSGTYPE) != MPLS_SUCCESS) { /* LRp.1 */ goto LRq_13; } if (f == NULL) { ldp_notif_send(g, s, us_attr, LDP_NOTIF_NO_ROUTE); /* LRq.5 */ goto LRq_13; } /* just find one valid nexthop session for now */ nh = MPLS_LIST_HEAD(&f->nh_root); while (nh) { nh_session = ldp_session_for_nexthop(nh); if (nh_session) { break; } nh = MPLS_LIST_NEXT(&f->nh_root, nh, _fec); } if (!nh_session) { egress = MPLS_BOOL_TRUE; } if (nh_session != NULL && s->index == nh_session->index) { /* LRq.3 */ ldp_notif_send(g, s, us_attr, LDP_NOTIF_LOOP_DETECTED); /* LRq.4 */ goto LRq_13; } if ((us_list = ldp_attr_find_upstream_all2(g, s, f)) != NULL) { us_temp = MPLS_LIST_HEAD(us_list); while (us_temp != NULL) { if (us_temp->state == LDP_LSP_STATE_REQ_RECV && /* LRq.6 */ us_temp->msg_id == us_attr->msg_id) { /* LRq.7 */ goto LRq_13; } us_temp = MPLS_LIST_NEXT(us_list, us_temp, _fs); } } us_attr->state = LDP_LSP_STATE_REQ_RECV; /* LRq.8 */ if (ldp_attr_insert_upstream2(g, s, us_attr, f) != MPLS_SUCCESS) { LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_ERROR, "Couldn't insert recv attributes in tree\n"); goto ldp_label_request_process_error; } if (nh_session) { ds_attr = ldp_attr_find_downstream_state2(g, nh_session, f, LDP_LSP_STATE_MAP_RECV); } else { ds_attr = NULL; } if (g->lsp_control_mode == LDP_CONTROL_INDEPENDENT) { /* LRq.9 */ if (ldp_label_mapping_with_xc(g, s, f, &us_attr, ds_attr) != MPLS_SUCCESS) { goto ldp_label_request_process_error; } if (egress == MPLS_BOOL_TRUE || ds_attr) { goto LRq_11; } } else { if ((!(egress == MPLS_BOOL_TRUE || ds_attr)) || (g->label_merge == MPLS_BOOL_FALSE)) { goto LRq_10; } if (ldp_label_mapping_with_xc(g, s, f, &us_attr, ds_attr) != MPLS_SUCCESS) { goto ldp_label_request_process_error; } goto LRq_11; } LRq_10: ds_attr = NULL; if (ldp_label_request_for_xc(g, nh_session, &f->info, us_attr, &ds_attr) != MPLS_SUCCESS) { goto ldp_label_request_process_error; } LRq_11: /* the work done by LRq_11 is handled in ldp_label_mapping_with_xc() */ LRq_13: if (ds_attr != NULL && ds_attr->in_tree == MPLS_BOOL_FALSE) { ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); } return MPLS_SUCCESS; ldp_label_request_process_error: return MPLS_FAILURE; }
mpls_return_enum ldp_label_mapping_with_xc(ldp_global * g, ldp_session * s, ldp_fec * f, ldp_attr ** us_attr, ldp_attr * ds_attr) { mpls_return_enum result = MPLS_SUCCESS; mpls_bool propogating = MPLS_BOOL_TRUE; mpls_bool egress = MPLS_BOOL_TRUE; mpls_bool created = MPLS_BOOL_FALSE; MPLS_ASSERT(us_attr); if (!(*us_attr)) { if (!((*us_attr) = ldp_attr_create(&f->info))) { return MPLS_FAILURE; } created = MPLS_BOOL_TRUE; } if (!ds_attr) { propogating = MPLS_BOOL_FALSE; egress = MPLS_BOOL_TRUE; } Prepare_Label_Mapping_Attributes(g, s, &f->info, ds_attr, (*us_attr), propogating, MPLS_BOOL_TRUE, egress); result = ldp_label_mapping_send(g, s, f, (*us_attr), ds_attr); if (result != MPLS_SUCCESS) { if (created == MPLS_BOOL_TRUE) { ldp_attr_delete(*us_attr); } return result; } if (created == MPLS_BOOL_TRUE) { result = ldp_attr_insert_upstream2(g, s, (*us_attr), f); if (result != MPLS_SUCCESS) { ldp_attr_delete(*us_attr); return result; } } /* * If we have a downstream mapping (not neccessarily installed) and * the downstream and upstream session are not the same.... */ if (ds_attr && ((*us_attr)->session->index != ds_attr->session->index)) { /* then link the attra */ ldp_attr_add_us2ds((*us_attr), ds_attr); /* if we just created the upstream, and we have install the * downstream, then cross connect them */ if ((created == MPLS_BOOL_TRUE) && ds_attr->outlabel) { if ((*us_attr)->inlabel->outlabel) { /* * if we use an existing upstream mapping (in ldp_label_mapping_send()) * the inlabel will already be be connected to an outlabel; */ MPLS_ASSERT((*us_attr)->inlabel->outlabel == ds_attr->outlabel); } else { LDP_TRACE_LOG(g->user_data,MPLS_TRACE_STATE_ALL,LDP_TRACE_FLAG_BINDING, "Cross Connect Added for %08x/%d from %s -> %s\n", f->info.u.prefix.network.u.ipv4, f->info.u.prefix.length, (*us_attr)->session->session_name, ds_attr->session->session_name); result = ldp_inlabel_add_outlabel(g,(*us_attr)->inlabel, ds_attr->outlabel); if (result != MPLS_SUCCESS) { return result; } } } } return MPLS_SUCCESS; }