How to insert a new module (simple FIFO, sFIFO) into NCTUNS?

 

[Background]

1.      This is a simplified version of First In First Out (Drop Tail) Queue. The codes were mainly re-written from original FIFO.cc/FIFO.h.

2.      Please refer to DeveloperManual.pdf which is under /root/ NCTUns-6.0/doc/Developer.Manual folder. Take a closer look at the chapter 2 and chapter 5.

 

[Preparation]

1.      Change the path to /root/NCTUns-6.0/src/nctuns/module/ps

2.      Create a new folder named sFIFO.

3.      Prepare 3 files under sFIFO.

(sfifo.h)

#ifndef __NCTUNS_sfifo_h__

#define __NCTUNS_sfifo_h__

 

#include <object.h>

#include <packet.h>

#include <timer.h>

 

/* Define Interface Queue for every Interface */

struct ifqueue {

        ePacket_          *ifq_head; /* head of ifq */

        ePacket_          *ifq_tail; /* tail of ifq */

        int                    ifq_len;   /* current queue length */

        int                    ifq_maxlen;/* max queue length */

        int                    ifq_drops; /* drops count */

};

 

 

/* Define Macros for IFq */

#define IF_QFULL(ifq)           ((ifq)->ifq_len >= (ifq)->ifq_maxlen)

#define IF_DROP(ifq)            ((ifq)->ifq_drops++)

#define IF_ENQUEUE(ifq, m) { \

        if ((ifq)->ifq_tail == 0) \

                (ifq)->ifq_head = m; \

        else \

                (ifq)->ifq_tail->next_ep = m; \

        (ifq)->ifq_tail = m; \

        (ifq)->ifq_len++; \

}

#define IF_PREPEND(ifq, m) { \

        (m)->next_ep = (ifq)->ifq_head; \

        if ((ifq)->ifq_tail == 0) \

                (ifq)->ifq_tail = (m); \

        (ifq)->ifq_head = (m); \

        (ifq)->ifq_len++; \

}

#define IF_DEQUEUE(ifq, m) { \

        (m) = (ifq)->ifq_head; \

        if (m) { \

                if (((ifq)->ifq_head = (m)->next_ep) == 0) \

                        (ifq)->ifq_tail = 0; \

                (m)->next_ep = 0; \

                (ifq)->ifq_len--; \

        } \

}

 

 

class sfifo : public NslObject {

 

 private:

 

        struct ifqueue          if_snd; /* output interface queue */

 

 protected:

       int                   intrq(MBinder *);

 

 public:

 

        sfifo(u_int32_t type, u_int32_t id, struct plist* pl, const char *name);

        ~sfifo();

 

        int                    init();

        int                    recv(ePacket_ *);

        int                    send(ePacket_ *);

};

 

 

#endif /* __NCTUNS_sfifo_h__ */

 

(sfifo.cc)

#include <stdio.h>

#include <stdlib.h>

#include <assert.h>

#include <fcntl.h>

#include <unistd.h>

#include <sys/stat.h>

#include <nctuns_api.h>

#include <ps/sFIFO/sfifo.h>

#include <exportStr.h>

#include <mbinder.h>

 

MODULE_GENERATOR(sfifo);

 

sfifo::sfifo(u_int32_t type, u_int32_t id, struct plist* pl, const char *name)

                : NslObject(type, id, pl, name)

{

        /* disable flow control */

        s_flowctl = DISABLED;

        r_flowctl = DISABLED;

 

        /* initialize interface queue */

        if_snd.ifq_head = if_snd.ifq_tail = 0;

        if_snd.ifq_len = 0;

        if_snd.ifq_drops = 0;

 

        /* bind variable */

        vBind("max_qlen", &if_snd.ifq_maxlen);

 

        if_snd.ifq_len = 0;

        if_snd.ifq_maxlen = 50; /* by default */

}

 

sfifo::~sfifo() {

 

}

 

 

int sfifo::init() {

 

        int       (NslObject::*upcall)(MBinder *);

 

        /* set upcall */

  upcall = (int (NslObject::*)(MBinder *))&sfifo::intrq;

  sendtarget_->set_upcall(this, upcall);

  return(1);

}

 

