Public Member Functions | Protected Member Functions | Protected Attributes

IPv6 Class Reference

#include <IPv6.h>

Inheritance diagram for IPv6:
QueueBase AbstractQueue

List of all members.

Public Member Functions

 IPv6 ()

Protected Member Functions

virtual InterfaceEntrygetSourceInterfaceFrom (cPacket *msg)
virtual void updateDisplayString ()
virtual IPv6Datagramencapsulate (cPacket *transportPacket, InterfaceEntry *&destIE)
virtual void handleDatagramFromNetwork (IPv6Datagram *datagram)
virtual void handleMessageFromHL (cPacket *msg)
virtual void handleReceivedICMP (ICMPv6Message *msg)
virtual void fragmentAndRoute (IPv6Datagram *datagram, InterfaceEntry *destIE=NULL)
virtual void routePacket (IPv6Datagram *datagram, InterfaceEntry *destIE, bool fromHL)
virtual void routeMulticastPacket (IPv6Datagram *datagram, InterfaceEntry *destIE, InterfaceEntry *fromIE)
virtual void isLocalAddress (IPv6Datagram *datagram)
virtual cPacket * decapsulate (IPv6Datagram *datagram)
virtual void sendDatagramToOutput (IPv6Datagram *datagram, InterfaceEntry *ie, const MACAddress &macAddr)
virtual void initialize ()
virtual void endService (cPacket *msg)

Protected Attributes

IInterfaceTableift
RoutingTable6rt
IPv6NeighbourDiscoverynd
ICMPv6icmp
long curFragmentId
IPv6FragBuf fragbuf
simtime_t lastCheckTime
ProtocolMapping mapping
int numMulticast
int numLocalDeliver
int numDropped
int numUnroutable
int numForwarded

Detailed Description

IPv6 implementation.

Definition at line 36 of file IPv6.h.


Constructor & Destructor Documentation

IPv6::IPv6 (  )  [inline]

Definition at line 124 of file IPv6.h.

{}


Member Function Documentation

cPacket * IPv6::decapsulate ( IPv6Datagram datagram  )  [protected, virtual]

Decapsulate and return encapsulated packet after attaching IPv6ControlInfo.

Definition at line 479 of file IPv6.cc.

Referenced by isLocalAddress().

{
    // decapsulate transport packet
    InterfaceEntry *fromIE = getSourceInterfaceFrom(datagram);
    cPacket *packet = datagram->decapsulate();

    // create and fill in control info
    IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
    controlInfo->setProtocol(datagram->getTransportProtocol());
    controlInfo->setSrcAddr(datagram->getSrcAddress());
    controlInfo->setDestAddr(datagram->getDestAddress());
    controlInfo->setHopLimit(datagram->getHopLimit());
    controlInfo->setInterfaceId(fromIE ? fromIE->getInterfaceId() : -1);

    // original IP datagram might be needed in upper layers to send back ICMP error message
    controlInfo->setOrigDatagram(datagram);

    // attach control info
    packet->setControlInfo(controlInfo);

    return packet;
}

IPv6Datagram * IPv6::encapsulate ( cPacket *  transportPacket,
InterfaceEntry *&  destIE 
) [protected, virtual]

Encapsulate packet coming from higher layers into IPv6Datagram

Definition at line 502 of file IPv6.cc.

Referenced by handleMessageFromHL().

{
    IPv6ControlInfo *controlInfo = check_and_cast<IPv6ControlInfo*>(transportPacket->removeControlInfo());

    IPv6Datagram *datagram = new IPv6Datagram(transportPacket->getName());
    datagram->setByteLength(datagram->calculateHeaderByteLength());
    datagram->encapsulate(transportPacket);

    // IPV6_MULTICAST_IF option, but allow interface selection for unicast packets as well
    destIE = ift->getInterfaceById(controlInfo->getInterfaceId());

    // set source and destination address
    IPv6Address dest = controlInfo->getDestAddr();
    datagram->setDestAddress(dest);

    IPv6Address src = controlInfo->getSrcAddr();

    // when source address was given, use it; otherwise it'll get the address
    // of the outgoing interface after routing
    if (!src.isUnspecified())
    {
        // if interface parameter does not match existing interface, do not send datagram
        if (rt->getInterfaceByAddress(src)==NULL)
            opp_error("Wrong source address %s in (%s)%s: no interface with such address",
                      src.str().c_str(), transportPacket->getClassName(), transportPacket->getFullName());
        datagram->setSrcAddress(src);
    }

    // set other fields
    datagram->setHopLimit(controlInfo->getHopLimit()>0 ? controlInfo->getHopLimit() : 32); //FIXME use iface hop limit instead of 32?
    datagram->setTransportProtocol(controlInfo->getProtocol());
    delete controlInfo;

    // setting IP options is currently not supported

    return datagram;
}

