?? mld6igmp_node.cc
字號:
// -*- 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/contrib/mld6igmp_lite/mld6igmp_node.cc,v 1.2 2008/07/23 05:09:49 pavlin Exp $"//// Multicast Listener Discovery and Internet Group Management Protocol// node implementation (common part).// IGMPv1 and IGMPv2 (RFC 2236), IGMPv3 (RFC 3376),// MLDv1 (RFC 2710), and MLDv2 (RFC 3810).//#include "mld6igmp_module.h"#include "libxorp/xorp.h"#include "libxorp/xlog.h"#include "libxorp/debug.h"#include "libxorp/ipvx.hh"#include "mld6igmp_node.hh"#include "mld6igmp_vif.hh"//// Exported variables////// Local constants definitions////// Local structures/classes, typedefs and macros////// Local variables////// Local functions prototypes///** * Mld6igmpNode::Mld6igmpNode: * @family: The address family (%AF_INET or %AF_INET6 * for IPv4 and IPv6 respectively). * @module_id: The module ID (must be %XORP_MODULE_MLD6IGMP). * @eventloop: The event loop. * * MLD6IGMP node constructor. **/Mld6igmpNode::Mld6igmpNode(int family, xorp_module_id module_id, EventLoop& eventloop) : ProtoNode<Mld6igmpVif>(family, module_id, eventloop), _is_log_trace(false){ XLOG_ASSERT(module_id == XORP_MODULE_MLD6IGMP); if (module_id != XORP_MODULE_MLD6IGMP) { XLOG_FATAL("Invalid module ID = %d (must be 'XORP_MODULE_MLD6IGMP' = %d)", module_id, XORP_MODULE_MLD6IGMP); } _buffer_recv = BUFFER_MALLOC(BUF_SIZE_DEFAULT); // // Set the node status // ProtoNode<Mld6igmpVif>::set_node_status(PROC_STARTUP); // // Set myself as an observer when the node status changes // set_observer(this);}/** * Mld6igmpNode::~Mld6igmpNode: * @: * * MLD6IGMP node destructor. * **/Mld6igmpNode::~Mld6igmpNode(){ // // Unset myself as an observer when the node status changes // unset_observer(this); stop(); ProtoNode<Mld6igmpVif>::set_node_status(PROC_NULL); delete_all_vifs(); BUFFER_FREE(_buffer_recv);}/** * Mld6igmpNode::start: * @: * * Start the MLD or IGMP protocol. * TODO: This function should not start the protocol operation on the * interfaces. The interfaces must be activated separately. * After the startup operations are completed, * Mld6igmpNode::final_start() is called to complete the job. * * Return value: %XORP_OK on success, otherwize %XORP_ERROR. **/intMld6igmpNode::start(){ if (! is_enabled()) return (XORP_OK); // // Test the service status // if ((ServiceBase::status() == SERVICE_STARTING) || (ServiceBase::status() == SERVICE_RUNNING)) { return (XORP_OK); } if (ServiceBase::status() != SERVICE_READY) { return (XORP_ERROR); } if (ProtoNode<Mld6igmpVif>::pending_start() != XORP_OK) return (XORP_ERROR); // // Register with the FEA and MFEA // fea_register_startup(); mfea_register_startup(); // // Set the node status // ProtoNode<Mld6igmpVif>::set_node_status(PROC_STARTUP); // // Update the node status // update_status(); return (XORP_OK);}/** * Mld6igmpNode::final_start: * @: * * Complete the start-up of the MLD/IGMP protocol. * * Return value: %XORP_OK on success, otherwise %XORP_ERROR. **/intMld6igmpNode::final_start(){#if 0 // TODO: XXX: PAVPAVPAV if (! is_pending_up()) return (XORP_ERROR);#endif if (ProtoNode<Mld6igmpVif>::start() != XORP_OK) { ProtoNode<Mld6igmpVif>::stop(); return (XORP_ERROR); } // Start the mld6igmp_vifs start_all_vifs(); XLOG_INFO("Protocol started"); return (XORP_OK);}/** * Mld6igmpNode::stop: * @: * * Gracefully stop the MLD or IGMP protocol. * XXX: After the cleanup is completed, * Mld6igmpNode::final_stop() is called to complete the job. * XXX: This function, unlike start(), will stop the protocol * operation on all interfaces. * * Return value: %XORP_OK on success, otherwise %XORP_ERROR. **/intMld6igmpNode::stop(){ // // Test the service status // if ((ServiceBase::status() == SERVICE_SHUTDOWN) || (ServiceBase::status() == SERVICE_SHUTTING_DOWN) || (ServiceBase::status() == SERVICE_FAILED)) { return (XORP_OK); } if ((ServiceBase::status() != SERVICE_RUNNING) && (ServiceBase::status() != SERVICE_STARTING) && (ServiceBase::status() != SERVICE_PAUSING) && (ServiceBase::status() != SERVICE_PAUSED) && (ServiceBase::status() != SERVICE_RESUMING)) { return (XORP_ERROR); } if (ProtoNode<Mld6igmpVif>::pending_stop() != XORP_OK) return (XORP_ERROR); // // Perform misc. MLD6IGMP-specific stop operations // // XXX: nothing to do // Stop the vifs stop_all_vifs(); // // Set the node status // ProtoNode<Mld6igmpVif>::set_node_status(PROC_SHUTDOWN); // // Update the node status // update_status(); return (XORP_OK);}/** * Mld6igmpNode::final_stop: * @: * * Completely stop the MLD/IGMP protocol. * * Return value: %XORP_OK on success, otherwise %XORP_ERROR. **/intMld6igmpNode::final_stop(){ if (! (is_up() || is_pending_up() || is_pending_down())) return (XORP_ERROR); if (ProtoNode<Mld6igmpVif>::stop() != XORP_OK) return (XORP_ERROR); XLOG_INFO("Protocol stopped"); return (XORP_OK);}/** * Enable the node operation. * * If an unit is not enabled, it cannot be start, or pending-start. */voidMld6igmpNode::enable(){ ProtoUnit::enable(); XLOG_INFO("Protocol enabled");}/** * Disable the node operation. * * If an unit is disabled, it cannot be start or pending-start. * If the unit was runnning, it will be stop first. */voidMld6igmpNode::disable(){ stop(); ProtoUnit::disable(); XLOG_INFO("Protocol disabled");}/** * Get the IP protocol number. * * @return the IP protocol number. */uint8_tMld6igmpNode::ip_protocol_number() const{ if (proto_is_igmp()) return (IPPROTO_IGMP); if (proto_is_mld6()) return (IPPROTO_ICMPV6); XLOG_UNREACHABLE(); return (0);}voidMld6igmpNode::status_change(ServiceBase* service, ServiceStatus old_status, ServiceStatus new_status){ if (service == this) { if ((old_status == SERVICE_STARTING) && (new_status == SERVICE_RUNNING)) { // The startup process has completed if (final_start() != XORP_OK) { XLOG_ERROR("Cannot complete the startup process; " "current state is %s", ProtoNode<Mld6igmpVif>::state_str().c_str()); return; } ProtoNode<Mld6igmpVif>::set_node_status(PROC_READY); return; } if ((old_status == SERVICE_SHUTTING_DOWN) && (new_status == SERVICE_SHUTDOWN)) { // The shutdown process has completed final_stop(); // Set the node status ProtoNode<Mld6igmpVif>::set_node_status(PROC_DONE); return; } // // TODO: check if there was an error // return; } if (service == ifmgr_mirror_service_base()) { if ((old_status == SERVICE_SHUTTING_DOWN) && (new_status == SERVICE_SHUTDOWN)) { decr_shutdown_requests_n(); // XXX: for the ifmgr } }}voidMld6igmpNode::tree_complete(){ decr_startup_requests_n(); // XXX: for the ifmgr // // XXX: we use same actions when the tree is completed or updates are made // updates_made();}voidMld6igmpNode::updates_made(){ map<string, Vif>::iterator mld6igmp_vif_iter; string error_msg; // // Update the local copy of the interface tree // _iftree = ifmgr_iftree(); // // Add new vifs and update existing ones // IfMgrIfTree::IfMap::const_iterator ifmgr_iface_iter; for (ifmgr_iface_iter = _iftree.interfaces().begin(); ifmgr_iface_iter != _iftree.interfaces().end(); ++ifmgr_iface_iter) { const IfMgrIfAtom& ifmgr_iface = ifmgr_iface_iter->second; IfMgrIfAtom::VifMap::const_iterator ifmgr_vif_iter; for (ifmgr_vif_iter = ifmgr_iface.vifs().begin(); ifmgr_vif_iter != ifmgr_iface.vifs().end(); ++ifmgr_vif_iter) { const IfMgrVifAtom& ifmgr_vif = ifmgr_vif_iter->second; const string& ifmgr_vif_name = ifmgr_vif.name(); Vif* node_vif = NULL; mld6igmp_vif_iter = configured_vifs().find(ifmgr_vif_name); if (mld6igmp_vif_iter != configured_vifs().end()) { node_vif = &(mld6igmp_vif_iter->second); } // // Add a new vif // if (node_vif == NULL) { uint32_t vif_index = ifmgr_vif.vif_index(); XLOG_ASSERT(vif_index != Vif::VIF_INDEX_INVALID); if (add_config_vif(ifmgr_vif_name, vif_index, error_msg) != XORP_OK) { XLOG_ERROR("Cannot add vif %s to the set of configured " "vifs: %s", ifmgr_vif_name.c_str(), error_msg.c_str()); continue; } mld6igmp_vif_iter = configured_vifs().find(ifmgr_vif_name); XLOG_ASSERT(mld6igmp_vif_iter != configured_vifs().end()); node_vif = &(mld6igmp_vif_iter->second); // FALLTHROUGH } // // Update the pif_index // set_config_pif_index(ifmgr_vif_name, ifmgr_vif.pif_index(), error_msg); // // Update the vif flags // bool is_up = ifmgr_iface.enabled(); is_up &= (! ifmgr_iface.no_carrier()); is_up &= ifmgr_vif.enabled(); set_config_vif_flags(ifmgr_vif_name, ifmgr_vif.pim_register(), ifmgr_vif.p2p_capable(), ifmgr_vif.loopback(), ifmgr_vif.multicast_capable(), ifmgr_vif.broadcast_capable(), is_up, ifmgr_iface.mtu(), error_msg); } } // // Add new vif addresses, update existing ones, and remove old addresses // for (ifmgr_iface_iter = _iftree.interfaces().begin(); ifmgr_iface_iter != _iftree.interfaces().end(); ++ifmgr_iface_iter) { const IfMgrIfAtom& ifmgr_iface = ifmgr_iface_iter->second; const string& ifmgr_iface_name = ifmgr_iface.name(); IfMgrIfAtom::VifMap::const_iterator ifmgr_vif_iter; for (ifmgr_vif_iter = ifmgr_iface.vifs().begin(); ifmgr_vif_iter != ifmgr_iface.vifs().end(); ++ifmgr_vif_iter) { const IfMgrVifAtom& ifmgr_vif = ifmgr_vif_iter->second; const string& ifmgr_vif_name = ifmgr_vif.name(); Vif* node_vif = NULL; // // Add new vif addresses and update existing ones // mld6igmp_vif_iter = configured_vifs().find(ifmgr_vif_name); if (mld6igmp_vif_iter != configured_vifs().end()) { node_vif = &(mld6igmp_vif_iter->second); } if (is_ipv4()) { IfMgrVifAtom::IPv4Map::const_iterator a4_iter; for (a4_iter = ifmgr_vif.ipv4addrs().begin(); a4_iter != ifmgr_vif.ipv4addrs().end(); ++a4_iter) { const IfMgrIPv4Atom& a4 = a4_iter->second; VifAddr* node_vif_addr = node_vif->find_address(IPvX(a4.addr())); IPvX addr(a4.addr()); IPvXNet subnet_addr(addr, a4.prefix_len()); IPvX broadcast_addr(IPvX::ZERO(family())); IPvX peer_addr(IPvX::ZERO(family())); if (a4.has_broadcast()) broadcast_addr = IPvX(a4.broadcast_addr()); if (a4.has_endpoint()) peer_addr = IPvX(a4.endpoint_addr()); if (node_vif_addr == NULL) { if (add_config_vif_addr( ifmgr_vif_name, addr, subnet_addr, broadcast_addr, peer_addr, error_msg) != XORP_OK) { XLOG_ERROR("Cannot add address %s to vif %s from " "the set of configured vifs: %s", cstring(addr), ifmgr_vif_name.c_str(), error_msg.c_str()); } continue; } if ((addr == node_vif_addr->addr()) && (subnet_addr == node_vif_addr->subnet_addr()) && (broadcast_addr == node_vif_addr->broadcast_addr()) && (peer_addr == node_vif_addr->peer_addr())) { continue; // Nothing changed } // Update the address if (delete_config_vif_addr(ifmgr_vif_name, addr, error_msg)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -