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

📄 ospfh_flood.c

📁 实现禁位自动排列在禁位中具体实现了此方法所以这是一个创新很有应用价值在VC平台上调试通过
💻 C
📖 第 1 页 / 共 2 页
字号:
	     struct stream *s, struct ospf *top, u_int16_t size)
{
	struct ospf_neighbor *nbr;
	struct mpls_te_link *lp;
	struct in_addr source;
    source.s_addr=iph->sourceIP.s_addr;                                  /*@*/

	/* increment statistics. */
    top->ls_ack_in++;

	nbr = ospf_nbr_lookup_by_addr (top->nbrlist, &source);       /*@*/

	if (nbr == NULL)
		return;

	while (size >= 120)
	{
		struct ospf_lsa *lsa, *lsr;

        lsa=malloc(sizeof(struct ospf_lsa));
        ospf_lsa_new(lsa);
        lsa->data = (struct lsa_header *) STREAM_PNT (s);
        stream_forward(s,sizeof(struct lsa_header));
		lp= (struct mpls_te_link *) stream_pnt (s);
        lsa->lp=lp;


		size -= 120;
		stream_forward (s, 100);

		if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
		{
			lsa->data = NULL;
	        ospf_lsa_discard (lsa);
	        continue;
		}

		lsr = ospf_ls_retransmit_lookup (nbr, lsa);

        if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
		{ospf_ls_retransmit_delete (nbr, lsr);
 
	//	OSPF_TIMER_OFF(nbr->t_ls_upd);
        printf("remove a lsa from %s 's retx.\n",inet_ntoa(nbr->nbr_id));
		}
	
		lsa->data = NULL;
        ospf_lsa_discard (lsa);
	}
}


void 
ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)                 /*保留nbr*/
{
	

    if (listcount (nbr->top->ls_ack_direct.ls_ack) == 0)
		nbr->top->ls_ack_direct.dst = nbr->nbr_id;
  
    listnode_add (nbr->top->ls_ack_direct.ls_ack, ospf_lsa_lock(lsa));


	ospf_ls_ack_send_list(nbr->top, nbr->top->ls_ack_direct.ls_ack);   /*@?*/ 

  }

void
ospf_ls_ack_send_list (struct ospf *top, struct list *ack)        /*@*/
{
	struct thread_master *master;
    struct ospf* ospf_top;
      
    struct ospf_packet *op;
	u_int16_t length;


    ospf_top=top;
    master=top->master;
    
	length = OSPF_HEADER_SIZE;

    op = ospf_packet_new (top->mtu);

    /* Prepare OSPF common header. */
    ospf_make_header (OSPF_MSG_LS_ACK, top, op->s);                              

    /* Prepare OSPF Link State Acknowledgment body. */                            
    length += ospf_make_ls_ack (ack, op->s);                                   /*@*/ 

    /* Fill OSPF header. */
    ospf_fill_header (op->s, length);                                        
    /* Set packet length. */
    op->length = length;

    /* Set destination IP address. */
//   op->dst = dst;
  
	/* Add packet to the interface output queue. */
    //ospf_packet_add (oi, op);
    ospf_fifo_push (top->outbuf, op); 

    /* Hook thread to write packet. */
    OSPFH_WRITE_ON();
}

int
ospf_make_ls_ack (struct list *ack, struct stream *s)
{
	struct listnode *node;
    struct listnode *next;
    unsigned long delta = stream_get_putp(s) + 20;  //Different from zebra: +24
	
	u_int16_t length = OSPF_LS_ACK_MIN_SIZE;

	struct ospf_lsa *lsa;
	int count;
    count = ack->count;

    for (node = ack->head; node; node = next)
    {
		
		if (count)
		{
			lsa = node->data;
		    next = node->next;
          
            if (length + delta > OSPF_PACKET_MAX)                     /*@*/
				break;
      
            stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
            stream_put(s,lsa->lp,sizeof(struct mpls_te_link));
			length += (OSPF_LSA_HEADER_SIZE+sizeof(struct mpls_te_link));

	        listnode_delete (ack, lsa);
            ospf_lsa_unlock (lsa);
			count--;
		}
		else
			break;
	}
	      
    return length;
}


void ospf_ls_ack_send_delayed (struct ospf * top)
{
//	struct in_addr dst;
//	dst = ((struct ospf_neighbor *)(top->nbrlist->head->data))->nbr_id;    not used
//	dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
	while (listcount (top->ls_ack_direct.ls_ack))
		ospf_ls_ack_send_list (top, top->ls_ack_direct.ls_ack);
}