int sfifo::send(ePacket_ *pkt) {

 

        assert(pkt&&pkt->DataInfo_);

        /*

         * If Module-Binder Queue(MBQ) is full, we should

         * insert the outgoing packet into the interface

         * queue. If MBQ is not full, we can call the

         * put() or NslObject::send() method to pass the

         * outgoing packet to next module.

         */

        if( sendtarget_->qfull() ) {

                /* MBQ is full, insert to ifq */

                if (IF_QFULL(&if_snd)) {

                        /* ifq full, drop it! */

                        IF_DROP(&if_snd);

                        freePacket(pkt);

                        return(1);

                }

                /* otherwise, ifq not full, insert it */

                IF_ENQUEUE(&if_snd, pkt);

                return(1);

        }

        else {

                /*

                 * MBQ is not full, pass outgoing packet

                 * to next module.

                 */

                return(NslObject::send(pkt));

        }

}

 

 

int sfifo::recv(ePacket_ *pkt) {

 

        /* Just by pass incoming packet */

        assert(pkt&&pkt->DataInfo_);

        return(NslObject::recv(pkt));

}

 

 

int sfifo::intrq(MBinder *port) {

 

        ePacket_  *pkt;

 

        /*

         * Push the packet in the interface queue

         * to the MBQ. Whenever the pakcet in the

         * MBQ is sent, the scheduler will call this

         * member function to give sfifo module a

         * chance to send the next packet in the

         * interface queue.

         */

        IF_DEQUEUE(&if_snd, pkt);

 

        if (pkt != NULL) {

                /*

                 * If still exist packet in the interface

                 * queue, we try to push it to the MBQ,

                 */

                assert(sendtarget_->enqueue(pkt) == 0);

        }

        return(1);

}

 

(Makefile)

#

# Makefile for the NCTUns engine module

#

 

obj-y        = sfifo.o

 

 

4.      Change path to /root/NCTUns-6.0/src/nctuns/module/ps and edit the Makefile

(add sFIFO/  \ in the obj-y)

 

 

5.      Change path to /root/NCTUns-6.0/src/nctuns and edit the nctuns.cc

add REG_MODULE(“sFIFO”, sfifo);

 

6.      Recompile the nctuns

 

7.      If nothing wrong, sfifo is inserted into NCTUNS.

 

[Test]

1.      Create a topology that contains two wired nodes.

2.      In the “E” edit mode, add rtcp program in node 2 and stcp program in node 1.

 

 

3.      Click “R” to change to Run mode. But don’t click Simulation/Run to start simulation. Open a terminal to edit the tcl file. (Assume this project is named test)

  

   (change FIFO to sFIFO and remove some redundant functions)

Set RandomNumberSeed = 0

Set SimSpeed = AS_FAST_AS_POSSIBLE

Set TickToNanoSec = 100

Set WireLogFlag = on

Set WirelessLogFlag = on

Set GPRSLogFlag = on

Set OphyLogFlag = on

Set WiMAXLogFlag = on

Set MobileWIMAXLogFlag = on

Set MobileRelayWIMAXLogFlag = on

Set MR_WIMAX_NT_LogFlag = on

Set WiMAXChannelCoding = Off

Set WiFiChannelCoding = Off

Set WAVEChannelCoding = Off

Set MobileWIMAXChannelCoding = Off

Set MobileRelayWIMAXChannelCoding = Off

Set MR_WIMAXChannelCoding_NT = Off

Set DVBChannelCoding = off

Set SatLogFlag = off

Set DynamicMovingPath = Off

Set OnlinePacketTransmission = Off

Set GdbStart = off

 

 

