?? mld6igmp_group_record.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.//// The Lightweight IGMP/MLD modifications to this file are copyrighted by://// Copyright (c) 2008 Huawei Technologies Co. Ltd//#ident "$XORP: xorp/contrib/mld6igmp_lite/mld6igmp_group_record.cc,v 1.4 2008/07/23 05:09:48 pavlin Exp $"//// Multicast group record information used by// 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_group_record.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///** * Mld6igmpGroupRecord::Mld6igmpGroupRecord: * @mld6igmp_vif: The vif interface this entry belongs to. * @group: The entry group address. * * Return value: **/Mld6igmpGroupRecord::Mld6igmpGroupRecord(Mld6igmpVif& mld6igmp_vif, const IPvX& group) : _mld6igmp_vif(mld6igmp_vif), _group(group), _do_forward_sources(*this), _last_reported_host(IPvX::ZERO(family())), _query_retransmission_count(0){ }/** * Mld6igmpGroupRecord::~Mld6igmpGroupRecord: * @: * * Mld6igmpGroupRecord destructor. **/Mld6igmpGroupRecord::~Mld6igmpGroupRecord(){ _do_forward_sources.delete_payload_and_clear();}/** * Get the corresponding event loop. * * @return the corresponding event loop. */EventLoop&Mld6igmpGroupRecord::eventloop(){ return (_mld6igmp_vif.mld6igmp_node().eventloop());}/** * Find a source that should be forwarded. * * @param source the source address. * @return the corresponding source record (@ref Mld6igmpSourceRecord) * if found, otherwise NULL. */Mld6igmpSourceRecord*Mld6igmpGroupRecord::find_do_forward_source(const IPvX& source){ return (_do_forward_sources.find_source_record(source));}/** * Test whether the entry is unused. * * @return true if the entry is unused, otherwise false. */boolMld6igmpGroupRecord::is_unused() const{ if (is_include_mode()) { if (_do_forward_sources.empty()) { return (true); } return (false); } if (is_asm_mode()) { // // XXX: the group timer must be running in EXCLUDE mode, // otherwise there must have been transition to INCLUDE mode. // if (_group_timer.scheduled()) return (false); XLOG_ASSERT(_do_forward_sources.empty()); return (true); } XLOG_UNREACHABLE(); return (true);}/** * Process MODE_IS_INCLUDE report. * * @param sources the source addresses. * @param last_reported_host the address of the host that last reported * as member. */voidMld6igmpGroupRecord::process_mode_is_include(const set<IPvX>& sources, const IPvX& last_reported_host){ bool old_is_include_mode = is_include_mode(); set<IPvX> old_do_forward_sources = _do_forward_sources.extract_source_addresses(); set_last_reported_host(last_reported_host); if (is_include_mode()) { // // Router State: INCLUDE (A) // Report Received: IS_IN (B) // New Router State: INCLUDE (A + B) // Actions: (B) = GMI // Mld6igmpSourceSet& a = _do_forward_sources; const set<IPvX>& b = sources; TimeVal gmi = _mld6igmp_vif.group_membership_interval(); _do_forward_sources = a + b; // (A + B) _do_forward_sources.set_source_timer(b, gmi); // (B) = GMI calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; } if (is_asm_mode()) { // // Router State: EXCLUDE (X, Y) // Report Received: IS_IN (A) // New Router State: EXCLUDE (X + A, Y - A) // Actions: (A) = GMI // Mld6igmpSourceSet& x = _do_forward_sources; const set<IPvX>& a = sources; TimeVal gmi = _mld6igmp_vif.group_membership_interval(); // XXX: first transfer (Y * A) from (Y) to (X) _do_forward_sources = x + a; // (X + A) _do_forward_sources.set_source_timer(a, gmi); // (A) = GMI calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; }}/** * Process MODE_IS_EXCLUDE report. * * @param sources the source addresses. * @param last_reported_host the address of the host that last reported * as member. */voidMld6igmpGroupRecord::process_mode_is_exclude(const set<IPvX>& sources, const IPvX& last_reported_host){ bool old_is_include_mode = is_include_mode(); set<IPvX> old_do_forward_sources = _do_forward_sources.extract_source_addresses(); set_last_reported_host(last_reported_host); if (! sources.empty()) { XLOG_WARNING("Non-empty list of sources when processing mode is EXCLUDE"); } if (is_include_mode()) { // // Router State: INCLUDE (A) // Report Received: IS_EX (B) // New Router State: EXCLUDE (A * B, B - A) // Actions: (B - A) = 0 // Delete (A - B) // Group Timer = GMI // TimeVal gmi = _mld6igmp_vif.group_membership_interval(); _group_timer = eventloop().new_oneoff_after( gmi, callback(this, &Mld6igmpGroupRecord::group_timer_timeout)); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; } if (is_asm_mode()) { // // Router State: EXCLUDE (X, Y) // Report Received: IS_EX (A) // New Router State: EXCLUDE (A - Y, Y * A) // Actions: (A - X - Y) = GMI // Delete (X - A) // Delete (Y - A) // Group Timer = GMI // TimeVal gmi = _mld6igmp_vif.group_membership_interval(); _group_timer = eventloop().new_oneoff_after( gmi, callback(this, &Mld6igmpGroupRecord::group_timer_timeout)); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; }}/** * Process CHANGE_TO_INCLUDE_MODE report. * * @param sources the source addresses. * @param last_reported_host the address of the host that last reported * as member. */voidMld6igmpGroupRecord::process_change_to_include_mode(const set<IPvX>& sources, const IPvX& last_reported_host){ bool old_is_include_mode = is_include_mode(); set<IPvX> old_do_forward_sources = _do_forward_sources.extract_source_addresses(); string dummy_error_msg; set_last_reported_host(last_reported_host); if (is_include_mode()) { // // Router State: INCLUDE (A) // Report Received: TO_IN (B) // New Router State: INCLUDE (A + B) // Actions: (B) = GMI // Send Q(G, A - B) // Mld6igmpSourceSet& a = _do_forward_sources; const set<IPvX>& b = sources; TimeVal gmi = _mld6igmp_vif.group_membership_interval(); Mld6igmpSourceSet a_minus_b = a - b; // A - B _do_forward_sources = a + b; // A + B _do_forward_sources.set_source_timer(b, gmi); // (B) = GMI // Send Q(G, A - B) with a_minus_b _mld6igmp_vif.mld6igmp_group_source_query_send( group(), a_minus_b.extract_source_addresses(), dummy_error_msg); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; } if (is_asm_mode()) { // // Router State: EXCLUDE (X, Y) // Report Received: TO_IN (A) // New Router State: EXCLUDE (X + A, Y - A) // Actions: (A) = GMI // Send Q(G, X - A) // Send Q(G) // Mld6igmpSourceSet& x = _do_forward_sources; const set<IPvX>& a = sources; TimeVal gmi = _mld6igmp_vif.group_membership_interval(); Mld6igmpSourceSet x_minus_a = x - a; // X - A // XXX: first transfer (Y * A) from (Y) to (X) _do_forward_sources = x + a; // X + A _do_forward_sources.set_source_timer(a, gmi); // (A) = GMI // Send Q(G, X - A) with x_minus_a _mld6igmp_vif.mld6igmp_group_source_query_send( group(), x_minus_a.extract_source_addresses(), dummy_error_msg); // Send Q(G) _mld6igmp_vif.mld6igmp_group_query_send(group(), dummy_error_msg); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; }}/** * Process CHANGE_TO_EXCLUDE_MODE report. * * @param sources the source addresses. * @param last_reported_host the address of the host that last reported * as member. */voidMld6igmpGroupRecord::process_change_to_exclude_mode(const set<IPvX>& sources, const IPvX& last_reported_host){ bool old_is_include_mode = is_include_mode(); set<IPvX> old_do_forward_sources = _do_forward_sources.extract_source_addresses(); string dummy_error_msg; if (! sources.empty()) { XLOG_WARNING("Non-empty list of sources when processing change to EXCLUDE"); } set_last_reported_host(last_reported_host); if (is_include_mode()) { // // Router State: INCLUDE (A) // Report Received: TO_EX (B) // New Router State: EXCLUDE (A * B, B - A) // Actions: (B - A) = 0 // Delete (A - B) // Send Q(G, A * B) // Group Timer = GMI // TimeVal gmi = _mld6igmp_vif.group_membership_interval(); _group_timer = eventloop().new_oneoff_after( gmi, callback(this, &Mld6igmpGroupRecord::group_timer_timeout)); // Send Q(G, A * B) with _do_forward_sources _mld6igmp_vif.mld6igmp_group_source_query_send( group(), _do_forward_sources.extract_source_addresses(), dummy_error_msg); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; } if (is_asm_mode()) { // // Router State: EXCLUDE (X, Y) // Report Received: TO_EX (A) // New Router State: EXCLUDE (A - Y, Y * A) // Actions: (A - X - Y) = Group Timer // Delete (X - A) // Delete (Y - A) // Send Q(G, A - Y) // Group Timer = GMI // TimeVal gmi = _mld6igmp_vif.group_membership_interval(); TimeVal gt; _group_timer.time_remaining(gt); _group_timer = eventloop().new_oneoff_after( gmi, callback(this, &Mld6igmpGroupRecord::group_timer_timeout)); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; }}/** * Process ALLOW_NEW_SOURCES report. * * @param sources the source addresses. * @param last_reported_host the address of the host that last reported * as member. */voidMld6igmpGroupRecord::process_allow_new_sources(const set<IPvX>& sources, const IPvX& last_reported_host){ bool old_is_include_mode = is_include_mode(); set<IPvX> old_do_forward_sources = _do_forward_sources.extract_source_addresses(); set_last_reported_host(last_reported_host); if (is_include_mode()) { // // Router State: INCLUDE (A) // Report Received: ALLOW (B) // New Router State: INCLUDE (A + B) // Actions: (B) = GMI // Mld6igmpSourceSet& a = _do_forward_sources; const set<IPvX>& b = sources; TimeVal gmi = _mld6igmp_vif.group_membership_interval(); _do_forward_sources = a + b; // A + B _do_forward_sources.set_source_timer(b, gmi); // (B) = GMI calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; } if (is_asm_mode()) { // // Router State: EXCLUDE (X, Y) // Report Received: ALLOW (A) // New Router State: EXCLUDE (X + A, Y - A) // Actions: (A) = GMI // Mld6igmpSourceSet& x = _do_forward_sources; const set<IPvX>& a = sources; TimeVal gmi = _mld6igmp_vif.group_membership_interval(); // XXX: first transfer (Y * A) from (Y) to (X) _do_forward_sources = x + a; // X + A _do_forward_sources.set_source_timer(a, gmi); // (A) = GMI calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources); return; }}/** * Process BLOCK_OLD_SOURCES report. * * @param sources the source addresses. * @param last_reported_host the address of the host that last reported * as member. */voidMld6igmpGroupRecord::process_block_old_sources(const set<IPvX>& sources, const IPvX& last_reported_host){ bool old_is_include_mode = is_include_mode(); set<IPvX> old_do_forward_sources = _do_forward_sources.extract_source_addresses(); string dummy_error_msg; set_last_reported_host(last_reported_host); if (is_include_mode()) { // // Router State: INCLUDE (A) // Report Received: BLOCK (B) // New Router State: INCLUDE (A) // Actions: Send Q(G, A * B) // Mld6igmpSourceSet& a = _do_forward_sources; const set<IPvX>& b = sources; Mld6igmpSourceSet a_and_b = a * b; // Send Q(G, A * B) with a_and_b _mld6igmp_vif.mld6igmp_group_source_query_send( group(), a_and_b.extract_source_addresses(), dummy_error_msg); calculate_forwarding_changes(old_is_include_mode, old_do_forward_sources);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -