Search code examples
c++omnet++ethernetinet

Adding a new simple custom layer to EthernetSwitch from INET framework in Omnet++, but receiveing an error when trying to send messges through it


I want to add a new layer to the EthernetSwitch model from INET in Omnet++. The layer for now only receives a message and sends it to the next layer but I'm getting the following error:

handlePacket(): Unknown protocol: protocolId = 12, protocolName = ethernetmac, servicePrimitive = INDICATION, pathStartGate = Tictoc.smartSwitch.eth[0].mac.upperLayerOut, pathEndGate = Tictoc.smartSwitch.li.in[2] -- in module (inet::MessageDispatcher) Tictoc.smartSwitch.li (id=63), at t=0.00000581s, event #8

My code is as follows: network .ini: It only sends a ping from one host to the other

[General]
network = Tictoc
cpu-time-limit = 60s
#debug-on-errors = true

*.host1.numApps = 2
*.host1.app[0].typename = "TcpSessionApp"
*.host1.app[0].dataTransferMode = "bytestream"
*.host1.app[0].connectAddress = "host2"
*.host1.app[0].tOpen = 10ms
*.host1.app[0].tSend = 10ms
*.host1.app[1].typename = "PingApp"
*.host1.app[1].destAddr = "host2"
*.host1.app[1].startTime = 0s
*.host1.app[1].sendInterval = 5ms

*.host2.numApps = 1
*.host2.app[0].typename = "TcpSinkApp"

network ned:

//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

package test.simulations;

import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator;
import inet.visualizer.common.IntegratedVisualizer;
import inet.node.inet.StandardHost;
import inet.node.ethernet.Eth100M;
import inet.smart.SmartSwitch;


//
// Two instances (tic and toc) of Txc connected.
//
network Tictoc
{
    @display("bgb=294,331");
    submodules:
        configurator: Ipv4NetworkConfigurator {
            parameters:
                @display("p=100,100;is=s");
        }
        visualizer: IntegratedVisualizer {
            parameters:
                @display("p=100,200;is=s");
        }
        smartSwitch: SmartSwitch {
            @display("p=144,176");
        }
        host1: StandardHost {
            @display("p=233,123");
        }
        host2: StandardHost {
            @display("p=45,256");
        }
    connections:
        smartSwitch.ethg++ <--> Eth100M <--> host1.ethg++;
        smartSwitch.ethg++ <--> Eth100M <--> host2.ethg++;
}

new ethernet switch compound module ned: (I basically just copied the EthernetSwitch code and connected my simple module new layer between the rl layer and the relay)

package inet.smart;
import inet.common.MessageDispatcher;
import inet.common.lifecycle.NodeStatus;
import inet.common.packet.recorder.PcapRecorder;
import inet.linklayer.configurator.L2NodeConfigurator;
import inet.linklayer.contract.IEthernetInterface;
import inet.linklayer.contract.IMacAddressTable;
import inet.linklayer.contract.IMacRelayUnit;
import inet.linklayer.contract.IPolicyLayer;
import inet.linklayer.contract.ISpanningTree;
import inet.linklayer.ethernet.contract.IEthernetEncapsulation;
import inet.linklayer.ethernet.contract.IEthernetLayer;
import inet.linklayer.ieee8021q.Ieee8021qLayer;
import inet.networklayer.common.InterfaceTable;
import inet.smart.SmartLayer;

//
// Model of a Smart Ethernet switch.
//
// TWorks just as a regular switch but has a new layer that aggregates Tensors sent in the network
//
module SmartSwitch
{
    parameters:
        @networkNode();
        @labels(node,ethernet-node);
        @display("i=device/switch");
        int numPcapRecorders = default(0);
        bool hasStatus = default(false);
        bool hasStp = default(false);
        bool enableCutthrough = default(false);
        string fcsMode @enum("declared","computed") = default("declared");
        string spanningTreeProtocol = default("Stp");
        int numEthInterfaces = default(0);  // minimum number of ethernet interfaces
        eth[*].encap.typename = default("OmittedEthernetEncapsulation");
        *.fcsMode = this.fcsMode;
        **.interfaceTableModule = default(absPath(".interfaceTable"));
        **.macTableModule = default(absPath(".macTable"));

        relayUnit.hasStp = this.hasStp;
        encap.registerProtocol = true;
        eth[*].mac.promiscuous = default(true);
        ethernet.*.promiscuous = default(true);