void IPv6::endService ( cPacket *  msg  )  [protected, virtual]

Processing of IPv6 datagrams. Called when a datagram reaches the front of the queue.

Implements AbstractQueue.

Definition at line 72 of file IPv6.cc.

{
    if (msg->getArrivalGate()->isName("transportIn") ||
       (msg->getArrivalGate()->isName("ndIn") && dynamic_cast<IPv6NDMessage*>(msg)) ||
       (msg->getArrivalGate()->isName("icmpIn") && dynamic_cast<ICMPv6Message*>(msg)))//Added this for ICMP msgs from ICMP module-WEI
    {
        // packet from upper layers or ND: encapsulate and send out
        handleMessageFromHL( msg );
    }
    else
    {
        // datagram from network or from ND: localDeliver and/or route
        IPv6Datagram *dgram = check_and_cast<IPv6Datagram *>(msg);
        handleDatagramFromNetwork(dgram);
    }

    if (ev.isGUI())
        updateDisplayString();
}

void IPv6::fragmentAndRoute ( IPv6Datagram datagram,
InterfaceEntry destIE = NULL 
) [protected, virtual]

Fragment packet if needed, then send it. The optional output gate index is only used if higher layer protocol explicitly requests the datagram to be sent out on a specific interface, bypassing the routing table.

Definition at line 145 of file IPv6.cc.

Referenced by handleMessageFromHL().

{
/*
FIXME implement fragmentation here.
   1. determine output interface
   2. compare packet size with interface MTU
   3. if bigger, do fragmentation
         int mtu = ift->interfaceByPortNo(outputGateIndex)->getMTU();
*/
    EV << "fragmentation not implemented yet\n";

    // route packet
    if (destIE!=NULL)
        sendDatagramToOutput(datagram, destIE, MACAddress::BROADCAST_ADDRESS); // FIXME what MAC address to use?
    else if (!datagram->getDestAddress().isMulticast())
        routePacket(datagram, destIE, true);
    else
        routeMulticastPacket(datagram, destIE, NULL);
}

InterfaceEntry * IPv6::getSourceInterfaceFrom ( cPacket *  msg  )  [protected, virtual]

Definition at line 92 of file IPv6.cc.

Referenced by decapsulate(), and handleDatagramFromNetwork().

{
    cGate *g = msg->getArrivalGate();
    return g ? ift->getInterfaceByNetworkLayerGateIndex(g->getIndex()) : NULL;
}

void IPv6::handleDatagramFromNetwork ( IPv6Datagram datagram  )  [protected, virtual]

Handle IPv6Datagram messages arriving from lower layer. Decrements TTL, then invokes routePacket().

Definition at line 98 of file IPv6.cc.

Referenced by endService().

{
    // check for header biterror
    if (datagram->hasBitError())
    {
        EV << "bit error\n";return; // revise!
/*FIXME revise
        // probability of bit error in header = size of header / size of total message
        // (ignore bit error if in payload)
        double relativeHeaderLength = datagram->getHeaderLength() / (double)datagram->getByteLength();
        if (dblrand() <= relativeHeaderLength)
        {
            EV << "bit error found, sending ICMP_PARAMETER_PROBLEM\n";
            icmp->sendErrorMessage(datagram, ICMP_PARAMETER_PROBLEM, 0);
            return;
        }
*/
    }

    // remove control info
    delete datagram->removeControlInfo();

    // routepacket
    if (!datagram->getDestAddress().isMulticast())
        routePacket(datagram, NULL, false);
    else
        routeMulticastPacket(datagram, NULL, getSourceInterfaceFrom(datagram));
}

void IPv6::handleMessageFromHL ( cPacket *  msg  )  [protected, virtual]

Handle messages (typically packets to be send in IPv6) from transport or ICMP. Invokes encapsulate(), then routePacket().

