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

📄 port.cc

📁 RIP 协议实现
💻 CC
📖 第 1 页 / 共 3 页
字号:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-// Copyright (c) 2001-2008 XORP, Inc.//// Permission is hereby granted, free of charge, to any person obtaining a// copy of this software and associated documentation files (the "Software")// to deal in the Software without restriction, subject to the conditions// listed in the XORP LICENSE file. These conditions include: you must// preserve this copyright notice, and you cannot mention the copyright// holders in advertising related to the Software without their permission.// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This// notice is a summary of the XORP LICENSE file; the license in that file is// legally binding.#ident "$XORP: xorp/rip/port.cc,v 1.73 2008/07/23 05:11:35 pavlin Exp $"#include "rip_module.h"#include "libxorp/xorp.h"#include "libxorp/debug.h"#include "libxorp/xlog.h"#include "libxorp/random.h"#include "libxorp/eventloop.hh"#include "libxorp/ipv4.hh"#include "libxorp/ipv6.hh"#include "constants.hh"#include "packets.hh"#include "auth.hh"#include "peer.hh"#include "port.hh"#include "port_manager.hh"#include "packet_assembly.hh"#include "packet_queue.hh"#include "system.hh"#include "output_table.hh"#include "output_updates.hh"// ----------------------------------------------------------------------------// Utilitiesinline static uint32_trange_random(uint32_t lo, uint32_t hi){    if (hi < lo) swap(hi, lo);    return lo + ( xorp_random() % (hi - lo) );}// ----------------------------------------------------------------------------// Address Family specific Port methods#ifdef INSTANTIATE_IPV4PortAFSpecState<IPv4>::PortAFSpecState(){    set_auth_handler(new NullAuthHandler());}PortAFSpecState<IPv4>::~PortAFSpecState(){    delete auth_handler();}AuthHandlerBase*PortAFSpecState<IPv4>::set_auth_handler(AuthHandlerBase* new_handler){    AuthHandlerBase* old_handler = _ah;    _ah = new_handler;    return old_handler;}const AuthHandlerBase*PortAFSpecState<IPv4>::auth_handler() const{    return _ah;}AuthHandlerBase*PortAFSpecState<IPv4>::auth_handler(){    return _ah;}#endif // INSTANTIATE_IPV4// ----------------------------------------------------------------------------// Generic Port<A> Implementationtemplate <typename A>Port<A>::Port(PortManagerBase<A>& pm)    :  _pm(pm),       _en(false),       _cost(1),       _horizon(SPLIT_POISON_REVERSE),       _advertise(false),       _adv_def_rt(true),       _acc_def_rt(true),       _passive(false),       _acc_non_rip_reqs(true),       _ur_out(0),       _tu_out(0),       _su_out(0){    _packet_queue = new PacketQueue<A>();}template <typename A>Port<A>::~Port(){    stop_output_processing();    delete _ur_out;    delete _su_out;    delete _tu_out;    while (_peers.empty() == false) {	delete _peers.front();	_peers.pop_front();    }    delete _packet_queue;}template <typename A>Peer<A>*Port<A>::create_peer(const Addr& addr){    if (peer(addr) == 0) {	Peer<A>* peer = new Peer<A>(*this, addr);	_peers.push_back(peer);	EventLoop& e = _pm.eventloop();	TimeVal now;	e.current_time(now);	peer->set_last_active(now);	start_peer_gc_timer();	return peer;    }    return 0;}template <typename A>Peer<A>*Port<A>::peer(const Addr& addr){    typename PeerList::iterator i = find_if(_peers.begin(), _peers.end(),					    peer_has_address<A>(addr));    return (i == _peers.end()) ? 0 : *i;}template <typename A>const Peer<A>*Port<A>::peer(const Addr& addr) const{    typename PeerList::const_iterator i = find_if(_peers.begin(), _peers.end(),						  peer_has_address<A>(addr));    return (i == _peers.end()) ? 0 : *i;}template <typename A>voidPort<A>::unsolicited_response_timeout(){    debug_msg("Unsolicited response timeout %p\n", this);    //    // Fast forward triggered updater because we're about to dump entire    // table.    //    if (_tu_out->running()) {	_tu_out->ffwd();    }    //    // Check if unsolicited response process already exists and kill    // it if so.    //    if (_ur_out->running()) {	XLOG_WARNING("Starting unsolicited response process while an "		     "existing one is already running.\n");	_ur_out->stop();    }    // Start output process.    _ur_out->start();    //    // Reschedule this callback in next interval    //    TimeVal interval = TimeVal(constants().update_interval(), 0);    double factor = constants().update_jitter() / 100.0;    _ur_timer.reschedule_after(random_uniform(interval, factor));}template <typename A>voidPort<A>::triggered_update_timeout(){    debug_msg("Triggered update timeout %p\n", this);    {	RouteDB<A>& rdb = _pm.system().route_db();	UNUSED(rdb);	debug_msg("- Route DB routes = %u\n",		  XORP_UINT_CAST(rdb.route_count()));    }    // Table dump is running, we should not be doing triggered updates.    if (_ur_out->running())	goto reschedule;    //    // Push triggered updater along.  It wont be running if we've just    // instantiated it, or if it was running and ran out of updates to    // announce.    //    if (_tu_out->running() == false) {	_tu_out->start();    } reschedule:    TimeVal delay = TimeVal(constants().triggered_update_delay(), 0);    double factor = constants().triggered_update_jitter() / 100.0;    _tu_timer.reschedule_after(random_uniform(delay, factor));}template <typename A>voidPort<A>::start_output_processing(){    EventLoop& e = _pm.eventloop();    RouteDB<A>& rdb = _pm.system().route_db();    // Create triggered update output process    _tu_out = new OutputUpdates<A>(e, *this, *_packet_queue, rdb);    // Schedule triggered update process    TimeVal interval = TimeVal(constants().update_interval(), 0);    double factor = constants().update_jitter() / 100.0;    _ur_timer =	e.new_oneoff_after(random_uniform(interval, factor),			   callback(this,				    &Port<A>::unsolicited_response_timeout));    // Create unsolicited response (table dump) output process    _ur_out = new OutputTable<A>(e, *this, *_packet_queue, rdb);    // Schedule unsolicited output process    TimeVal delay = TimeVal(constants().triggered_update_delay(), 0);    factor = constants().triggered_update_jitter() / 100.0;    _tu_timer =	e.new_oneoff_after(random_uniform(delay, factor),			   callback(this,				    &Port<A>::triggered_update_timeout));}template <typename A>voidPort<A>::stop_output_processing(){    delete _ur_out;    _ur_out = 0;    delete _tu_out;    _tu_out = 0;    _ur_timer.unschedule();    _tu_timer.unschedule();}template <typename A>voidPort<A>::start_request_table_timer(){    EventLoop& e = _pm.eventloop();    if (constants().table_request_period_secs() == 0) {	// Don't start the timer, but cancel it instead	_rt_timer.unschedule();	return;    }    _rt_timer = e.new_periodic_ms(	constants().table_request_period_secs() * 1000,	callback(this, &Port<A>::request_table_timeout));}template <typename A>voidPort<A>::reschedule_request_table_timer(){    if (! _rt_timer.scheduled())	return;    start_request_table_timer();}template <typename A>voidPort<A>::stop_request_table_timer(){    _rt_timer.unschedule();}template <typename A>boolPort<A>::request_table(){    RipPacket<A>* pkt = new RipPacket<A>(RIP_AF_CONSTANTS<A>::IP_GROUP(),					 RIP_AF_CONSTANTS<A>::IP_PORT);    list<RipPacket<A>*> auth_packets;    RequestTablePacketAssembler<A> rtpa(*this);    if (rtpa.prepare(pkt, auth_packets) == true) {	typename list<RipPacket<A>*>::iterator iter;	for (iter = auth_packets.begin(); iter != auth_packets.end(); ++iter) {	    RipPacket<A>* auth_pkt = *iter;	    _packet_queue->enqueue_packet(auth_pkt);	    counters().incr_table_requests_sent();	}    } else {	XLOG_ERROR("Failed to assemble table request.\n");    }    delete pkt;    push_packets();    debug_msg("Sending Request.\n");    return true;}template <typename A>boolPort<A>::request_table_timeout(){    if (_peers.empty() == false)	return false;    return (request_table());}template <typename A>voidPort<A>::start_peer_gc_timer(){    XLOG_ASSERT(_peers.empty() == false);    // Set peer garbage collection timeout to 180 seconds since for RIP    // MIB we need to keep track of quiescent peers for this long.    EventLoop& e = _pm.eventloop();    _gc_timer = e.new_periodic_ms(180 * 1000,				  callback(this, &Port<A>::peer_gc_timeout));}template <typename A>boolPort<A>::peer_gc_timeout(){    typename PeerList::iterator i = _peers.begin();    while (i != _peers.end()) {	Peer<A>* pp = *i;	if (pp->route_count() == 0) {	    delete pp;	    _peers.erase(i++);	} else {	    ++i;	}    }    if (_peers.empty()) {	start_request_table_timer();	return false;    }    return true;}template <typename A>voidPort<A>::record_packet(Peer<A>* p){    counters().incr_packets_recv();    if (p) {	EventLoop& e = _pm.eventloop();	TimeVal now;	e.current_time(now);	p->counters().incr_packets_recv();	p->set_last_active(now);    }}template <typename A>voidPort<A>::record_response_packet(Peer<A>* p){    counters().incr_update_packets_recv();    if (p) {	p->counters().incr_update_packets_recv();    }}template <typename A>voidPort<A>::record_request_packet(Peer<A>* p){    counters().incr_table_requests_recv();    if (p) {	p->counters().incr_table_requests_recv();    }}template <typename A>voidPort<A>::record_bad_packet(const string& why,			   const Addr&	 host,			   uint16_t	 port,			   Peer<A>*	 p){    XLOG_INFO("RIP port %s/%s/%s received bad packet from %s:%u - %s\n",	      this->_pio->ifname().c_str(), this->_pio->vifname().c_str(),	      this->_pio->address().str().c_str(), host.str().c_str(), port,	      why.c_str());    counters().incr_bad_packets();    if (p) {	p->counters().incr_bad_packets();    }}

⌨️ 快捷键说明

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