예제 #1
0
void process_lsr(void *packet,u_int32_t from,u_int32_t to,unsigned int size,struct ospf_interface *oiface) {
	struct ospf_lsr *lsr;
	struct ospf_lsa *lsa;
	struct ospf_neighbor *nbr;
	struct replay_nlist *tmp_item=NULL;

	//find the neighbor who sent the packet
	nbr=find_neighbor_by_ip(from);
	// if nbr found
	if(nbr) {
		// if the found nbr is not on the interface that we received the packet from then ignore this packet
		if(nbr->ospf_if != oiface) {
			nbr = NULL;
		}
	}
	// make sure packet exists, valid nbr found, and packet size is correct for LSR
	if(packet && (size>=(sizeof(struct ospfhdr)+sizeof(struct ospf_lsr))) && nbr) {
		// get the LSR portion of the packet
		lsr = (struct ospf_lsr *)(packet+sizeof(struct ospfhdr));
		// find the lsa the nbr is asking for
		lsa = find_lsa(lsr->advert_rtr,lsr->lsa_id,ntohl(lsr->lsa_type));
		// if lsa found and the nbr is supposed to be sending LSRs
		if(lsa&&(nbr->state>=OSPF_NBRSTATE_EXSTART)) {
			// create a one item nlist with lsa as the object and the lsa id as key
			tmp_item = add_to_nlist(tmp_item,(void *)lsa,(unsigned long long)(lsa->header->id.s_addr));
			// send the lsu
			send_lsu(nbr,tmp_item,OSPF_LSU_NOTRETX);
			// remove the nlist items (but not the lsa objects)
			remove_all_from_nlist(tmp_item);
		}
	}
}
예제 #2
0
/*---------------------------------------------------------------------
 * Method: pwospf_run_thread
 *
 * Main thread of pwospf subsystem.
 *
 *---------------------------------------------------------------------*/
