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

📄 phyint.c

📁 BCAST Implementation for NS2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *   OSPFD routing daemon
 *   Copyright (C) 1999 by John T. Moy
 *   
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2
 *   of the License, or (at your option) any later version.
 *   
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *   
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* Routines dealing with physical interfaces.
 * There may be one or more OSPF interfaces defined
 * over each physical interface; OSPF interfaces
 * are operated upon in spfifc.C.
 */

#include "ospfinc.h"
#include "phyint.h"
#include "ifcfsm.h"
#include "system.h"
#include "igmp.h"

/* Constructor for a physical interface.
 */

PhyInt::PhyInt(int phyint) 
  : AVLitem((uns32 ) phyint, 0), qrytim(this), strqtim(this), oqtim(this)

{
    operational = true;
    my_addr = 0;
    mospf_ifp = 0;
    igmp_querier = 0;
    igmp_enabled = false;
    // Initialize IGMP configurable constants to RFC 2236 defaults
    robustness_variable = 2;
    query_interval = 125;
    query_response_interval = 100;// Tenths of seconds
    group_membership_interval = robustness_variable * query_interval;
    // Next is more liberal than spec, to survive Querier changes
    group_membership_interval += (query_response_interval*3)/20;
    other_querier_present_interval = robustness_variable * query_interval;
    other_querier_present_interval += query_response_interval/20;
    startup_query_interval = query_interval/4;
    startup_query_count = robustness_variable;
    last_member_query_interval = 10;// Tenths of seconds
    last_member_query_count = robustness_variable;
}

/* OSPFD application attaches to a physical interface.
 */

void OSPF::phy_attach(int phyint)

{
    PhyInt *phyp;

    if (!(phyp = (PhyInt *)phyints.find((uns32) phyint, 0))) {
	phyp = new PhyInt((uns32) phyint);
	phyints.add(phyp);
	sys->phy_open(phyint);
    }
    
    phyp->ref();
    phyp->verify_igmp_capabilities();
}

/* OSPFD application leaves a group on a physical interface.
 */

void OSPF::phy_detach(int phyint, InAddr if_addr)

{
    PhyInt *phyp;

    if ((phyp = (PhyInt *)phyints.find((uns32) phyint, 0))) {
	phyp->deref();
	if (phyp->not_referenced()) {
	    sys->phy_close(phyint);
	    phyints.remove(phyp);
	    delete phyp;
	}
	else {
	    if (phyp->igmp_querier == if_addr)
	        phyp->igmp_querier = 0;
	    phyp->verify_igmp_capabilities();
	}
    }
}

/* OSPFD application joins a group on a physical interface.
 */

void OSPF::app_join(int phyint, InAddr group)

{
    AVLitem *member;

    if (!(member = ospfd_membership.find((uns32) phyint, group))) {
	member = new AVLitem((uns32) phyint, group);
	ospfd_membership.add(member);
	sys->join(group, phyint);
	if (spflog(LOG_JOIN, 4)) {
	    log(&group);
	    log(" Ifc ");
	    log(sys->phyname(phyint));
	}
    }
    
    member->ref();
}

/* OSPFD application leaves a group on a physical interface.
 */

void OSPF::app_leave(int phyint, InAddr group)

{
    AVLitem *member;

    if ((member = ospfd_membership.find((uns32) phyint, group))) {
	member->deref();
	if (member->not_referenced()) {
	    sys->leave(group, phyint);
	    ospfd_membership.remove(member);
	    member->chkref();
	    if (spflog(LOG_LEAVE, 4)) {
		log(&group);
		log(" Ifc ");
		log(sys->phyname(phyint));
	    }
	}
    }
}

/***************************************************************
 *   An implemention of Version 2 of the IGMP
 *   protocol.
 **************************************************************/

/* Go through all the OSPF interfaces associated with an interface
 * to determine whether we should run IGMP on the interface and,
 * if so, which address we should use in the Group Membership
 * Queries.
 * At least one of the interfaces must be numbered, with MOSPF
 * enabled, for us to send IGMP queries. As for what source address
 * to use, we always use the smallest interface address associated
 * with the interface (which might not be the interface running
 * MOSPF!).
 */