Definition at line 127 of file IPv6.cc.

Referenced by endService().

{
    // if no interface exists, do not send datagram
    if (ift->getNumInterfaces() == 0)
    {
        EV << "No interfaces exist, dropping packet\n";
        delete msg;
        return;
    }

    // encapsulate upper-layer packet into IPv6Datagram
    InterfaceEntry *destIE; // to be filled in by encapsulate()
    IPv6Datagram *datagram = encapsulate(msg, destIE);

    // possibly fragment (in IPv6, only the source node does that), then route it
    fragmentAndRoute(datagram, destIE);
}

void IPv6::handleReceivedICMP ( ICMPv6Message *  msg  )  [protected, virtual]

Handle incoming ICMP messages.

Definition at line 451 of file IPv6.cc.

{
    switch (msg->getType())
    {
        case ICMPv6_REDIRECT:  // TODO implement redirect handling
        case ICMPv6_DESTINATION_UNREACHABLE:
        case ICMPv6_PACKET_TOO_BIG:
        case ICMPv6_TIME_EXCEEDED:
        case ICMPv6_PARAMETER_PROBLEM: {
            // ICMP errors are delivered to the appropriate higher layer protocols
            IPv6Datagram *bogusPacket = check_and_cast<IPv6Datagram *>(msg->getEncapsulatedMsg());
            int protocol = bogusPacket->getTransportProtocol();
            int gateindex = mapping.getOutputGateForProtocol(protocol);
            send(msg, "transportOut", gateindex);
            break;
        }
        default: {
            // all others are delivered to ICMP:
            // ICMPv6_ECHO_REQUEST, ICMPv6_ECHO_REPLY, ICMPv6_MLD_QUERY, ICMPv6_MLD_REPORT,
            // ICMPv6_MLD_DONE, ICMPv6_ROUTER_SOL, ICMPv6_ROUTER_AD, ICMPv6_NEIGHBOUR_SOL,
            // ICMPv6_NEIGHBOUR_AD, ICMPv6_MLDv2_REPORT
            int gateindex = mapping.getOutputGateForProtocol(IP_PROT_ICMP);
            send(msg, "transportOut", gateindex);
        }
     }
}

void IPv6::initialize (  )  [protected, virtual]

Initialization

Reimplemented from QueueBase.

Definition at line 37 of file IPv6.cc.

void IPv6::isLocalAddress ( IPv6Datagram datagram  )  [protected, virtual]

Perform reassembly of fragmented datagrams, then send them up to the higher layers using sendToHL().

Definition at line 397 of file IPv6.cc.

Referenced by routeMulticastPacket(), and routePacket().

{
/* FIXME revise and complete defragmentation
    // Defragmentation. skip defragmentation if datagram is not fragmented
    if (datagram->getFragmentOffset()!=0 || datagram->getMoreFragments())
    {
        EV << "Datagram fragment: offset=" << datagram->getFragmentOffset()
           << ", MORE=" << (datagram->getMoreFragments() ? "true" : "false") << ".\n";

        // erase timed out fragments in fragmentation buffer; check every 10 seconds max
        if (simTime() >= lastCheckTime + 10)
        {
            lastCheckTime = simTime();
            fragbuf.purgeStaleFragments(simTime()-FRAGMENT_TIMEOUT);
        }

        datagram = fragbuf.addFragment(datagram, simTime());
        if (!datagram)
        {
            EV << "No complete datagram yet.\n";
            return;
        }
        EV << "This fragment completes the datagram.\n";
    }
*/
    // decapsulate and send on appropriate output gate
    int protocol = datagram->getTransportProtocol();
    cPacket *packet = decapsulate(datagram);

    if (protocol==IP_PROT_IPv6_ICMP && dynamic_cast<IPv6NDMessage*>(packet))
    {
        EV << "Neigbour Discovery packet: passing it to ND module\n";
        send(packet, "ndOut");
    }
    else if (protocol==IP_PROT_IPv6_ICMP && dynamic_cast<ICMPv6Message*>(packet))
    {
        EV << "ICMPv6 packet: passing it to ICMPv6 module\n";
        send(packet, "icmpOut");
    }//Added by WEI to forward ICMPv6 msgs to ICMPv6 module.
    else if (protocol==IP_PROT_IP || protocol==IP_PROT_IPv6)
    {
        EV << "Tunnelled IP datagram\n";
        // FIXME handle tunnelling
        error("tunnelling not yet implemented");
    }
    else
    {
        int gateindex = mapping.getOutputGateForProtocol(protocol);
        EV << "Protocol " << protocol << ", passing up on gate " << gateindex << "\n";
        //TODO: Indication of forward progress
        send(packet, "transportOut", gateindex);
    }
}

void IPv6::routeMulticastPacket ( IPv6Datagram datagram,
InterfaceEntry destIE,
InterfaceEntry fromIE 
) [protected, virtual]

Forwards packets to all multicast destinations, using fragmentAndSend().

Definition at line 272 of file IPv6.cc.

Referenced by fragmentAndRoute(), and handleDatagramFromNetwork().

{
    const IPv6Address& destAddr = datagram->getDestAddress();

    EV << "destination address " << destAddr << " is multicast, doing multicast routing\n";
    numMulticast++;

    // if received from the network...
    if (fromIE!=NULL)
    {
        // deliver locally
        if (rt->isLocalAddress(destAddr))
        {
            EV << "local delivery of multicast packet\n";
            numLocalDeliver++;
            isLocalAddress((IPv6Datagram *)datagram->dup());
        }

        // if datagram arrived from input gate and IP forwarding is off, delete datagram
        if (!rt->isRouter())
        {
            EV << "forwarding is off\n";
            delete datagram;
            return;
        }

        // make sure scope of multicast address is large enough to be forwarded to other links
        if (destAddr.getMulticastScope()<=2)
        {
            EV << "multicast dest address is link-local (or smaller) scope\n";
            delete datagram;
            return;
        }

        // hop counter decrement: only if datagram arrived from network, and will be
        // sent out to the network (hoplimit check will be done just before sending
        // out datagram)
        // TBD: in IPv4, arrange TTL check like this
        datagram->setHopLimit(datagram->getHopLimit()-1);
    }

    // for now, we just send it out on every interface except on which it came. FIXME better!!!
    EV << "sending out datagram on every interface (except incoming one)\n";
    for (int i=0; i<ift->getNumInterfaces(); i++)
    {
        InterfaceEntry *ie = ift->getInterface(i);
        if (fromIE!=ie)
            sendDatagramToOutput((IPv6Datagram *)datagram->dup(), ie, MACAddress::BROADCAST_ADDRESS);
    }
    delete datagram;

/* FIXME implement handling of multicast

    According to Gopi: "multicast routing table" should map
       srcAddr+multicastDestAddr to a set of next hops (interface+nexthopAddr)
    Where srcAddr is the multicast server, and destAddr sort of narrows it down to a given stream

    // FIXME multicast-->tunneling link (present in original IPSuite) missing from here

    // DVMRP: process datagram only if sent locally or arrived on the shortest
    // route (provided routing table already contains srcAddr); otherwise
    // discard and continue.
    int inputGateIndex = datagram->getArrivalGate() ? datagram->getArrivalGate()->getIndex() : -1;
    int shortestPathInputGateIndex = rt->outputGateIndexNo(datagram->getSrcAddress());
    if (inputGateIndex!=-1 && shortestPathInputGateIndex!=-1 && inputGateIndex!=shortestPathInputGateIndex)
    {
        // FIXME count dropped
        EV << "Packet dropped.\n";
        delete datagram;
        return;
    }

    // check for local delivery
    IPv6Address destAddress = datagram->getDestAddress();
    if (rt->isLocalMulticastAddress(destAddress))
    {
        IPv6Datagram *datagramCopy = (IPv6Datagram *) datagram->dup();

        // FIXME code from the MPLS model: set packet dest address to routerId (???)
        datagramCopy->setDestAddress(rt->getRouterId());

        isLocalAddress(datagramCopy);
    }

    // forward datagram only if IP forward is enabled, or sent locally
    if (inputGateIndex!=-1 && !rt->isRouter())
    {
        delete datagram;
        return;
    }

    MulticastRoutes routes = rt->getMulticastRoutesFor(destAddress);
    if (routes.size()==0)
    {
        // no destination: delete datagram
        delete datagram;
    }
    else
    {
        // copy original datagram for multiple destinations
        for (unsigned int i=0; i<routes.size(); i++)
        {
            int outputGateIndex = routes[i].interf->outputGateIndex();

            // don't forward to input port
            if (outputGateIndex>=0 && outputGateIndex!=inputGateIndex)
            {
                IPv6Datagram *datagramCopy = (IPv6Datagram *) datagram->dup();

                // set datagram source address if not yet set
                if (datagramCopy->getSrcAddress().isUnspecified())
                    datagramCopy->setSrcAddress(ift->interfaceByPortNo(outputGateIndex)->ipv6Data()->getIPAddress());

                // send
                IPv6Address nextHopAddr = routes[i].gateway;
                sendDatagramToOutput(datagramCopy, outputGateIndex, macAddr);
            }
        }

        // only copies sent, delete original datagram
        delete datagram;
    }
*/
}

void IPv6::routePacket ( IPv6Datagram datagram,
InterfaceEntry destIE,
bool  fromHL 
) [protected, virtual]

Performs routing. Based on the routing decision, it dispatches to isLocalAddress() for local packets, to fragmentAndSend() for forwarded packets, to routeMulticastPacket() for multicast packets, or drops the packet if it's unroutable or forwarding is off.

Definition at line 165 of file IPv6.cc.

Referenced by fragmentAndRoute(), and handleDatagramFromNetwork().

{
    // TBD add option handling code here
    IPv6Address destAddress = datagram->getDestAddress();

    EV << "Routing datagram `" << datagram->getName() << "' with dest=" << destAddress << ": ";

    // local delivery of unicast packets
    if (rt->isLocalAddress(destAddress))
    {
        EV << "local delivery\n";
        if (datagram->getSrcAddress().isUnspecified())
            datagram->setSrcAddress(destAddress); // allows two apps on the same host to communicate
        numLocalDeliver++;
        isLocalAddress(datagram);
        return;
    }

    if (!fromHL)
    {
        // if datagram arrived from input gate and IP forwarding is off, delete datagram
        //yes but datagrams from the ND module is getting dropped too!-WEI
        //so we add a 2nd condition
        // FIXME rewrite code so that condition is cleaner --Andras
        //if (!rt->isRouter())
        if (!rt->isRouter() && !(datagram->getArrivalGate()->isName("ndIn")))
        {
            EV << "forwarding is off, dropping packet\n";
            numDropped++;
            delete datagram;
            return;
        }

        // don't forward link-local addresses or weaker
        if (destAddress.isLinkLocal() || destAddress.isLoopback())
        {
            EV << "dest address is link-local (or weaker) scope, doesn't get forwarded\n";
            delete datagram;
            return;
        }

        // hop counter decrement: only if datagram arrived from network, and will be
        // sent out to the network (hoplimit check will be done just before sending
        // out datagram)
        // TBD: in IPv4, arrange TTL check like this
        datagram->setHopLimit(datagram->getHopLimit()-1);
    }

    // routing
    // first try destination cache
    int interfaceId;
    IPv6Address nextHop = rt->lookupDestCache(destAddress, interfaceId);
    if (interfaceId==-1)
    {
        // address not in destination cache: do longest prefix match in routing table
        const IPv6Route *route = rt->doLongestPrefixMatch(destAddress);
        if (!route)
        {
            if (rt->isRouter())
            {
                EV << "unroutable, sending ICMPv6_DESTINATION_UNREACHABLE\n";
                numUnroutable++;
                icmp->sendErrorMessage(datagram, ICMPv6_DESTINATION_UNREACHABLE, 0); // FIXME check ICMP 'code'
            }
            else // host
            {
                EV << "no match in routing table, passing datagram to Neighbour Discovery module for default router selection\n";
                send(datagram, "ndOut");
            }
            return;
        }
        interfaceId = route->getInterfaceId();
        nextHop = route->getNextHop();
        if (nextHop.isUnspecified())
            nextHop = destAddress;  // next hop is the host itself

        // add result into destination cache
        rt->updateDestCache(destAddress, nextHop, interfaceId);
    }

    InterfaceEntry *ie = ift->getInterfaceById(interfaceId);
    ASSERT(ie!=NULL);
    EV << "next hop for " << destAddress << " is " << nextHop << ", interface " << ie->getName() << "\n";
    ASSERT(!nextHop.isUnspecified());

    MACAddress macAddr = nd->resolveNeighbour(nextHop, interfaceId);
    if (macAddr.isUnspecified())
    {
        EV << "no link-layer address for next hop yet, passing datagram to Neighbour Discovery module\n";
        send(datagram, "ndOut");
        return;
    }
    EV << "link-layer address: " << macAddr << "\n";

    // set datagram source address if not yet set
    if (datagram->getSrcAddress().isUnspecified())
    {
        const IPv6Address& srcAddr = ie->ipv6Data()->getPreferredAddress();
        ASSERT(!srcAddr.isUnspecified()); // FIXME what if we don't have an address yet?
        datagram->setSrcAddress(srcAddr);
    }

    // send out datagram
    numForwarded++;
    sendDatagramToOutput(datagram, ie, macAddr);
}

void IPv6::sendDatagramToOutput ( IPv6Datagram datagram,
InterfaceEntry ie,
const MACAddress macAddr 
) [protected, virtual]

Last hoplimit check, then send datagram on the given interface.

Definition at line 540 of file IPv6.cc.

Referenced by fragmentAndRoute(), routeMulticastPacket(), and routePacket().

{
    // hop counter check
    if (datagram->getHopLimit() <= 0)
    {
        // drop datagram, destruction responsibility in ICMP
        EV << "datagram hopLimit reached zero, sending ICMPv6_TIME_EXCEEDED\n";
        icmp->sendErrorMessage(datagram, ICMPv6_TIME_EXCEEDED, 0); // FIXME check icmp 'code'
        return;
    }

    // in link layer uses MAC addresses (basically, not PPP), add control info
    if (!macAddr.isUnspecified())
    {
        Ieee802Ctrl *controlInfo = new Ieee802Ctrl();
        controlInfo->setDest(macAddr);
        datagram->setControlInfo(controlInfo);
    }

    // send datagram to link layer
    send(datagram, "queueOut", ie->getNetworkLayerGateIndex());
}

void IPv6::updateDisplayString (  )  [protected, virtual]

Definition at line 61 of file IPv6.cc.

Referenced by endService().

{
    char buf[80] = "";
    if (numForwarded>0) sprintf(buf+strlen(buf), "fwd:%d ", numForwarded);
    if (numLocalDeliver>0) sprintf(buf+strlen(buf), "up:%d ", numLocalDeliver);
    if (numMulticast>0) sprintf(buf+strlen(buf), "mcast:%d ", numMulticast);
    if (numDropped>0) sprintf(buf+strlen(buf), "DROP:%d ", numDropped);
    if (numUnroutable>0) sprintf(buf+strlen(buf), "UNROUTABLE:%d ", numUnroutable);
    getDisplayString().setTagArg("t",0,buf);
}


Member Data Documentation

long IPv6::curFragmentId [protected]

Definition at line 45 of file IPv6.h.

Referenced by initialize().

Definition at line 46 of file IPv6.h.

Referenced by initialize().

ICMPv6* IPv6::icmp [protected]

Definition at line 42 of file IPv6.h.

simtime_t IPv6::lastCheckTime [protected]

Definition at line 47 of file IPv6.h.

Referenced by initialize().

Definition at line 48 of file IPv6.h.

Referenced by handleReceivedICMP(), initialize(), and isLocalAddress().

Definition at line 41 of file IPv6.h.

Referenced by initialize(), and routePacket().

int IPv6::numDropped [protected]

Definition at line 53 of file IPv6.h.

Referenced by initialize(), routePacket(), and updateDisplayString().

int IPv6::numForwarded [protected]

Definition at line 55 of file IPv6.h.

Referenced by initialize(), routePacket(), and updateDisplayString().

int IPv6::numLocalDeliver [protected]

Definition at line 52 of file IPv6.h.

Referenced by initialize(), routeMulticastPacket(), routePacket(), and updateDisplayString().

int IPv6::numMulticast [protected]

Definition at line 51 of file IPv6.h.

Referenced by initialize(), routeMulticastPacket(), and updateDisplayString().

int IPv6::numUnroutable [protected]

Definition at line 54 of file IPv6.h.

Referenced by initialize(), routePacket(), and updateDisplayString().

RoutingTable6* IPv6::rt [protected]

Definition at line 40 of file IPv6.h.

Referenced by encapsulate(), initialize(), routeMulticastPacket(), and routePacket().


The documentation for this class was generated from the following files: