Scalable Simulation Framework
How to write DML network models, continued

back to list of tutorials...

Simple network with two routers: IP and packet queues

At this point you should be familiar with the first tutorial on host protocol configuration and DML object-oriented support for attribute substitution and inheritance.

This tutorial shows how to specify the default routes in very simple networks without using the routing protocols (which are the subject of the following tutorial), and how to globally specify a traffic pattern in a network with several client and server hosts.

The operation of the SSFNet's IP protocol and packet queueing is summarized at the end.

After reading this tutorial, you should examine the directory ssfnet/src/SSF/OS/TCP/test/tcpdumpTest in the SSFNet distribution to see how to collect the packets in the tcpdump format from a network interface, and how to use the utility class SSF.OS.DumpPro to extract ascii data from the tcpdump file.

This network has two IP routers, R1 and R2, and on each side it has one client host "c" and one server host "s" connected by point-to-point links to the router. Clients and servers use a trivial protocol to request a single file transfer like in the "two hosts" example discussed in the previous tutorial.

We show how to specify the following traffic scenario: the "left side" client can request data from any of the two servers with equal probability, but the "right side" client can request the data only from the server on the opposite (left) side.

The IP address allocation is done automatically by class SSF.Net.Net when the model is initialized; and static routing tables are constructed when IP protocol sessions are initialized just before the start of the simulation. Therefore, here only the default route for each router and host needs to be explicitely specified in DML, as each IP session creates a table of networks (links) attached to host's or router's interfaces at the initialization stage.

UDP example: See the configuration file udpXnet.dml (opens in a new window) for this network, with a simple client-server UDP workload generation generating a streaming UDP traffic. This case is discussed in some detail below.

TCP example: See the configuration file tcpXnet.dml for this network, with clients using TCP (opens in a new window).

analysis of udpXnet.dml

The id numbers of hosts, routers and interfaces in this network are shown in the ascii art:
#  udpXnet.dml
#  2 X 2  network with UDP clients and servers, interfaces in NHI addressing
#
#   client 11(0)------1(1)                           2(1)------12(0) client
#                        \                          /
#                        [R1] 1(0)------------2(0)[R2]
#                        /                          \
#   server 21(0)------1(2)                           2(2)------22(0) server

The first new kind of DML code fragment specifies arrays of objects:

  # ROUTERS AND POINT-TO-POINT LINKS -----------------------------------
    
    router [ 
      idrange [from 1 to 2]
      graph [ProtocolSession [name ip use SSF.OS.IP]]
      interface [ id 0 buffer 8000 _extends .dictionary.100BaseT]
      interface [ idrange [from 1 to 3] buffer 16000 _extends .dictionary.10BaseT]
      route [dest default interface 0]
    ]
Above we specified two identical routers as elements of an array with id indices 1 and 2 using the attribute idrange.

We used the same construct to specify that each router has 3 10BaseT interfaces with id = 1,2,3. Note that we specified 3 10BaseT interfaces but only the first two are actually attached to point-to-point links. This is just to show that it is legal to have unconnected ("down") interfaces in SSFNet models - it will prove to be a very convenient trick for preconfiguring a library of networks that are later connected together.

The next new thing is the attribute interface.buffer, here specifying buffer 8000. This is the size of interface output queue buffer in bytes.

Finally, using the attribute route we specified that if an IP packet's address is not in the IP routing table, the router should forward it via interface with id=0. If you look at the the file udpXnet.dml, you'll see that the link connecting the two routers is attached to interface 0 of router 1 and to interface 0 of router 2: Thus, for each router dest default simply says "if a packet's destination IP address is not on any link directly connected to a router, send it to the other router".


The other new DML construct in this tutorial section is the array notation for multiple server NHI addresses:

 # CLIENTS-SERVER TRAFFIC PATTERN --------------------------------------
   
    # "left side" client can request data from any server
    # "right side" client can request data only from "left side" server
    
    traffic [
      pattern [
        client 11
        servers [nhi_range [from 21(0) to 22(0)] port 1600]
      ]
      pattern [
        client 12
        servers [nhi 21(0) port 1600]
      ]
    ]

The expression

servers [nhi_range [from 21(0) to 22(0)] port 1600]
is the array notation equivalent to two separate single-server addresses:
servers [nhi 21(0) port 1600]
servers [nhi 22(0) port 1600]
Note that in the above array notation the host id is the running index, while the interface id remains the same for all array elements. The client's session udpStreamClient chooses one server uniformly at random from the list specified by the servers attributes.


SSF.OS.IP, SSF.Net.NIC and packet queues

In SSFNet 1.1 the IP ProtocolSession (implemented in class SSF.OS.IP) provides the following services:

  1. It contains the list of interfaces installed in a host or router, and the IP addresses of interfaces that are attached to links.
  2. It contains the routing table. SSF.OS.IP itself does not compute the routes, and "by itself" only knows the addresses of networks directly attached to the interfaces. Routes to other destination are either computed by a routing protocol such as SSF.OS.OSPF or SSF.OS.BGP4 (if installed in the ProtocolGraph), or explicitly specified by the route or nhi_route attributes in the host/router (see SSFNet 1.1 DML Reference for full details).
  3. It decrements the TTL field in the IP header and drop IP packets whose TTL field reaches zero.
  4. It pushes an outgoing IP packet to the interface obtained from the routing table, or drops it if no route is found.
  5. It examines the destination IP address of an incoming IP packet, and:
    • if the destination is this host/router, it will push up the packet to the ProtocolSession identified in the protocol number field in the IP header,
    • if the destination is not this host/router, it will push down the packet to the interface obtained from the routing table, or drop it if no route is found.

SSF.OS.IP does not maintain outgoing packet queues. It immediately pushes an outgoing packet to the "network interface card" implemented in class SSF.Net.NIC.

SSFNet models the Internet at the logical IP level of detail, and SSF.OS.IP does not implement packet fragmentation and reassembly.

The NIC is a bottom-level pseudo-protocol that maintains a pair of SSF in/outChannels to the world outside the protocol graph. It represents the border between the internal operation of the protocol graph (characterized by the push() of ProtocolMessages between ProtocolSessions in zero elapsed simulation time) and the IP packet transmission to external network nodes (characterized by sending of PacketEvents in positive elapsed simulation time).

IP packets that arrive on the NIC's IN channel are immediately pushed up to the IP protocol session.

IP packets that are pushed down from IP to NIC are handed to an instance of class packetQueue, which schedules event transmission on behalf of the NIC. By default, this queue manager is of type dropTailQueue, but the modeler may write another class to be used and load it from DML configuration using the method NIC.config().

SSF.Net.dropTailQueue and packet transmission timing

Logical model: The dropTailQueue capacity is specified by the interface.buffer attribute (infinite capacity if omitted). The timing resolution is at the bit level: bits go out one by one at the NIC's bitrate. If NIC attempts to enqueue a message whose size is larger than the currently available free buffer space, the message is dropped.

Transmit a message: Each interface tracks its "queueing delay," which accumulates as packets are written out onto the link. Each packet contributes its transmission time (size in bits / bitrate) to the queueing delay of future packets. This guarantees that the interface will never exceed its configured bitrate.

Warning: if Net.frequency (ticks per second) is smaller than NIC's bitrate (bits/sec) the delay calculations are not accurate enough to obtain correct value of number of bits in the buffer.

Fairness among competing outgoing flows is an entirely separate issue; and is not dealt with. The packets are enqueued in the order they are pushed to the NIC by IP.

 

continue the tutorials...