Ejemplo n.º 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;
}
Ejemplo n.º 2
0
mpls_return_enum ldp_label_withdraw_process(ldp_global * g, ldp_session * s,
  ldp_adj * a, ldp_entity * e, ldp_attr * r_attr, ldp_fec * f)
{
  mpls_bool label_exists = MPLS_BOOL_FALSE;
  ldp_attr_list *ds_list = NULL;
  ldp_attr *ds_attr = NULL;
  ldp_attr *ds_temp = NULL;
  ldp_attr *us_temp = NULL;
  ldp_nexthop *nh = NULL;
  mpls_return_enum retval = MPLS_SUCCESS;

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

  LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
    "Withdraw Recv for %s\n", s->session_name);

  if (r_attr->genLblTlvExists || r_attr->atmLblTlvExists
    || r_attr->frLblTlvExists) {
    label_exists = MPLS_BOOL_TRUE;
  } else {
    MPLS_ASSERT(0);
  }

  if (f) {
    if ((ds_list = ldp_attr_find_downstream_all2(g, s, f)) != NULL) {
      ds_temp = MPLS_LIST_HEAD(ds_list);
      while (ds_temp) {
        if (ds_temp->state == LDP_LSP_STATE_MAP_RECV) { /* LWd.3 */
          if (ldp_attr_is_equal(r_attr, ds_temp, LDP_ATTR_LABEL)) {
            ds_attr = ds_temp;
	    break;
          }
        }
        ds_temp = MPLS_LIST_NEXT(ds_list, ds_temp, _fs);
      }
    }

    if (!ds_attr) {
      retval = MPLS_FAILURE;
      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_RECV, LDP_TRACE_FLAG_LABEL,
        "Withdraw Recv for a non-existant mapping from %s\n",s->session_name);
      goto LWd_13;
    }

    /*
     * we want to remove it from the tree, but not delete it yet
     * so hold a refcnt, we will release that refcnt at the end, thus
     * deleting it if no one else it holding a refcnt
     */
    MPLS_REFCNT_HOLD(ds_attr);
    ldp_attr_remove_complete(g, ds_attr, MPLS_BOOL_FALSE); /* LWd.4 */

    /* LWd.2 */
    if (ldp_label_release_send(g, s, ds_attr, LDP_NOTIF_NONE) != MPLS_SUCCESS) {
      retval = MPLS_FATAL;
      goto LWd_13;
    }

    if (g->lsp_control_mode == LDP_CONTROL_ORDERED) { /* LWd.5 */
      goto LWd_8;
    }

    if (s->oper_distribution_mode != LDP_DISTRIBUTION_ONDEMAND) { /* LWd.6 */
      goto LWd_13;
    }

    MPLS_ASSERT((nh = ldp_nexthop_for_fec_session(f, s)));
    retval = ldp_fec_process_add(g, f, nh, s);	/* LWd.7 */
    goto LWd_13;

  LWd_8:
    /* I can only propogate a label withdraw to the upstreams attached
       to the downstream found above */

    us_temp = MPLS_LIST_HEAD(&ds_attr->us_attr_root);
    while (us_temp) {
      if (us_temp->state == LDP_LSP_STATE_MAP_SENT) {
        if (ldp_label_withdraw_send(g, us_temp->session, us_temp,
            LDP_NOTIF_NONE) != MPLS_SUCCESS) { /* LWd.11 */
          retval = MPLS_FATAL;
          goto LWd_13;
        }
      }
      us_temp = MPLS_LIST_NEXT(&ds_attr->us_attr_root, us_temp, _ds_attr);
    }
  } else {
    /* JLEU: process wildcard FEC stuff here */
    MPLS_ASSERT(0);
  }

LWd_13:
  if (ds_attr) {
    MPLS_REFCNT_RELEASE2(g, ds_attr, ldp_attr_delete);
  }

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

  return retval;
}