Beispiel #1
0
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;
}