Example #1
0
mpls_return_enum ldp_fec_process_change(ldp_global * g, ldp_fec * f,
  ldp_nexthop *nh, ldp_nexthop *nh_old, ldp_session *nh_session_old) {
  ldp_session *peer = NULL;
  ldp_attr *us_attr = NULL;
  ldp_attr *ds_attr = NULL;
  ldp_session *nh_session = NULL;

  LDP_ENTER(g->user_data, "ldp_fec_process_change");

  if (!nh_session_old) {
    nh_session_old = ldp_session_for_nexthop(nh_old);
  }

  /*
   * NH 1-5 decide if we need to release an existing mapping
   */
  ds_attr = ldp_attr_find_downstream_state2(g, nh_session_old, f,
      LDP_LSP_STATE_MAP_RECV);
  if (!ds_attr) {               /* NH.1 */
    goto Detect_Change_Fec_Next_Hop_6;
  }

  if (ds_attr->ingress == MPLS_BOOL_TRUE) {

#if MPLS_USE_LSR
    lsr_ftn ftn;
    ftn.outsegment_index = ds_attr->outlabel->info.handle;
    memcpy(&ftn.fec, &f->info, sizeof(mpls_fec));
    lsr_cfg_ftn_set2(g->lsr_handle, &ftn, LSR_CFG_DEL);
#else
    mpls_mpls_fec2out_del(g->mpls_handle, &f->info, &ds_attr->outlabel->info);
#endif
    ds_attr->ingress = MPLS_BOOL_FALSE;
    ds_attr->outlabel->merge_count--;
  }

  if (g->label_retention_mode == LDP_RETENTION_LIBERAL) { /* NH.3 */
    ldp_attr *us_temp;
    us_attr = MPLS_LIST_HEAD(&ds_attr->us_attr_root);
    while (us_attr) {
      /* need to walk the list in such a way as not to
       * "pull the rug out from under me self"
       */
      us_temp = MPLS_LIST_NEXT(&ds_attr->us_attr_root, us_attr, _ds_attr);
      if (us_attr->state == LDP_LSP_STATE_MAP_SENT) {
        ldp_inlabel_del_outlabel(g, us_attr->inlabel);  /* NH.2 */
        ldp_attr_del_us2ds(us_attr, ds_attr);
      }
      us_attr = us_temp;
    }
    goto Detect_Change_Fec_Next_Hop_6;
  }

  ldp_label_release_send(g, nh_session_old, ds_attr, LDP_NOTIF_NONE); /* NH.4 */
  ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); /* NH.2,5 */

Detect_Change_Fec_Next_Hop_6:

  /*
   * NH 6-9 decides is we need to send a label request abort
   */
  ds_attr = ldp_attr_find_downstream_state2(g, nh_session_old, f,
    LDP_LSP_STATE_REQ_SENT);
  if (ds_attr) {               /* NH.6 */
    if (g->label_retention_mode != LDP_RETENTION_CONSERVATIVE) { /* NH.7 */
      /* NH.8,9 */
      if (ldp_label_abort_send(g, nh_session_old, ds_attr) != MPLS_SUCCESS) {
        return MPLS_FAILURE;
      }
    }
  }
  
  /*
   * NH 10-12 decides if we can use a mapping from our database
   */
  if (!(nh_session = ldp_get_next_hop_session_for_fec2(f,nh))){
    goto Detect_Change_Fec_Next_Hop_16;
  }
 
  ds_attr = ldp_attr_find_downstream_state2(g, nh_session, f,
    LDP_LSP_STATE_MAP_RECV);
  if (!ds_attr) {               /* NH.11 */
    goto Detect_Change_Fec_Next_Hop_13;
  }

  if (ldp_label_mapping_process(g, nh_session, NULL, NULL, ds_attr, f) !=
    MPLS_SUCCESS) { /* NH.12 */
    return MPLS_FAILURE;
  }
  goto Detect_Change_Fec_Next_Hop_20;

Detect_Change_Fec_Next_Hop_13:

  /*
   * NH 13-15 decides if we need to make a label request
   */
  if (nh_session->oper_distribution_mode == LDP_DISTRIBUTION_ONDEMAND &&
    g->label_retention_mode == LDP_RETENTION_CONSERVATIVE) {
    /* NH.14-15 */
    if (ldp_label_request_for_xc(g, nh_session, &f->info, NULL, &ds_attr) !=
        MPLS_SUCCESS) {
      return MPLS_FAILURE;
    }
  }
  goto Detect_Change_Fec_Next_Hop_20;