static
void* pwospf_run_thread(void* arg)
{
    struct sr_instance* sr = (struct sr_instance*)arg;
    while(1)
    {
        /* -- PWOSPF subsystem functionality should start  here! -- */
        int i;
        for(i = 0; i < OSPF_DEFAULT_LSUINT; i += OSPF_DEFAULT_HELLOINT)
        {
        	send_HELLO(sr);
        	sleep(OSPF_DEFAULT_HELLOINT);
        }
        /*Send LSU updates*/
        
        check_top_invalid(sr); /*Check for expired topo entries*/
    	send_lsu(sr);
    }
} /* -- run_ospf_thread -- */
예제 #3
0
void process_lsu(void *packet,u_int32_t from,u_int32_t to,unsigned int size,struct ospf_interface *oiface) {
	struct ospf_lsa *lsa;
	struct lsa_header *lsahdr,*new_hdr,*need_hdr;
	struct ospf_neighbor *nbr,*tmp_nbr;
	struct replay_nlist *updated=NULL;
	struct replay_list *tmp_item,*tmp_item2;
	long long lsa_ptr=0;
	int ignore=0,send=0,changed_need_list=0;
	struct timeval now,orig;
	struct ospf_interface *tmp_if;

	// find the nbr who sent the packet and make sure their iface matches the packet iface
	nbr=find_neighbor_by_ip(from);
	if(nbr) {
		if(nbr->ospf_if != oiface) {
			nbr = NULL;
		}
	}
	gettimeofday(&now,NULL);
	// if nbr, interface and packet are valid
	if(nbr&&oiface&&packet) {
		//ignore packet if from nbr who's < exstart
		if(nbr->state>=OSPF_NBRSTATE_EXSTART) {
			//start with the first lsa hdr in the LSU
			lsa_ptr = (long long)packet + sizeof(struct ospfhdr) + sizeof(struct ospf_lsu);
			// while we haven't reached the end of the packet
			while(lsa_ptr<((long long)packet+size)) {
				// get the current lsa hdr
				lsahdr = (struct lsa_header *)lsa_ptr;
				// increment the lsahdr's age by the transmit delay
				lsahdr->ls_age = htons(ntohs(lsahdr->ls_age) + (u_int16_t)(ospf0->transmit_delay));
				// find an existing lsa for this hdr if one exists
				lsa = find_lsa(lsahdr->adv_router.s_addr,lsahdr->id.s_addr,lsahdr->type);
				// get the time the lsa was originated
				orig.tv_sec = now.tv_sec - lsahdr->ls_age;
				// if lsa was found and lsa in lsdb is within margin of lsa recieved in lsu then ignore it
				if(lsa) {
					if((lsa->tv_orig.tv_sec+REPLAY_LSA_AGE_MARGIN)>orig.tv_sec) {
						ignore = 1;
					// else remove the old lsa
					} else {
						//ensure proper removal out of any lists?
						remove_lsa(lsa);
					}
				}
				// if we're not ignoring the current lsu packet's lsa hdr then add it to the lsdb
				if(!ignore) {
					// malloc the new lsa
					new_hdr = malloc(ntohs(lsahdr->length));
					memset(new_hdr,0,ntohs(lsahdr->length));
					// copy the packet's current lsa into the new system lsa
					memcpy(new_hdr,lsahdr,ntohs(lsahdr->length));
					// add this lsa to the lsdb
					lsa = add_lsa(new_hdr);
					// if LSA recording is on for this interface, then write the lsa to disk
					if(oiface->iface->record) {
						fwrite(new_hdr,ntohs(new_hdr->length),1,oiface->iface->record);
					}
					// if successfully added then add the new lsa to the updated list
					if(lsa) {
						updated = add_to_nlist(updated,(void *)lsa,new_hdr->id.s_addr);
					}
					// find the new hdr in the need list and remove it if found
					tmp_item = nbr->lsa_need_list;
					while(tmp_item) {
						need_hdr = (struct lsa_header *)(tmp_item->object);
						if(need_hdr) {
							if((need_hdr->adv_router.s_addr==new_hdr->adv_router.s_addr)&&(need_hdr->id.s_addr==new_hdr->id.s_addr)&&(need_hdr->type==new_hdr->type)) {
								changed_need_list = 1;
								nbr->lsa_need_list = remove_from_list(nbr->lsa_need_list,tmp_item);
								tmp_item = NULL;
							}
						}
						if(tmp_item) {
							tmp_item = tmp_item->next;
						}
					}
				}
				// move to next lsa
				lsa_ptr = lsa_ptr + ntohs(lsahdr->length);
			}
			// ack the recieved lsu
			send_lsack(nbr,updated);

			if(changed_need_list) {

				// remove the LSR retransmit
				find_and_remove_event((void *)nbr,OSPF_EVENT_LSR_RETX);

				// if anything is still needed then send a new, updated lsr
				// otherwise move the nbr to FULL
				if(nbr->lsa_need_list) {
					send_lsr(nbr);
				} else {
					nbr->state = OSPF_NBRSTATE_FULL;
				}
			}

			// for each active ospf interface
			tmp_item = ospf0->iflist;
			while(tmp_item) {
				tmp_if = (struct ospf_interface *)(tmp_item->object);
				if(tmp_if) {
					// for each nbr in this iface
					tmp_item2 = tmp_if->nbrlist;
					send = 0;
					while(tmp_item2) {
						// get the current nbr from the list item
						tmp_nbr = (struct ospf_neighbor *)(tmp_item2->object);
						// if the nbr exists and is not the nbr who sent the lsu
						if(tmp_nbr && (tmp_nbr != nbr)) {
							// if the nbr is at a state to recieve LSAs
							if(tmp_nbr->state>=OSPF_NBRSTATE_EXSTART) {
								// then set the send flag
								send = 1;
								tmp_item2=NULL;
							}
						}
						// move to the next nbr
						if(tmp_item2) {
							tmp_item2 = tmp_item2->next;
						}
					}
				}
				// if a valid target for the lsu was found on this iface then send it
				if(send) {
					send_lsu(tmp_nbr,updated,OSPF_LSU_NOTRETX);
				}
				tmp_item = tmp_item->next;
			}

			remove_all_from_nlist(updated);
		}
	}
}