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

📄 ospfh_lsa.c

📁 实现禁位自动排列在禁位中具体实现了此方法所以这是一个创新很有应用价值在VC平台上调试通过
💻 C
字号:
/* LSA */
#include "ospfh.h"
#include "ospfh_patch.h"


/*liuaibo*/

struct timeval
tv_adjust (struct timeval a)
{
  while (a.tv_usec >= 1000000)
    {
      a.tv_usec -= 1000000;
      a.tv_sec++;
    }

  while (a.tv_usec < 0)
    {
      a.tv_usec += 1000000;
      a.tv_sec--;
    }

  return a;
}

int
tv_floor (struct timeval a)
{
  a = tv_adjust (a);

  return a.tv_sec;
}

struct timeval
tv_sub (struct timeval a, struct timeval b)
{
  struct timeval ret;

  ret.tv_sec = a.tv_sec - b.tv_sec;
  ret.tv_usec = a.tv_usec - b.tv_usec;

  return tv_adjust (ret);
}

int
get_age (struct ospf_lsa *lsa)
{
  int age;
  struct timeval now;

  gettimeofday (&now, NULL);
  age = ntohs (lsa->data->ls_age) + tv_floor (tv_sub (now, lsa->tv_recv));

  return age;
}


//Lei
/* Fletcher Checksum -- Refer to RFC1008. */
#define MODX                 4102
#define LSA_CHECKSUM_OFFSET    15

u_int16_t
ospf_lsa_checksum (struct lsa_header *lsa)
{


  return 1;
}

/* If there is self-originated LSA, then return 1, otherwise return 0. */
/* An interface-independent version of ospf_lsa_is_self_originated */
int 
ospf_lsa_is_self_originated (struct ospf_lsa *lsa, struct ospf *ospf_top)
{
//	struct listnode *node;

    /* This LSA is already checked. */
    if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED))
		return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);

    /* Make sure LSA is self-checked. */
    SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED);

    /* AdvRouter and Router ID is the same. */
    if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf_top->self_rc_id))
		SET_FLAG (lsa->flags, OSPF_LSA_SELF);

    /* LSA is router-LSA. */
    else if (IPV4_ADDR_SAME (&lsa->data->id, &ospf_top->self_rc_id))
			 SET_FLAG (lsa->flags, OSPF_LSA_SELF);

	return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
}

/* Lock LSA. */
struct ospf_lsa *
ospf_lsa_lock (struct ospf_lsa *lsa)
{
	lsa->lock++;
    return lsa;
}

/* Unlock LSA. */
void
ospf_lsa_unlock (struct ospf_lsa *lsa)
{
	/* This is sanity check. */
    if (!lsa)
		return;
  
    lsa->lock--;
  
    if (lsa->lock == 0)
		ospf_lsa_free (lsa);
    
}

/* Check discard flag. */
void
ospf_lsa_discard (struct ospf_lsa *lsa)
{
  if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
    {
      SET_FLAG (lsa->flags, OSPF_LSA_DISCARD);
      ospf_lsa_unlock (lsa);
    }
}

/* Create OSPF LSA. */
void
ospf_lsa_new (struct ospf_lsa *newlsa)
{
	
    newlsa->flags = 0;
    newlsa->lock = 1;
    newlsa->retransmit_counter = 0;
    gettimeofday (&newlsa->tv_recv, NULL);
    newlsa->tv_orig = newlsa->tv_recv;
	newlsa->lsa_list = list_new (); 
}


/* Create LSA data. */
struct lsa_header *
ospf_lsa_data_new (u_int32_t size)
{
	struct lsa_header *new;

    new = (struct lsa_header *) XMALLOC (MTYPE_OSPF_LSA_DATA, size);
    memset (new, 0, size);

    return new;
}

/* Free OSPF LSA. */
void
ospf_lsa_free (struct ospf_lsa *lsa)
{	
    /* Delete LSA data. */
    if (lsa->data != NULL)
		ospf_lsa_data_free (lsa->data);
  
    memset (lsa, 0, sizeof (struct ospf_lsa)); 
    XFREE (MTYPE_OSPF_LSA, lsa);
}

