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

📄 ospf.c

📁 BCAST Implementation for NS2
💻 C
📖 第 1 页 / 共 2 页
字号:
	ap = new SpfArea(m->area_id);    if (!(hp = (HostAddr *) ap->hosts.find(m->net, m->mask)))	hp = new HostAddr(ap, m->net, m->mask);    if (status == DELETE_ITEM) {	ap->hosts.remove(hp);	delete hp->ip;	delete hp;    }    else {        hp->r_cost = m->cost;	hp->updated = true;	hp->ip->updated = true;	ap->updated = true;    }    // Reoriginate router-LSA for all areas    // Can't do just one, because host address may be advertised    // in a different area if configured area has no active interfaces    rl_orig();    calc_my_addr();}/* Transfer host parameters to cfg structure */static void host_to_cfg(const HostAddr& h, CfgHost& msg){    msg.net = h.r_rte->net();    msg.mask = h.r_rte->mask();    msg.area_id = h.r_area;    msg.cost = h.r_cost;}/* Query Host information */bool OSPF::qryHost(struct CfgHost& msg,		   aid_t	   area_id,		   InAddr	   net,		   InMask	   mask) const{    const SpfArea* ap = FindArea(area_id);    if (ap == 0) return false;    HostAddr* hp = (HostAddr *) ap->hosts.find(net, mask);    if (hp == 0) return false;    host_to_cfg(*hp, msg);    return true;}/* Get all host information associated with area */void OSPF::getHosts(std::list<CfgHost>& l, aid_t area_id) const{    SpfArea* ap = FindArea(area_id);    if (ap == 0) return;    AVLsearch hiter(&ap->hosts);    HostAddr* hp;    while ((hp = (HostAddr*)hiter.next())) {	CfgHost msg;	host_to_cfg(*hp, msg);	l.push_back(msg);    }}/* Host not listed in a reconfig. Delete it. */void HostAddr::clear_config(){    ap->hosts.remove(this);    ospf->rl_orig();    delete this;    ospf->calc_my_addr();}/* Process an incoming monitor request. */void OSPF::monitor(MonMsg *msg, byte type, int, int conn_id){    switch(type) {      case MonReq_Stat:	// Global statistics	global_stats(msg, conn_id);	break;      case MonReq_Area:	// Area statistics	area_stats(msg, conn_id);	break;      case MonReq_Ifc:	// Interface statistics	interface_stats(msg, conn_id);	break;      case MonReq_VL:	// Virtual link statistics	vl_stats(msg, conn_id);	break;      case MonReq_Nbr:	// Neighbor statistics	neighbor_stats(msg, conn_id);	break;      case MonReq_VLNbr: // Virtual neighbor statistics	vlnbr_stats(msg, conn_id);	break;      case MonReq_LSA:  // Dump LSA contents	lsa_stats(msg, conn_id);	break;      case MonReq_Rte:	// Dump routing table entry	rte_stats(msg, conn_id);	break;      case MonReq_OpqReg:	register_for_opqs(conn_id);	break;      case MonReq_OpqNext:	opq_stats(msg, conn_id);	break;      case MonReq_LLLSA:  // Dump Link-local LSA contents	lllsa_stats(msg, conn_id);	break;      default:	break;    }}/* We have received an update of the elapsed real time * since the program was started. Go through the timer * queue and execute those timers which are now due to * fire. */void OSPF::tick(){    Timer *tqelt;    uns32 sec;    uns32 msec;    sec = sys_etime.sec;    msec = sys_etime.msec;    while ((tqelt = (Timer *) timerq.priq_gethead())) {	if (tqelt->cost0 > sec)	    break;	if (tqelt->cost0 == sec && tqelt->cost1 > msec)	    break;	// Fire timer	tqelt = (Timer *) timerq.priq_rmhead();	tqelt->fire();    }}/* Return the number of milliseconds until the next wakeup. * Returns -1 if there is no pending wakeup. */int OSPF::timeout(){    Timer *tqelt;    SPFtime wakeup_time;     if (!(tqelt = (Timer *) timerq.priq_gethead()))	return(-1);    wakeup_time.sec = tqelt->cost0;    wakeup_time.msec = tqelt->cost1;    if (time_less(wakeup_time, sys_etime))	return(0);    else	return(time_diff(wakeup_time, sys_etime));}/* An indication that the physical or data link layer * has failed. Execute the down event on all associated * OSPF interfaces. * Redo the external routing calculation in case the * physical interface contains non-OSPF subnets which * are referenced in imported external routes. * Also, turn off IGMP processing. */void OSPF::phy_down(int phyint){    IfcIterator iter(this);    SpfIfc *ip;    PhyInt *phyp;    ase_sched = true;    while ((ip = iter.get_next())) {	if (ip->if_phyint == phyint)	    ip->run_fsm(IFE_DOWN);    }    if ((phyp = (PhyInt *)phyints.find((uns32) phyint, 0))) {        phyp->operational = false;	phyp->verify_igmp_capabilities();    }    // Delete phyint from routing table entries' next hops    INrte *rte;    INiterator rtiter(inrttbl);    while ((rte = rtiter.nextrte())) {        MPath *old;        if (!rte->valid())	    continue;	if (!rte->r_mpath)	    continue;	old = rte->r_mpath;	rte->r_mpath = old->prune_phyint(phyint);	if (!rte->r_mpath)	    rte->declare_unreachable();	if (rte->r_mpath != old) {	    rte->changed = true;	    rte->sys_install();	}    }}/* An indication that the physical and data link layers * are operational. Execute the up event on all associated * OSPF interfaces. * Redo the external routing calculation in case the * physical interface contains non-OSPF subnets which * are referenced in imported external routes. * * In additional, force a routing calculation because a * previous phy_down() deleted routing table entries, and * if LSAs have not changed (say because of a quick link * flap) we need to put them back. */void OSPF::phy_up(int phyint){    IfcIterator iter(this);    SpfIfc *ip;    ase_sched = true;    while ((ip = iter.get_next())) {        if (ip->if_phyint == phyint) {	    ip->run_fsm(IFE_UP);	    full_sched = true;	    ase_sched = true;	}    }}/* An indication that a group member has appeared * on a directly attached interface. If the phyint == -1, * the group member is a MOSPF internal group. * This routine is usually called by IGMP. */void OSPF::join_indication(InAddr group, int phyint){    GroupMembership *gentry;    PhyInt *phyp;    gentry = new GroupMembership(group, phyint);    local_membership.add(gentry);    phyp = (PhyInt *) phyints.find((uns32) phyint, 0);    if (phyp && phyp->mospf_ifp)        phyp->mospf_ifp->area()->grp_orig(group, 0);    else if (phyint == -1)        grp_orig(group, 0);    if (spflog(LOG_NEWGRP, 4)) {	log(&group);	if (phyint != -1) {	    log(" on ");	    log(sys->phyname(phyint));	}    }}/* Leave group processing, similar to the above * join, just in reverse. */void OSPF::leave_indication(InAddr group, int phyint){    GroupMembership *gentry;    PhyInt *phyp;    gentry = (GroupMembership *) local_membership.find(group, phyint);    if (!gentry)	return;    local_membership.remove(gentry);    phyp = (PhyInt *)phyints.find(phyint, 0);    if (phyp && phyp->mospf_ifp)	phyp->mospf_ifp->area()->grp_orig(group, 0);    else if (phyint == -1)        grp_orig(group, 0);    if (spflog(LOG_GRPEXP, 4)) {	log(&group);	if (phyint != -1) {	    log(" on ");	    log(sys->phyname(phyint));	}    }    delete gentry;}/* Kernel has indicated that it has deleted one of the * routes that we have added. This is probably due to * a network interface going down. Store the information * so that if we don't soon delete the entry also, we * will re-add it to the kernel in OSPF::krt_sync(). */void OSPF::krt_delete_notification(InAddr net, InMask mask){    INrte *rte;    // Ignore delete notifications while in hitless restart    if (in_hitless_restart())        return;    // Normally store and reinstall into kernel after short delay    if ((rte = inrttbl->find(net, mask)) && rte->valid()) {	printf("route was valid - add it to deletes\n");        KrtSync *item;	item = new KrtSync(net, mask);	krtdeletes.add(item);    }    printf("find returned: %p\n", rte); }/* Kernel has indicated that we have previously installed * a route to this destination. If we don't have the destination * currently in our routing table, assume that it is a remnant * from a previous execution run, and delete the route. */void OSPF::remnant_notification(InAddr net, InMask mask){    INrte *rte;    // If we're in hitless restart, just store remnant    // for later processing    if (in_hitless_restart()) {        AVLitem *rem;	if (!(rem = remnants.find(net, mask))) {	    rem = new AVLitem(net, mask);	    remnants.add(rem);	}        return;    }    // Normally delete all remnants from the kernel immediately    if (!(rte = inrttbl->find(net, mask)) || !rte->valid()) {        if (spflog(LOG_REMNANT, 5)) {	    log(&net, &mask);	}	sys->rtdel(net, mask, 0);    }}/* Perform a lookup in OSPF's copy of the IP routing * table. Used on those platforms that do not maintain * a "kernel" copy of the routing table. */MPath *OSPF::ip_lookup(InAddr dest){    INrte *rte;    if ((rte = inrttbl->best_match(dest)))	return(rte->r_mpath);    return(0);}/* Find the source address that would be used to send * packets to the given destination. */InAddr OSPF::ip_source(InAddr dest){    INrte *rte;    SpfIfc *ip = 0;    if ((rte = inrttbl->best_match(dest)) &&	(ip = rte->ifc()) &&	(!ip->unnumbered()))        return(ip->if_addr);    return(my_addr());}/* Return the IP address associated with a given physical * interface. */InAddr OSPF::if_addr(int phyint){    PhyInt *phyp;    phyp = (PhyInt *)phyints.find(phyint, 0);    return(phyp ? phyp->my_addr : 0);}/* The graceful shutdown procedure. Executed in phases. * First flush all locally-originated LSAs, except network-LSAs. * Then flush the network-LSAs. Finally, remove OSPF entries * from the system routing table, send out empty hellos, and * exit. * * A maximum time limit is placed on the entire procedure. */void OSPF::shutdown(int seconds){    AreaIterator aiter(this);    SpfArea *a;    IfcIterator iiter(this);    SpfIfc *ip;    if (shutdown_phase)	return;    shutdown_phase++;    // Set timer    countdown = seconds;    // Flush self-originated LSAs    flush_self_orig(FindLSdb(0, 0, LST_ASL));    flush_self_orig(FindLSdb(0, 0, LST_AS_OPQ));    while ((a = aiter.get_next())) {	flush_self_orig(FindLSdb(0, a, LST_RTR));	flush_self_orig(FindLSdb(0, a, LST_SUMM));	flush_self_orig(FindLSdb(0, a, LST_ASBR));	flush_self_orig(FindLSdb(0, a, LST_GM));	flush_self_orig(FindLSdb(0, a, LST_AREA_OPQ));    }    while ((ip = iiter.get_next()))	flush_self_orig(FindLSdb(ip, 0, LST_LINK_OPQ));}/* Continue the shutdown process. */void OSPF::shutdown_continue(){    AreaIterator aiter(this);    IfcIterator iiter(this);    SpfArea *a;    SpfIfc *ip;    INrte *rte;    INiterator iter(inrttbl);    switch(shutdown_phase++) {      case 1:	// Reset timer	countdown = 1;	// Flush network-LSAs	while ((a = aiter.get_next()))	    flush_self_orig(FindLSdb(0, a, LST_NET));	break;      case 2:	// Send empty Hellos	while((ip = iiter.get_next()))	    ip->send_hello(true);	// Withdraw routing entries	while ((rte = iter.nextrte())) {	    switch(rte->type()) {	      case RT_SPF:	      case RT_SPFIA:	      case RT_EXTT1:	      case RT_EXTT2:	      case RT_STATIC:		sys->rtdel(rte->net(), rte->mask(), rte->last_mpath);		break;	      default:		break;	    }	}	// Exit program	sys->halt(0, "Shutdown complete");	break;      default:	sys->halt(0, "Shutdown complete");	break;    }}/* Entry point to initiate a hitless restart. * After preparation is complete, halt will be called. */void OSPF::hitless_restart(int seconds, byte reason){    if (hitless_prep_phase > 0)        return;    grace_period = seconds;    restart_reason = reason;    hitless_prep_phase = 1;    phase_duration = 0;    prepare_hitless_restart();}

⌨️ 快捷键说明

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