Alex Bikfalvi
SimStream Documentation
LayerIgmp.cpp
00001 #include "Headers.h" 00002 #include "LayerIgmp.h" 00003 00004 CLayerIgmp::CLayerIgmp( 00005 CSimHandler* sim, 00006 CAddress address, 00007 __uint32 numGroups, 00008 EIgmpType type 00009 ) : CLayer(sim) 00010 { 00011 this->address = address; 00012 this->numGroups = numGroups; 00013 this->type = type; 00014 00015 // Local groups 00016 this->memberships = new CLayerIpMcastMembership[this->numGroups]; 00017 00018 // Remote groups 00019 this->groups = new CLayerIpMcastGroup[this->numGroups]; 00020 00021 // Delegates 00022 this->delegateRecv = new Delegate2<CLayerIgmp, void, __uint32, CPacketIp*>(this, &CLayerIgmp::Recv); 00023 this->delegateJoin = new Delegate2<CLayerIgmp, void, CAddress, __uint32>(this, &CLayerIgmp::Join); 00024 this->delegateLeave = new Delegate1<CLayerIgmp, void, CAddress>(this, &CLayerIgmp::Leave); 00025 00026 // Events 00027 this->eventJoin = new Event3<void, __uint32, CAddress, CLayerIpMcastGroup*>(); 00028 this->eventLeave = new Event3<void, __uint32, CAddress, CLayerIpMcastGroup*>(); 00029 this->eventLocalJoin = new Event2<void, __uint32, CAddress>(); 00030 this->eventLocalLeave = new Event2<void, __uint32, CAddress>(); 00031 this->eventSend = new Event2<void, __uint32, CPacketIp*>(); 00032 00033 // Statistics 00034 this->statEntries = 0; 00035 this->statEntriesNum = 0; 00036 this->statEntriesLast = 0; 00037 } 00038 00039 CLayerIgmp::~CLayerIgmp() 00040 { 00041 delete[] this->memberships; 00042 delete[] this->groups; 00043 00044 delete this->delegateRecv; 00045 delete this->delegateJoin; 00046 delete this->delegateLeave; 00047 00048 delete this->eventJoin; 00049 delete this->eventLeave; 00050 00051 delete this->eventLocalJoin; 00052 delete this->eventLocalLeave; 00053 00054 delete this->eventSend; 00055 } 00056 00057 void CLayerIgmp::Join(CAddress address, __uint32 entry) 00058 { 00059 __uint32 group = address.MulticastGroup(); 00060 assert(group < this->numGroups); 00061 00062 // If the host is part of the multicast group, return 00063 if(this->memberships[group].State() == CLayerIpMcastMembership::MEMBER) return; 00064 00065 // Send an unsolicited membership report to the IP multicast address of the group 00066 CPacketIgmp* packet = new CPacketIgmp(address, CPacketIgmp::PACKET_IGMP_MEMBERSHIP_REPORT); 00067 00068 // Send the IGMP packet on the joined interface, group multicast address and TTL of 1 00069 this->Send(entry, address, 1, packet); 00070 00071 // Set the group state to joined 00072 this->memberships[group].Join(entry); 00073 00074 // Call event for membership change 00075 (*this->eventLocalJoin)(entry, address); 00076 } 00077 00078 void CLayerIgmp::Leave(CAddress address) 00079 { 00080 __uint32 group = address.MulticastGroup(); 00081 assert(group < this->numGroups); 00082 00083 // If the host is not part of the multicast group, return 00084 if(this->memberships[group].State() == CLayerIpMcastMembership::NON_MEMBER) return; 00085 00086 // Send a membership leave to the all routers multicast address 00087 CPacketIgmp* packet = new CPacketIgmp(address, CPacketIgmp::PACKET_IGMP_LEAVE_GROUP); 00088 00089 // Send the IGMP packet on the joined interface, all routers multicast address and TTL of 1 00090 this->Send(this->memberships[group].Entry(), ADDRESS_MCAST_ALL_ROUTERS, 1, packet); 00091 00092 // Call event for membership change 00093 (*this->eventLocalLeave)(this->memberships[group].Entry(), address); 00094 00095 // Set group state to leave 00096 this->memberships[group].Leave(); 00097 } 00098 00099 void CLayerIgmp::Recv(__uint32 entry, CPacketIp* packet) 00100 { 00101 // Process only IGMP packet 00102 if(packet->Payload() == NULL) return; 00103 if(packet->Payload()->Type() != PACKET_TYPE_IGMP) return; 00104 00105 #ifdef LOG_LAYER 00106 printf("\n\tT = %7.3lf IGMP RECV local=%u bytes=%u src=%u dst=%u", this->sim->Time(), this->address, packet->Size(), packet->Src(), packet->Dst()); 00107 #endif 00108 00109 switch(packet->Dst().Address()) 00110 { 00111 case ADDRESS_MCAST_ALL_SYSTEMS: this->RecvIgmpAllSystems(entry, packet->Src(), packet->Dst(), type_cast<CPacketIgmp*>(packet->Payload())); break; 00112 case ADDRESS_MCAST_ALL_ROUTERS: this->RecvIgmpAllRouters(entry, packet->Src(), packet->Dst(), type_cast<CPacketIgmp*>(packet->Payload())); break; 00113 default: this->RecvIgmpOther(entry, packet->Src(), packet->Dst(), type_cast<CPacketIgmp*>(packet->Payload())); break; 00114 } 00115 } 00116 00117 void CLayerIgmp::RecvIgmpAllSystems(__uint32 entry, CAddress src, CAddress dst, CPacketIgmp* packet) 00118 { 00119 // Do nothing (current implementation does not process all systems IGMP packets) 00120 } 00121 00122 void CLayerIgmp::RecvIgmpAllRouters(__uint32 entry, CAddress src, CAddress dst, CPacketIgmp* packet) 00123 { 00124 // Process all routers IGMP packets if the IGMP type is router 00125 if(this->type != IGMP_ROUTER) return; 00126 00127 switch(packet->IgmpType()) 00128 { 00129 case CPacketIgmp::PACKET_IGMP_LEAVE_GROUP: this->RecvIgmpLeaveGroup(entry, src, dst, packet); break; // Leave group 00130 default:; // Do nothing 00131 } 00132 } 00133 00134 void CLayerIgmp::RecvIgmpOther(__uint32 entry, CAddress src, CAddress dst, CPacketIgmp* packet) 00135 { 00136 // Process only multicast addresses or unicast addressed to this host 00137 if((!dst.IsMulticast()) && (dst != this->address)) return; 00138 00139 switch(packet->IgmpType()) 00140 { 00141 case CPacketIgmp::PACKET_IGMP_MEMBERSHIP_REPORT: this->RecvIgmpJoinGroup(entry, src, dst, packet); break; // Join group 00142 default:; // Do nothing 00143 } 00144 } 00145 00146 void CLayerIgmp::RecvIgmpJoinGroup(__uint32 entry, CAddress src, CAddress dst, CPacketIgmp* packet) 00147 { 00148 // Join group (membership report) 00149 __uint32 group = dst.MulticastGroup(); 00150 assert(group < this->numGroups); 00151 00152 // Statistics 00153 this->statEntries += (this->sim->Time() - this->statEntriesLast) * this->statEntriesNum; 00154 this->statEntriesNum -= this->groups[group].Out()->size(); 00155 00156 // Add the interface to the group 00157 this->groups[group].Out()->insert(entry); 00158 00159 // Statistics 00160 this->statEntriesNum += this->groups[group].Out()->size(); 00161 this->statEntriesLast = this->sim->Time(); 00162 00163 // Call event for this group 00164 (*this->eventJoin)(entry, dst, &this->groups[group]); 00165 } 00166 00167 void CLayerIgmp::RecvIgmpLeaveGroup(__uint32 entry, CAddress src, CAddress dst, CPacketIgmp* packet) 00168 { 00169 // Leave group 00170 __uint32 group = packet->Group().MulticastGroup(); 00171 assert(group < this->numGroups); 00172 00173 // Statistics 00174 this->statEntries += (this->sim->Time() - this->statEntriesLast) * this->statEntriesNum; 00175 this->statEntriesNum -= this->groups[group].Out()->size(); 00176 00177 // Remove the interface from the group 00178 this->groups[group].Out()->erase(entry); 00179 00180 // Statistics 00181 this->statEntriesNum += this->groups[group].Out()->size(); 00182 this->statEntriesLast = this->sim->Time(); 00183 00184 // Call event for this group 00185 (*this->eventLeave)(entry, packet->Group(), &this->groups[group]); 00186 } 00187 00188 void CLayerIgmp::Send(__uint32 entry, CAddress dst, __byte ttl, CPacket* payload) 00189 { 00190 // Create a new IP packet 00191 CPacketIp* packet = new CPacketIp(this->address, dst, ttl, payload); 00192 00193 #ifdef LOG_LAYER 00194 printf("\n\tT = %7.3lf IGMP SEND local=%u bytes=%u src=%u dst=%u", this->sim->Time(), this->address, packet->Size(), packet->Src(), packet->Dst()); 00195 #endif 00196 00197 // Send the packet to the lower layer 00198 (*this->eventSend)(entry, packet); 00199 } 00200 00201 void CLayerIgmp::Finalize() 00202 { 00203 this->statEntries += (this->sim->Time() - this->statEntriesLast) * this->statEntriesNum; 00204 this->statEntries /= this->sim->Time(); 00205 }
Last updated: February 8, 2011