Create Node 1 as HOST with name = HOST1

        Define port 1

                Module Interface : Node1_Interface_LINK_1

                        Set Node1_Interface_LINK_1.guitag_ordinary = yes

                        Set Node1_Interface_LINK_1.ip = 1.0.1.1

                        Set Node1_Interface_LINK_1.netmask = 255.255.255.0

 

                Module ARP : Node1_ARP_LINK_1

                        Set Node1_ARP_LINK_1.guitag_ordinary = yes

                        Set Node1_ARP_LINK_1.arpMode = RunARP

                        Set Node1_ARP_LINK_1.flushInterval = 3000

                        Set Node1_ARP_LINK_1.ArpTableFileName = test.arp

 

                Module sFIFO : Node1_sFIFO_LINK_1

                        Set Node1_sFIFO_LINK_1.max_qlen = 50

 

                Module MAC8023 : Node1_MAC8023_LINK_1

                        Set Node1_MAC8023_LINK_1.guitag_ordinary = yes

                        Set Node1_MAC8023_LINK_1.mac = 0:1:0:0:0:2

                        Set Node1_MAC8023_LINK_1.PromisOpt = off

                        Set Node1_MAC8023_LINK_1.mode = full

                        Set Node1_MAC8023_LINK_1.log = off

                        Set Node1_MAC8023_LINK_1.logInterval = 1

                        Set Node1_MAC8023_LINK_1.NumCollision = off

                        Set Node1_MAC8023_LINK_1.NumUniInPkt = off

                        Set Node1_MAC8023_LINK_1.NumUniOutPkt = off

                        Set Node1_MAC8023_LINK_1.NumUniInOutPkt = off

                        Set Node1_MAC8023_LINK_1.NumBroInPkt = off

                        Set Node1_MAC8023_LINK_1.NumBroOutPkt = off

                        Set Node1_MAC8023_LINK_1.NumBroInOutPkt = off

                        Set Node1_MAC8023_LINK_1.NumDrop = off

                        Set Node1_MAC8023_LINK_1.InThrput = off

                        Set Node1_MAC8023_LINK_1.OutThrput = off

                        Set Node1_MAC8023_LINK_1.InOutThrput = off

                        Set Node1_MAC8023_LINK_1.UniInLogFile = test.8023_N1_P1_UniIn.log

                        Set Node1_MAC8023_LINK_1.UniOutLogFile = test.8023_N1_P1_UniOut.log

                        Set Node1_MAC8023_LINK_1.UniInOutLogFile = test.8023_N1_P1_UniInOut.log

                        Set Node1_MAC8023_LINK_1.BroInLogFile = test.8023_N1_P1_BroIn.log

                        Set Node1_MAC8023_LINK_1.BroOutLogFile = test.8023_N1_P1_BroOut.log

                        Set Node1_MAC8023_LINK_1.BroInOutLogFile = test.8023_N1_P1_BroInOut.log

                        Set Node1_MAC8023_LINK_1.CollLogFile = test.8023_N1_P1_Coll.log

                        Set Node1_MAC8023_LINK_1.DropLogFile = test.8023_N1_P1_Drop.log

                        Set Node1_MAC8023_LINK_1.InThrputLogFile = test.8023_N1_P1_InThrput.log

                        Set Node1_MAC8023_LINK_1.OutThrputLogFile = test.8023_N1_P1_OutThrput.log

                        Set Node1_MAC8023_LINK_1.InOutThrputLogFile = test.8023_N1_P1_InOutThrput.log

 

                Module TCPDUMP : Node1_TCPDUMP_LINK_1

                        Set Node1_TCPDUMP_LINK_1.guitag_ordinary = yes

 

                Module Phy : Node1_Phy_LINK_1

                        Set Node1_Phy_LINK_1.guitag_ordinary = yes

                        Set Node1_Phy_LINK_1.Bw = 10

                        Set Node1_Phy_LINK_1.BER = 0.0

                        Set Node1_Phy_LINK_1.PropDelay = 1

                        Set Node1_Phy_LINK_1.linkfail = off

                        Set Node1_Phy_LINK_1.linkfailFileName = test.phy_N1_P1.linkfail

 

                Module Link : Node1_LINK_1

                        Set Node1_LINK_1.guitag_remotenode = yes

 

 

                Bind Node1_Interface_LINK_1 Node1_ARP_LINK_1

                Bind Node1_ARP_LINK_1 Node1_sFIFO_LINK_1

                Bind Node1_sFIFO_LINK_1 Node1_MAC8023_LINK_1

                Bind Node1_MAC8023_LINK_1 Node1_TCPDUMP_LINK_1

                Bind Node1_TCPDUMP_LINK_1 Node1_Phy_LINK_1

                Bind Node1_Phy_LINK_1 Node1_LINK_1

        EndDefine

 

EndCreate

 

Create Node 2 as HOST with name = HOST2

        Define port 1

                Module Interface : Node2_Interface_LINK_1

                        Set Node2_Interface_LINK_1.guitag_ordinary = yes

                        Set Node2_Interface_LINK_1.ip = 1.0.1.2

                        Set Node2_Interface_LINK_1.netmask = 255.255.255.0

 

                Module ARP : Node2_ARP_LINK_1

                        Set Node2_ARP_LINK_1.guitag_ordinary = yes

                        Set Node2_ARP_LINK_1.arpMode = RunARP

                        Set Node2_ARP_LINK_1.flushInterval = 3000

                        Set Node2_ARP_LINK_1.ArpTableFileName = test.arp

 

                Module sFIFO : Node2_sFIFO_LINK_1

                        Set Node2_sFIFO_LINK_1.max_qlen = 50

 

                Module MAC8023 : Node2_MAC8023_LINK_1

                        Set Node2_MAC8023_LINK_1.guitag_ordinary = yes

                        Set Node2_MAC8023_LINK_1.mac = 0:1:0:0:0:3

                        Set Node2_MAC8023_LINK_1.PromisOpt = off

                        Set Node2_MAC8023_LINK_1.mode = full

                        Set Node2_MAC8023_LINK_1.log = off

                        Set Node2_MAC8023_LINK_1.logInterval = 1

                        Set Node2_MAC8023_LINK_1.NumCollision = off

                        Set Node2_MAC8023_LINK_1.NumUniInPkt = off

                        Set Node2_MAC8023_LINK_1.NumUniOutPkt = off

                        Set Node2_MAC8023_LINK_1.NumUniInOutPkt = off

                        Set Node2_MAC8023_LINK_1.NumBroInPkt = off

                        Set Node2_MAC8023_LINK_1.NumBroOutPkt = off

                        Set Node2_MAC8023_LINK_1.NumBroInOutPkt = off

                        Set Node2_MAC8023_LINK_1.NumDrop = off

                        Set Node2_MAC8023_LINK_1.InThrput = off

                        Set Node2_MAC8023_LINK_1.OutThrput = off

                        Set Node2_MAC8023_LINK_1.InOutThrput = off

                        Set Node2_MAC8023_LINK_1.UniInLogFile = test.8023_N2_P1_UniIn.log

                        Set Node2_MAC8023_LINK_1.UniOutLogFile = test.8023_N2_P1_UniOut.log

                        Set Node2_MAC8023_LINK_1.UniInOutLogFile = test.8023_N2_P1_UniInOut.log

                        Set Node2_MAC8023_LINK_1.BroInLogFile = test.8023_N2_P1_BroIn.log

                        Set Node2_MAC8023_LINK_1.BroOutLogFile = test.8023_N2_P1_BroOut.log

                        Set Node2_MAC8023_LINK_1.BroInOutLogFile = test.8023_N2_P1_BroInOut.log

                        Set Node2_MAC8023_LINK_1.CollLogFile = test.8023_N2_P1_Coll.log

                        Set Node2_MAC8023_LINK_1.DropLogFile = test.8023_N2_P1_Drop.log

                        Set Node2_MAC8023_LINK_1.InThrputLogFile = test.8023_N2_P1_InThrput.log

                        Set Node2_MAC8023_LINK_1.OutThrputLogFile = test.8023_N2_P1_OutThrput.log

                        Set Node2_MAC8023_LINK_1.InOutThrputLogFile = test.8023_N2_P1_InOutThrput.log

 

                Module TCPDUMP : Node2_TCPDUMP_LINK_1

                        Set Node2_TCPDUMP_LINK_1.guitag_ordinary = yes

 

                Module Phy : Node2_Phy_LINK_1

                        Set Node2_Phy_LINK_1.guitag_ordinary = yes

                        Set Node2_Phy_LINK_1.Bw = 10

                        Set Node2_Phy_LINK_1.BER = 0.0

                        Set Node2_Phy_LINK_1.PropDelay = 1

                        Set Node2_Phy_LINK_1.linkfail = off

                        Set Node2_Phy_LINK_1.linkfailFileName = test.phy_N2_P1.linkfail

 

                Module Link : Node2_LINK_1

                        Set Node2_LINK_1.guitag_remotenode = yes

 

 

                Bind Node2_Interface_LINK_1 Node2_ARP_LINK_1

                Bind Node2_ARP_LINK_1 Node2_sFIFO_LINK_1

                Bind Node2_sFIFO_LINK_1 Node2_MAC8023_LINK_1

                Bind Node2_MAC8023_LINK_1 Node2_TCPDUMP_LINK_1

                Bind Node2_TCPDUMP_LINK_1 Node2_Phy_LINK_1

                Bind Node2_Phy_LINK_1 Node2_LINK_1

        EndDefine

 

EndCreate

 

Connect WIRE 1.Node1_LINK_1 2.Node2_LINK_1

 

 

 

Run 50

 

4.      After editing the test.tcl, click Simulation/Run to start simulation.

 

5.      After simulation, not wrong is ok.

 

 

 

p.s.

If you want to change the sFIFO queue directly from GUI, please refer to DeveloperManual.pdf and add the codes under /usr/local/nctuns/etc/mdf/PSBM.

 

Dr. Chih-Heng Ke (http://csie.nqu.edu.tw/smallko), smallko@gmail.com

Department of Computer Science and Information Engineering, National Quemoy University, Taiwan