void PhyInt::verify_igmp_capabilities()

{
    bool was_querier;
    bool multicast_routing;
    int phyint = index1();
    bool igmp_was_enabled;

    multicast_routing = false;
    was_querier = IAmQuerier();
    my_addr = 0;
    mospf_ifp = 0;
    igmp_was_enabled = igmp_enabled;
    if (operational) {
	IfcIterator iter(ospf);
	SpfIfc *ip;
	InAddr igmp_addr;
	while ((ip = iter.get_next())) {
            if (ip->if_phyint != phyint)
	        continue;
	    // IGMP allowed?
	    if (!ip->igmp_enabled)
	        continue;
	    // mulicast routing enabled?
	    if (ospf->mospf_enabled() &&
		(ip->if_mcfwd == IF_MCFWD_MC))
		multicast_routing = true;
	    // Address to use for IGMP
	    igmp_addr = (ip->unnumbered() ? ospf->myaddr : ip->if_addr);
	    // Can do IGMP on the interface
	    if (my_addr == 0 || igmp_addr < my_addr)
	        my_addr = igmp_addr;
	    // Running MOSPF too?
	    if (ospf->mospf_enabled() &&
		(ip->if_mcfwd == IF_MCFWD_MC))
		mospf_ifp = ip;
	}
    }

    // Enable/disable multicast routing on interface
    sys->set_multicast_routing(phyint, multicast_routing);
    igmp_enabled = (my_addr && mospf_ifp);
    if (igmp_enabled != igmp_was_enabled) {
        if (igmp_enabled)
	    ospf->app_join(phyint, IGMPAllRouters);
	else
	    ospf->app_leave(phyint, IGMPAllRouters);
    }

    // Should we be querier?
    if (igmp_enabled) {
        if (!igmp_querier || my_addr < igmp_querier ||
	    (was_querier && (my_addr != igmp_querier))) {
	    igmp_querier = my_addr;
	    if (ospf->spflog(LOG_QUERIER, 4)) {
	        ospf->log(&igmp_querier);
	        ospf->log(" Ifc ");
	        ospf->log(sys->phyname(phyint));
	    }
	}
    }

    // Notice IGMP querier state changes
    if (IAmQuerier()) {
        if (!was_querier)
	    start_query_duties();
    }
    else if (was_querier)
	stop_query_duties();
}

/* Start the IGMP querier duties by sending out a sequence
 * of General Queries at a higher rate.
 */

void PhyInt::start_query_duties()

{
    oqtim.stop();
    send_query(0);
    if (startup_query_count > 1) {
        strqtim.startup_queries = startup_query_count - 1;
        strqtim.start(startup_query_interval*Timer::SECOND, false);
    }
}

/* Stop IGMP query duties by stopping any timers which
 * might generate General Queries.
 */

void PhyInt::stop_query_duties()

{
    strqtim.stop();
    qrytim.stop();
}

/* The Startup Query Timer.
 * "startup_queries" will be set right before the timer is started,
 * so that it will have the most recently configured value.
 */

StartupQueryTimer::StartupQueryTimer(PhyInt *p)

{
    phyp = p;
}

void StartupQueryTimer::action()

{
    phyp->send_query(0);
    if (--startup_queries <= 0) {
        stop();
	phyp->qrytim.start(phyp->query_interval*Timer::SECOND, false);
    }
}

/* The regular query timer. Goes off continuously, sending
 * out Host Membership Queries at a regular interval.
 */

IGMPQueryTimer::IGMPQueryTimer(PhyInt *p)

{
    phyp = p;
}

void IGMPQueryTimer::action()

{
    phyp->send_query(0);
}

/* The timer measuring whether we should replace the
 * current querier, when/if it disappears.
 */

IGMPOtherQuerierTimer::IGMPOtherQuerierTimer(PhyInt *p)

{
    phyp = p;

⌨️ 快捷键说明

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