Detect_Change_Fec_Next_Hop_16:

  peer = MPLS_LIST_HEAD(&g->session);
  while (peer) {
    if (peer->state == LDP_STATE_OPERATIONAL) {
      us_attr = ldp_attr_find_upstream_state2(g, peer, f,
	LDP_LSP_STATE_MAP_SENT);
      if (us_attr) {	/* NH.17 */
        if (ldp_label_withdraw_send(g, peer, us_attr, LDP_NOTIF_NONE) !=
          MPLS_SUCCESS) { /* NH.18 */
          ldp_attr_remove_complete(g, us_attr, MPLS_BOOL_FALSE);
          return MPLS_FAILURE;
        }
      }
    }
    peer = MPLS_LIST_NEXT(&g->session, peer, _global);
  }

Detect_Change_Fec_Next_Hop_20:

  LDP_EXIT(g->user_data, "ldp_fec_process_change");

  return MPLS_SUCCESS;
}
Example #2
0
void ldp_attr_remove_complete(ldp_global * g, ldp_attr * attr,
		mpls_bool complete)
{
  ldp_session *session = attr->session;
  ldp_outlabel *out = NULL;
  ldp_inlabel *in = NULL;
  ldp_attr *us_temp = NULL;
  mpls_fec fec;
  int i;

  switch (attr->state) {
    case LDP_LSP_STATE_MAP_RECV:
      if (attr->ingress == MPLS_BOOL_TRUE) {
        out = attr->outlabel;
        MPLS_ASSERT(out != NULL);
        while ((in = MPLS_LIST_HEAD(&out->inlabel_root)) != NULL) {
          ldp_inlabel_del_outlabel(g, in);
        }

        if (out->merge_count > 0) {
          for (i = 0; i < attr->fecTlv.numberFecElements; i++) {
            fec_tlv2mpls_fec(&attr->fecTlv, i, &fec);
            out->merge_count--;
#if MPLS_USE_LSR
            {
              lsr_ftn ftn;
              memcpy(&ftn.fec, &fec, sizeof(mpls_fec));
              ftn.outsegment_index = out->info.handle;
              lsr_cfg_ftn_set2(g->lsr_handle, &ftn, LSR_CFG_DEL);
            }
#else
            mpls_mpls_fec2out_del(g->mpls_handle, &fec, &out->info);
#endif
          }
        }
        MPLS_ASSERT(out->merge_count == 0);
        ldp_attr_del_outlabel(g, attr);
        ldp_session_del_outlabel(g, session, out);
      }
      while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
        ldp_attr_del_us2ds(g, us_temp, attr);
      }
      ldp_attr_delete_downstream(g, session, attr);
      break;
    case LDP_LSP_STATE_MAP_SENT:
      in = attr->inlabel;
      out = in->outlabel;

      if (in->reuse_count == 1 && out) {
        ldp_inlabel_del_outlabel(g, in);
      }
      ldp_attr_del_inlabel(g, attr);
      ldp_attr_delete_upstream(g, session, attr);
      ldp_attr_del_us2ds(g, attr, attr->ds_attr);
      ldp_session_del_inlabel(g, session, in);
      break;
    case LDP_LSP_STATE_ABORT_SENT:
    case LDP_LSP_STATE_NOTIF_SENT:
    case LDP_LSP_STATE_REQ_RECV:
    case LDP_LSP_STATE_WITH_SENT:
    case LDP_LSP_STATE_NO_LABEL_RESOURCE_SENT:
      {
        ldp_attr_del_us2ds(g, attr, attr->ds_attr);
        ldp_attr_delete_upstream(g, session, attr);
        break;
      }
    case LDP_LSP_STATE_ABORT_RECV:
    case LDP_LSP_STATE_NOTIF_RECV:
    case LDP_LSP_STATE_REQ_SENT:
    case LDP_LSP_STATE_WITH_RECV:
    case LDP_LSP_STATE_NO_LABEL_RESOURCE_RECV:
      {
        while ((us_temp = MPLS_LIST_HEAD(&attr->us_attr_root)) != NULL) {
          ldp_attr_del_us2ds(g, us_temp, attr);
        }
        ldp_attr_delete_downstream(g, session, attr);
        break;
      }
  }
}