【问题标题】:How can I combine my customize module with Omnet++INET's simple module如何将我的自定义模块与 Omnet++INET 的简单模块结合起来
【发布时间】:2016-04-14 06:25:14
【问题描述】:

由于所有简单模块的行为,如 80211 mac 层,都已在 INET 模块中定义。如果我想在mac层和网络层之间添加一个自定义层来处理网络编码。如何结合自定义模块和 INET 的简单模块?

【问题讨论】:

    标签: c++ omnet++ inet


    【解决方案1】:

    要在网络层和 MAC 层之间添加一个新模块,我建议在新项目中创建一个修改过的主机。对于OMNeT++ 4.6 和INET 3.2.4,请执行以下操作:

    1. 使用 src 和模拟目录创建一个新的 OMNeT++ 空项目。
    2. 在新项目中打开Properties | Project References 并选择 inet
    3. 右键单击src 并选择New | Simple module。叫它DummyLayer.ned
    4. 打开DummyLayer.ned并添加:

      @namespace(inet);
      import inet.linklayer.contract.INic;
      
      simple DummyLayer like INic {
      parameters:
          @display("i=block/buffer");
          // here you can add others parameter
      gates:
          input ifIn;
          output ifOut;
          input upperLayerIn;
          output upperLayerOut;
      }
      
    5. 修改DummyLayer.hDummyLayer.cc(这个模块只是传递上下的每条消息,以及递增计数器):

      // DummyLayer.h
      #include <omnetpp.h>
      namespace inet {
      class DummyLayer: public cSimpleModule {
      protected:
          virtual void initialize();
          virtual void handleMessage(cMessage *msg);
      private:
          int upNumber;
          int downNumber;
      };
      } //namespace
      
      //----------------------------------------------
      // DummyLayer.cc
      #include "DummyLayer.h"
      namespace inet {
      Define_Module(DummyLayer);
      
      void DummyLayer::initialize() {
         upNumber = 0;
         downNumber = 0;
      }
      
      void DummyLayer::handleMessage(cMessage *msg) {
        if (msg->arrivedOn("upperLayerIn")) {
            send(msg, "ifOut");
            downNumber++;
        } else if (msg->arrivedOn("ifIn")) {
            send(msg, "upperLayerOut");
            upNumber++;
        } else {
            error("Incorrect gate");
        }
        char buf[128];
        sprintf(buf, "up: %d, down: %d", upNumber, downNumber);
        getDisplayString().setTagArg("t", 0, buf);
        }
      } //namespace
      
    6. 为自己的主机创建一个新的复合模块,命名为WirelessHostEx.ned

      import inet.common.lifecycle.NodeStatus;
      import inet.linklayer.contract.IWiredNic;
      import inet.linklayer.contract.IWirelessNic;
      import inet.linklayer.loopback.LoopbackInterface;
      import inet.mobility.contract.IMobility;
      import inet.networklayer.contract.IRoutingTable;
      import inet.networklayer.common.InterfaceTable;
      import inet.networklayer.contract.INetworkLayer;
      import inet.power.contract.IEnergyStorage;
      import inet.power.contract.IEnergyGenerator;
      import inet.applications.contract.IPingApp;
      import inet.applications.contract.ISCTPApp;
      import inet.applications.contract.ITCPApp;
      import inet.applications.contract.IUDPApp;
      import inet.transportlayer.contract.ISCTP;
      import inet.transportlayer.contract.ITCP;
      import inet.transportlayer.contract.IUDP;
      import inet.node.inet.INetworkNode;
      
      module WirelessHostEx like INetworkNode
      {
          parameters:
              @networkNode;
              @display("i=device/wifilaptop");
              @labels(wireless-node);
              bool hasStatus = default(false);
              int numExtInterfaces = default(0);
              int numRadios = 1;
              int numTunInterfaces = default(0);
              string mobilityType = default(numRadios > 0 ? "StationaryMobility" : "");
              string networkLayerType = default("IPv4NetworkLayer");
              string routingTableType = default("IPv4RoutingTable");
              bool forwarding = default(true);
              bool multicastForwarding = default(false);
              string energyStorageType = default("");
              string energyGeneratorType = default("");
              routingTable.forwarding = forwarding;
              routingTable.multicastForwarding = multicastForwarding;  
              *.interfaceTableModule = default(absPath(".interfaceTable"));
              *.routingTableModule = default(routingTableType != "" ? absPath(".routingTable") : "");
              *.energySourceModule = default(energyStorageType != "" ? absPath(".energyStorage") : "");
              *.mobilityModule = default(mobilityType != "" ? absPath(".mobility") : "");
              int numTcpApps = default(0);
              int numUdpApps = default(0); 
              int numPingApps = default(0); 
              bool hasTcp = default(numTcpApps > 0);
              bool hasUdp = default(numUdpApps > 0);
              string tcpType = default(firstAvailableOrEmpty("TCP", "TCP_lwIP", "TCP_NSC"));  // tcp implementation (e.g. ~TCP, ~TCP_lwIP, ~TCP_NSC) or ~TCPSpoof
              string udpType = default(firstAvailableOrEmpty("UDP"));
              forwarding = default(false);  // disable routing by default
              networkLayer.proxyARP = default(false);
          gates:
              input radioIn[numRadios] @directIn;
              inout pppg[] @labels(PPPFrame-conn);
              inout ethg[] @labels(EtherFrame-conn);
          submodules:
              status: NodeStatus if hasStatus {
                  @display("p=50,50");
              }
              energyStorage: <energyStorageType> like IEnergyStorage if energyStorageType != "" {
                  parameters:
                      @display("p=50,100;i=block/plug;is=s");
              }
              energyGenerator: <energyGeneratorType> like IEnergyGenerator if energyGeneratorType != "" {
                  parameters:
                      @display("p=50,150;i=block/plug;is=s");
              }
              mobility: <mobilityType> like IMobility if mobilityType != "" {
                  parameters:
                      @display("p=53,200");
              }
              networkLayer: <networkLayerType> like INetworkLayer {
                  parameters:
                      @display("p=329,287;q=queue");
              }
              routingTable: <routingTableType> like IRoutingTable if routingTableType != "" {
                  parameters:
                      @display("p=53,250;is=s");
              }
              interfaceTable: InterfaceTable {
                  parameters:
                      @display("p=53,300;is=s");
              }
              lo0: LoopbackInterface {
                  @display("p=78,406");
              }
              wlan[numRadios]: <default("Ieee80211Nic")> like IWirelessNic {
                  parameters:
                      @display("p=216,406,row,60;q=queue");
              }
              eth[sizeof(ethg)]: <default("EthernetInterface")> like IWiredNic {
                  parameters:
                      @display("p=368,406,row,60;q=txQueue");
              }
              ppp[sizeof(pppg)]: <default("PPPInterface")> like IWiredNic {
                  parameters:
                      @display("p=558,406,row,60;q=txQueue");
              }
              tcpApp[numTcpApps]: <> like ITCPApp {
                  parameters:
                      @display("p=147,54,row,60");
              }
              tcp: <tcpType> like ITCP if hasTcp {
                  parameters:
                      @display("p=147,141");
              }
              udpApp[numUdpApps]: <> like IUDPApp {
                  parameters:
                      @display("p=329,54,row,60");
              }
              udp: <udpType> like IUDP if hasUdp {
                  parameters:
                      @display("p=329,141");
              }
              pingApp[numPingApps]: <default("PingApp")> like IPingApp {
                  parameters:
                      @display("p=635,141,row,60");
              }
              dummy: DummyLayer {
                  @display("p=273,350");
              }
          connections allowunconnected:
              radioIn[0] --> { @display("m=s"); } --> wlan[0].radioIn;
              // the order of connections is important here
              wlan[0].upperLayerOut --> dummy.ifIn;
              dummy.upperLayerOut --> networkLayer.ifIn++;
              wlan[0].upperLayerIn <-- dummy.ifOut;
              dummy.upperLayerIn <-- networkLayer.ifOut++;
              networkLayer.ifOut++ --> lo0.upperLayerIn;
              lo0.upperLayerOut --> networkLayer.ifIn++;
              for i=0..sizeof(ethg)-1 {
                  ethg[i] <--> { @display("m=s"); } <--> eth[i].phys;
                  eth[i].upperLayerOut --> networkLayer.ifIn++;
                  eth[i].upperLayerIn <-- networkLayer.ifOut++;
              }
              for i=0..sizeof(pppg)-1 {
                  pppg[i] <--> { @display("m=s"); } <--> ppp[i].phys;
                  ppp[i].upperLayerOut --> networkLayer.ifIn++;
                  ppp[i].upperLayerIn <-- networkLayer.ifOut++;
              }
              for i=0..numTcpApps-1 {
                  tcpApp[i].tcpOut --> tcp.appIn++;
                  tcpApp[i].tcpIn <-- tcp.appOut++;
              }
              tcp.ipOut --> networkLayer.transportIn++ if hasTcp;
              tcp.ipIn <-- networkLayer.transportOut++ if hasTcp;
              for i=0..numUdpApps-1 {
                  udpApp[i].udpOut --> udp.appIn++;
                  udpApp[i].udpIn <-- udp.appOut++;
              }
              udp.ipOut --> networkLayer.transportIn++ if hasUdp;
              udp.ipIn <-- networkLayer.transportOut++ if hasUdp;
              for i=0..numPingApps-1 {
                  networkLayer.pingOut++ --> pingApp[i].pingIn;
                  networkLayer.pingIn++ <-- pingApp[i].pingOut;
              }
      }
      

    一个自己的主机模块是必要的,因为来自INETStandardHost会自动创建MAC和网络层之间的连接,并且不可能在这些层之间添加自己的模块。

    1. 创建一个网络(用于测试):

      import inet.networklayer.configurator.ipv4.IPv4NetworkConfigurator;
      import inet.physicallayer.ieee80211.packetlevel.Ieee80211ScalarRadioMedium;
      import inet.node.wireless.AccessPoint;
      
      network WirelessNetwork {
          submodules:
              configurator: IPv4NetworkConfigurator {
                  @display("p=33,81");
              }
              radioMedium: Ieee80211ScalarRadioMedium {
                  @display("p=33,30");
              }
              node0: WirelessHostEx {
                  @display("p=128,121");
              }
              node1: WirelessHostEx {
                  @display("p=384,115");
              }
              ap: AccessPoint {
                  @display("p=273,54");
              }
      }
      
    2. 修改omnetpp.ini:

      [General]
      network = WirelessNetwork
      
      // node0 will send ping to node1
      **.node0.numPingApps = 1
      **.node0.pingApp[0].destAddr = "node1" // using IP address here is allowed too
      

    启动模拟后可以看到在每个主机dummyLayer 发送消息转发。

    【讨论】:

    • 非常感谢 Jerzy。它对我有很大帮助。阅读代码后,我有一些问题。因为我不熟悉NED的语言,所以你能解释一下wlan[numRadios]: &lt;default("Ieee80211Nic")&gt; like IWirelessNic这样的代码吗? 之类的是什么意思。有没有像 NED 的语言一样的语言?而在 DummyLayer.cc 中,getDisplayString().setTagArg("t", 0, buf); 是什么意思?
    • wlan[numRadios]: &lt;default("Ieee80211Nic")&gt; like IWirelessNic 行表示:创建 wlan 模块的numRadios 实例,每个Ieee80211Nic NED 类型,除非在omnetpp.ini 中选择了另一种类型。要选择另一种类型的wlan 模块,应写入omnetpp.ini,例如:**.wlan[*].typename = "IdealWirelessNic" 其中IdealWirelessNic 是必须从IWirelessNic 继承的复合模块的名称。 typename 词是 NED 语法的一部分,请参阅 OMNeT++ 手册。
    • getDisplayString().setTagArg("t", 0, buf); 行只是在模块图标上方添加了来自buf 的文本。显示字符串在 OMNeT++ 手册第 8.1 章中有详细描述。一般来说,显示字符串允许向模块的图标添加任何文本,以及更改颜色、位置、添加工具提示等。
    • 所以代码&lt;default("Ieee80211Nic")&gt; like IWirelessNic 表示Ieee80211Nic 继承自IWirelessNic ?正如你所说的linegetDisplayString().setTagArg("t", 0, buf);在模块图标上方添加了一个文本表单buf,但是我在哪里可以看到它?
    • 嗨,杰兹。当我查看主机内部并开始模拟时,我发现传输只是基于mac层而不是通过dummy层。此模型中使用的协议是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多