    gates:
        inout ethg[numEthInterfaces] @labels(EtherFrame-conn);
    submodules:
        status: NodeStatus if hasStatus {
            @display("p=100,400;is=s");
        }
        l2NodeConfigurator: L2NodeConfigurator if hasStp {
            @display("p=100,300;is=s");
        }
        interfaceTable: InterfaceTable {
            @display("p=100,200;is=s");
        }
        pcapRecorder[numPcapRecorders]: PcapRecorder {
            @display("p=100,500;is=s");
        }
        macTable: <default("MacAddressTable")> like IMacAddressTable {
            @display("p=100,100;is=s");
        }
        relayUnit: <default(firstAvailable("Ieee8021dRelay","MacRelayUnit"))> like IMacRelayUnit {
            @display("p=1101,308;is=m");
        }
        stp: <spanningTreeProtocol> like ISpanningTree if hasStp {
            @display("p=500,100");
        }
        nr: MessageDispatcher {
            parameters:
                @display("p=800,200;b=1200,5");
        }
        li: MessageDispatcher {
            parameters:
                @display("p=800,527;b=1200,5");
        }
        eth[sizeof(ethg)]: <default(enableCutthrough ? "EthernetCutthroughInterface" : "EthernetInterface")> like IEthernetInterface {
            parameters:
                @display("p=250,700,row,150;q=txQueue");
        }
        encap: <default("EthernetEncapsulation")> like IEthernetEncapsulation if typename != "" {
            @display("p=582,269");
        }
        policy: <default("OmittedPolicyLayer")> like IPolicyLayer {
            @display("p=582,347");
        }
        rl: MessageDispatcher {
            parameters:
                @display("p=800,400;b=1200,5");
        }
        ethernet: <default("")> like IEthernetLayer if typename != "" {
            @display("p=408,450");
        }
        ieee8021q: Ieee8021qLayer {
            @display("p=700,450");
        }
        cutthrough: MessageDispatcher if enableCutthrough {
            @display("p=800,600;b=1200,5");
        }
        smartLayer: SmartLayer {

            @display("p=850,450");
        }
    connections allowunconnected:
        ethernet.lowerLayerOut --> li.in++ if exists(ethernet);
        li.out++ --> ethernet.lowerLayerIn if exists(ethernet);

        ieee8021q.lowerLayerOut --> li.in++ if exists(ieee8021q);
        li.out++ --> ieee8021q.lowerLayerIn if exists(ieee8021q);

        for i=0..sizeof(ethg)-1 {
            eth[i].cutthroughOut --> cutthrough.in++ if enableCutthrough;
            eth[i].cutthroughIn <-- cutthrough.out++ if enableCutthrough;
        }

        relayUnit.ifOut --> policy.upperLayerIn if exists(policy);
        policy.upperLayerOut --> relayUnit.ifIn if exists(policy);

        policy.lowerLayerOut --> rl.in++;
        rl.out++ --> policy.lowerLayerIn;


        // adding smart layer smart
        rl.out++ --> smartLayer.fromUpperL;
        smartLayer.toLowerL --> li.in++;
        li.out++ --> smartLayer.fromLowerL;
        smartLayer.toUpperL --> rl.in++;
        //

        ieee8021q.upperLayerOut --> rl.in++ if exists(ieee8021q);
        rl.out++ --> ieee8021q.upperLayerIn if exists(ieee8021q);

        rl.out++ --> ethernet.upperLayerIn if exists(ethernet);
        ethernet.upperLayerOut --> rl.in++ if exists(ethernet);

        relayUnit.ifOut --> li.in++ if !exists(policy);
        li.out++ --> relayUnit.ifIn if !exists(policy);

        for i=0..sizeof(ethg)-1 {
            li.out++ --> eth[i].upperLayerIn;
            li.in++ <-- eth[i].upperLayerOut;
            eth[i].phys <--> { @display("m=s"); } <--> ethg[i];
        }

        if hasStp {
            stp.relayIn <-- nr.out++; // relayUnit.stpOut;
            stp.relayOut --> nr.in++; // relayUnit.stpIn;
        }
        relayUnit.upperLayerOut --> nr.in++ if !exists(encap);
        nr.out++ --> relayUnit.upperLayerIn if !exists(encap);
        relayUnit.upperLayerOut --> encap.lowerLayerIn if exists(encap);
        encap.lowerLayerOut --> relayUnit.upperLayerIn if exists(encap);
        encap.upperLayerOut --> nr.in++ if exists(encap);
        nr.out++ --> encap.upperLayerIn if exists(encap);
}

.cc code of my new simple module:

#include "SmartLayer.h"

namespace inet {

Define_Module(SmartLayer);

void SmartLayer::initialize()
{
    // TODO - Generated method body
    this->up=0;
    this->down=0;
}

void SmartLayer::handleMessage(cMessage *msg)
{
    // TODO - Generated method body
    if (msg->arrivedOn("fromUpperL")) { // if the message is already processed then just forward it to send
            down++;
            send(msg, "toLowerL");
        } else if (msg->arrivedOn("fromLowerL")) {
            // new message arrived and needs to be processed
            up++;
            send(msg, "toUpperL");
        } else {
            error("arrived on unknown gate");
        }
        char buf[128];
        sprintf(buf, "up: %d, down: %d", up, down);
        getDisplayString().setTagArg("t", 0, buf);
}

} //namespace

