Scalable Simulation Framework
Composition of larger networks:
Net import, address hierarchy, routing

back to list of tutorials...

Net inclusion and topological addressing

This tutorial shows how to use the included Net attributes to compose larger networks from a library of pre-configured Nets, how to install the OSPF protocol in the routers for automatic generation of the routing tables, and a few other new concepts. Net inclusion is a very powerful feature of SSFNet that significantly simplifies design validation: first validate smaller components, then bring them together. Below is a diagram of a simplified "campus network" that will be explained in detail.

Open (or print) the DML configuration file campus2auto.dml now:

(will open in new window), and examine it side-by-side with the graphical representation of the network.

campus2auto. The complete model - named "campus2auto.dml" - is constructed by importing Nets 0 - 3, and specifying a couple of routers and a few links to join the imported Nets together. The routers and hosts are represented by rectangles annotated by their topological addresses in the fully expanded NHI notation relative to the top-level network. The ovals represent LANs, i.e. level 2 links with more than two interfaces attached. [ PDF version for printing. ]

The Net inclusion discussed in this tutorial also illustrates the benefits of topological NHI addressing together with automatic IP address generation provided by SSFNet. Below is a fragment of the SSFNet Reference Manual illustrating the concept:

The basis of all addressing schemes is network topology, and in SSFNet, NHI (Net, Host, Interface) strings are the basic notation for identifying nodes and edges in the network graph.

Each Net, Host, Router, and NIC must either specify an integer ID (the id attribute) or an integer ID range (the idrange attribute). At a given level (e.g., within a given Net) the IDs and ID ranges of sub-Nets may not overlap; they need not be exactly in sequential order, however. The same is true of Hosts and Routers, and of NICs within their respective address spaces (nearest enclosing Net, and enclosing Host, respectively).

The global NHI address of a network is created by concatenating the ID of each network from the outermost to the innermost, separated by colons (":"). Similarly, the global NHI address of a host or router is created by concatenating the global NHI address of its containing network with the Host ID, separated by a colon. Finally, the NHI address of a NIC is created by adding the NIC ID, in parenthesis, to the containing Host NIC address.

For example, in this nested Net:

Net [
  Net [id 7 
    Net [id 88
      host [id 19 ...
            interface [id 2]
      ]
    ]
  ]
]

The toplevel (root) Net has no explicit NHI address, the next Net has address 7, and the innermost Net has address 7:88. The Host has NHI address 7:88:19, and the interface has NHI address 7:88:19(2).

NHI numbers are manually specified by the modeler's use of ID attributes. The ids have integer values that need not be sequentially assigned, although it is recommended. The component link does not have the id attribute. The IDs are never automatically generated; omitting an id or idrange attribute at any level other than the topmost level is an error. As per the Net schema, the root Net should not have an id, idrange, or cidr address specified; only imported Nets acquire these.

Configuration database campus2auto.dml

Let us now examine the model configuration file campus2auto.dml explaining the new attributes that were not covered in the preceding tutorials. First, notice that the file has four top-level attributes: _schema, Net, networks, dictionary. The last two, networks and dictionary, are used to store reusable components, that are brought into the model via substitution or inheritance in order to make the configuration more compact, and less susceptible to design errors. We note here that attributes networks and dictionary could in fact be stored in separate file(s), to further promote the reuse of pre-configured components.

# campus2auto.dml

_schema [ _find .schemas.Net]

