Alex Bikfalvi
SimStream Documentation
LayerPimSm.cpp
00001 #include "Headers.h" 00002 #include "LayerPimSm.h" 00003 00004 CLayerPimSm::CLayerPimSm( 00005 CSimHandler* sim, 00006 __uint32 numGroups, 00007 CAddress address, 00008 CAddress* rp, 00009 CRoute* route 00010 ) : CLayer(sim) 00011 { 00012 this->numGroups = numGroups; 00013 this->address = address; 00014 this->route = route; 00015 00016 // Rendezvous-points 00017 this->rp = rp; 00018 00019 // Memeberships (IGMP) 00020 this->memberships = new CLayerPimSmMembership[this->numGroups]; 00021 00022 // Groups (*, G) 00023 this->groups = new CLayerIpMcastGroup[this->numGroups]; 00024 00025 // Delegates 00026 this->delegateRecv = new Delegate2<CLayerPimSm, void, __uint32, CPacketIp*>(this, &CLayerPimSm::Recv); 00027 this->delegateJoin = new Delegate3<CLayerPimSm, void, __uint32, CAddress, CLayerIpMcastGroup*>(this, &CLayerPimSm::Join); 00028 this->delegateLeave = new Delegate3<CLayerPimSm, void, __uint32, CAddress, CLayerIpMcastGroup*>(this, &CLayerPimSm::Leave); 00029 00030 // Events 00031 this->eventJoin = new Event3<void, __uint32, CAddress, CLayerIpMcastGroup*>(); 00032 this->eventLeave = new Event3<void, __uint32, CAddress, CLayerIpMcastGroup*>(); 00033 this->eventSend = new Event2<void, __uint32, CPacketIp*>(); 00034 00035 // Statistics 00036 this->statEntries = 0; 00037 this->statEntriesNum = 0; 00038 this->statEntriesLast = 0; 00039 } 00040 00041 CLayerPimSm::~CLayerPimSm() 00042 { 00043 // Memberships (IGMP) 00044 delete[] this->memberships; 00045 00046 // Groups (*, G) 00047 delete[] this->groups; 00048 00049 // Delegates 00050 delete this->delegateRecv; 00051 delete this->delegateJoin; 00052 delete this->delegateLeave; 00053 00054 // Events 00055 delete this->eventJoin; 00056 delete this->eventLeave; 00057 delete this->eventSend; 00058 } 00059 00060 void CLayerPimSm::Recv(__uint32 entry, CPacketIp* packet) 00061 { 00062 // Process only PIM-SM packets 00063 if(packet->Dst() != ADDRESS_MCAST_PIM_SM) return; 00064 if(packet->Payload() == NULL) return; 00065 if(packet->Payload()->Type() != PACKET_TYPE_PIM_SM) return; 00066 00067 #ifdef LOG_LAYER 00068 printf("\n\tT = %7.3lf PIM_SM RECV local=%u entry=%u bytes=%u src=%u dst=%u", this->sim->Time(), this->address, entry, packet->Size(), packet->Src(), packet->Dst()); 00069 #endif 00070 00071 this->RecvPimSm(entry, packet->Src(), packet->Dst(), type_cast<CPacketPimSm*>(packet->Payload())); 00072 } 00073 00074 void CLayerPimSm::RecvPimSm(__uint32 entry, CAddress src, CAddress dst, CPacketPimSm* packet) 00075 { 00076 switch(packet->PimSmType()) 00077 { 00078 case CPacketPimSm::JOIN_PRUNE: this->RecvPimSmJoinPrune(entry, src, dst, type_cast<CPacketPimSmJoinPrune*>(packet)); break; 00079 default:; // do nothing 00080 } 00081 } 00082 00083 void CLayerPimSm::RecvPimSmJoinPrune(__uint32 entry, CAddress src, CAddress dst, CPacketPimSmJoinPrune* packet) 00084 { 00085 // Get the group 00086 __uint32 group = packet->Address().MulticastGroup(); 00087 assert(group < this->numGroups); 00088 00089 switch(packet->JoinPruneType()) 00090 { 00091 case CPacketPimSmJoinPrune::JOIN: 00092 #ifdef LOG_LAYER 00093 printf("\n\tT = %7.3lf PIM_SM RECV local=%u JOIN %u", this->sim->Time(), this->address, group); 00094 #endif 00095 00096 // Join the group 00097 this->JoinGroup(group, packet->Address()); 00098 00099 // Statistics 00100 this->statEntries += (this->sim->Time() - this->statEntriesLast) * this->statEntriesNum; 00101 this->statEntriesNum -= this->groups[group].Out()->size(); 00102 00103 // Add the interface to the list of outbound interfaces for this group 00104 this->groups[group].Out()->insert(entry); 00105 00106 // Statistics 00107 this->statEntriesNum += this->groups[group].Out()->size(); 00108 this->statEntriesLast = this->sim->Time(); 00109 00110 // Call event for this group 00111 (*this->eventJoin)(entry, packet->Address(), &this->groups[group]); 00112 00113 break; 00114 case CPacketPimSmJoinPrune::PRUNE: 00115 #ifdef LOG_LAYER 00116 printf("\n\tT = %7.3lf PIM_SM RECV local=%u PRUNE %u", this->sim->Time(), this->address, group); 00117 #endif 00118 00119 // Statistics 00120 this->statEntries += (this->sim->Time() - this->statEntriesLast) * this->statEntriesNum; 00121 this->statEntriesNum -= this->groups[group].Out()->size(); 00122 00123 // Remove the interface from the list of outbound interfaces for this group 00124 this->groups[group].Out()->erase(entry); 00125 00126 // Statistics 00127 this->statEntriesNum += this->groups[group].Out()->size(); 00128 this->statEntriesLast = this->sim->Time(); 00129 00130 // Leave the group 00131 this->LeaveGroup(group, packet->Address()); 00132 00133 // Call event for this group 00134 (*this->eventLeave)(entry, packet->Address(), &this->groups[group]); 00135 00136 break; 00137 } 00138 } 00139 00140 void CLayerPimSm::Join(__uint32 entry, CAddress address, CLayerIpMcastGroup* igmp) 00141 { 00142 __uint32 group = address.MulticastGroup(); 00143 assert(group < this->numGroups); 00144 00145 // Join the group 00146 this->JoinGroup(group, address); 00147 00148 // Update group membership 00149 this->memberships[group] = igmp->Out()->size()?CLayerPimSmMembership::MEMBER:CLayerPimSmMembership::NON_MEMBER; 00150 } 00151 00152 void CLayerPimSm::Leave(__uint32 entry, CAddress address, CLayerIpMcastGroup* igmp) 00153 { 00154 __uint32 group = address.MulticastGroup(); 00155 assert(group < this->numGroups); 00156 00157 // Update group membership 00158 this->memberships[group] = igmp->Out()->size()?CLayerPimSmMembership::MEMBER:CLayerPimSmMembership::NON_MEMBER; 00159 00160 // Leave the group 00161 this->LeaveGroup(group, address); 00162 } 00163 00164 void CLayerPimSm::JoinGroup(__uint32 group, CAddress address) 00165 { 00166 // If the group is new (i.e. no output interfaces) and this is not the RP router for this group and there is no (IGMP) membership 00167 if((this->groups[group].Out()->size() == 0) && (this->rp[group] != this->address) && (this->memberships[group].State() == CLayerPimSmMembership::NON_MEMBER)) 00168 { 00169 // Send a JOIN message toward the RP router 00170 CPacketPimSmJoinPrune* join = new CPacketPimSmJoinPrune( 00171 CPacketPimSmJoinPrune::JOIN, 00172 address 00173 ); 00174 00175 // Send the packet on the link toward the RP with TTL of 1 00176 __uint32 link = this->route->Forward(this->address, this->rp[group]); 00177 00178 this->Send(link, ADDRESS_MCAST_PIM_SM, 1, join); 00179 } 00180 } 00181 00182 void CLayerPimSm::LeaveGroup(__uint32 group, CAddress address) 00183 { 00184 // If the group is empty (i.e. no output interfaces) and this is not the RP router for this group and there are no memberships (IGMP) 00185 if((this->groups[group].Out()->size() == 0) && (this->rp[group] != this->address) && (this->memberships[group].State() == CLayerPimSmMembership::NON_MEMBER)) 00186 { 00187 // Send a PRUNE message toward the RP router 00188 CPacketPimSmJoinPrune* prune = new CPacketPimSmJoinPrune( 00189 CPacketPimSmJoinPrune::PRUNE, 00190 address 00191 ); 00192 00193 // Send the packet on the link toward the RP with TTL of 1 00194 __uint32 link = this->route->Forward(this->address, this->rp[group]); 00195 00196 this->Send(link, ADDRESS_MCAST_PIM_SM, 1, prune); 00197 } 00198 } 00199 00200 void CLayerPimSm::Send(__uint32 entry, CAddress dst, __byte ttl, CPacket* payload) 00201 { 00202 // Create a new IP packet 00203 CPacketIp* packet = new CPacketIp(this->address, dst, ttl, payload); 00204 00205 #ifdef LOG_LAYER 00206 printf("\n\tT = %7.3lf PIM_SM SEND local=%u entry=%u bytes=%u src=%u dst=%u", this->sim->Time(), this->address, entry, packet->Size(), packet->Src(), packet->Dst()); 00207 #endif 00208 00209 // Send the packet to the lower layer 00210 (*this->eventSend)(entry, packet); 00211 } 00212 00213 void CLayerPimSm::Finalize() 00214 { 00215 this->statEntries += (this->sim->Time() - this->statEntriesLast) * this->statEntriesNum; 00216 this->statEntries /= this->sim->Time(); 00217 }
Last updated: February 8, 2011