Multicast Routing Modelling In OMNeT++
AnsaIP.cc
Go to the documentation of this file.
00001 
00009 #include <omnetpp.h>
00010 #include "AnsaIP.h"
00011 #include "PimSplitter.h"
00012 
00013 Define_Module(AnsaIP);
00014 
00015 
00023 void AnsaIP::initialize(int stage)
00024 {
00025         INET_API IP::initialize();
00026 
00027         mrt = MulticastRoutingTableAccess().get();
00028         nb = NotificationBoardAccess().get();
00029 
00030 }
00031 
00044 void AnsaIP::handlePacketFromNetwork(IPDatagram *datagram)
00045 {
00046     //
00047     // "Prerouting"
00048     //
00049 
00050     // check for header biterror
00051     if (datagram->hasBitError())
00052     {
00053         // probability of bit error in header = size of header / size of total message
00054         // (ignore bit error if in payload)
00055         double relativeHeaderLength = datagram->getHeaderLength() / (double)datagram->getByteLength();
00056         if (dblrand() <= relativeHeaderLength)
00057         {
00058             EV << "bit error found, sending ICMP_PARAMETER_PROBLEM\n";
00059             icmpAccess.get()->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0);
00060             return;
00061         }
00062     }
00063 
00064     // remove control info
00065     if (datagram->getTransportProtocol()!=IP_PROT_DSR && datagram->getTransportProtocol()!=IP_PROT_MANET && !datagram->getDestAddress().isMulticast() && datagram->getTransportProtocol()!=IP_PROT_PIM)
00066     {
00067         delete datagram->removeControlInfo();
00068     }
00069     else if (datagram->getMoreFragments())
00070         delete datagram->removeControlInfo(); // delete all control message except the last
00071 
00072     //MYWORK Add all neccessery info to the IP Control Info for future use.
00073     if (datagram->getDestAddress().isMulticast() || datagram->getTransportProtocol() == IP_PROT_PIM)
00074     {
00075         IPControlInfo *ctrl = (IPControlInfo*)(datagram->removeControlInfo());
00076         ctrl->setSrcAddr(datagram->getSrcAddress());
00077         ctrl->setDestAddr(datagram->getDestAddress());
00078         ctrl->setInterfaceId(getSourceInterfaceFrom(datagram)->getInterfaceId());
00079         datagram->setControlInfo(ctrl);
00080     }
00081 
00082     // hop counter decrement; FIXME but not if it will be locally delivered
00083     datagram->setTimeToLive(datagram->getTimeToLive()-1);
00084 
00085     // send IGMP packet to IGMP module
00086     if (datagram->getTransportProtocol() == IP_PROT_IGMP)
00087     {
00088         cPacket *packet = decapsulateIP(datagram);
00089         send(packet, "transportOut", mapping.getOutputGateForProtocol(IP_PROT_IGMP));
00090         return;
00091     }
00092 
00093     //MYWORK send PIM packet to PIM module
00094     if (datagram->getTransportProtocol() == IP_PROT_PIM)
00095         {
00096                 cPacket *packet = decapsulateIP(datagram);
00097                 send(packet, "transportOut", mapping.getOutputGateForProtocol(IP_PROT_PIM));
00098         return;
00099         }
00100         
00101     //MYWORK route packet
00102     if (!datagram->getDestAddress().isMulticast())
00103         routePacket(datagram, NULL, false,NULL);
00104     else
00105         routeMulticastPacket(datagram, NULL, getSourceInterfaceFrom(datagram));
00106 }
00107 
00124 void AnsaIP::routeMulticastPacket(IPDatagram *datagram, InterfaceEntry *destIE, InterfaceEntry *fromIE)
00125 {
00126     IPAddress destAddr = datagram->getDestAddress();
00127     IPAddress srcAddr = datagram->getSrcAddress();
00128     IPControlInfo *ctrl = (IPControlInfo *) datagram->getControlInfo();
00129     EV << "Routing multicast datagram `" << datagram->getName() << "' with dest=" << destAddr << "\n";
00130     MulticastIPRoute *route = mrt->getRouteFor(destAddr, srcAddr);
00131 
00132     numMulticast++;
00133 
00134     // Process datagram only if sent locally or arrived on the shortest
00135     // route (provided routing table already contains srcAddr) = RPF interface;
00136     // otherwise discard and continue.
00137     InterfaceEntry *rpfInt = rt->getInterfaceForDestAddr(datagram->getSrcAddress());
00138     if (fromIE!=NULL && rpfInt!=NULL && fromIE!=rpfInt)
00139     {
00140         //MYWORK RPF interface has changed
00141         /*if (route != NULL && (route->getInIntId() != rpfInt->getInterfaceId()))
00142         {
00143                 EV << "RPF interface has changed" << endl;
00144                 nb->fireChangeNotification(NF_IPv4_RPF_CHANGE, route);
00145         }*/
00146         //MYWORK Data come to non-RPF interface
00147         if (!rt->isLocalMulticastAddress(destAddr) && !destAddr.isLinkLocalMulticast())
00148         {
00149                 EV << "Data on non-RPF interface" << endl;
00150                 nb->fireChangeNotification(NF_IPv4_DATA_ON_NONRPF, ctrl);
00151                 return;
00152         }
00153         else
00154         {
00155                         // FIXME count dropped
00156                         EV << "Packet dropped." << endl;
00157                         delete datagram;
00158                         return;
00159         }
00160     }
00161 
00162     //MYWORK for local traffic to given destination (PIM messages)
00163     if (fromIE == NULL && destIE != NULL)
00164     {
00165                 IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00166                 datagramCopy->setSrcAddress(destIE->ipv4Data()->getIPAddress());
00167                 fragmentAndSend(datagramCopy, destIE, destAddr);
00168 
00169         delete datagram;
00170         return;
00171     }
00172 
00173     // if received from the network...
00174     if (fromIE!=NULL)
00175     {
00176         EV << "Packet was received from the network..." << endl;
00177         // check for local delivery (multicast assigned to any interface)
00178         if (rt->isLocalMulticastAddress(destAddr))
00179         {
00180                 EV << "isLocalMulticastAddress." << endl;
00181             IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00182 
00183             // FIXME code from the MPLS model: set packet dest address to routerId
00184             datagramCopy->setDestAddress(rt->getRouterId());
00185             reassembleAndDeliver(datagramCopy);
00186         }
00187 
00188         // don't forward if IP forwarding is off
00189         if (!rt->isIPForwardingEnabled())
00190         {
00191                 EV << "IP forwarding is off." << endl;
00192             delete datagram;
00193             return;
00194         }
00195 
00196         // don't forward if dest address is link-scope
00197         // address is in the range 224.0.0.0 to 224.0.0.255
00198         if (destAddr.isLinkLocalMulticast())
00199         {
00200                 EV << "isLinkLocalMulticast." << endl;
00201             delete datagram;
00202             return;
00203         }
00204     }
00205 
00206 //MYWORK(to the end) now: routing
00207     EV << "AnsaIP::routeMulticastPacket - Multicast routing." << endl;
00208 
00209     // multicast group is not in multicast routing table and has to be added
00210     if (route == NULL)
00211     {
00212         EV << "AnsaIP::routeMulticastPacket - Multicast route does not exist, try to add." << endl;
00213         nb->fireChangeNotification(NF_IPv4_NEW_MULTICAST, ctrl);
00214         delete datagram->removeControlInfo();
00215         ctrl = NULL;
00216         // read new record
00217         route = mrt->getRouteFor(destAddr, srcAddr);
00218     }
00219 
00220         if (route == NULL)
00221         {
00222                 EV << "Still do not exist." << endl;
00223                 delete datagram;
00224                 return;
00225         }
00226 
00227         nb->fireChangeNotification(NF_IPv4_DATA_ON_RPF, route);
00228 
00229         // data won't be sent because there is no outgoing interface and/or route is pruned
00230     InterfaceVector outInt = route->getOutInt();
00231     if (outInt.size() == 0 || route->isFlagSet(P))
00232     {
00233         EV << "Route does not have any outgoing interface or it is pruned." << endl;
00234         if(ctrl != NULL)
00235         {
00236                         if (!route->isFlagSet(A))
00237                                 nb->fireChangeNotification(NF_IPv4_DATA_ON_PRUNED_INT, ctrl);
00238         }
00239                 delete datagram;
00240                 return;
00241     }
00242 
00243     // send packet to all outgoing interfaces of route (oilist)
00244         for (unsigned int i=0; i<outInt.size(); i++)
00245         {
00246                 // do not send to pruned interface
00247                 if (outInt[i].forwarding == Pruned)
00248                         continue;
00249 
00250                 InterfaceEntry *destIE = outInt[i].intPtr;
00251                 IPDatagram *datagramCopy = (IPDatagram *) datagram->dup();
00252 
00253                 // set datagram source address if not yet set
00254                 if (datagramCopy->getSrcAddress().isUnspecified())
00255                         datagramCopy->setSrcAddress(destIE->ipv4Data()->getIPAddress());
00256 
00257                 // send
00258                 fragmentAndSend(datagramCopy, destIE, destAddr);
00259         }
00260 
00261         // only copies sent, delete original datagram
00262         delete datagram;
00263 }
00264