/* Free LSA data. */
void
ospf_lsa_data_free (struct lsa_header *lsah)
{  
	XFREE (MTYPE_OSPF_LSA_DATA, lsah);
}


/* return +n, l1 is more recent.
   return -n, l2 is more recent.
   return 0, l1 and l2 is identical. */
int
ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2)
{
	int r;
    int x, y;

    if (l1 == NULL && l2 == NULL)
		return 0;
    if (l1 == NULL)
		return -1;
    if (l2 == NULL)
		return 1;

    /* compare LS sequence number. */
    x = (int) ntohl (l1->data->ls_seqnum);
    y = (int) ntohl (l2->data->ls_seqnum);
    if (x > y)
		return 1;
    if (x < y)
		return -1;

    /* compare LS checksum. */
    r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum);
    if (r)
		return r;

    /* compare LS age. */
    if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
		return 1;
    else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2))
		return -1;

    /* compare LS age with MaxAgeDiff. */
    if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF)
		return -1;
    else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF)
		return 1;

    /* LSAs are identical. */
    return 0;
}



////////////改//////////////////
int
ospf_lsa_timer (struct thread *t)                     /*@*/
{
	struct ospf *top;
  
    top = THREAD_ARG (t);
    top->t_lsa_self = NULL;

    /* Now refresh LSA. */
//    if (top->lsa_self)

//		ospf_router_lsa_refresh (top->lsa_self);          /*?*/
    /* Newly originate router-LSA. */
//    else
//		ospf_router_lsa_originate (area, area->top);        /*?*/

    return 0;
}
//////////////改///
void
ospf_lsa_timer_add (struct ospf *top)                                       /*@*/
{
	/* Keep area's self-originated router-LSA. */
    struct ospf_lsa *lsa = top->lsa_self;
	struct thread_master *master;
	master=top->master;
  
    OSPF_TIMER_OFF (top->t_lsa_self);

    /* Immediately refresh LSA. */
    OSPF_TOP_TIMER_ON (top->t_lsa_self, ospf_lsa_timer, 0);
}



/* Set a link information. */
void
link_info_set (struct stream *s, struct in_addr id,
	       struct in_addr data, u_char type, u_char tos, u_int16_t cost)
{
	/* TOS based routing is not supported. */
    stream_put_ipv4 (s, id.s_addr);		/* Link ID. */
    stream_put_ipv4 (s, data.s_addr);		/* Link Data. */
    stream_putc (s, type);			/* Link Type. */
    stream_putc (s, tos);				/* TOS = 0. */
    stream_putw (s, cost);			/* Link Cost. */
}



void
ospf_discard_from_db (struct ospf *top, struct ospf_lsa *lsa)     /*@*/
{
	struct list *lsa_list=top->lsa_list;
	ospf_ls_retransmit_delete_nbr_all (top, lsa);

	listnode_delete(lsa_list, lsa);

//	ospf_lsa_maxage_delete (lsa);
    ospf_lsa_discard (lsa);
}

void
ospf_lsa_maxage (struct ospf_lsa *lsa, struct ospf *top)
{
    
    struct thread_master *master;
	master=top->master;
    /* When we saw a MaxAge LSA flooded to us, we put it on the list
     and schedule the MaxAge LSA remover. */
	if (ospf_lsa_maxage_exist (lsa, top))
		return;
    
    listnode_add (top->maxage_lsa, ospf_lsa_lock (lsa));

    OSPF_SCHEDULE_MAXAGE (top->t_maxage, ospf_maxage_lsa_remover);
}

int
ospf_lsa_maxage_exist (struct ospf_lsa *new, struct ospf *top)
{
	struct listnode *node;

    for (node = (top->maxage_lsa)->head; node; node = node->next)
		if (((struct ospf_lsa *) node->data) == new)
      return 1;

    return 0;
}

int
ospf_maxage_lsa_remover (struct thread *thread)
{
	struct listnode *node;
    struct listnode *next;
    struct ospf_lsa *lsa;
	int reschedule = 0;
    struct ospf *top = THREAD_ARG (thread);
	struct thread_master *master;
	master=top->master;

    top->t_maxage = NULL;


//    if (!reschedule)
		for (node = (top->maxage_lsa)->head; node; node = next)
		{
			lsa = node->data;
            next = node->next;

            if (lsa->retransmit_counter > 0)
			{
				reschedule = 1;
                continue;
			}
            
	        /* Flood max age LSA. */
	        ospf_flood_through_area (top, NULL, lsa);  //???

 	        /* Remove from lsdb. */
            ospf_discard_from_db (top, lsa);
		}

        /*    A MaxAge LSA must be removed immediately from the router's link
        state database as soon as both a) it is no longer contained on any
        neighbor Link state retransmission lists and b) none of the router's
        neighbors are in states Exchange or Loading. */
//    if (reschedule)
//	   OSPF_SCHEDULE_MAXAGE (top->t_maxage, ospf_maxage_lsa_remover);

       return 0;
}

/* Periodical check of MaxAge LSA. */
int
ospf_lsa_maxage_walker (struct thread *t)
{
//	struct listnode *node;
	struct ospf *top = THREAD_ARG (t);
    struct listnode *n;

    struct thread_master *master;
	master=top->master;
    top->t_maxage_walker = NULL;

   
	    if (top->lsa_list->count)
		{
		for(n = top->lsa_list->head; n; n = n->next)
		{
			if(n != NULL)
			  ospf_lsa_maxage_walker_remover(n->data, top, 0);
		}
		}
		


    top->t_maxage_walker = 
    thread_add_timer (master, ospf_lsa_maxage_walker, NULL,
                      OSPF_LSA_MAXAGE_CHECK_INTERVAL);
    return 0;
}

int
ospf_lsa_maxage_walker_remover (struct ospf_lsa *lsa, void *p_arg, int int_arg)
{
	if (IS_LSA_MAXAGE (lsa))
	{
//-------------------------Different from zebra---------------------------------
		//ospf_spf_calculate_schedule (p_arg);
        ospf_flood_through_area (p_arg, NULL, lsa); 
		ospf_lsa_maxage (lsa, p_arg);
//------------------------------------------------------------------------------
	}
      
    return 0;
}


/* If two LSAs are different, return 1, otherwise return 0. */
int
ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2)
{
	char *p1, *p2;  

    if (l1->data->options != l2->data->options)
		return 1;

    if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
		return 1;

    if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1))
		return 1;

    if (l1->data->length != l2->data->length)
		return 1;

    if (l1->data->length ==  0)
		return 1;
	
	p1 = (char *) l1->data;
    p2 = (char *) l2->data;

    if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
              ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0)
			  return 1;

    return 0;
}



int
ospf_lsa_refresh_delay (struct ospf_lsa *lsa)
{
	struct timeval delta, now;
    int delay = 0;

    gettimeofday (&now, NULL);
    delta = tv_sub (now, lsa->tv_orig);

    if (tv_cmp (delta, int2tv (OSPF_MIN_LS_INTERVAL)) < 0)
		delay = tv_ceil (tv_sub (int2tv (OSPF_MIN_LS_INTERVAL), delta));

    return delay;
}



int
tv_ceil (struct timeval a)
{
  a = tv_adjust (a);

  return (a.tv_usec ? a.tv_sec + 1 : a.tv_sec);
}


int
tv_cmp (struct timeval a, struct timeval b)
{
	return (a.tv_sec == b.tv_sec ?
	  a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
}

struct timeval
int2tv (int a)
{
	struct timeval ret;

    ret.tv_sec = a;
    ret.tv_usec = 0;

    return ret;
}


struct ospf_lsa *ospf_lsa_lookup_in_list ( struct list *lsalist , struct ospf_lsa *lsa )
{
	struct in_addr local_id;
	struct in_addr remote_id;
	struct listnode *node;
	struct ospf_lsa *lsa_in_list;

	local_id=lsa->lp->local_id.value;
	remote_id=lsa->lp->remote_id.value;

	for(node=lsalist->head;node;node=node->next)   
    {   
       lsa_in_list=(struct ospf_lsa*)node->data;
	   if(lsa_in_list->lp->local_id.value.s_addr==lsa->lp->local_id.value.s_addr
		   &&lsa_in_list->lp->remote_id.value.s_addr==lsa->lp->remote_id.value.s_addr)
		   return lsa_in_list;		   
	}
return NULL;
}

⌨️ 快捷键说明

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