int
ospf_ls_ack_timer (struct thread *thread)    /*@not used*/
{
	struct ospf *top;
    struct thread_master* master;
	
    top = THREAD_ARG (thread);
    top->t_ls_ack = NULL;
    master=top->master;
    /* Send Link State Acknowledgment. */
    if (listcount (top->ls_ack_direct.ls_ack) > 0)
		ospf_ls_ack_send_delayed (top);           /*@*/  

    /* Set LS Ack timer. */
  OSPF_ISM_TIMER_ON (top->t_ls_ack, ospf_ls_ack_timer, top->v_ls_ack);

    return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

int
ospf_flood (struct ospf_neighbor *nbr, struct ospf_lsa *current,
	    struct ospf_lsa *new, struct ospf *top)                /*@*/       
{
	struct timeval now;
    int lsa_ack_flag;
    int num; 
	int layer;
	u_char index;
    struct thread_master* master;
	/*a*/
    master=top->master;
    lsa_ack_flag = 0;

    /* Get current time. */
    gettimeofday (&now, NULL);

    /* If there is already a database copy, and if the
     database copy was received via flooding and installed less
     than MinLSArrival seconds ago, discard the new LSA
     (without acknowledging it). */
    if (current != NULL)		/* -- endo. */
    {
		if (tv_cmp (tv_sub (now, current->tv_recv),int2tv (OSPF_MIN_LS_ARRIVAL)) < 0)
			return -1;       
    }

    /* Flood the new LSA out . */
    lsa_ack_flag = ospf_flood_through_area (top, nbr, new) ;
	layer=id_to_layernum(top->speaker_rc_id);
    

	
    
	/* Remove the current database copy from all neighbors' Link state
     retransmission lists.  */
    if (current)
    {
		ospf_ls_retransmit_delete_nbr_all (top, current);                     /*@*/
          
    }

    /* Do some internal house keeping that is needed here */
    SET_FLAG (new->flags, OSPF_LSA_RECEIVED);
    ospf_lsa_is_self_originated (new, top); /* Let it set the flag */         /*@*/

    /* Install the new LSA in the link state database
     (replacing the current database copy).  This may cause the
     routing table calculation to be scheduled.  In addition,
     timestamp the new LSA with the current time.  The flooding
     procedure cannot overwrite the newly installed LSA until
     MinLSArrival seconds have elapsed. */  

    num=id_to_layernum(new->data->adv_router);                              /*@*/
	
	index=ospf_lsa_install (num, new); 

		/*触发feed_up/feed_down*/
	if(id_to_layernum(top->speaker_rc_id)!=OSPF_MAX_LAYERNUM)
		OSPF_TIMER_OFF(top->t_ls_feed_up_timer);
		OSPF_ISM_TIMER_ON (top->t_ls_feed_up_timer,ospfh_feed_up_timer,top->v_ls_feed_up);                                            /*@*/
    
	
	if(id_to_layernum(top->speaker_rc_id)!=1)
		ospfh_feed_down_send(top,layer,index-1,new);  
 
    /* Acknowledge the receipt of the LSA by sending a Link State
     Acknowledgment packet back out the receiving interface. */
//    if (lsa_ack_flag)
//		ospf_flood_delayed_lsa_ack (top, new);     

//	else
		/* Update statistics value for OSPF-MIB. */
  
    ospf_ls_ack_send(nbr,new);
	top->rx_lsa_count++;

    return 0;
}


int
ospf_flood_through_area (struct ospf* top,struct ospf_neighbor *inbr,
			 struct ospf_lsa *lsa)
{
    int lsa_ack_flag = 0;

    if (ospf_flood_out (top, inbr, lsa))
			lsa_ack_flag = 1;

    return (lsa_ack_flag);
}


/* OSPF LSA flooding -- RFC2328 Section 13.3. */
int
ospf_flood_out (struct ospf *top,     
			      struct ospf_neighbor *inbr,
			      struct ospf_lsa *lsa)
{
	struct ospf_neighbor *onbr;
    struct listnode *rn;
    int retx_flag;    
	struct list * update;

    /* Remember if new LSA is added to a retransmit list. */
    retx_flag = 0;

    /* Each of the neighbors  are examined,
     to determine whether they must receive the new LSA.  The following
     steps are executed for each neighbor: */
    for (rn = top->nbrlist->head; rn; rn = rn->next)
    {
		/*struct ospf_lsa *ls_req;*/
 
        if (rn->data == NULL)
			continue;

        onbr = rn->data;        

        /*delete some nbr state check here*/

         /* If the new LSA was received from this neighbor,examine the next neighbor. */

         if (inbr)
			 if (IPV4_ADDR_SAME (&inbr->nbr_id, &onbr->nbr_id))
				 continue;

         /* Add the new LSA to the Link state retransmission list
	      for the adjacency. The LSA will be retransmitted
	      at intervals until an acknowledgment is seen from
	      the neighbor. */
         ospf_ls_retransmit_add (onbr, lsa);
         

         retx_flag = 1;
	}

    /* If in the previous step, the LSA was NOT added to any of
     the Link state retransmission lists, there is no need to
     flood . */
    if (retx_flag == 0) 
		return ; 

    /* The LSA must be flooded out the interface. Send a Link State
     Update packet (including the new LSA as contents) out the
     interface.  The LSA's LS age must be incremented by InfTransDelay
     (which	must be	> 0) when it is copied into the outgoing Link
     State Update packet (until the LS age field reaches the maximum
     value of MaxAge). */

    /*  RFC2328  Section 13.3
      On non-broadcast networks, separate	Link State Update
      packets must be sent, as unicasts, to each adjacent	neighbor
      (i.e., those in state Exchange or greater).	 The destination
      IP addresses for these packets are the neighbors' IP
      addresses.   */
	
	
	
	update = list_new ();

	listnode_add (update, ospf_lsa_lock(lsa));
    
    ospf_ls_upd_send (onbr, update, OSPF_SEND_PACKET_INDIRECT);

	list_delete (update);

    return 0;
}



/* Remove All neighbor/interface's Link State Retransmit list . */
void
ospf_ls_retransmit_delete_nbr_all (struct ospf *top,
				   struct ospf_lsa *lsa)
{
	    struct listnode *rn;
        struct ospf_neighbor *nbr;
        struct ospf_lsa *lsr;

		for (rn =(top->nbrlist)->head; rn; rn = rn->next)
			/* If LSA find in LS-retransmit list, then remove it. */
	        if ((nbr = rn->data) != NULL)
			{
				lsr = ospf_ls_retransmit_lookup (nbr, lsa);
	     
	            /* If LSA find in ls-retransmit list, remove it. */
	            if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
			    	ospf_ls_retransmit_delete (nbr, lsr);
			}
}


/* Remove LSA from neighbor's ls-request list. */
void
ospf_ls_retransmit_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
{
	struct list *ls_rxmt;

	ls_rxmt=nbr->ls_rxmt;

	lsa->retransmit_counter--;  

	listnode_delete(ls_rxmt, lsa);

    ospf_lsa_unlock(lsa);

}

/* Lookup LSA from neighbor's ls-retransmit list. */
struct ospf_lsa *
ospf_ls_retransmit_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
{
    struct list *ls_rxmt;	
	struct ospf_lsa *match;

    ls_rxmt=nbr->ls_rxmt;

    match = ospf_lsa_lookup_in_list (ls_rxmt, lsa);
    //ospfh_lsalist_install(ls_rxmt,id_to_layernum (lsah->adv_router));

	
	return match;  
}

/* Add LSA to be retransmitted to neighbor's ls-retransmit list. */
void
ospf_ls_retransmit_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
{
	struct ospf_lsa *old;

    old = ospf_ls_retransmit_lookup (nbr, lsa);

    if (ospf_lsa_more_recent (old, lsa) < 0)
    {
		if (old)
		{
			old->retransmit_counter--;
	        listnode_delete (nbr->ls_rxmt, old);
			ospf_lsa_unlock(old);
		}
        lsa->retransmit_counter++;
       
        listnode_add (nbr->ls_rxmt, ospf_lsa_lock(lsa));
    	printf("lsa added to %s 's retxlist\n",inet_ntoa(nbr->nbr_id));
	}
}
/* Do the LSA acking specified in table 19, Section 13.5, row 2
 * This get called from ospf_flood_out_interface. Declared inline 
 * for speed. */
void
ospf_flood_delayed_lsa_ack (struct ospf *top, struct ospf_lsa *lsa) //temp
{
    /* LSA is more recent than database copy, but was not
     flooded back out receiving interface. 

    /* Whether LSA is more recent or not, and whether this is in
     response to the LSA being sent out recieving interface has been 
     worked out previously */  

    /* Schedule a delayed LSA Ack to be sent */ 
	listnode_add (top->ls_ack_direct.ls_ack, ospf_lsa_lock(lsa));      /*@*/
}

⌨️ 快捷键说明

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