`
and its ned:
`package inet.smart;

//
// TODO auto-generated module
//
simple SmartLayer
{
    parameters:
    @display("i=block/layer");
//    @class(inet::showcases::emulation::proj::projsrc::SmartLayer);

    gates:
        input fromUpperL;
        output toUpperL;
        input fromLowerL;
        output toLowerL;
}

I basically followed the answer i found here for adding a new layer but it doesn't work for me. Does anybody know what might be the problem?

I also read this and understood that maybe I shouldn't use the send() function but i didn't understand what i should do instead.

I'm sorry if the answer is obvious im pretty new to INET and OMNET in general


Solution

  • I figured a way to add the new layer to the EthernetSwitch. Basically the connections there are a bit weird and somehow it connected the relayUnit to the policy block while there was no policy block while running and it created other problems and sync issues with the indices of the gates from what i gathered while running the simulation and going into each layer and seeing what he does and where exactly it falls. So i got rid of the policy block and connected my layer straight to the relay unit.

    this is the upadated code:

    package inet.smart;
    import inet.common.MessageDispatcher;
    import inet.common.lifecycle.NodeStatus;
    import inet.common.packet.recorder.PcapRecorder;
    import inet.linklayer.configurator.L2NodeConfigurator;
    import inet.linklayer.contract.IEthernetInterface;
    import inet.linklayer.contract.IMacAddressTable;
    import inet.linklayer.contract.IMacRelayUnit;
    import inet.linklayer.contract.IPolicyLayer;
    import inet.linklayer.contract.ISpanningTree;
    import inet.linklayer.ethernet.contract.IEthernetEncapsulation;
    import inet.linklayer.ethernet.contract.IEthernetLayer;
    import inet.linklayer.ieee8021q.Ieee8021qLayer;
    import inet.networklayer.common.InterfaceTable;
    import inet.smart.SmartLayer;
    
    //
    // Model of a Smart Ethernet switch.
    //
    // TWorks just as a regular switch but has a new layer that aggregates Tensors sent in the network
    //
    module SmartSwitch
    {
        parameters:
            @networkNode();
            @labels(node,ethernet-node);
            @display("i=device/switch");
            int numPcapRecorders = default(0);
            bool hasStatus = default(false);
            bool hasStp = default(false);
            bool enableCutthrough = default(false);
            string fcsMode @enum("declared","computed") = default("declared");
            string spanningTreeProtocol = default("Stp");
            int numEthInterfaces = default(0);  // minimum number of ethernet interfaces
            eth[*].encap.typename = default("OmittedEthernetEncapsulation");
            *.fcsMode = this.fcsMode;
            **.interfaceTableModule = default(absPath(".interfaceTable"));
            **.macTableModule = default(absPath(".macTable"));
    
            relayUnit.hasStp = this.hasStp;
            encap.registerProtocol = true;
            eth[*].mac.promiscuous = default(true);
            ethernet.*.promiscuous = default(true);
    
        gates:
            inout ethg[numEthInterfaces] @labels(EtherFrame-conn);
        submodules:
            status: NodeStatus if hasStatus {
                @display("p=100,400;is=s");
            }
            l2NodeConfigurator: L2NodeConfigurator if hasStp {
                @display("p=100,300;is=s");
            }
            interfaceTable: InterfaceTable {
                @display("p=100,200;is=s");
            }
            pcapRecorder[numPcapRecorders]: PcapRecorder {
                @display("p=100,500;is=s");
            }
            macTable: <default("MacAddressTable")> like IMacAddressTable {
                @display("p=100,100;is=s");
            }
            relayUnit: <default(firstAvailable("Ieee8021dRelay","MacRelayUnit"))> like IMacRelayUnit {
                @display("p=1101,308;is=m");
            }
            li: MessageDispatcher {
                parameters:
                    @display("p=800,527;b=1200,5");
            }
            eth[sizeof(ethg)]: <default(enableCutthrough ? "EthernetCutthroughInterface" : "EthernetInterface")> like IEthernetInterface {
                parameters:
                    @display("p=250,700,row,150;q=txQueue");
            }
            smartLayer: SmartLayer {
    
                @display("p=800,308");
            }
        connections allowunconnected:
            relayUnit.ifOut --> smartLayer.fromUpperL;
            smartLayer.toLowerL --> li.in++;
            li.out++ --> relayUnit.ifIn;
    
            for i=0..sizeof(ethg)-1 {
                li.out++ --> eth[i].upperLayerIn;
                li.in++ <-- eth[i].upperLayerOut;
                eth[i].phys <--> { @display("m=s"); } <--> ethg[i];
            }
    
    }