⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldp_hello.c

📁 实现了MPLS中的标签分发协议(LDP 3036 )的基本功能
💻 C
字号:
/* *  Copyright (C) James R. Leu 2000 *  jleu@mindspring.com * *  This software is covered under the LGPL, for more *  info check out http://www.gnu.org/copyleft/lgpl.html */#include <stdio.h>#include <sys/socket.h>#include "ldp_struct.h"#include "ldp_hello.h"#include "ldp_mesg.h"#include "ldp_buf.h"#include "ldp_adj.h"#include "ldp_hello.h"#include "ldp_entity.h"#include "ldp_session.h"#include "ldp_inet_addr.h"#include "ldp_pdu_setup.h"#include "mpls_assert.h"#include "mpls_socket_impl.h"#include "mpls_timer_impl.h"#include "mpls_lock_impl.h"#include "mpls_trace_impl.h"void ldp_hello_timeout_callback(mpls_timer_handle timer, void *extra,  mpls_cfg_handle handle){  ldp_adj *a = (ldp_adj *) extra;  ldp_global *g = (ldp_global*)handle;  LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_TIMER,    "Hello Timout fired: adj(%d)\n", a->index);  mpls_lock_get(g->global_lock);  if (a->session) {    a->session->shutdown_notif = LDP_NOTIF_HOLD_TIMER_EXPIRED;    a->session->shutdown_fatal = MPLS_BOOL_FALSE;  }  ldp_adj_shutdown(g, a);  /* timer is deleted inside of ldp_adj_shutdown */  /* the refcount release for the time is done in ldp_adj_shutdown as well */  mpls_lock_release(g->global_lock);}void ldp_hello_send_callback(mpls_timer_handle timer, void *extra,  mpls_cfg_handle handle){  ldp_entity *e = (ldp_entity*)extra;  ldp_global *g = (ldp_global*)handle;  LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_TIMER,    "Hello Send fired: entity(%d)\n", e->index);  mpls_lock_get(g->global_lock);  ldp_hello_send(g, e);  mpls_lock_release(g->global_lock);}mpls_return_enum ldp_hello_send(ldp_global * g, ldp_entity * e){  ldp_mesg **hello = NULL;  mpls_timer_handle *timer;  int *oper_duration = 0;  int targeted = 0;  int duration = 0;  int request = 0;  MPLS_ASSERT(g != NULL && e != NULL);  switch (e->entity_type) {    case LDP_DIRECT:      MPLS_ASSERT(e->p.iff != NULL);      hello = &e->p.iff->hello;      oper_duration = &e->p.iff->hellotime_send_timer_duration;      timer = &e->p.iff->hellotime_send_timer;      targeted = 0;      request = 0;      break;    case LDP_INDIRECT:      MPLS_ASSERT(e->p.peer != NULL);      hello = &e->p.peer->hello;      oper_duration = &e->p.peer->hellotime_send_timer_duration;      timer = &e->p.peer->hellotime_send_timer;      targeted = 1;      if (e->p.peer->target_role == LDP_ACTIVE) {        request = 1;      } else {        request = 0;      }      break;    default:      MPLS_ASSERT(0);  }  if (!*hello) {    *hello = ldp_hello_create(g->message_identifier++,      e->hellotime_timer, &e->transport_address,      g->configuration_sequence_number, targeted, request);  }  duration = e->hellotime_interval;  if (mpls_timer_handle_verify(g->timer_handle, *timer) == MPLS_BOOL_FALSE) {    MPLS_REFCNT_HOLD(e);    *timer = mpls_timer_create(g->timer_handle, MPLS_UNIT_SEC,      duration, (void *)e, g, ldp_hello_send_callback);    if (mpls_timer_handle_verify(g->timer_handle, *timer) == MPLS_BOOL_FALSE) {      *oper_duration = 0;      MPLS_REFCNT_RELEASE(e, ldp_entity_delete);      return MPLS_FAILURE;    }    *oper_duration = duration;    mpls_timer_start(g->timer_handle, *timer, MPLS_TIMER_REOCCURRING);  } else {    if ((*oper_duration) != duration) {      mpls_timer_stop(g->timer_handle, *timer);      *oper_duration = duration;      mpls_timer_modify(g->timer_handle, *timer, duration);      mpls_timer_start(g->timer_handle, *timer, MPLS_TIMER_REOCCURRING);    }  }  LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_SEND, LDP_TRACE_FLAG_PERIODIC,    "Hello Send: entity(%d)\n", e->index);  return ldp_mesg_send_udp(g, e, *hello);}ldp_mesg *ldp_hello_create(uint32_t msgid, int holdtime, mpls_inet_addr * traddr,  uint32_t confnum, int targeted, int request){  mplsLdpHelloMsg_t *hello = NULL;  ldp_mesg *msg = NULL;  msg = ldp_mesg_create();  ldp_mesg_prepare(msg, MPLS_HELLO_MSGTYPE, msgid);  if (msg != NULL) {    hello = &msg->u.hello;    hello->trAdrTlvExists = 0;    hello->csnTlvExists = 0;    hello->chpTlvExists = 1;    /* this assumes we always want to receive updates for targeted hellos */    hello->baseMsg.msgLength += setupChpTlv(&(hello->chp), targeted,      request, 0, holdtime);    if (traddr && traddr->type == MPLS_FAMILY_IPV4 && traddr->u.ipv4 > 0) {      hello->trAdrTlvExists = 1;      hello->baseMsg.msgLength +=        setupTrAddrTlv(&(hello->trAdr), traddr->u.ipv4);    }    if (confnum > 0) {      hello->csnTlvExists = 1;      hello->baseMsg.msgLength += setupCsnTlv(&(hello->csn), confnum);    }  }  return msg;}mpls_return_enum ldp_hello_process(ldp_global * g, ldp_adj * a, ldp_entity *e,  int hellotime, uint32_t csn, mpls_inet_addr * traddr, int targeted,  int request){  mpls_inet_addr *local = NULL, *remote = NULL;  MPLS_ASSERT(a && e);  LDP_ENTER(g->user_data, "ldp_hello_process: a = %p, e = %p", a, e);  LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_PERIODIC,    "Hello Recv: entity(%d)\n", e->index);  switch (e->entity_type) {    case LDP_DIRECT:      /* ldp-11 3.5.2. Hello Message */      if (hellotime == 0) {        hellotime = 15;      }      if (MPLS_LIST_HEAD(&e->p.iff->addr_root)) {	local = &(MPLS_LIST_HEAD(&e->p.iff->addr_root)->address);      } else {        local = &g->lsr_identifier;      }      break;    case LDP_INDIRECT:      /* ldp-11 3.5.2. Hello Message */      if (hellotime == 0) {        hellotime = 45;      }      local = &g->lsr_identifier;      break;    default:      MPLS_ASSERT(0);  }  if (hellotime < e->hellotime_timer) {    LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_NORMAL,      "ldp_hello_process: adjusting hellotime_timer to match adj\n");    e->hellotime_timer = hellotime;  }  if (traddr != NULL) {    memcpy(&a->remote_transport_address, traddr, sizeof(struct mpls_inet_addr));  }  if (csn != a->remote_csn) {    /* the remote csn changes all we can do is clear the backoff time */    /* this will only enable a lsr in the active role to try again */    a->remote_csn = csn;    if (a->session && mpls_timer_handle_verify(g->timer_handle,      a->session->backoff_timer) == MPLS_BOOL_TRUE) {      ldp_session_backoff_stop(g, a->session);    }  }  /* JLEU should verify that the hello hasn't changed */  if (a->session) {    /*  && a->session->state == LDP_STATE_OPERATIONAL) */    /* all that matters is that we have a session in progress */    /* we already have an established session */    LDP_EXIT(g->user_data, "ldp_hello_process");    return MPLS_SUCCESS;  }  if (e->transport_address.type != MPLS_FAMILY_NONE) {    local = &e->transport_address;  }  if (a->remote_transport_address.type != MPLS_FAMILY_NONE) {    remote = &a->remote_transport_address;  } else {    remote = &a->remote_source_address;  }  switch (mpls_inet_addr_compare(local, remote)) {    case 1:      /* if at one point we through WE were passive */      if (a->role == LDP_PASSIVE && a->session) {        ldp_session_shutdown(g, a->session, MPLS_BOOL_TRUE);      }      a->role = LDP_ACTIVE;      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_STATE,        "ldp_hello_process: ACTIVE(%d)\n", a->index);      if (ldp_session_create_active(g, a) != MPLS_SUCCESS) {	LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_NORMAL,	  "ldp_hello_process: creating an active session failed(%d)\n",	  a->index);        /* return FAILURE so we don't try to continue with the new adj */	return MPLS_FAILURE;      }      break;    case -1:      /* if at one point we through WE were active */      if (a->role == LDP_ACTIVE && a->session) {	ldp_session_shutdown(g, a->session, MPLS_BOOL_TRUE);      }      a->role = LDP_PASSIVE;      LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_STATE,        "ldp_hello_process: PASSIVE(%d)\n", a->index);      break;    default:      LDP_PRINT(g->user_data,        "ldp_hello_process: exit(%d) configuration error\n", a->index);      if (a->session) {	ldp_session_shutdown(g, a->session, MPLS_BOOL_TRUE);      }      a->role = LDP_NONE;      MPLS_ASSERT(a->session == NULL);      /* return FAILURE so we don't try to continue with the new adj */      LDP_EXIT(g->user_data, "ldp_hello_process: FAILURE");      return MPLS_FAILURE;  }  LDP_EXIT(g->user_data, "ldp_hello_process");  return MPLS_SUCCESS;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -