diff --git a/src/inet/common/ResultFilters.cc b/src/inet/common/ResultFilters.cc index ab7310337db..745ae1fbb2a 100644 --- a/src/inet/common/ResultFilters.cc +++ b/src/inet/common/ResultFilters.cc @@ -49,6 +49,82 @@ class INET_API PacketRegionValue : public cObject cValue value; }; +Register_ResultFilter("duplicatePacket", DuplicatePacketFilter); + +void DuplicatePacketFilter::init(Context *ctx) +{ + cObjectResultFilter::init(ctx); + std::string fullPath = ctx->component->getFullPath() + "." + ctx->attrsProperty->getIndex() + ".duplicatePacket"; + cConfiguration *cfg = getEnvir()->getConfig(); + auto sizeLimitValue = cfg->getPerObjectConfigValue(fullPath.c_str(), "sizeLimit"); + sizeLimit = cfg->parseDouble(sizeLimitValue, nullptr, nullptr, 100); +} + +void DuplicatePacketFilter::receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) +{ + auto packet = check_and_cast(object); + const char *packetName = packet->getFullName(); + const char *packetIndexAsString = strrchr(packetName, '-'); + if (packetIndexAsString != nullptr) { + int packetIndex = atoi(packetIndexAsString + 1); + if (packetIndices.find(packetIndex) != packetIndices.end()) + fire(this, t, object, details); + packetIndices.insert(packetIndex); + if (packetIndices.size() > sizeLimit) + packetIndices.erase(packetIndices.begin()); + } + else + throw cRuntimeError("Cannot find index in packet name: '%s'", packetName); +} + +Register_ResultFilter("outOfOrderPacket", OutOfOrderPacketFilter); + +void OutOfOrderPacketFilter::receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) +{ + auto packet = check_and_cast(object); + const char *packetName = packet->getFullName(); + const char *packetIndexAsString = strrchr(packetName, '-'); + if (packetIndexAsString != nullptr) { + int packetIndex = atoi(packetIndexAsString + 1); + if (packetIndex != maxIndex + 1) + fire(this, t, object, details); + maxIndex = std::max(packetIndex, maxIndex); + } + else + throw cRuntimeError("Cannot find index in packet name: '%s'", packetName); +} + +Register_ResultFilter("missingPacketIndex", MissingPacketIndexFilter); + +void MissingPacketIndexFilter::init(Context *ctx) +{ + cObjectResultFilter::init(ctx); + std::string fullPath = ctx->component->getFullPath() + "." + ctx->attrsProperty->getIndex() + ".missingPacketIndex"; + cConfiguration *cfg = getEnvir()->getConfig(); + auto sizeLimitValue = cfg->getPerObjectConfigValue(fullPath.c_str(), "sizeLimit"); + sizeLimit = cfg->parseDouble(sizeLimitValue, nullptr, nullptr, 100); +} + +void MissingPacketIndexFilter::receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) +{ + auto packet = check_and_cast(object); + const char *packetName = packet->getFullName(); + const char *packetIndexAsString = strrchr(packetName, '-'); + if (packetIndexAsString != nullptr) { + int packetIndex = atoi(packetIndexAsString + 1); + packetIndices.insert(packetIndex); + if (packetIndices.size() > sizeLimit) { + int removedIndex = *packetIndices.erase(packetIndices.begin()); + if (lastRemovedIndex != -1) + for (int i = lastRemovedIndex + 1; i < removedIndex; i++) + fire(this, t, (intval_t)i, details); + lastRemovedIndex = removedIndex; + } + } + else + throw cRuntimeError("Cannot find index in packet name: '%s'", packetName); +} + Register_ResultFilter("dataAge", DataAgeFilter); void DataAgeFilter::receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) diff --git a/src/inet/common/ResultFilters.h b/src/inet/common/ResultFilters.h index 2f9733a0074..bec512af999 100644 --- a/src/inet/common/ResultFilters.h +++ b/src/inet/common/ResultFilters.h @@ -27,6 +27,54 @@ class INET_API VoidPtrWrapper : public cObject void *getObject() const { return object; } }; +/** + * Filter that expects a Packet with a name that has an index suffix (e.g. Foo-42), + * and outputs the packet if it is a duplicate according to its index. + */ +class INET_API DuplicatePacketFilter : public cObjectResultFilter +{ + protected: + int sizeLimit = -1; + std::set packetIndices; // index of the last N packets + + protected: + virtual void init(Context *ctx) override; + + public: + virtual void receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) override; +}; + +/** + * Filter that expects a Packet with a name that has an index suffix (e.g. Foo-42), + * and outputs the packet if it arrived out of order. + */ +class INET_API OutOfOrderPacketFilter : public cObjectResultFilter +{ + protected: + int maxIndex = -1; // highest index ever received + + public: + virtual void receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) override; +}; + +/** + * Filter that expects a Packet with a name that has an index suffix (e.g. Foo-42), + * and outputs an integer for the missing packet indices. + */ +class INET_API MissingPacketIndexFilter : public cObjectResultFilter +{ + protected: + int sizeLimit = -1; + int lastRemovedIndex = -1; + std::set packetIndices; // index of the last N packets + + protected: + virtual void init(Context *ctx) override; + + public: + virtual void receiveSignal(cResultFilter *prev, simtime_t_cref t, cObject *object, cObject *details) override; +}; + /** * Filter that expects a Packet and outputs the age of packet data in seconds. */ diff --git a/src/inet/networklayer/common/NetworkInterface.cc b/src/inet/networklayer/common/NetworkInterface.cc index 3bf51691bff..d1ebec8c386 100644 --- a/src/inet/networklayer/common/NetworkInterface.cc +++ b/src/inet/networklayer/common/NetworkInterface.cc @@ -62,7 +62,7 @@ std::string NetworkInterfaceChangeDetails::str() const } bool NetworkInterface::LocalGate::deliver(cMessage *msg, const SendOptions &options, simtime_t t) { - if (networkInterface->isDown()) { + if (!networkInterface->isUp()) { if (networkInterface->upperLayerIn == this) { auto packet = check_and_cast(msg); EV_WARN << "Network interface is down, dropping packet" << EV_FIELD(packet) << EV_ENDL; @@ -209,7 +209,7 @@ void NetworkInterface::pushPacket(Packet *packet, const cGate *gate) Enter_Method("pushPacket"); take(packet); if (gate == upperLayerIn) { - if (isDown()) { + if (!isUp()) { EV_WARN << "Network interface is down, dropping packet" << EV_FIELD(packet) << EV_ENDL; dropPacket(packet, INTERFACE_DOWN); } @@ -233,7 +233,7 @@ void NetworkInterface::pushPacketStart(Packet *packet, const cGate *gate, bps da Enter_Method("pushPacket"); take(packet); if (gate == upperLayerIn) { - if (isDown()) { + if (!isUp()) { EV_WARN << "Network interface is down, dropping packet" << EV_FIELD(packet) << EV_ENDL; dropPacket(packet, INTERFACE_DOWN); } @@ -258,7 +258,7 @@ void NetworkInterface::pushPacketEnd(Packet *packet, const cGate *gate) Enter_Method("pushPacketEnd"); take(packet); if (gate == upperLayerIn) { - if (isDown()) { + if (!isUp()) { EV_WARN << "Network interface is down, dropping packet" << EV_FIELD(packet) << EV_ENDL; dropPacket(packet, INTERFACE_DOWN); } diff --git a/src/inet/networklayer/common/NetworkInterface.h b/src/inet/networklayer/common/NetworkInterface.h index e691b9e1199..6aff25b63ac 100644 --- a/src/inet/networklayer/common/NetworkInterface.h +++ b/src/inet/networklayer/common/NetworkInterface.h @@ -217,13 +217,6 @@ class INET_API NetworkInterface : public queueing::PacketProcessorBase, public q cChannel *getRxTransmissionChannel() { return rxTransmissionChannel; } cChannel *getTxTransmissionChannel() { return txTransmissionChannel; } - /** - * Returns the combined state of the carrier and the interface requested state. - */ - // TODO remove hasCarrier from this function and update all call sites accordingly - bool isUp() const { return getState() == UP && hasCarrier(); } - bool isDown() const { return getState() != UP; } - void setHasModuleIdAddress(bool value) { hasModuleIdAddress = value; } void setHasModulePathAddress(bool value) { hasModulePathAddress = value; } const ModuleIdAddress getModuleIdAddress() const { return hasModuleIdAddress ? ModuleIdAddress(getId()) : ModuleIdAddress(0); } @@ -240,6 +233,7 @@ class INET_API NetworkInterface : public queueing::PacketProcessorBase, public q int getNodeInputGateId() const { return nodeInputGateId; } int getMtu() const { return mtu; } bool hasCarrier() const { return carrier; } + bool isUp() const { return state == UP; } bool isBroadcast() const { return broadcast; } bool isMulticast() const { return multicast; } bool isPointToPoint() const { return pointToPoint; } diff --git a/src/inet/networklayer/configurator/base/L3NetworkConfiguratorBase.cc b/src/inet/networklayer/configurator/base/L3NetworkConfiguratorBase.cc index 2511880c470..b0d8ee75a92 100644 --- a/src/inet/networklayer/configurator/base/L3NetworkConfiguratorBase.cc +++ b/src/inet/networklayer/configurator/base/L3NetworkConfiguratorBase.cc @@ -318,7 +318,11 @@ double L3NetworkConfiguratorBase::computeNodeWeight(Node *node, const char *metr double L3NetworkConfiguratorBase::computeLinkWeight(Link *link, const char *metric, cXMLElement *parameters) { - if ((link->sourceInterfaceInfo && link->sourceInterfaceInfo->networkInterface->isWireless()) || + if (link->sourceInterfaceInfo != nullptr && (!link->sourceInterfaceInfo->networkInterface->isUp() || !link->sourceInterfaceInfo->networkInterface->hasCarrier())) + return std::numeric_limits::infinity(); + else if (link->destinationInterfaceInfo != nullptr && (!link->destinationInterfaceInfo->networkInterface->isUp() || !link->destinationInterfaceInfo->networkInterface->hasCarrier())) + return std::numeric_limits::infinity(); + else if ((link->sourceInterfaceInfo && link->sourceInterfaceInfo->networkInterface->isWireless()) || (link->destinationInterfaceInfo && link->destinationInterfaceInfo->networkInterface->isWireless())) return computeWirelessLinkWeight(link, metric, parameters); else diff --git a/src/inet/networklayer/configurator/ipv4/Ipv4NetworkConfigurator.cc b/src/inet/networklayer/configurator/ipv4/Ipv4NetworkConfigurator.cc index 8bbc69077dc..6e40d4e2299 100644 --- a/src/inet/networklayer/configurator/ipv4/Ipv4NetworkConfigurator.cc +++ b/src/inet/networklayer/configurator/ipv4/Ipv4NetworkConfigurator.cc @@ -1842,7 +1842,7 @@ void Ipv4NetworkConfigurator::addStaticMulticastRoutes(Topology& topology) auto sourceNode = findNode(topology, sourceAddress); if (!sourceNode) throw cRuntimeError("Multicast group source node %s not found", sourceAttr); - topology.calculateUnweightedSingleShortestPathsTo(sourceNode); + topology.calculateWeightedSingleShortestPathsTo(sourceNode); Matcher hostMatcher(hostAttr); for (int i = 0; i < topology.getNumNodes(); i++) { Node *receiverNode = (Node *)topology.getNode(i); @@ -1864,7 +1864,7 @@ void Ipv4NetworkConfigurator::addStaticMulticastRoutes(Topology& topology, Node InterfaceInfo *inInterfaceInfo = nullptr; InterfaceInfo *outInterfaceInfo = nullptr; Node *node = receiverNode; - while (node != sourceNode) { + while (node != sourceNode && node->getNumPaths() > 0) { auto link = (Link *)node->getPath(0); outInterfaceInfo = static_cast(link->destinationInterfaceInfo); node = (Node *)link->getLinkOutRemoteNode(); diff --git a/src/inet/networklayer/configurator/ipv4/Ipv4NodeConfigurator.cc b/src/inet/networklayer/configurator/ipv4/Ipv4NodeConfigurator.cc index 70e5ce727b6..df3426b6212 100644 --- a/src/inet/networklayer/configurator/ipv4/Ipv4NodeConfigurator.cc +++ b/src/inet/networklayer/configurator/ipv4/Ipv4NodeConfigurator.cc @@ -161,7 +161,7 @@ void Ipv4NodeConfigurator::receiveSignal(cComponent *source, simsignal_t signalI auto fieldId = ieChangeDetails->getFieldId(); if (fieldId == NetworkInterface::F_STATE || fieldId == NetworkInterface::F_CARRIER) { auto *entry = ieChangeDetails->getNetworkInterface(); - if (entry->isUp() && networkConfigurator) { + if (entry->isUp() && entry->hasCarrier() && networkConfigurator) { networkConfigurator->configureInterface(entry); if (par("configureRoutingTable")) networkConfigurator->configureRoutingTable(routingTable, entry); diff --git a/src/inet/networklayer/contract/IRoute.h b/src/inet/networklayer/contract/IRoute.h index 121eb1149c7..c1af4cb03a0 100644 --- a/src/inet/networklayer/contract/IRoute.h +++ b/src/inet/networklayer/contract/IRoute.h @@ -77,14 +77,6 @@ class INET_API IRoute dUnknown = 255 }; - // TODO maybe: -// virtual std::string info() const; -// virtual std::string detailedInfo() const; -// -// bool operator==(const IRoute& route) const { return equals(route); } -// bool operator!=(const IRoute& route) const { return !equals(route); } -// bool equals(const IRoute& route) const; - virtual ~IRoute() {} /** The routing table in which this route is inserted, or nullptr. */ @@ -200,16 +192,12 @@ class INET_API IMulticastRoute typedef std::vector OutInterfaceVector; - // TODO maybe: -// virtual std::string info() const; -// virtual std::string detailedInfo() const; - + public: virtual ~IMulticastRoute() {} /** The routing table in which this route is inserted, or nullptr. */ virtual IRoutingTable *getRoutingTableAsGeneric() const = 0; - virtual void setEnabled(bool enabled) = 0; virtual void setOrigin(const L3Address& origin) = 0; virtual void setPrefixLength(int len) = 0; virtual void setMulticastGroup(const L3Address& group) = 0; @@ -222,12 +210,6 @@ class INET_API IMulticastRoute virtual void setSourceType(SourceType type) = 0; virtual void setMetric(int metric) = 0; - /** Disabled entries are ignored by routing until the became enabled again. */ - virtual bool isEnabled() const = 0; - - /** Expired entries are ignored by routing, and may be periodically purged. */ - virtual bool isExpired() const = 0; - /** Source address prefix to match */ virtual L3Address getOriginAsGeneric() const = 0; diff --git a/src/inet/networklayer/ipv4/IIpv4RoutingTable.h b/src/inet/networklayer/ipv4/IIpv4RoutingTable.h index 1128b042a73..8ac2751fc9a 100644 --- a/src/inet/networklayer/ipv4/IIpv4RoutingTable.h +++ b/src/inet/networklayer/ipv4/IIpv4RoutingTable.h @@ -187,12 +187,6 @@ class INET_API IIpv4RoutingTable : public IRoutingTable virtual bool deleteMulticastRoute(Ipv4MulticastRoute *entry) = 0; using IRoutingTable::deleteMulticastRoute; - /** - * Deletes invalid routes from the routing table. Invalid routes are those - * where the isValid() method returns false. - */ - virtual void purge() = 0; - /** * Utility function: Returns a vector of all addresses of the node. */ diff --git a/src/inet/networklayer/ipv4/Ipv4Route.h b/src/inet/networklayer/ipv4/Ipv4Route.h index f54d45d531c..62041bf1919 100644 --- a/src/inet/networklayer/ipv4/Ipv4Route.h +++ b/src/inet/networklayer/ipv4/Ipv4Route.h @@ -58,9 +58,6 @@ class INET_API Ipv4Route : public cObject, public IRoute virtual void setRoutingTable(IIpv4RoutingTable *rt) { this->rt = rt; } IIpv4RoutingTable *getRoutingTable() const { return rt; } - /** test validity of route entry, e.g. check expiry */ - virtual bool isValid() const { return true; } - virtual void setDestination(Ipv4Address _dest) { if (dest != _dest) { dest = _dest; changed(F_DESTINATION); } } virtual void setNetmask(Ipv4Address _netmask) { if (netmask != _netmask) { netmask = _netmask; changed(F_PREFIX_LENGTH); } } virtual void setGateway(Ipv4Address _gateway) { if (gateway != _gateway) { gateway = _gateway; changed(F_NEXTHOP); } } @@ -167,9 +164,6 @@ class INET_API Ipv4MulticastRoute : public cObject, public IMulticastRoute virtual void setRoutingTable(IIpv4RoutingTable *rt) { this->rt = rt; } IIpv4RoutingTable *getRoutingTable() const { return rt; } - /** test validity of route entry, e.g. check expiry */ - virtual bool isValid() const { return true; } - virtual bool matches(const Ipv4Address& origin, const Ipv4Address& group) const; virtual void setOrigin(Ipv4Address _origin) { if (origin != _origin) { origin = _origin; changed(F_ORIGIN); } } @@ -211,13 +205,10 @@ class INET_API Ipv4MulticastRoute : public cObject, public IMulticastRoute cObject *getSource() const override { return source; } virtual IRoutingTable *getRoutingTableAsGeneric() const override; - virtual void setEnabled(bool enabled) override { /*TODO setEnabled(enabled);*/ } virtual void setOrigin(const L3Address& origin) override { setOrigin(origin.toIpv4()); } virtual void setPrefixLength(int len) override { setOriginNetmask(Ipv4Address::makeNetmask(len)); } // TODO inconsistent naming virtual void setMulticastGroup(const L3Address& group) override { setMulticastGroup(group.toIpv4()); } - virtual bool isEnabled() const override { return true; /*TODO isEnabled();*/ } - virtual bool isExpired() const override { return !isValid(); } // TODO rename Ipv4 method virtual L3Address getOriginAsGeneric() const override { return getOrigin(); } virtual int getPrefixLength() const override { return getOriginNetmask().getNetmaskLength(); } // TODO inconsistent naming virtual L3Address getMulticastGroupAsGeneric() const override { return getMulticastGroup(); } diff --git a/src/inet/networklayer/ipv4/Ipv4RoutingTable.cc b/src/inet/networklayer/ipv4/Ipv4RoutingTable.cc index bc997ea790f..0a3db01032e 100644 --- a/src/inet/networklayer/ipv4/Ipv4RoutingTable.cc +++ b/src/inet/networklayer/ipv4/Ipv4RoutingTable.cc @@ -177,7 +177,7 @@ void Ipv4RoutingTable::receiveSignal(cComponent *source, simsignal_t signalID, c if (fieldId == NetworkInterface::F_STATE || fieldId == NetworkInterface::F_CARRIER) { const auto *entry = ieChangeDetails->getNetworkInterface(); updateNetmaskRoutes(); - if (!entry->isUp()) + if (!entry->isUp() || !entry->hasCarrier()) deleteInterfaceRoutes(entry); invalidateCache(); } @@ -361,56 +361,21 @@ bool Ipv4RoutingTable::isLocalMulticastAddress(const Ipv4Address& dest) const return false; } -void Ipv4RoutingTable::purge() -{ - // purge unicast routes - for (auto it = routes.begin(); it != routes.end();) { - Ipv4Route *route = *it; - if (route->isValid()) - ++it; - else { - it = routes.erase(it); - invalidateCache(); - ASSERT(route->getRoutingTable() == this); // still filled in, for the listeners' benefit - emit(routeDeletedSignal, route); - delete route; - } - } - - // purge multicast routes - for (auto it = multicastRoutes.begin(); it != multicastRoutes.end();) { - Ipv4MulticastRoute *route = *it; - if (route->isValid()) - ++it; - else { - it = multicastRoutes.erase(it); - invalidateCache(); - ASSERT(route->getRoutingTable() == this); // still filled in, for the listeners' benefit - emit(mrouteDeletedSignal, route); - delete route; - } - } -} - Ipv4Route *Ipv4RoutingTable::findBestMatchingRoute(const Ipv4Address& dest) const { Enter_Method("findBestMatchingRoute(%u.%u.%u.%u)", dest.getDByte(0), dest.getDByte(1), dest.getDByte(2), dest.getDByte(3)); // note: str().c_str() too slow here auto it = routingCache.find(dest); - if (it != routingCache.end()) { - if (it->second == nullptr || it->second->isValid()) - return it->second; - } + if (it != routingCache.end()) + return it->second; // find best match (one with longest prefix) // default route has zero prefix length, so (if exists) it'll be selected as last resort Ipv4Route *bestRoute = nullptr; for (auto e : routes) { - if (e->isValid()) { - if (Ipv4Address::maskedAddrAreEqual(dest, e->getDestination(), e->getNetmask())) { // match - bestRoute = const_cast(e); - break; - } + if (Ipv4Address::maskedAddrAreEqual(dest, e->getDestination(), e->getNetmask())) { // match + bestRoute = const_cast(e); + break; } } @@ -443,7 +408,7 @@ const Ipv4MulticastRoute *Ipv4RoutingTable::findBestMatchingMulticastRoute(const // TODO caching? for (auto e : multicastRoutes) { - if (e->isValid() && e->matches(origin, group)) + if (e->matches(origin, group)) return e; } @@ -459,12 +424,8 @@ Ipv4Route *Ipv4RoutingTable::getRoute(int k) const Ipv4Route *Ipv4RoutingTable::getDefaultRoute() const { - // if exists default route entry, it is the last valid entry - for (RouteVector::const_reverse_iterator i = routes.rbegin(); i != routes.rend() && (*i)->getNetmask().isUnspecified(); ++i) { - if ((*i)->isValid()) - return *i; - } - return nullptr; + // if exists default route entry, it is the last entry + return !routes.empty() && (*routes.rbegin())->getNetmask().isUnspecified() ? *routes.rbegin() : nullptr; } // The 'routes' vector stores the routes in this order. @@ -725,7 +686,7 @@ void Ipv4RoutingTable::updateNetmaskRoutes() PatternMatcher interfaceNameMatcher(netmaskRoutes, false, true, true); for (int i = 0; i < ift->getNumInterfaces(); i++) { NetworkInterface *ie = ift->getInterface(i); - if (ie->isUp() && interfaceNameMatcher.matches(ie->getFullName())) { + if (ie->isUp() && ie->hasCarrier() && interfaceNameMatcher.matches(ie->getFullName())) { auto ipv4Data = ie->findProtocolData(); if (ipv4Data && ipv4Data->getNetmask() != Ipv4Address::ALLONES_ADDRESS) { Ipv4Route *route = createNewRoute(); diff --git a/src/inet/networklayer/ipv4/Ipv4RoutingTable.h b/src/inet/networklayer/ipv4/Ipv4RoutingTable.h index b2763a74a3f..ec50580ab64 100644 --- a/src/inet/networklayer/ipv4/Ipv4RoutingTable.h +++ b/src/inet/networklayer/ipv4/Ipv4RoutingTable.h @@ -328,12 +328,6 @@ class INET_API Ipv4RoutingTable : public cSimpleModule, public IIpv4RoutingTable */ virtual bool deleteMulticastRoute(Ipv4MulticastRoute *entry) override; - /** - * Deletes invalid routes from the routing table. Invalid routes are those - * where the isValid() method returns false. - */ - virtual void purge() override; - /** * Utility function: Returns a vector of all addresses of the node. */ diff --git a/src/inet/networklayer/ipv6/Ipv6RoutingTable.cc b/src/inet/networklayer/ipv6/Ipv6RoutingTable.cc index b1afbeb8516..ffcebfc2b32 100644 --- a/src/inet/networklayer/ipv6/Ipv6RoutingTable.cc +++ b/src/inet/networklayer/ipv6/Ipv6RoutingTable.cc @@ -191,7 +191,7 @@ void Ipv6RoutingTable::receiveSignal(cComponent *source, simsignal_t signalID, c int networkInterfaceId = networkInterface->getInterfaceId(); // an interface went down - if (!networkInterface->isUp()) { + if (!networkInterface->isUp() || !networkInterface->hasCarrier()) { deleteInterfaceRoutes(networkInterface); purgeDestCacheForInterfaceId(networkInterfaceId); } diff --git a/src/inet/queueing/base/PassivePacketSinkBase.ned b/src/inet/queueing/base/PassivePacketSinkBase.ned index 63545957d86..d68bfbca76d 100644 --- a/src/inet/queueing/base/PassivePacketSinkBase.ned +++ b/src/inet/queueing/base/PassivePacketSinkBase.ned @@ -19,6 +19,16 @@ simple PassivePacketSinkBase extends PacketSinkBase @signal[packetPushed](type=inet::Packet); // the statistical value is the packet @statistic[packets](title="packets"; source=packetPushed; record=count; unit=pk); + // the statistical value is the packet, packet name must have an index suffix (e.g. Foo-42) + @statistic[duplicatePackets](title="duplicate packets"; source=duplicatePacket(packetPushed); record=count?; unit=pk); + // the statistical value is the length of the packet, packet name must have an index suffix (e.g. Foo-42) + @statistic[duplicatePacketLengths](title="duplicate packet lengths"; source=packetLength(duplicatePacket(packetPushed)); record=vector?; unit=b); + // the statistical value is the packet, packet name must have an index suffix (e.g. Foo-42) + @statistic[outOfOrderPackets](title="out of order packets"; source=outOfOrderPacket(packetPushed); record=count?; unit=pk); + // the statistical value is the length of the packet, packet name must have an index suffix (e.g. Foo-42) + @statistic[outOfOrderPacketLengths](title="out of order packet lenghts"; source=packetLength(outOfOrderPacket(packetPushed)); record=vector?; unit=b); + // the statistical value is the packet index, packet name must have an index suffix (e.g. Foo-42) + @statistic[missingPacketIndices](title="missing packet indices"; source=missingPacketIndex(packetPushed); record=count?; unit=pk); // the statistical value is the length of the packet @statistic[packetLengths](title="packet lengths"; source=packetLength(packetPushed); record=sum,histogram,vector; unit=b; interpolationmode=none); // the statistical value is the data rate of the packets diff --git a/src/inet/routing/dsdv/Dsdv.cc b/src/inet/routing/dsdv/Dsdv.cc index 19b4604aa78..52767e3b2b1 100644 --- a/src/inet/routing/dsdv/Dsdv.cc +++ b/src/inet/routing/dsdv/Dsdv.cc @@ -41,6 +41,7 @@ Dsdv::~Dsdv() stop(); // Dispose of dynamically allocated the objects delete event; + delete purgeTimer; delete forwardList; // delete Hello; } @@ -60,6 +61,7 @@ void Dsdv::initialize(int stage) helloInterval = par("helloInterval"); forwardList = new std::list(); event = new cMessage("event"); + purgeTimer = new cMessage("purge"); } else if (stage == INITSTAGE_ROUTING_PROTOCOLS) { registerProtocol(Protocol::manet, gate("ipOut"), gate("ipIn")); @@ -109,6 +111,7 @@ void Dsdv::start() void Dsdv::stop() { cancelEvent(event); + cancelEvent(purgeTimer); while (!forwardList->empty()) { ForwardEntry *fh = forwardList->front(); if (fh->event) @@ -131,7 +134,7 @@ void Dsdv::handleSelfMessage(cMessage *msg) if (msg == event) { auto hello = makeShared(); - rt->purge(); + purge(); // count non-loopback interfaces // int numIntf = 0; @@ -180,6 +183,10 @@ void Dsdv::handleSelfMessage(cMessage *msg) scheduleAfter(helloInterval + broadcastDelay->doubleValue(), event); bubble("Sending new hello message"); } + else if (msg == purgeTimer) { + purge(); + reschedulePurgeTimer(); + } else { for (auto it = forwardList->begin(); it != forwardList->end(); it++) { if ((*it)->event == msg) { @@ -285,6 +292,7 @@ void Dsdv::handleMessageWhenUp(cMessage *msg) e->setSequencenumber(msgsequencenumber); e->setExpiryTime(simTime() + routeLifetime); rt->addRoute(e); + reschedulePurgeTimer(); } if (!isForwardHello) { recHello->setNextAddress(source); @@ -328,5 +336,29 @@ void Dsdv::handleMessageWhenUp(cMessage *msg) throw cRuntimeError("Message not supported %s", msg->getName()); } +void Dsdv::reschedulePurgeTimer() +{ + simtime_t purgeTime = SimTime::getMaxTime(); + for (int i = 0; i < rt->getNumRoutes(); i++) { + auto route = dynamic_cast(rt->getRoute(i)); + if (route && !route->isExpired() && route->getExpiryTime() < purgeTime) + purgeTime = route->getExpiryTime(); + } + cancelEvent(purgeTimer); + if (purgeTime != SimTime::getMaxTime()) + scheduleAt(purgeTime, purgeTimer); +} + +void Dsdv::purge() +{ + for (int i = 0; i < rt->getNumRoutes();) { + auto route = dynamic_cast(rt->getRoute(i)); + if (route && route->isExpired()) + rt->deleteRoute(route); + else + i++; + } +} + } // namespace inet diff --git a/src/inet/routing/dsdv/Dsdv.h b/src/inet/routing/dsdv/Dsdv.h index 29ff03d653e..320b09bcc1a 100644 --- a/src/inet/routing/dsdv/Dsdv.h +++ b/src/inet/routing/dsdv/Dsdv.h @@ -52,6 +52,7 @@ class INET_API Dsdv : public RoutingProtocolBase bool isForwardHello = false; cMessage *event = nullptr; + cMessage *purgeTimer = nullptr; cPar *broadcastDelay = nullptr; std::list *forwardList = nullptr; NetworkInterface *interface80211ptr = nullptr; @@ -76,6 +77,9 @@ class INET_API Dsdv : public RoutingProtocolBase void handleSelfMessage(cMessage *msg); + void reschedulePurgeTimer(); + void purge(); + // lifecycle virtual void handleStartOperation(LifecycleOperation *operation) override { start(); } virtual void handleStopOperation(LifecycleOperation *operation) override { stop(); } @@ -94,7 +98,7 @@ class INET_API DsdvIpv4Route : public Ipv4Route simtime_t expiryTime; // time the routing entry is valid until public: - virtual bool isValid() const override { return expiryTime == 0 || expiryTime > simTime(); } + bool isExpired() const { return expiryTime != 0 && expiryTime <= simTime(); } simtime_t getExpiryTime() const { return expiryTime; } void setExpiryTime(simtime_t time) { expiryTime = time; } diff --git a/src/inet/routing/eigrp/pdms/EigrpIpv4Pdm.cc b/src/inet/routing/eigrp/pdms/EigrpIpv4Pdm.cc index df3bcbc5395..7a7cf08016d 100644 --- a/src/inet/routing/eigrp/pdms/EigrpIpv4Pdm.cc +++ b/src/inet/routing/eigrp/pdms/EigrpIpv4Pdm.cc @@ -181,7 +181,7 @@ void EigrpIpv4Pdm::processIfaceStateChange(NetworkInterface *iface) Ipv4Address ifAddress = iface->getIpv4Address().doAnd(ifMask); int networkId; - if (iface->isUp()) { // an interface goes up + if (iface->isUp() && iface->hasCarrier()) { // an interface goes up if (routingForNetworks->isInterfaceIncluded(ifAddress, ifMask, &networkId)) { // Interface is included in EIGRP if ((eigrpIface = getInterfaceById(ifaceId)) == nullptr) { // Create EIGRP interface eigrpIface = new EigrpInterface(iface, networkId, false); diff --git a/src/inet/routing/eigrp/pdms/EigrpIpv6Pdm.cc b/src/inet/routing/eigrp/pdms/EigrpIpv6Pdm.cc index ed1a182335c..dbfd2212630 100644 --- a/src/inet/routing/eigrp/pdms/EigrpIpv6Pdm.cc +++ b/src/inet/routing/eigrp/pdms/EigrpIpv6Pdm.cc @@ -154,7 +154,7 @@ void EigrpIpv6Pdm::processIfaceStateChange(NetworkInterface *iface) EigrpInterface *eigrpIface; int ifaceId = iface->getInterfaceId(); - if (iface->isUp()) { // an interface goes up + if (iface->isUp() && iface->hasCarrier()) { // an interface goes up // add directly-connected routes to RT PrefixVector::iterator it; diff --git a/src/inet/routing/ospfv2/Ospfv2.cc b/src/inet/routing/ospfv2/Ospfv2.cc index 31f2084acc0..e88e311c0c9 100644 --- a/src/inet/routing/ospfv2/Ospfv2.cc +++ b/src/inet/routing/ospfv2/Ospfv2.cc @@ -112,7 +112,7 @@ void Ospfv2::receiveSignal(cComponent *source, simsignal_t signalID, cObject *ob auto fieldId = change->getFieldId(); if (fieldId == NetworkInterface::F_STATE || fieldId == NetworkInterface::F_CARRIER) { const NetworkInterface *ie = change->getNetworkInterface(); - if (!ie->isUp()) + if (!ie->isUp() || !ie->hasCarrier()) handleInterfaceDown(ie); else { // interface went back online. Do nothing! diff --git a/src/inet/routing/pim/modes/PimDm.cc b/src/inet/routing/pim/modes/PimDm.cc index c0453f543a7..7bba478e3d5 100644 --- a/src/inet/routing/pim/modes/PimDm.cc +++ b/src/inet/routing/pim/modes/PimDm.cc @@ -491,23 +491,27 @@ void PimDm::processJoinPrunePacket(Packet *pk) int numRpfNeighbors = pimNbt->getNumNeighbors(incomingInterface->getInterfaceId()); for (unsigned int i = 0; i < pkt->getJoinPruneGroupsArraySize(); i++) { - JoinPruneGroup group = pkt->getJoinPruneGroups(i); - Ipv4Address groupAddr = group.getGroupAddress().groupAddress.toIpv4(); + JoinPruneGroup joinPruneGroup = pkt->getJoinPruneGroups(i); + Ipv4Address group = joinPruneGroup.getGroupAddress().groupAddress.toIpv4(); // go through list of joined sources - for (unsigned int j = 0; j < group.getJoinedSourceAddressArraySize(); j++) { - const auto& source = group.getJoinedSourceAddress(j); - Route *route = findRoute(source.sourceAddress.toIpv4(), groupAddr); - ASSERT(route); - processJoin(route, incomingInterface->getInterfaceId(), numRpfNeighbors, upstreamNeighborAddress); + for (unsigned int j = 0; j < joinPruneGroup.getJoinedSourceAddressArraySize(); j++) { + Ipv4Address source = joinPruneGroup.getJoinedSourceAddress(j).sourceAddress.toIpv4(); + Route *route = findRoute(source, group); + if (route != nullptr) + processJoin(route, incomingInterface->getInterfaceId(), numRpfNeighbors, upstreamNeighborAddress); + else + EV_WARN << "Route not found for join" << EV_FIELD(source) << EV_FIELD(group) << std::endl; } // go through list of pruned sources - for (unsigned int j = 0; j < group.getPrunedSourceAddressArraySize(); j++) { - const auto& source = group.getPrunedSourceAddress(j); - Route *route = findRoute(source.sourceAddress.toIpv4(), groupAddr); - ASSERT(route); - processPrune(route, incomingInterface->getInterfaceId(), pkt->getHoldTime(), numRpfNeighbors, upstreamNeighborAddress); + for (unsigned int j = 0; j < joinPruneGroup.getPrunedSourceAddressArraySize(); j++) { + Ipv4Address source = joinPruneGroup.getPrunedSourceAddress(j).sourceAddress.toIpv4(); + Route *route = findRoute(source, group); + if (route != nullptr) + processPrune(route, incomingInterface->getInterfaceId(), pkt->getHoldTime(), numRpfNeighbors, upstreamNeighborAddress); + else + EV_WARN << "Route not found for prune" << EV_FIELD(source) << EV_FIELD(group) << std::endl; } } @@ -713,7 +717,10 @@ void PimDm::processGraft(Ipv4Address source, Ipv4Address group, Ipv4Address send EV_DEBUG << "Processing Graft(S=" << source << ", G=" << group << "), sender=" << sender << "incoming if=" << incomingInterfaceId << endl; Route *route = findRoute(source, group); - ASSERT(route); + if (route == nullptr) { + EV_WARN << "Route not found for graft" << EV_FIELD(source) << EV_FIELD(group) << std::endl; + return; + } UpstreamInterface *upstream = route->upstreamInterface; @@ -1246,6 +1253,7 @@ void PimDm::multicastPacketArrivedOnNonRpfInterface(Ipv4Address group, Ipv4Addre // if there is no outgoing interface, Prune msg has to be sent on upstream if (route->isOilistNull()) { + processOlistEmptyEvent(route); EV << "Route is not forwarding any more, send Prune to upstream" << endl; upstream->graftPruneState = UpstreamInterface::PRUNED; if (!upstream->isSourceDirectlyConnected()) { @@ -1287,7 +1295,10 @@ void PimDm::multicastPacketArrivedOnRpfInterface(int interfaceId, Ipv4Address gr EV_DETAIL << "Multicast datagram arrived: source=" << source << ", group=" << group << ".\n"; Route *route = findRoute(source, group); - ASSERT(route); + if (route == nullptr) { + EV_WARN << "Route not found for packet on RPF interface" << EV_FIELD(source) << EV_FIELD(group) << std::endl; + return; + } UpstreamInterface *upstream = route->upstreamInterface; // RFC 3973 4.5.2.2 @@ -1392,7 +1403,7 @@ void PimDm::rpfInterfaceHasChanged(Ipv4MulticastRoute *ipv4Route, Ipv4Route *rou } // old RPF interface should be now a downstream interface if it is not down - if (oldRpfInterface && oldRpfInterface->isUp()) { + if (oldRpfInterface && oldRpfInterface->isUp() && oldRpfInterface->hasCarrier()) { DownstreamInterface *downstream = route->createDownstreamInterface(oldRpfInterface); ipv4Route->addOutInterface(new PimDmOutInterface(oldRpfInterface, downstream)); } diff --git a/src/inet/routing/pim/modes/PimDm.ned b/src/inet/routing/pim/modes/PimDm.ned index 01d5996202c..6785ac0f4f2 100644 --- a/src/inet/routing/pim/modes/PimDm.ned +++ b/src/inet/routing/pim/modes/PimDm.ned @@ -39,16 +39,16 @@ simple PimDm string pimNeighborTableModule; volatile double triggeredHelloDelay @unit(s) = uniform(0s,5s); - double helloPeriod @unit(s) = 30s; - double holdTime @unit(s) = default(3.5 * helloPeriod); - double pruneInterval @unit(s) = 180s; - double pruneLimitInterval @unit(s) = 210s; - double overrideInterval @unit(s) = 2.5s; + double helloPeriod @unit(s) = 30s; // "Hello_Period: Periodic interval for hello messages" + double holdTime @unit(s) = default(3.5 * helloPeriod); // "The Hold Time in the Hello Message should be set to a value that can reasonably be expected to keep the Hello active until a new Hello message is received. On most links, this will be 3.5 times the value of Hello_Period." + double pruneInterval @unit(s) = 180s; // "The Prune Timer expires, indicating that it is again time to flood data from S addressed to group G onto interface I." + double pruneLimitInterval @unit(s) = 210s; // "t_limit: Used to prevent Prune storms on a LAN" + double overrideInterval @unit(s) = 2.5s; // "J/P_Override_Interval: Short time after a Prune to allow other routers on the LAN to send a Join" double propagationDelay @unit(s) = 0.5s; - double graftRetryInterval @unit(s) = 3s; - double sourceActiveInterval @unit(s) = 210s; - double stateRefreshInterval @unit(s) = 60s; - double assertTime @unit(s) = 180s; + double graftRetryInterval @unit(s) = 3s; // "Graft_Retry_Period: In the absence of receipt of a GraftAck message, the time before retransmission of a Graft message" + double sourceActiveInterval @unit(s) = 210s; // "SourceLifetime: Period of time after receiving a multicast message a directly attached router will continue to send State Refresh messages" + double stateRefreshInterval @unit(s) = 60s; // "RefreshInterval: Interval between successive state refresh messages" + double assertTime @unit(s) = 180s; // "Assert Time: Period after last assert before assert state is timed out" @signal[sentHelloPk](type=cPacket); @signal[rcvdHelloPk](type=cPacket); diff --git a/src/inet/routing/rip/Rip.cc b/src/inet/routing/rip/Rip.cc index d715a84c2cc..357cf2c2fae 100644 --- a/src/inet/routing/rip/Rip.cc +++ b/src/inet/routing/rip/Rip.cc @@ -326,7 +326,7 @@ void Rip::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, auto fieldId = change->getFieldId(); if (fieldId == NetworkInterface::F_STATE || fieldId == NetworkInterface::F_CARRIER) { ie = change->getNetworkInterface(); - if (!ie->isUp()) { + if (!ie->isUp() || !ie->hasCarrier()) { for (auto& elem : ripRoutingTable) if ((elem)->getInterface() == ie) { invalidateRoute(elem); @@ -441,7 +441,7 @@ void Rip::processUpdate(bool triggered) EV_INFO << "sending regular updates on all interfaces\n"; for (auto& ripInterface : ripInterfaces) - if (ripInterface.ie->isUp()) + if (ripInterface.ie->isUp() && ripInterface.ie->hasCarrier()) sendRoutes(addressType->getLinkLocalRIPRoutersMulticastAddress(), ripUdpPort, ripInterface, triggered); // clear changed flags diff --git a/src/inet/visualizer/base/ChannelVisualizerBase.cc b/src/inet/visualizer/base/ChannelVisualizerBase.cc new file mode 100644 index 00000000000..2c381edb8b4 --- /dev/null +++ b/src/inet/visualizer/base/ChannelVisualizerBase.cc @@ -0,0 +1,188 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +#include "inet/physicallayer/common/Signal.h" +#include "inet/visualizer/base/ChannelVisualizerBase.h" + +namespace inet { + +namespace visualizer { + +static simsignal_t messageSentSignal = cComponent::registerSignal("messageSent"); + +ChannelVisualizerBase::ChannelVisualization::ChannelVisualization(int sourceModuleId, int destinationModuleId) : + LineManager::ModuleLine(sourceModuleId, destinationModuleId) +{ +} + +std::string ChannelVisualizerBase::DirectiveResolver::resolveDirective(char directive) const +{ + switch (directive) { + case 'n': + return packet->getName(); + case 'c': + return packet->getClassName(); + default: + throw cRuntimeError("Unknown directive: %c", directive); + } +} + +void ChannelVisualizerBase::preDelete(cComponent *root) +{ + if (displayChannelActivity) { + unsubscribe(); + removeAllChannelVisualizations(); + } +} + +void ChannelVisualizerBase::initialize(int stage) +{ + VisualizerBase::initialize(stage); + if (!hasGUI()) return; + if (stage == INITSTAGE_LOCAL) { + displayChannelActivity = par("displayChannelActivity"); + nodeFilter.setPattern(par("nodeFilter")); + packetFilter.setExpression(par("packetFilter").objectValue()); + lineColor = cFigure::Color(par("lineColor")); + lineStyle = cFigure::parseLineStyle(par("lineStyle")); + lineWidth = par("lineWidth"); + lineShift = par("lineShift"); + lineShiftMode = par("lineShiftMode"); + lineContactSpacing = par("lineContactSpacing"); + lineContactMode = par("lineContactMode"); + labelFormat.parseFormat(par("labelFormat")); + labelFont = cFigure::parseFont(par("labelFont")); + labelColor = cFigure::Color(par("labelColor")); + fadeOutMode = par("fadeOutMode"); + fadeOutTime = par("fadeOutTime"); + fadeOutAnimationSpeed = par("fadeOutAnimationSpeed"); + holdAnimationTime = par("holdAnimationTime"); + if (displayChannelActivity) + subscribe(); + } +} + +void ChannelVisualizerBase::handleParameterChange(const char *name) +{ + if (!hasGUI()) return; + if (!strcmp(name, "nodeFilter")) + nodeFilter.setPattern(par("nodeFilter")); + else if (!strcmp(name, "packetFilter")) + packetFilter.setExpression(par("packetFilter").objectValue()); + removeAllChannelVisualizations(); +} + +void ChannelVisualizerBase::refreshDisplay() const +{ + if (displayChannelActivity) { + AnimationPosition currentAnimationPosition; + std::vector removedChannelVisualizations; + for (auto it : channelVisualizations) { + auto channelVisualization = it.second; + double delta; + if (!strcmp(fadeOutMode, "simulationTime")) + delta = (currentAnimationPosition.getSimulationTime() - channelVisualization->lastUsageAnimationPosition.getSimulationTime()).dbl(); + else if (!strcmp(fadeOutMode, "animationTime")) + delta = currentAnimationPosition.getAnimationTime() - channelVisualization->lastUsageAnimationPosition.getAnimationTime(); + else if (!strcmp(fadeOutMode, "realTime")) + delta = currentAnimationPosition.getRealTime() - channelVisualization->lastUsageAnimationPosition.getRealTime(); + else + throw cRuntimeError("Unknown fadeOutMode: %s", fadeOutMode); + if (delta > fadeOutTime) + removedChannelVisualizations.push_back(channelVisualization); + else + setAlpha(channelVisualization, 1 - delta / fadeOutTime); + } + for (auto channelVisualization : removedChannelVisualizations) { + const_cast(this)->removeChannelVisualization(channelVisualization); + delete channelVisualization; + } + } +} + +void ChannelVisualizerBase::subscribe() +{ + visualizationSubjectModule->subscribe(messageSentSignal, this); +} + +void ChannelVisualizerBase::unsubscribe() +{ + // NOTE: lookup the module again because it may have been deleted first + auto visualizationSubjectModule = findModuleFromPar(par("visualizationSubjectModule"), this); + visualizationSubjectModule->unsubscribe(messageSentSignal, this); +} + +const ChannelVisualizerBase::ChannelVisualization *ChannelVisualizerBase::getChannelVisualization(std::pair channelVisualization) +{ + auto it = channelVisualizations.find(channelVisualization); + return it == channelVisualizations.end() ? nullptr : it->second; +} + +void ChannelVisualizerBase::addChannelVisualization(std::pair sourceAndDestination, const ChannelVisualization *channelVisualization) +{ + channelVisualizations[sourceAndDestination] = channelVisualization; + if (holdAnimationTime != 0) + visualizationTargetModule->getCanvas()->holdSimulationFor(holdAnimationTime); +} + +void ChannelVisualizerBase::removeChannelVisualization(const ChannelVisualization *channelVisualization) +{ + channelVisualizations.erase(channelVisualizations.find(std::pair(channelVisualization->sourceModuleId, channelVisualization->destinationModuleId))); +} + +void ChannelVisualizerBase::removeAllChannelVisualizations() +{ + std::vector removedChannelVisualizations; + for (auto it : channelVisualizations) + removedChannelVisualizations.push_back(it.second); + for (auto it : removedChannelVisualizations) { + removeChannelVisualization(it); + delete it; + } +} + +std::string ChannelVisualizerBase::getChannelVisualizationText(cPacket *packet) const +{ + DirectiveResolver directiveResolver(packet); + return labelFormat.formatString(&directiveResolver); +} + +void ChannelVisualizerBase::refreshChannelVisualization(const ChannelVisualization *channelVisualization, cPacket *packet) +{ + channelVisualization->lastUsageAnimationPosition = AnimationPosition(); +} + +void ChannelVisualizerBase::updateChannelVisualization(cModule *source, cModule *destination, cPacket *packet) +{ + auto key = std::pair(source->getId(), destination->getId()); + auto channelVisualization = getChannelVisualization(key); + if (channelVisualization == nullptr) { + channelVisualization = createChannelVisualization(source, destination, packet); + addChannelVisualization(key, channelVisualization); + } + else + refreshChannelVisualization(channelVisualization, packet); +} + +void ChannelVisualizerBase::receiveSignal(cComponent *source, simsignal_t signal, cObject *object, cObject *details) +{ + if (signal == messageSentSignal) { + auto messageSentSignalValue = check_and_cast(object); + auto signal = check_and_cast(messageSentSignalValue->msg); + auto packet = check_and_cast(signal->getEncapsulatedPacket()); + auto channel = check_and_cast(source); + cModule *sourceNode = getContainingNode(channel->getSourceGate()->getOwnerModule()); + cModule *destinationNode = getContainingNode(channel->getSourceGate()->getPathEndGate()->getOwnerModule()); + if (nodeFilter.matches(sourceNode) && nodeFilter.matches(destinationNode) && packetFilter.matches(packet)) + updateChannelVisualization(sourceNode, destinationNode, packet); + } +} + +} // namespace visualizer + +} // namespace inet + diff --git a/src/inet/visualizer/base/ChannelVisualizerBase.h b/src/inet/visualizer/base/ChannelVisualizerBase.h new file mode 100644 index 00000000000..31ab12563aa --- /dev/null +++ b/src/inet/visualizer/base/ChannelVisualizerBase.h @@ -0,0 +1,101 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +#ifndef __INET_CHANNELVISUALIZERBASE_H +#define __INET_CHANNELVISUALIZERBASE_H + +#include "inet/common/packet/PacketFilter.h" +#include "inet/visualizer/base/VisualizerBase.h" +#include "inet/visualizer/base/VisualizerBase.h" +#include "inet/visualizer/util/AnimationPosition.h" +#include "inet/visualizer/util/LineManager.h" +#include "inet/visualizer/util/NetworkNodeFilter.h" + +namespace inet { + +namespace visualizer { + +class INET_API ChannelVisualizerBase : public VisualizerBase, public cListener +{ + protected: + class INET_API ChannelVisualization : public LineManager::ModuleLine { + public: + mutable AnimationPosition lastUsageAnimationPosition; + + public: + ChannelVisualization(int sourceModuleId, int destinationModuleId); + virtual ~ChannelVisualization() {} + }; + + class INET_API DirectiveResolver : public StringFormat::IDirectiveResolver { + protected: + const cPacket *packet = nullptr; + + public: + DirectiveResolver(const cPacket *packet) : packet(packet) {} + + virtual std::string resolveDirective(char directive) const override; + }; + + protected: + /** @name Parameters */ + //@{ + bool displayChannelActivity = false; + NetworkNodeFilter nodeFilter; + PacketFilter packetFilter; + cFigure::Color lineColor; + cFigure::LineStyle lineStyle; + double lineWidth = NaN; + double lineShift = NaN; + const char *lineShiftMode = nullptr; + double lineContactSpacing = NaN; + const char *lineContactMode = nullptr; + StringFormat labelFormat; + cFigure::Font labelFont; + cFigure::Color labelColor; + const char *fadeOutMode = nullptr; + double fadeOutTime = NaN; + double fadeOutAnimationSpeed = NaN; + double holdAnimationTime = NaN; + //@} + + LineManager *lineManager = nullptr; + /** + * Maps source/destination module ids to channel activity visualizations. + */ + std::map, const ChannelVisualization *> channelVisualizations; + + protected: + virtual void initialize(int stage) override; + virtual void handleParameterChange(const char *name) override; + virtual void refreshDisplay() const override; + virtual void preDelete(cComponent *root) override; + + virtual void subscribe(); + virtual void unsubscribe(); + + virtual const ChannelVisualization *createChannelVisualization(cModule *source, cModule *destination, cPacket *packet) const = 0; + virtual const ChannelVisualization *getChannelVisualization(std::pair channelVisualization); + virtual void addChannelVisualization(std::pair sourceAndDestination, const ChannelVisualization *channelVisualization); + virtual void removeChannelVisualization(const ChannelVisualization *channelVisualization); + virtual void removeAllChannelVisualizations(); + virtual void setAlpha(const ChannelVisualization *channelVisualization, double alpha) const = 0; + + virtual std::string getChannelVisualizationText(cPacket *packet) const; + virtual void refreshChannelVisualization(const ChannelVisualization *channelVisualization, cPacket *packet); + virtual void updateChannelVisualization(cModule *source, cModule *destination, cPacket *packet); + + public: + virtual void receiveSignal(cComponent *source, simsignal_t signal, cObject *object, cObject *details) override; +}; + +} // namespace visualizer + +} // namespace inet + +#endif + diff --git a/src/inet/visualizer/base/ChannelVisualizerBase.ned b/src/inet/visualizer/base/ChannelVisualizerBase.ned new file mode 100644 index 00000000000..0d402f4b8ba --- /dev/null +++ b/src/inet/visualizer/base/ChannelVisualizerBase.ned @@ -0,0 +1,40 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +package inet.visualizer.base; + +simple ChannelVisualizerBase extends VisualizerBase +{ + parameters: + bool displayChannelActivity = default(false); // display arrows for active channels, disabled by default + + string nodeFilter @mutable = default("*"); // which nodes are considered, matches all nodes by default + object packetFilter @mutable = default("*"); // which packets are considered, matches all packets by default + + string lineColor = default("blue"); // arrow color, black by default + string lineStyle = default("solid"); // arrow style (solid, dashed, dotted) + double lineWidth = default(3); // arrow width + + double lineShift = default(16); // line shift to avoid overlapping arrows + string lineShiftMode = default("normal"); // determines how overlapping arrows are shifted, possible values are: none, normal, x, y, z; optional prefix + or - + + double lineContactSpacing = default(3); // spacing between arrow end and submodule icon + string lineContactMode @enum("circular", "rectangular") = default("rectangular"); // determines how arrows are clipped at the submodules + + string labelFormat = default("%n"); // determines what data is displayed + string labelFont = default(", 8px"); // label font, automatic by default + string labelColor = default("blue"); // label color, black by default + + string fadeOutMode @enum("realTime", "animationTime", "simulationTime") = default("realTime"); // specifies how inactive channels fade out + double fadeOutTime @unit(s) = default(1s); // how quickly inactive channels fade away, 1 second by default + double fadeOutAnimationSpeed = default(0); // animation speed while there are active channels, value must be in the range (0, +inf) + + double holdAnimationTime @unit(s) = default(0s); // hold simulation (no progress) for the specified amount of animation time when the channel is activated + + @class(ChannelVisualizerBase); +} + diff --git a/src/inet/visualizer/base/RoutingTableVisualizerBase.cc b/src/inet/visualizer/base/RoutingTableVisualizerBase.cc index 5feddb27c57..84e9d0d2029 100644 --- a/src/inet/visualizer/base/RoutingTableVisualizerBase.cc +++ b/src/inet/visualizer/base/RoutingTableVisualizerBase.cc @@ -24,6 +24,12 @@ RoutingTableVisualizerBase::RouteVisualization::RouteVisualization(const Ipv4Rou { } +RoutingTableVisualizerBase::MulticastRouteVisualization::MulticastRouteVisualization(const Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId) : + ModuleLine(nodeModuleId, nextHopModuleId), + route(route) +{ +} + std::string RoutingTableVisualizerBase::DirectiveResolver::resolveDirective(char directive) const { switch (directive) { @@ -46,6 +52,20 @@ std::string RoutingTableVisualizerBase::DirectiveResolver::resolveDirective(char } } +std::string RoutingTableVisualizerBase::MulticastDirectiveResolver::resolveDirective(char directive) const +{ + switch (directive) { + case 'e': + return std::to_string(route->getMetric()); + case 'i': + return route->str(); + case 's': + return route->str(); + default: + throw cRuntimeError("Unknown directive: %c", directive); + } +} + void RoutingTableVisualizerBase::preDelete(cComponent *root) { if (displayRoutingTables) { @@ -63,6 +83,9 @@ void RoutingTableVisualizerBase::initialize(int stage) displayRoutesIndividually = par("displayRoutesIndividually"); displayLabels = par("displayLabels"); destinationFilter.setPattern(par("destinationFilter")); + multicastSourceNodeFilter.setPattern(par("multicastSourceNodeFilter")); + multicastSourceAddressFilter.setPattern(par("multicastSourceAddressFilter"), false, true, true); + multicastGroupFilter.setPattern(par("multicastGroupFilter"), false, true, true); nodeFilter.setPattern(par("nodeFilter")); lineColor = cFigure::Color(par("lineColor")); lineStyle = cFigure::parseLineStyle(par("lineStyle")); @@ -86,6 +109,8 @@ void RoutingTableVisualizerBase::handleParameterChange(const char *name) destinationFilter.setPattern(par("destinationFilter")); else if (!strcmp(name, "nodeFilter")) nodeFilter.setPattern(par("nodeFilter")); + else if (!strcmp(name, "multicastSourceNodeFilter")) + multicastSourceNodeFilter.setPattern(par("multicastSourceNodeFilter")); else if (!strcmp(name, "labelFormat")) labelFormat.parseFormat(par("labelFormat")); updateAllRouteVisualizations(); @@ -96,6 +121,9 @@ void RoutingTableVisualizerBase::subscribe() visualizationSubjectModule->subscribe(routeAddedSignal, this); visualizationSubjectModule->subscribe(routeDeletedSignal, this); visualizationSubjectModule->subscribe(routeChangedSignal, this); + visualizationSubjectModule->subscribe(mrouteAddedSignal, this); + visualizationSubjectModule->subscribe(mrouteDeletedSignal, this); + visualizationSubjectModule->subscribe(mrouteChangedSignal, this); visualizationSubjectModule->subscribe(interfaceIpv4ConfigChangedSignal, this); } @@ -107,6 +135,9 @@ void RoutingTableVisualizerBase::unsubscribe() visualizationSubjectModule->unsubscribe(routeAddedSignal, this); visualizationSubjectModule->unsubscribe(routeDeletedSignal, this); visualizationSubjectModule->unsubscribe(routeChangedSignal, this); + visualizationSubjectModule->unsubscribe(mrouteAddedSignal, this); + visualizationSubjectModule->unsubscribe(mrouteDeletedSignal, this); + visualizationSubjectModule->unsubscribe(mrouteChangedSignal, this); visualizationSubjectModule->unsubscribe(interfaceIpv4ConfigChangedSignal, this); } } @@ -115,7 +146,9 @@ void RoutingTableVisualizerBase::receiveSignal(cComponent *source, simsignal_t s { Enter_Method("%s", cComponent::getSignalName(signal)); - if (signal == routeAddedSignal || signal == routeDeletedSignal || signal == routeChangedSignal) { + if (signal == routeAddedSignal || signal == routeDeletedSignal || signal == routeChangedSignal || + signal == mrouteAddedSignal || signal == mrouteDeletedSignal || signal == mrouteChangedSignal) + { auto routingTable = check_and_cast(source); auto networkNode = getContainingNode(check_and_cast(source)); if (nodeFilter.matches(networkNode)) @@ -155,6 +188,34 @@ void RoutingTableVisualizerBase::removeRouteVisualization(const RouteVisualizati routeVisualizations.erase(routeVisualizations.find(key)); } +const RoutingTableVisualizerBase::MulticastRouteVisualization *RoutingTableVisualizerBase::getMulticastRouteVisualization(Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId) +{ + Ipv4Address routerId; + if (route != nullptr) + routerId = route->getRoutingTable()->getRouterId(); + auto key = std::make_tuple(routerId, nodeModuleId, nextHopModuleId); + auto it = multicastRouteVisualizations.find(key); + return it == multicastRouteVisualizations.end() ? nullptr : it->second; +} + +void RoutingTableVisualizerBase::addMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) +{ + Ipv4Address routerId; + if (routeVisualization->route != nullptr) + routerId = routeVisualization->route->getRoutingTable()->getRouterId(); + auto key = std::make_tuple(routerId, routeVisualization->sourceModuleId, routeVisualization->destinationModuleId); + multicastRouteVisualizations[key] = routeVisualization; +} + +void RoutingTableVisualizerBase::removeMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) +{ + Ipv4Address routerId; + if (routeVisualization->route != nullptr) + routerId = routeVisualization->route->getRoutingTable()->getRouterId(); + auto key = std::make_tuple(routerId, routeVisualization->sourceModuleId, routeVisualization->destinationModuleId); + multicastRouteVisualizations.erase(multicastRouteVisualizations.find(key)); +} + std::vector RoutingTableVisualizerBase::getDestinations() { L3AddressResolver addressResolver; @@ -176,6 +237,57 @@ std::vector RoutingTableVisualizerBase::getDestinations() return destinations; } +std::vector RoutingTableVisualizerBase::getMulticastSources() +{ + L3AddressResolver addressResolver; + std::vector multicastSources; + for (cModule::SubmoduleIterator it(visualizationSubjectModule); !it.end(); it++) { + auto networkNode = *it; + if (isNetworkNode(networkNode) && multicastSourceNodeFilter.matches(networkNode)) { + auto interfaceTable = addressResolver.findInterfaceTableOf(networkNode); + if (interfaceTable != nullptr) { + for (int i = 0; i < interfaceTable->getNumInterfaces(); i++) { + auto interface = interfaceTable->getInterface(i); + cMatchableString matchableAddress(interface->getIpv4Address().str().c_str()); + if (!interface->isLoopback() && multicastSourceAddressFilter.matches(&matchableAddress)) { + auto address = interface->getIpv4Address(); + if (!address.isUnspecified()) + multicastSources.push_back(address); + } + } + } + } + } + return multicastSources; +} + +std::vector RoutingTableVisualizerBase::getMulticastGroups() +{ + L3AddressResolver addressResolver; + std::set multicastGroups; + for (cModule::SubmoduleIterator it(visualizationSubjectModule); !it.end(); it++) { + auto networkNode = *it; + if (isNetworkNode(networkNode)) { + auto interfaceTable = addressResolver.findInterfaceTableOf(networkNode); + if (interfaceTable != nullptr) { + for (int i = 0; i < interfaceTable->getNumInterfaces(); i++) { + auto interface = interfaceTable->getInterface(i); + auto protocolData = interface->findProtocolData(); + if (protocolData != nullptr) { + for (int j = 0; j < protocolData->getNumOfJoinedMulticastGroups(); j++) { + auto multicastGroup = protocolData->getJoinedMulticastGroup(j); + cMatchableString matchableGroup(multicastGroup.str().c_str()); + if (multicastGroupFilter.matches(&matchableGroup)) + multicastGroups.insert(multicastGroup); + } + } + } + } + } + } + return std::vector(multicastGroups.begin(), multicastGroups.end()); +} + void RoutingTableVisualizerBase::addRouteVisualizations(IIpv4RoutingTable *routingTable) { L3AddressResolver addressResolver; @@ -198,6 +310,37 @@ void RoutingTableVisualizerBase::addRouteVisualizations(IIpv4RoutingTable *routi } } } + auto multicastSources = getMulticastSources(); + auto multicastGroups = getMulticastGroups(); + for (auto source : multicastSources) { + for (auto group : multicastGroups) { + auto route = const_cast(routingTable->findBestMatchingMulticastRoute(source, group)); + if (route != nullptr) { + for (int i = 0; i < route->getNumOutInterfaces(); i++) { + auto outInterface = route->getOutInterface(i); + if (outInterface->isEnabled()) { + auto interface = const_cast(outInterface->getInterface()); + auto channel = interface->getTxTransmissionChannel(); + if (channel != nullptr) { + auto endGate = channel->getSourceGate()->getPathEndGate(); + if (endGate != nullptr) { + auto nextHop = getContainingNode(endGate->getOwnerModule()); + if (nextHop != nullptr) { + auto routeVisualization = getMulticastRouteVisualization(displayRoutesIndividually ? route : nullptr, node->getId(), nextHop->getId()); + if (routeVisualization == nullptr) + addMulticastRouteVisualization(createMulticastRouteVisualization(displayRoutesIndividually ? route : nullptr, node, nextHop)); + else { + routeVisualization->numRoutes++; + refreshMulticastRouteVisualization(routeVisualization); + } + } + } + } + } + } + } + } + } } void RoutingTableVisualizerBase::removeRouteVisualizations(IIpv4RoutingTable *routingTable) @@ -211,6 +354,14 @@ void RoutingTableVisualizerBase::removeRouteVisualizations(IIpv4RoutingTable *ro removeRouteVisualization(it); delete it; } + std::vector removedMulticastRouteVisualizations; + for (auto it : multicastRouteVisualizations) + if (std::get<1>(it.first) == networkNode->getId() && it.second) + removedMulticastRouteVisualizations.push_back(it.second); + for (auto it : removedMulticastRouteVisualizations) { + removeMulticastRouteVisualization(it); + delete it; + } } void RoutingTableVisualizerBase::removeAllRouteVisualizations() @@ -222,6 +373,13 @@ void RoutingTableVisualizerBase::removeAllRouteVisualizations() removeRouteVisualization(it); delete it; } + std::vector removedMulticastRouteVisualizations; + for (auto it : multicastRouteVisualizations) + removedMulticastRouteVisualizations.push_back(it.second); + for (auto it : removedMulticastRouteVisualizations) { + removeMulticastRouteVisualization(it); + delete it; + } } void RoutingTableVisualizerBase::updateRouteVisualizations(IIpv4RoutingTable *routingTable) @@ -250,6 +408,12 @@ std::string RoutingTableVisualizerBase::getRouteVisualizationText(const Ipv4Rout return labelFormat.formatString(&directiveResolver); } +std::string RoutingTableVisualizerBase::getMulticastRouteVisualizationText(const Ipv4MulticastRoute *route) const +{ + MulticastDirectiveResolver directiveResolver(route); + return labelFormat.formatString(&directiveResolver); +} + } // namespace visualizer } // namespace inet diff --git a/src/inet/visualizer/base/RoutingTableVisualizerBase.h b/src/inet/visualizer/base/RoutingTableVisualizerBase.h index 7ebb5d36b58..b5de9f335e4 100644 --- a/src/inet/visualizer/base/RoutingTableVisualizerBase.h +++ b/src/inet/visualizer/base/RoutingTableVisualizerBase.h @@ -34,6 +34,16 @@ class INET_API RoutingTableVisualizerBase : public VisualizerBase, public cListe virtual ~RouteVisualization() {} }; + class INET_API MulticastRouteVisualization : public LineManager::ModuleLine { + public: + mutable int numRoutes = 1; + const Ipv4MulticastRoute *route = nullptr; + + public: + MulticastRouteVisualization(const Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId); + virtual ~MulticastRouteVisualization() {} + }; + class INET_API DirectiveResolver : public StringFormat::IDirectiveResolver { protected: const Ipv4Route *route = nullptr; @@ -44,6 +54,16 @@ class INET_API RoutingTableVisualizerBase : public VisualizerBase, public cListe virtual std::string resolveDirective(char directive) const override; }; + class INET_API MulticastDirectiveResolver : public StringFormat::IDirectiveResolver { + protected: + const Ipv4MulticastRoute *route = nullptr; + + public: + MulticastDirectiveResolver(const Ipv4MulticastRoute *route) : route(route) {} + + virtual std::string resolveDirective(char directive) const override; + }; + protected: /** @name Parameters */ //@{ @@ -52,6 +72,9 @@ class INET_API RoutingTableVisualizerBase : public VisualizerBase, public cListe bool displayLabels = false; NetworkNodeFilter destinationFilter; NetworkNodeFilter nodeFilter; + NetworkNodeFilter multicastSourceNodeFilter; + cMatchExpression multicastSourceAddressFilter; + cMatchExpression multicastGroupFilter; cFigure::Color lineColor; cFigure::LineStyle lineStyle; double lineShift = NaN; @@ -69,6 +92,9 @@ class INET_API RoutingTableVisualizerBase : public VisualizerBase, public cListe // key is router ID, source module ID, destination module ID std::map, const RouteVisualization *> routeVisualizations; + // key is router ID, source module ID, destination module ID + std::map, const MulticastRouteVisualization *> multicastRouteVisualizations; + protected: virtual void initialize(int stage) override; virtual void handleParameterChange(const char *name) override; @@ -82,7 +108,14 @@ class INET_API RoutingTableVisualizerBase : public VisualizerBase, public cListe virtual void addRouteVisualization(const RouteVisualization *routeVisualization); virtual void removeRouteVisualization(const RouteVisualization *routeVisualization); + virtual const MulticastRouteVisualization *createMulticastRouteVisualization(Ipv4MulticastRoute *route, cModule *node, cModule *nextHop) const = 0; + virtual const MulticastRouteVisualization *getMulticastRouteVisualization(Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId); + virtual void addMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization); + virtual void removeMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization); + virtual std::vector getDestinations(); + virtual std::vector getMulticastSources(); + virtual std::vector getMulticastGroups(); virtual void addRouteVisualizations(IIpv4RoutingTable *routingTable); virtual void removeRouteVisualizations(IIpv4RoutingTable *routingTable); @@ -91,7 +124,10 @@ class INET_API RoutingTableVisualizerBase : public VisualizerBase, public cListe virtual void updateAllRouteVisualizations(); virtual std::string getRouteVisualizationText(const Ipv4Route *route) const; + virtual std::string getMulticastRouteVisualizationText(const Ipv4MulticastRoute *route) const; + virtual void refreshRouteVisualization(const RouteVisualization *routeVisualization) const = 0; + virtual void refreshMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) const = 0; public: virtual void receiveSignal(cComponent *source, simsignal_t signal, cObject *obj, cObject *details) override; diff --git a/src/inet/visualizer/base/RoutingTableVisualizerBase.ned b/src/inet/visualizer/base/RoutingTableVisualizerBase.ned index 46e8122337a..e76a8bc7d6c 100644 --- a/src/inet/visualizer/base/RoutingTableVisualizerBase.ned +++ b/src/inet/visualizer/base/RoutingTableVisualizerBase.ned @@ -37,6 +37,9 @@ simple RoutingTableVisualizerBase extends VisualizerBase string destinationFilter @mutable = default("*"); // which destinations are considered, matches all destinations by default string nodeFilter @mutable = default("*"); // which nodes are considered, matches all nodes by default + string multicastSourceNodeFilter @mutable = default("*"); // which multicast source nodes are considered, matches all nodes by default + string multicastSourceAddressFilter @mutable = default("*"); // which multicast source addresses are considered, matches all addresses by default + string multicastGroupFilter @mutable = default("*"); // which multicast group addresses are considered, matches all group addresses by default string lineColor = default("black"); // route line color, black by default string lineStyle = default("solid"); // route line style (solid, dashed, dotted) diff --git a/src/inet/visualizer/canvas/integrated/IntegratedCanvasVisualizer.ned b/src/inet/visualizer/canvas/integrated/IntegratedCanvasVisualizer.ned index fec680fbd00..59971fcab8f 100644 --- a/src/inet/visualizer/canvas/integrated/IntegratedCanvasVisualizer.ned +++ b/src/inet/visualizer/canvas/integrated/IntegratedCanvasVisualizer.ned @@ -7,8 +7,10 @@ package inet.visualizer.canvas.integrated; +import inet.visualizer.contract.IChannelVisualizer; import inet.visualizer.contract.IDataLinkVisualizer; import inet.visualizer.contract.IEnergyStorageVisualizer; +import inet.visualizer.contract.IFailureProtectionConfigurationVisualizer; import inet.visualizer.contract.IGateScheduleVisualizer; import inet.visualizer.contract.IIeee80211Visualizer; import inet.visualizer.contract.IInfoVisualizer; @@ -33,7 +35,6 @@ import inet.visualizer.contract.IStreamRedundancyConfigurationVisualizer; import inet.visualizer.contract.ITracingObstacleLossVisualizer; import inet.visualizer.contract.ITransportConnectionVisualizer; import inet.visualizer.contract.ITransportRouteVisualizer; -import inet.visualizer.contract.IFailureProtectionConfigurationVisualizer; // // This module integrates all canvas visualizers into a single module. It @@ -153,5 +154,9 @@ module IntegratedCanvasVisualizer like IIntegratedVisualizer parameters: @display("p=750,200"); } + channelVisualizer: like IChannelVisualizer if typename != "" { + parameters: + @display("p=750,300"); + } } diff --git a/src/inet/visualizer/canvas/integrated/IntegratedMultiCanvasVisualizer.ned b/src/inet/visualizer/canvas/integrated/IntegratedMultiCanvasVisualizer.ned index 00b1be41b67..4185cf7e1d1 100644 --- a/src/inet/visualizer/canvas/integrated/IntegratedMultiCanvasVisualizer.ned +++ b/src/inet/visualizer/canvas/integrated/IntegratedMultiCanvasVisualizer.ned @@ -7,8 +7,10 @@ package inet.visualizer.canvas.integrated; +import inet.visualizer.contract.IChannelVisualizer; import inet.visualizer.contract.IDataLinkVisualizer; import inet.visualizer.contract.IEnergyStorageVisualizer; +import inet.visualizer.contract.IFailureProtectionConfigurationVisualizer; import inet.visualizer.contract.IGateScheduleVisualizer; import inet.visualizer.contract.IIeee80211Visualizer; import inet.visualizer.contract.IInfoVisualizer; @@ -32,7 +34,7 @@ import inet.visualizer.contract.IStreamRedundancyConfigurationVisualizer; import inet.visualizer.contract.ITracingObstacleLossVisualizer; import inet.visualizer.contract.ITransportConnectionVisualizer; import inet.visualizer.contract.ITransportRouteVisualizer; -import inet.visualizer.contract.IFailureProtectionConfigurationVisualizer; + // // This module integrates all canvas visualizers into a single module. It @@ -70,6 +72,7 @@ module IntegratedMultiCanvasVisualizer like IIntegratedVisualizer int numTransportConnectionVisualizers = default(1); int numFailureProtectionConfigurationVisualizers = default(1); int numStreamRedundancyConfigurationVisualizers = default(1); + int numChannelVisualizers = default(1); *.visualizationTargetModule = default("^.^"); *.visualizationSubjectModule = default("^.^"); *.networkNodeVisualizerModule = default(absPath(".networkNodeVisualizer[0]")); @@ -174,5 +177,9 @@ module IntegratedMultiCanvasVisualizer like IIntegratedVisualizer parameters: @display("p=750,200"); } + channelVisualizer[numChannelVisualizers]: like IChannelVisualizer { + parameters: + @display("p=750,300"); + } } diff --git a/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.cc b/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.cc index 5eb687c7e65..6028e28dfc5 100644 --- a/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.cc +++ b/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.cc @@ -24,6 +24,17 @@ RoutingTableCanvasVisualizer::RouteCanvasVisualization::~RouteCanvasVisualizatio delete figure; } +RoutingTableCanvasVisualizer::MulticastRouteCanvasVisualization::MulticastRouteCanvasVisualization(LabeledLineFigure *figure, const Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId) : + MulticastRouteVisualization(route, nodeModuleId, nextHopModuleId), + figure(figure) +{ +} + +RoutingTableCanvasVisualizer::MulticastRouteCanvasVisualization::~MulticastRouteCanvasVisualization() +{ + delete figure; +} + void RoutingTableCanvasVisualizer::initialize(int stage) { RoutingTableVisualizerBase::initialize(stage); @@ -54,6 +65,18 @@ void RoutingTableCanvasVisualizer::refreshDisplay() const figure->setStart(canvasProjection->computeCanvasPoint(sourcePosition + shift)); figure->setEnd(canvasProjection->computeCanvasPoint(destinationPosition + shift)); } + for (auto it : multicastRouteVisualizations) { + auto routeVisualization = it.second; + auto routeCanvasVisualization = static_cast(routeVisualization); + auto figure = routeCanvasVisualization->figure; + auto sourceModule = simulation->getModule(routeVisualization->sourceModuleId); + auto destinationModule = simulation->getModule(routeVisualization->destinationModuleId); + auto sourcePosition = getContactPosition(sourceModule, getPosition(destinationModule), lineContactMode, lineContactSpacing); + auto destinationPosition = getContactPosition(destinationModule, getPosition(sourceModule), lineContactMode, lineContactSpacing); + auto shift = lineManager->getLineShift(routeVisualization->sourceModuleId, routeVisualization->destinationModuleId, sourcePosition, destinationPosition, lineShiftMode, routeVisualization->shiftOffset) * lineShift; + figure->setStart(canvasProjection->computeCanvasPoint(sourcePosition + shift)); + figure->setEnd(canvasProjection->computeCanvasPoint(destinationPosition + shift)); + } } const RoutingTableVisualizerBase::RouteVisualization *RoutingTableCanvasVisualizer::createRouteVisualization(Ipv4Route *route, cModule *node, cModule *nextHop) const @@ -101,6 +124,51 @@ void RoutingTableCanvasVisualizer::refreshRouteVisualization(const RouteVisualiz labelFigure->setText(text.c_str()); } +const RoutingTableVisualizerBase::MulticastRouteVisualization *RoutingTableCanvasVisualizer::createMulticastRouteVisualization(Ipv4MulticastRoute *route, cModule *node, cModule *nextHop) const +{ + auto figure = new LabeledLineFigure("routing entry"); + figure->setTags((std::string("route ") + tags).c_str()); + figure->setTooltip("This arrow represents a route in a routing table"); + figure->setAssociatedObject(route); + auto lineFigure = figure->getLineFigure(); + lineFigure->setEndArrowhead(cFigure::ARROW_TRIANGLE); + lineFigure->setLineWidth(lineWidth); + lineFigure->setLineColor(lineColor); + lineFigure->setLineStyle(lineStyle); + auto labelFigure = figure->getLabelFigure(); + labelFigure->setFont(labelFont); + labelFigure->setColor(labelColor); + labelFigure->setVisible(displayLabels); + auto routeVisualization = new MulticastRouteCanvasVisualization(figure, route, node->getId(), nextHop->getId()); + routeVisualization->shiftPriority = 0.5; + refreshMulticastRouteVisualization(routeVisualization); + return routeVisualization; +} + +void RoutingTableCanvasVisualizer::addMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) +{ + RoutingTableVisualizerBase::addMulticastRouteVisualization(routeVisualization); + auto routeCanvasVisualization = static_cast(routeVisualization); + lineManager->addModuleLine(routeVisualization); + routeGroup->addFigure(routeCanvasVisualization->figure); +} + +void RoutingTableCanvasVisualizer::removeMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) +{ + RoutingTableVisualizerBase::removeMulticastRouteVisualization(routeVisualization); + auto routeCanvasVisualization = static_cast(routeVisualization); + lineManager->removeModuleLine(routeVisualization); + routeGroup->removeFigure(routeCanvasVisualization->figure); +} + +void RoutingTableCanvasVisualizer::refreshMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) const +{ + auto routeCanvasVisualization = static_cast(routeVisualization); + auto labelFigure = routeCanvasVisualization->figure->getLabelFigure(); + auto text = displayRoutesIndividually ? getMulticastRouteVisualizationText(routeCanvasVisualization->route) : std::to_string(routeVisualization->numRoutes) + (routeVisualization->numRoutes > 1 ? " routes" : " route"); + labelFigure->setText(text.c_str()); +} + } // namespace visualizer } // namespace inet diff --git a/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.h b/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.h index ad1b9a219e4..6c7b9970f56 100644 --- a/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.h +++ b/src/inet/visualizer/canvas/networklayer/RoutingTableCanvasVisualizer.h @@ -28,6 +28,15 @@ class INET_API RoutingTableCanvasVisualizer : public RoutingTableVisualizerBase virtual ~RouteCanvasVisualization(); }; + class INET_API MulticastRouteCanvasVisualization : public MulticastRouteVisualization { + public: + LabeledLineFigure *figure = nullptr; + + public: + MulticastRouteCanvasVisualization(LabeledLineFigure *figure, const Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId); + virtual ~MulticastRouteCanvasVisualization(); + }; + protected: double zIndex = NaN; const CanvasProjection *canvasProjection = nullptr; @@ -41,6 +50,11 @@ class INET_API RoutingTableCanvasVisualizer : public RoutingTableVisualizerBase virtual void addRouteVisualization(const RouteVisualization *routeVisualization) override; virtual void removeRouteVisualization(const RouteVisualization *routeVisualization) override; virtual void refreshRouteVisualization(const RouteVisualization *routeVisualization) const override; + + virtual const MulticastRouteVisualization *createMulticastRouteVisualization(Ipv4MulticastRoute *route, cModule *node, cModule *nextHop) const override; + virtual void addMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) override; + virtual void removeMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) override; + virtual void refreshMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) const override; }; } // namespace visualizer diff --git a/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.cc b/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.cc new file mode 100644 index 00000000000..cd6c638addb --- /dev/null +++ b/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.cc @@ -0,0 +1,116 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +#include "inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.h" + +namespace inet { + +namespace visualizer { + +Define_Module(ChannelCanvasVisualizer); + +ChannelCanvasVisualizer::ChannelCanvasVisualization::ChannelCanvasVisualization(LabeledLineFigure *figure, int sourceModuleId, int destinationModuleId) : + ChannelVisualization(sourceModuleId, destinationModuleId), + figure(figure) +{ +} + +ChannelCanvasVisualizer::ChannelCanvasVisualization::~ChannelCanvasVisualization() +{ + delete figure; +} + +void ChannelCanvasVisualizer::initialize(int stage) +{ + ChannelVisualizerBase::initialize(stage); + if (!hasGUI()) return; + if (stage == INITSTAGE_LOCAL) { + zIndex = par("zIndex"); + auto canvas = visualizationTargetModule->getCanvas(); + lineManager = LineManager::getCanvasLineManager(canvas); + canvasProjection = CanvasProjection::getCanvasProjection(canvas); + channelActivityGroup = new cGroupFigure("channels"); + channelActivityGroup->setZIndex(zIndex); + canvas->addFigure(channelActivityGroup); + } +} + +void ChannelCanvasVisualizer::refreshDisplay() const +{ + ChannelVisualizerBase::refreshDisplay(); + auto simulation = getSimulation(); + for (auto it : channelVisualizations) { + auto channelVisualization = it.second; + auto channelCanvasVisualization = static_cast(channelVisualization); + auto figure = channelCanvasVisualization->figure; + auto sourceModule = simulation->getModule(channelVisualization->sourceModuleId); + auto destinationModule = simulation->getModule(channelVisualization->destinationModuleId); + if (sourceModule != nullptr && destinationModule != nullptr) { + auto sourcePosition = getContactPosition(sourceModule, getPosition(destinationModule), lineContactMode, lineContactSpacing); + auto destinationPosition = getContactPosition(destinationModule, getPosition(sourceModule), lineContactMode, lineContactSpacing); + auto shift = lineManager->getLineShift(channelVisualization->sourceModuleId, channelVisualization->destinationModuleId, sourcePosition, destinationPosition, lineShiftMode, channelVisualization->shiftOffset) * lineShift; + figure->setStart(canvasProjection->computeCanvasPoint(sourcePosition + shift)); + figure->setEnd(canvasProjection->computeCanvasPoint(destinationPosition + shift)); + } + } + visualizationTargetModule->getCanvas()->setAnimationSpeed(channelVisualizations.empty() ? 0 : fadeOutAnimationSpeed, this); +} + +const ChannelVisualizerBase::ChannelVisualization *ChannelCanvasVisualizer::createChannelVisualization(cModule *source, cModule *destination, cPacket *packet) const +{ + auto figure = new LabeledLineFigure("channel activity"); + figure->setTags((std::string("channel ") + tags).c_str()); + figure->setTooltip("This arrow represents channel activity between two network nodes"); + auto lineFigure = figure->getLineFigure(); + lineFigure->setEndArrowhead(cFigure::ARROW_BARBED); + lineFigure->setLineWidth(lineWidth); + lineFigure->setLineColor(lineColor); + lineFigure->setLineStyle(lineStyle); + auto labelFigure = figure->getLabelFigure(); + labelFigure->setFont(labelFont); + labelFigure->setColor(labelColor); + auto text = getChannelVisualizationText(packet); + labelFigure->setText(text.c_str()); + return new ChannelCanvasVisualization(figure, source->getId(), destination->getId()); +} + +void ChannelCanvasVisualizer::addChannelVisualization(std::pair sourceAndDestination, const ChannelVisualization *channelVisualization) +{ + ChannelVisualizerBase::addChannelVisualization(sourceAndDestination, channelVisualization); + auto channelCanvasVisualization = static_cast(channelVisualization); + auto figure = channelCanvasVisualization->figure; + lineManager->addModuleLine(channelVisualization); + channelActivityGroup->addFigure(figure); +} + +void ChannelCanvasVisualizer::removeChannelVisualization(const ChannelVisualization *channelVisualization) +{ + ChannelVisualizerBase::removeChannelVisualization(channelVisualization); + auto channelCanvasVisualization = static_cast(channelVisualization); + lineManager->removeModuleLine(channelVisualization); + channelActivityGroup->removeFigure(channelCanvasVisualization->figure); +} + +void ChannelCanvasVisualizer::setAlpha(const ChannelVisualization *channelVisualization, double alpha) const +{ + auto channelCanvasVisualization = static_cast(channelVisualization); + auto figure = channelCanvasVisualization->figure; + figure->getLineFigure()->setLineOpacity(alpha); +} + +void ChannelCanvasVisualizer::refreshChannelVisualization(const ChannelVisualization *channelVisualization, cPacket *packet) +{ + ChannelVisualizerBase::refreshChannelVisualization(channelVisualization, packet); + auto channelCanvasVisualization = static_cast(channelVisualization); + auto text = getChannelVisualizationText(packet); + channelCanvasVisualization->figure->getLabelFigure()->setText(text.c_str()); +} + +} // namespace visualizer + +} // namespace inet + diff --git a/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.h b/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.h new file mode 100644 index 00000000000..61dba217e0b --- /dev/null +++ b/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.h @@ -0,0 +1,52 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +#ifndef __INET_CHANNELCANVASVISUALIZER_H +#define __INET_CHANNELCANVASVISUALIZER_H + +#include "inet/common/figures/LabeledLineFigure.h" +#include "inet/common/geometry/common/CanvasProjection.h" +#include "inet/visualizer/base/ChannelVisualizerBase.h" + +namespace inet { + +namespace visualizer { + +class INET_API ChannelCanvasVisualizer : public ChannelVisualizerBase +{ + protected: + class INET_API ChannelCanvasVisualization : public ChannelVisualization { + public: + LabeledLineFigure *figure = nullptr; + + public: + ChannelCanvasVisualization(LabeledLineFigure *figure, int sourceModuleId, int destinationModuleId); + virtual ~ChannelCanvasVisualization(); + }; + + protected: + double zIndex = NaN; + const CanvasProjection *canvasProjection = nullptr; + cGroupFigure *channelActivityGroup = nullptr; + + protected: + virtual void initialize(int stage) override; + virtual void refreshDisplay() const override; + + virtual const ChannelVisualization *createChannelVisualization(cModule *source, cModule *destination, cPacket *packet) const override; + virtual void addChannelVisualization(std::pair sourceAndDestination, const ChannelVisualization *channelVisualization) override; + virtual void removeChannelVisualization(const ChannelVisualization *channelVisualization) override; + virtual void setAlpha(const ChannelVisualization *channelVisualization, double alpha) const override; + virtual void refreshChannelVisualization(const ChannelVisualization *channelVisualization, cPacket *packet) override; +}; + +} // namespace visualizer + +} // namespace inet + +#endif + diff --git a/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.ned b/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.ned new file mode 100644 index 00000000000..c311b28fb38 --- /dev/null +++ b/src/inet/visualizer/canvas/physicallayer/ChannelCanvasVisualizer.ned @@ -0,0 +1,19 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +package inet.visualizer.canvas.physicallayer; + +import inet.visualizer.base.ChannelVisualizerBase; +import inet.visualizer.contract.IChannelVisualizer; + +simple ChannelCanvasVisualizer extends ChannelVisualizerBase like IChannelVisualizer +{ + parameters: + double zIndex = default(1); // determines the drawing order of figures relative to other visualizers + @class(ChannelCanvasVisualizer); +} + diff --git a/src/inet/visualizer/contract/IChannelVisualizer.ned b/src/inet/visualizer/contract/IChannelVisualizer.ned new file mode 100644 index 00000000000..3dde36bff08 --- /dev/null +++ b/src/inet/visualizer/contract/IChannelVisualizer.ned @@ -0,0 +1,15 @@ +// +// Copyright (C) 2024 OpenSim Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +package inet.visualizer.contract; + +moduleinterface IChannelVisualizer +{ + parameters: + @display("i=block/app"); +} + diff --git a/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.cc b/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.cc index d5dc96136c3..5b39e0fdfe9 100644 --- a/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.cc +++ b/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.cc @@ -25,6 +25,12 @@ RoutingTableOsgVisualizer::RouteOsgVisualization::RouteOsgVisualization(osg::Nod { } +RoutingTableOsgVisualizer::MulticastRouteOsgVisualization::MulticastRouteOsgVisualization(osg::Node *node, const Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId) : + MulticastRouteVisualization(route, nodeModuleId, nextHopModuleId), + node(node) +{ +} + void RoutingTableOsgVisualizer::initialize(int stage) { RoutingTableVisualizerBase::initialize(stage); @@ -72,6 +78,44 @@ void RoutingTableOsgVisualizer::refreshRouteVisualization(const RouteVisualizati // auto text = getRouteVisualizationText(routeVisualization->route); } + +const RoutingTableVisualizerBase::MulticastRouteVisualization *RoutingTableOsgVisualizer::createMulticastRouteVisualization(Ipv4MulticastRoute *route, cModule *node, cModule *nextHop) const +{ + auto nodePosition = getPosition(node); + auto nextHopPosition = getPosition(nextHop); + auto osgNode = inet::osg::createLine(nodePosition, nextHopPosition, cFigure::ARROW_NONE, cFigure::ARROW_BARBED); + auto stateSet = inet::osg::createStateSet(lineColor, 1.0, false); + stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); + auto lineWidth = new osg::LineWidth(); + lineWidth->setWidth(this->lineWidth); + stateSet->setAttributeAndModes(lineWidth, osg::StateAttribute::ON); + osgNode->setStateSet(stateSet); + return new MulticastRouteOsgVisualization(osgNode, route, node->getId(), nextHop->getId()); +} + +void RoutingTableOsgVisualizer::addMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) +{ + RoutingTableVisualizerBase::addMulticastRouteVisualization(routeVisualization); + auto routeOsgVisualization = static_cast(routeVisualization); + auto scene = inet::osg::TopLevelScene::getSimulationScene(visualizationTargetModule); + scene->addChild(routeOsgVisualization->node); +} + +void RoutingTableOsgVisualizer::removeMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) +{ + RoutingTableVisualizerBase::removeMulticastRouteVisualization(routeVisualization); + auto routeOsgVisualization = static_cast(routeVisualization); + auto node = routeOsgVisualization->node; + node->getParent(0)->removeChild(node); +} + +void RoutingTableOsgVisualizer::refreshMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) const +{ + // TODO +// auto routeOsgVisualization = static_cast(routeVisualization); +// auto text = getMulticastRouteVisualizationText(routeVisualization->route); +} + } // namespace visualizer } // namespace inet diff --git a/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.h b/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.h index 98162532b0a..ed0192d310a 100644 --- a/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.h +++ b/src/inet/visualizer/osg/networklayer/RoutingTableOsgVisualizer.h @@ -27,6 +27,14 @@ class INET_API RoutingTableOsgVisualizer : public RoutingTableVisualizerBase RouteOsgVisualization(osg::Node *node, const Ipv4Route *route, int nodeModuleId, int nextHopModuleId); }; + class INET_API MulticastRouteOsgVisualization : public MulticastRouteVisualization { + public: + osg::ref_ptr node; + + public: + MulticastRouteOsgVisualization(osg::Node *node, const Ipv4MulticastRoute *route, int nodeModuleId, int nextHopModuleId); + }; + protected: virtual void initialize(int stage) override; @@ -34,6 +42,11 @@ class INET_API RoutingTableOsgVisualizer : public RoutingTableVisualizerBase virtual void addRouteVisualization(const RouteVisualization *routeVisualization) override; virtual void removeRouteVisualization(const RouteVisualization *routeVisualization) override; virtual void refreshRouteVisualization(const RouteVisualization *routeVisualization) const override; + + virtual const MulticastRouteVisualization *createMulticastRouteVisualization(Ipv4MulticastRoute *route, cModule *node, cModule *nextHop) const override; + virtual void addMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) override; + virtual void removeMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) override; + virtual void refreshMulticastRouteVisualization(const MulticastRouteVisualization *routeVisualization) const override; }; } // namespace visualizer diff --git a/tests/fingerprint/examples.csv b/tests/fingerprint/examples.csv index edd23ce3a40..e01c3d4c01a 100644 --- a/tests/fingerprint/examples.csv +++ b/tests/fingerprint/examples.csv @@ -1,7 +1,7 @@ # working directory, command line arguments, simulation time limit, fingerprint, expected result, tags # /examples/adhoc/idealwireless/, -f .qtenv.ini -c General -r 0 /examples/adhoc/hostautoconf/, -f omnetpp.ini -c General -r 0, 100s, 87cf-952a/tplx;48c6-665e/~tNl;e8e2-932a/~tND;ef88-5542/tyf, PASS, wireless adhoc Ipv4 -/examples/adhoc/idealwireless/, -f omnetpp.ini -c Ping1 -r 0, 100s, 3e42-6e3c/tplx;d8ca-e3f9/~tNl;0c2d-6d2e/~tND;bd32-4b81/tyf, PASS, wireless adhoc Ipv4 +/examples/adhoc/idealwireless/, -f omnetpp.ini -c Ping1 -r 0, 100s, 3e42-6e3c/tplx;d8ca-e3f9/~tNl;f3cd-6929/~tND;bd32-4b81/tyf, PASS, wireless adhoc Ipv4 # /examples/adhoc/idealwireless/, -f omnetpp.ini -c Ping2 -r 0, 100s, 0000-0000/tplx;0000-0000/~tNl;0000-0000/~tND, ERROR, wireless adhoc # interactive config, needed a *.numHosts parameter /examples/adhoc/ieee80211/, -f omnetpp.ini -c Ping1 -r 0, 1000s, 26e4-a191/tplx;ff15-2e9f/~tNl;afea-362d/~tND;132a-f75d/tyf, PASS, wireless adhoc Ipv4 # /examples/adhoc/ieee80211/, -f omnetpp.ini -c Ping2 -r 0, 100s, 0000-0000/tplx;0000-0000/~tNl;0000-0000/~tND, ERROR, wireless adhoc # [Config Ping2] # interactive config, needed a *.numHosts parameter @@ -328,9 +328,9 @@ /examples/ipv6/nclients/, -f omnetpp.ini -c PPP -r 0, 1000s, a39a-669a/tplx;ad75-e817/~tNl;ca30-d6dc/tyf, PASS, /examples/ipv6/nclients/, -f omnetpp.ini -c PPP_SCTP -r 0, 100s, 1607-36dd/tplx;9c89-c7c1/~tNl;0e90-dcad/~tND;f4ae-8bb4/tyf, PASS, -/examples/manetrouting/dsdv/, -f omnetpp.ini -c IPv4 -r 0, 10s, cd11-7c78/tplx;1ba1-8398/~tNl;04ca-d934/~tND;6388-bbad/tyf, PASS, wireless adhoc Ipv4 -/examples/manetrouting/dsdv/, -f omnetpp.ini -c MultiIPv4 -r 0, 10s, 94c8-51dd/tplx;e9e8-7d0b/~tNl;e9f0-b256/~tND;e86f-d3fa/tyf, PASS, wireless adhoc Ipv4 -/examples/manetrouting/dsdv/, -f omnetpp.ini -c DynamicIPv4 -r 0, 22s, 6699-04d7/tplx;3e2c-1eee/~tNl;eecc-7593/~tND;90d2-3ffa/tyf, PASS, wireless adhoc Ipv4 +/examples/manetrouting/dsdv/, -f omnetpp.ini -c IPv4 -r 0, 10s, 2d1b-0515/tplx;1ba1-8398/~tNl;04ca-d934/~tND;6388-bbad/tyf, PASS, wireless adhoc Ipv4 +/examples/manetrouting/dsdv/, -f omnetpp.ini -c MultiIPv4 -r 0, 10s, 4d24-d5b6/tplx;e9e8-7d0b/~tNl;e9f0-b256/~tND;e86f-d3fa/tyf, PASS, wireless adhoc Ipv4 +/examples/manetrouting/dsdv/, -f omnetpp.ini -c DynamicIPv4 -r 0, 22s, b5fe-a1b2/tplx;3e2c-1eee/~tNl;eecc-7593/~tND;90d2-3ffa/tyf, PASS, wireless adhoc Ipv4 # /examples/manetrouting/dymo/, -f omnetpp.ini -c _IPv4 -r 0 # abstract-config /examples/manetrouting/dymo/, -f omnetpp.ini -c IPv4 -r 0, 10s, 1a85-cb5d/tplx;dfe8-11b9/~tNl;483b-544e/tyf, PASS, wireless adhoc Ipv4 @@ -502,7 +502,7 @@ /examples/wireless/crosstalk/, -f omnetpp.ini -c General -r 0, 2s, 0a4f-e755/tplx;7ef5-c624/~tNl;105a-8a94/~tND;4b4c-0831/tyf, PASS, wireless Ipv4 -/examples/wireless/dynamic/, -f omnetpp.ini -c General -r 0, 100s, 4b91-925c/tplx;2b55-3ab9/~tNl;944e-11b0/~tND;c39c-a7b0/tyf, PASS, wireless Ipv4 +/examples/wireless/dynamic/, -f omnetpp.ini -c General -r 0, 100s, 4b91-925c/tplx;2b55-3ab9/~tNl;1ab2-bb7c/~tND;c39c-a7b0/tyf, PASS, wireless Ipv4 /examples/wireless/errorrate/, -f omnetpp.ini -c General -r 0, 100s, 0bb3-adca/tplx;b0b7-4a84/~tNl;1c49-63dd/~tND;ac68-ada4/tyf, PASS, wireless Ipv4 @@ -563,9 +563,9 @@ # /examples/wireless/nic/, -f omnetpp.ini -c AbstractApskDimensionalRadio -r 0, # abstract-config # /examples/wireless/nic/, -f omnetpp.ini -c AbstractIeee80211ScalarRadio -r 0, # abstract-config # /examples/wireless/nic/, -f omnetpp.ini -c AbstractIeee80211DimensionalRadio -r 0 # abstract-config -/examples/wireless/nic/, -f omnetpp.ini -c AckingMacWithUnitDiskRadio -r 0, 100s, aa02-d13c/tplx;6268-2984/~tNl;1486-5ece/~tND;2fdc-a5d4/tyf, PASS, wireless AckingWirelessInterface Ipv4 -/examples/wireless/nic/, -f omnetpp.ini -c AckingMacWithApskScalarRadio -r 0, 100s, aa02-d13c/tplx;6268-2984/~tNl;97bb-e537/~tND;5fb3-0e09/tyf, PASS, wireless AckingWirelessInterface Ipv4 -/examples/wireless/nic/, -f omnetpp.ini -c AckingMacWithApskDimensionalRadio -r 0, 100s, aa02-d13c/tplx;6268-2984/~tNl;97bb-e537/~tND;5fb3-0e09/tyf, PASS, wireless AckingWirelessInterface Ipv4 +/examples/wireless/nic/, -f omnetpp.ini -c AckingMacWithUnitDiskRadio -r 0, 100s, aa02-d13c/tplx;6268-2984/~tNl;a686-55e2/~tND;2fdc-a5d4/tyf, PASS, wireless AckingWirelessInterface Ipv4 +/examples/wireless/nic/, -f omnetpp.ini -c AckingMacWithApskScalarRadio -r 0, 100s, aa02-d13c/tplx;6268-2984/~tNl;05bb-ec13/~tND;5fb3-0e09/tyf, PASS, wireless AckingWirelessInterface Ipv4 +/examples/wireless/nic/, -f omnetpp.ini -c AckingMacWithApskDimensionalRadio -r 0, 100s, aa02-d13c/tplx;6268-2984/~tNl;05bb-ec13/~tND;5fb3-0e09/tyf, PASS, wireless AckingWirelessInterface Ipv4 /examples/wireless/nic/, -f omnetpp.ini -c LMacWithUnitDiskRadio -r 0, 100s, ae44-849a/tplx;a263-5bef/~tNl;cd2e-fed3/tyf, PASS, wireless Ipv4 /examples/wireless/nic/, -f omnetpp.ini -c LMacWithApskScalarRadio -r 0, 100s, 340e-9ace/tplx;f8ab-769b/~tNl;9567-1b81/tyf, PASS, wireless Ipv4 /examples/wireless/nic/, -f omnetpp.ini -c LMacWithApskDimensionalRadio -r 0, 100s, 340e-9ace/tplx;f8ab-769b/~tNl;9567-1b81/tyf, PASS, wireless Ipv4 @@ -601,9 +601,9 @@ /examples/wireless/ratecontrol/, -f omnetpp.ini -c Mac -r 0, 100s, bf30-2f13/tplx;7b2f-653d/~tNl;2456-c0fc/~tND;3e9e-7f1d/tyf, PASS, wireless # /examples/wireless/scaling/, -f omnetpp.ini -c AbstractAckingMac -r 0, # abstract-config -/examples/wireless/scaling/, -f omnetpp.ini -c UnitDiskRadioMedium -r 0, 1s, bb94-17a2/tplx;2220-d64e/~tNl;0f1b-2b86/~tND, PASS, wireless AckingWirelessInterface Ipv4 -/examples/wireless/scaling/, -f omnetpp.ini -c ScalarRadioMedium -r 0, 1s, 9b3b-f88a/tplx;be94-9c8e/~tNl;fed7-df1c/~tND, PASS, wireless AckingWirelessInterface Ipv4 -/examples/wireless/scaling/, -f omnetpp.ini -c DimensionalRadioMedium -r 0, 0.1s, fa11-2540/tplx;c2a2-d597/~tNl;4989-a0f1/~tND, PASS, wireless AckingWirelessInterface Ipv4 +/examples/wireless/scaling/, -f omnetpp.ini -c UnitDiskRadioMedium -r 0, 1s, bb94-17a2/tplx;2220-d64e/~tNl;a868-09d0/~tND, PASS, wireless AckingWirelessInterface Ipv4 +/examples/wireless/scaling/, -f omnetpp.ini -c ScalarRadioMedium -r 0, 1s, 9b3b-f88a/tplx;be94-9c8e/~tNl;ff47-27c4/~tND, PASS, wireless AckingWirelessInterface Ipv4 +/examples/wireless/scaling/, -f omnetpp.ini -c DimensionalRadioMedium -r 0, 0.1s, fa11-2540/tplx;c2a2-d597/~tNl;89ae-8e19/~tND, PASS, wireless AckingWirelessInterface Ipv4 /examples/wireless/shortcut/, -f omnetpp.ini -c ShortcutMac -r 0, 1000s, 91d1-098d/tplx;6924-7e35/~tNl;1069-9852/tyf, PASS, wireless Ipv4 /examples/wireless/shortcut/, -f omnetpp.ini -c ShortcutRadio -r 0, 1000s, 4e2a-4349/tplx;1d1b-2b6d/~tNl;7a3c-9e0d/tyf, PASS, wireless AckingWirelessInterface Ipv4 diff --git a/tests/fingerprint/showcases.csv b/tests/fingerprint/showcases.csv index 8b950fe7e6b..8f5c13bcf1c 100644 --- a/tests/fingerprint/showcases.csv +++ b/tests/fingerprint/showcases.csv @@ -40,7 +40,7 @@ # /showcases/routing/manet/, -f omnetpp.ini -c MobileNodesBase -r 0, 100s, 0000-0000/tplx;0000-0000/~tNl;0000-0000/~tND, PASS, # MobileNodesBase extended /showcases/routing/manet/, -f omnetpp.ini -c Aodv -r 0, 100s, d4f1-1c35/tplx;c268-fae7/~tNl;0d5b-c7a9/~tND;e74e-6ba9/tyf, PASS, wireless Ipv4 -/showcases/routing/manet/, -f omnetpp.ini -c Dsdv -r 0, 100s, 4eff-8dbc/tplx;bdad-9a28/~tNl;cdce-1d3c/~tND;0fca-2874/tyf, PASS, wireless Ipv4 +/showcases/routing/manet/, -f omnetpp.ini -c Dsdv -r 0, 100s, 84f0-9aea/tplx;bdad-9a28/~tNl;cdce-1d3c/~tND;0fca-2874/tyf, PASS, wireless Ipv4 /showcases/routing/manet/, -f omnetpp.ini -c Gpsr -r 0, 100s, 53c9-5456/tplx;5452-5da6/~tNl;9c5c-ecb8/tyf, PASS, wireless Ipv4 /showcases/tsn/combiningfeatures/fpandtas/, -f omnetpp.ini -c General -r 0, 10ms, ba97-42a3/tplx;9c73-6822/~tNl;063b-8262/~tND;d75b-92b0/tyf, PASS, @@ -150,7 +150,7 @@ /showcases/visualizer/canvas/packetdrop/, -f omnetpp.ini -c QueueOverflow -r 0, 2002ms, c23c-c6c8/tplx;b7e8-1b57/~tNl;b4fc-c0f1/~tND;ea28-df1a/tyf, PASS, wireless EthernetMac Ipv4 /showcases/visualizer/canvas/packetdrop/, -f omnetpp.ini -c ArpResolutionFailed -r 0, 500s, 9069-cca6/tplx;0000-0000/~tNl;0000-0000/~tND;2811-6bc6/tyf, PASS, wireless Ipv4 /showcases/visualizer/canvas/packetdrop/, -f omnetpp.ini -c MACRetryLimitReached -r 0, 500s, 1f7a-e5f3/tplx;14cf-73d2/~tNl;c5f5-7ea6/~tND;2a6f-66de/tyf, PASS, wireless Ipv4 -/showcases/visualizer/canvas/packetdrop/, -f omnetpp.ini -c InterfaceNotConnected -r 0, 500s, d05f-642a/tplx;0000-0000/~tNl;0000-0000/~tND;4c62-3d46/tyf, PASS, EthernetMac Ipv4 +/showcases/visualizer/canvas/packetdrop/, -f omnetpp.ini -c InterfaceNotConnected -r 0, 500s, 280f-b030/tplx;0000-0000/~tNl;0000-0000/~tND;4c62-3d46/tyf, PASS, EthernetMac Ipv4 /showcases/visualizer/canvas/packetdrop/, -f omnetpp.ini -c NoRouteToDestination -r 0, 500s, 4c38-3589/tplx;0000-0000/~tNl;0000-0000/~tND;a35d-f318/tyf, PASS, Ipv4 /showcases/visualizer/canvas/physicallinkactivity/, -f omnetpp.ini -c EnablingVisualization -r 0, 500s, a1da-0032/tplx;bde3-9c6e/~tNl;7f8e-b45a/~tND;b709-d035/tyf, PASS, wireless Ipv4 diff --git a/tests/fingerprint/tutorials.csv b/tests/fingerprint/tutorials.csv index cc295c519f6..08cebb5b154 100644 --- a/tests/fingerprint/tutorials.csv +++ b/tests/fingerprint/tutorials.csv @@ -80,11 +80,11 @@ # /tutorials/visualization/, -f omnetpp.ini -c Visualization24 -r 0, 500s, 0000-0000/tplx;0000-0000/~tNl;0000-0000/~tND, PASS, # Visualization24 extended # /tutorials/visualization/, -f omnetpp.ini -c Visualization25 -r 0, 500s, 0000-0000/tplx;0000-0000/~tNl;0000-0000/~tND, PASS, -/tutorials/wireless/, -f omnetpp.ini -c Wireless01 -r 0, 25s, f1e2-4b56/tplx;e2dd-0f31/~tNl;4098-a657/~tND;5a2d-6cf2/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless01 extended -/tutorials/wireless/, -f omnetpp.ini -c Wireless02 -r 0, 25s, f1e2-4b56/tplx;e2dd-0f31/~tNl;4098-a657/~tND;a6da-1d38/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless02 extended -/tutorials/wireless/, -f omnetpp.ini -c Wireless03 -r 0, 25s, c717-aadf/tplx;a116-8238/~tNl;2d82-931a/~tND;9ae8-8502/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless03 extended -/tutorials/wireless/, -f omnetpp.ini -c Wireless04 -r 0, 25s, 4355-a265/tplx;4c4b-2267/~tNl;d95f-38c5/~tND;ae0e-912b/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless04 extended -/tutorials/wireless/, -f omnetpp.ini -c Wireless05 -r 0, 25s, 74de-d95e/tplx;4c4b-2267/~tNl;d95f-38c5/~tND;191d-0a08/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless05 extended +/tutorials/wireless/, -f omnetpp.ini -c Wireless01 -r 0, 25s, f1e2-4b56/tplx;e2dd-0f31/~tNl;4098-a667/~tND;5a2d-6cf2/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless01 extended +/tutorials/wireless/, -f omnetpp.ini -c Wireless02 -r 0, 25s, f1e2-4b56/tplx;e2dd-0f31/~tNl;4098-a667/~tND;a6da-1d38/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless02 extended +/tutorials/wireless/, -f omnetpp.ini -c Wireless03 -r 0, 25s, c717-aadf/tplx;a116-8238/~tNl;6906-dba8/~tND;9ae8-8502/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless03 extended +/tutorials/wireless/, -f omnetpp.ini -c Wireless04 -r 0, 25s, 4355-a265/tplx;4c4b-2267/~tNl;7148-e1b4/~tND;ae0e-912b/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless04 extended +/tutorials/wireless/, -f omnetpp.ini -c Wireless05 -r 0, 25s, 74de-d95e/tplx;4c4b-2267/~tNl;7148-e1b4/~tND;191d-0a08/tyf, PASS, wireless adhoc AckingWirelessInterface Ipv4 # Wireless05 extended /tutorials/wireless/, -f omnetpp.ini -c Wireless06 -r 0, 25s, c613-c450/tplx;dee1-89f2/~tNl;3c20-c88b/~tND;efb4-20c4/tyf, PASS, wireless adhoc CsmaCaInterface Ipv4 # Wireless06 extended /tutorials/wireless/, -f omnetpp.ini -c Wireless07 -r 0, 25s, 79bc-9afe/tplx;23e6-cc0b/~tNl;4c98-416d/~tND;f4f9-3cc9/tyf, PASS, wireless adhoc CsmaCaInterface Ipv4 # Wireless07 extended /tutorials/wireless/, -f omnetpp.ini -c Wireless08 -r 0, 25s, 79bc-9afe/tplx;23e6-cc0b/~tNl;4c98-416d/~tND;38be-0057/tyf, PASS, wireless adhoc CsmaCaInterface Ipv4 # Wireless08 extended