Net [
  frequency 100000000

  Net [id 0 _extends .networks.network0.Net]
  Net [id 1 _extends .networks.network1.Net]
  Net [id 2 _extends .networks.network2.Net]
  Net [id 3 _extends .networks.network3.Net]

     ....stuff omitted

Automatic validation of Net configuration database

The first non-commented line:

_schema [ _find .schemas.Net]

directs the DML parser to validate the network configuration, that is to verify that all attributes have required value types (string, float or int), that mandatory attributes are indeed present, etc., etc. The validation is performed against the Net's master schema that is stored in the runtime configuration database in the attribute .schemas.Net. That schema is loaded from a DML file specified on command line when a simulation is executed, see "How to run SSFNet models" for details; and in SSFNet 1.1 the master schema is in the file ssfnet/examples/net.dml.

The validation of network configurations against the master schema is strongly recommended, and we find it very helpful in debugging larger models.

See the DML Reference Manual for details about the DML schemas. We note that the schema itself is also written in DML, as a good example of the rule that all configuration files in SSFNet are written in DML.

Import of pre-configured Nets

The next four lines of the configuration file campus2auto.dml specify that the model is composed of four "imported" pre-configured Nets. We'll examine the first line, the other three are similar.

  Net [id 0 _extends .networks.network0.Net]

As explained in the first tutorial, the keyword _extends indicates that the first imported Net attribute extends (i.e., inherits from) the attribute .networks.network0.Net, thus contains all attributes present in .networks.network0.Net and in addition has its own id number.

You should find .networks.network0.Net in the file campus2auto.dml. It begins with:

networks [
  network0 [
    Net [
      router [ id 0
        interface [ id 0 _extends .dictionary.1Gb ]
        interface [ id 1 _extends .dictionary.1Gb ]
        interface [ id 2 _extends .dictionary.1Gb ]    # not attached
        _find .dictionary.routerGraph.graph
      ]
      
      ....stuff omitted...

Therefore, by inheritance semantics, the line
      
  Net [id 0 _extends .networks.network0.Net]

is equivalent to:

  Net [ id 0
    router [ id 0
      interface [ id 0 _extends .dictionary.1Gb ]
      interface [ id 1 _extends .dictionary.1Gb ]
      interface [ id 2 _extends .dictionary.1Gb ]    # not attached
      _find .dictionary.routerGraph.graph
    ]
      
    ....stuff omitted...
  ]

Notice that the router (whose fully expanded NHI address is 0:0) contains one interface, 0:0(2), that is not attached to any link contained within .networks.network0.Net.

This is necessary for reusing .networks.network0.Net in larger Nets, because the basic rule of Net inclusion is:

The enclosing Net does not modify any attributes in the included Nets.

Looking further at the file campus2auto.dml you can see that the toplevel .Net attribute specifies two routers (with id 4 and 5), and that the imported Nets become connected using their previously unattached interfaces, as shown in this code fragment:

  ...
  
  # links from backbone Net 0 to routers 4, 5, 1:0 
     
  link [ attach 0:0(2) attach 4(0) delay 0.01]
  link [ attach 0:1(1) attach 5(0) delay 0.01]
  link [ attach 0:2(0) attach 1:0(3) delay 0.01]

  # links to connect router 4 to net 2 
  
  ...

OSPF routers

Let us now look at another new feature of the model: its routers use the OSPF protocol to compute the routing tables. This specification appears in the routers' ProtocolGraph specification, and at the Net level by specification of the OSPF area number. Let's examine these in turn, beginning with the routers' ProtocolGraph.

All routers in this model contain the line

      _find .dictionary.routerGraph.graph
which (as you should know by now - find the attribute .dictionary.routerGraph in the file) is equivalent to:

   graph [
     ProtocolSession [name ospf use SSF.OS.OSPF.sOSPF]
     ProtocolSession [name ip use SSF.OS.IP]
  ]

The upper ProtocolSession entry instructs to load the class SSF.OS.OSPF.sOSPF, which installs a simplified model of the OSPFv2 protocol in the router. See the documentation of this OSPF implementation in the SSFNet distribution. At the beginning of the simulation the OSPF protocol installed in a router will find all neighbor routers, identify the router type (internal, border, backbone or AS boundary), create the link state database and compute the routes.

In order for OSPF to work properly, you must specify the partition of a model network into OSPF areas. In the toplevel Net in file campus2auto.dml this is specified in the following code fragment:

  ...
  # the enclosing Net is configured as one OSPF area:
     
  AS_status boundary
  ospf_area 0 

  ...

These two lines state that the Net containing these attributes encloses a single OSPF area (it must have number 0, i.e. it is the so-called backbone area) and - for possible reuse of this entire Net in some larger model running in addition the BGP4 interdomain routing protocol - that this entire Net would be treated as an Autonomous System.

Note: The version of OSPF distributed with SSFNet 1.1 does not implement all requirements of RFC 2328, "OSPF Version 2". It's most notable limitations are that the link state databases are computed statically at the beginning of the simulation, rather than by dynamic exchange of LSAs; and that multiple areas are not supported (hence ospf_area 0 is the only one you can specify). See the documentation and source code in the package SSF.OS.OSPF for details. The source code contains placeholders for multiple areas, the Hello and LSA exchanges, etc., and SSF.OS.OSPF is relatively easy to upgrade to a dynamic variant if there is sufficient interest among the users.

Traffic pattern specification for multiple clients and servers

The last code fragment in the toplevel Net in file campus2auto.dml that we will explain concerns the aggregated specification of which clients send requests to which servers. Note that this model (see the diagram at the top of this page) is configured with four hosts running the server application protocol, specified in .dictionary.serverGraph.graph as class SSF.OS.TCP.test.tcpServer with which you should be familiar by now. The remaining hosts all run the client application protocol SSF.OS.TCP.test.tcpClient, which at the configuration phase reads the following attributes:

  ...
  
  traffic [
    pattern [
      client 2
      servers [port 10 nhi_range [from 1:2(0) to 1:5(0)]]
    ]
    pattern [
      client 3
      servers [port 10 nhi_range [from 1:2(0) to 1:5(0)]]
    ]
  ]

The pattern attributes are interpreted by tcpClient's config() method as follows: traffic specification uses globally resolved NHI addresses, that begin with the id number of the topmost enclosing Net, thus client 2 is interpreted as identifying all clients in Net 2, and client 3 is interpreted as identifying all clients in Net 3.

If you examine the source code of SSF.OS.TCP.test.tcpClient, you'd see that a client protocol in any host in Net 2 would decide that the first pattern above applies to it, then would read the line

      servers [port 10 nhi_range [from 1:2(0) to 1:5(0)]]
to find that it is instructed to send a request to any of the four servers in Net 1 whose complete topological addresses are 1:2(0), 1:3(0), 1:4(0) and 1:5(0).

We remind again that at the simulation start the class SSF.Net.Net will automatically allocate IP addresses to all network interfaces in the model, and an interface address like 1:2(0) has a unique IP address associated with it.

Finally, the particular client application implemented in SSF.OS.TCP.test.tcpClient will randomly choose one server's address from the list, and send a request for a file transfer. You should be able at this stage to hack the simple examples of tcpClient and tcpServer to implement any other policy of choosing a server, of course.

Link-level routing in LANs

We conclude this tutorial with an explanation how to configure multiple hosts on a link. In the file campus2auto.dml find the specification of network2:

  network2 [
    Net [
      (... stuff omitted...)
      
      router [ id 2
        interface [ id 0 _extends .dictionary.100Mb ]
        interface [ id 1 _extends .dictionary.100Mb ]
        interface [ id 2 _extends .dictionary.100Mb ]
        interface [ id 3 _extends .dictionary.10Mb ]
        _find .dictionary.routerGraph.graph
      ]
      
      (... stuff omitted...)
      
      # hosts on LANs: note that next_hop must be specified as
      # the interface of a router on the LAN for all destination
      # addresses that are not on the same LAN 
      
      host [ id 7
        nhi_route [dest default interface 0 next_hop 2(3)] 
        _extends .dictionary.client10Mb
      ]
      host [ id 8
        nhi_route [dest default interface 0 next_hop 2(3)] 
        _extends .dictionary.client10Mb
      ]
      
      (... stuff omitted...)
      
      link [ attach 2(3) attach 7(0) attach 8(0) delay 0.003 ]

      (... stuff omitted...)
    ]
     
  ]  # end of network2

The first important rule you should always remember is that the topological NHI addresses of hosts and routers must be specified relative to the nearest enclosing Net. The obvious reason is that a Net cannot possibly know in advance if it is ever going to be imported into another Net, thus cannot contain references to anything outside of itself.

Next, look the specification of the router with id 2, and of two hosts with id 7 and 8. The router has a 10 Mbs network interface with id 3, whose topological address within network2 is 2(3). In .dictionary.client10Mb you'll find that each host has one 10 Mbs network interface with interface id 0, thus the hosts' interfaces addresses are 7(0) and 8(0), respectively.

Now look at the line

      link [ attach 2(3) attach 7(0) attach 8(0) delay 0.003 ]

It specifies that router 2 and hosts 7 and 8 are all attached to the same link (which behaves like a LAN). The SSFNet link is capable of simulated level 2 routing: e.g., host 7 can send IP packets to host 8 and the link will correctly resolve the IP address as belonging to this link, and deliver the packet where it should. This is done "under the hood" by the link implementation because SSFNet does not model the link-level frames and link-level addresses such as for instance Ethernet addresses.

Then, how does the link know that the IP packets from, say, host 7 to a destination address outside the link should be delivered to the router, i.e., to interface 2(3)?

The way it is done involves a construct analogous to a gateway address specification. In host 7 look at the line

        nhi_route [dest default interface 0 next_hop 2(3)] 

which specifies that IP packet destined to any address not on the link should be forwarded to the next_hop interface, which actually is on router 2. The router has a usual IP routing table, and will forward the packet on the way to the remote destination.

Note that we use here the NHI addressing, not the IP addressing. NHI addressing is very robust, and unlike IP addressing doesn't place any limitations on the Net import.

So far we have fully relied on the capability of SSFNet to correctly allocate IP addresses. The rules of the allocation algorithm follow the CIDR (Classless Inter Domain Routing) recommendations of variable length subnet mask (VLSM) IP address allocation, specified in rfc1519 and rfc1878, and further explained in rfc2328. The following tutorial explains these in detail, and the tutorial after that one shows how you may specify your own CIDR-compliant IP address aggregation scheme using the cidr attribute in Nets and links.

continue the tutorials...