#
# NS file for instantiating an OpenEPC setup.
#
# Look for the variable definitions near the top to adjust the composition
# of the resultant OpenEPC system.
#
source tb_compat.tcl
set ns [new Simulator]
##############################################################################
#
# Variables you can tweak w/o necessarily understanding this NS file.
#
# OS to use on the nodes. This image must be one that has been prepared
# the way OpenEPC expects!
set OEPC_OS "PhantomNet/UBUNTU12-64-BINOEPC"
# Were to log the output of the startup command on each node
set OEPC_LOGFILE "/var/tmp/openepc_start.log"
# Location of OpenEPC-in-Emulab startup script
set OEPC_SCRIPT "/usr/bin/sudo /opt/OpenEPC/bin/start_epc.sh"
# Set the type of node hardware to use. "pc" is a generic, real PC.
set OEPC_HWTYPE "pc"
# Set the link bandwidth. Note that "*" (meaning, use the fastest available
# native link speed) is incompatible with link encapsulation. Since link
# encapsulation is required for virtual nodes, this value has to be changed
# to something specific (e.g., 10Mb) if HWTYPE is set to "pcvm".
set OEPC_LINKBW "*"
# Number of clients to allocate (currently, value can be 1 or 2)
set num_clients 1
# Allocate the enodeb node (and an_lte network)?
# If we allocate, then currently the number can be from 1 to 3.
set alloc_enodeb 1
set num_enodeb 1
# Allocate UE shadow nodes (attached to UEs)?
set alloc_shadow_nodes 0
# UE shadow node OS
set SHADOW_NODE_OS "UBUNTU14-64-STD"
# UE shadow node subnet base address
set SHADOW_SUBNET_BASE 100
##############################################################################
#
# Code to generate OpenEPC topology and set it up follows.
#
# Various node lists (referenced by, or filled in by code below)
set nodelist ""
set clientlist "alice bob"
set enblist "enb1 enb2 enb3"
# List of lans that nodes may be added to below.
set lanlist "mgmt net_a net_b net_d an_lte an_umts an_wimax an_wifi"
# Initialize lan membership lists
array set lans {}
array set lanconf {}
foreach lan $lanlist {
set lans($lan) ""
set lanconf($lan) ""
}
proc addtolan {lan node {bw ""} {delay ""}} {
global lans
global lanconf
lappend lans($lan) $node
if {$bw != {} || $delay != {}} {
lappend lanconf($lan) [list $node $bw $delay]
}
}
proc epcnode {node {role ""} {hname ""} {prescr ""} {postscr ""} {usenat 0}} {
global nodelist
global OEPC_OS OEPC_LOGFILE OEPC_SCRIPT OEPC_HWTYPE
uplevel "set $node \[\$ns node]"
lappend nodelist $node
tb-set-hardware $node $OEPC_HWTYPE
tb-set-node-os $node $OEPC_OS
addtolan mgmt $node
if {$role != {}} {
set startcmd "$OEPC_SCRIPT -r $role"
if {$hname != {}} {
append startcmd " -h $hname"
}
if {$prescr != {}} {
append startcmd " -P $prescr"
}
if {$postscr != {}} {
append startcmd " -T $postscr"
}
if {$usenat == 1} {
append startcmd " -a"
}
append startcmd " >& $OEPC_LOGFILE"
tb-set-node-startcmd $node $startcmd
}
}
proc addclientstolan {lan} {
global num_clients
global clientlist
for {set i 0} {$i < $num_clients} {incr i} {
set clnode [lindex $clientlist $i]
addtolan $lan $clnode
}
}
# Check that num_clients isn't out of bounds. Ultimately we want to be
# able to set the number of clients arbitrarily high, but can't do that
# until the OpenEPC client setup is generalized more.
if {$num_clients < 1 || $num_clients > [llength $clientlist]} {
perror "num_clients must be between 1 and [llength $clientlist] (inclusive)!"
exit 1
}
# Create $num_clients client nodes, accompanying "shadow" nodes, and link between them.
set use_nat $alloc_shadow_nodes
for {set i 0} {$i < $num_clients} {incr i} {
set clnode [lindex $clientlist $i]
epcnode $clnode "epc-client" $clnode "" "" $use_nat
if {$alloc_shadow_nodes} {
set shnode "${clnode}-sn"
set shlink "link-${clnode}-sn"
set shsubn [expr $SHADOW_SUBNET_BASE + $i]
set $shnode [$ns node]
tb-set-node-os $shnode $SHADOW_NODE_OS
set $shlink [$ns duplex-link $clnode $shnode * 0ms DropTail]
tb-set-ip-link $clnode $shlink "192.168.${shsubn}.1"
tb-set-ip-link $shnode $shlink "192.168.${shsubn}.2"
}
}
# Create the epc-enablers node (Mandatory)
epcnode epc "epc-enablers"
addtolan net_a $epc
# Create the pgw node (Mandatory)
epcnode pgw "pgw"
addtolan net_a $pgw
addtolan net_b $pgw
# Create the sgw-mme-sgsn node (Mandatory)
epcnode sgw "sgw-mme-sgsn"
addtolan net_b $sgw
addtolan net_d $sgw
# Create the enodeb RAN node(s) (Optional)
if {$alloc_enodeb} {
# Check that num_enodeb isn't out of bounds.
if {$num_enodeb < 1 || $num_enodeb > [llength $enblist]} {
perror "num_enodeb must be between 1 and [llength $enblist] (inclusive)!"
exit 1
}
# Create the number of enodeb nodes requested.
for {set i 0} {$i < $num_enodeb} {incr i} {
set enbnode [lindex $enblist $i]
epcnode $enbnode "enodeb" $enbnode
addtolan an_lte $enbnode
addtolan net_d $enbnode
}
addclientstolan an_lte
}
# Create all lans that have at least two members
foreach lan $lanlist {
# Since DNS doesn't officially allow underscores, we have to convert
# them to dashes in the names of the lans before instantiation.
set nslan [regsub -all -- "_" $lan "-"]
if {[llength $lans($lan)] > 1} {
set $nslan [ns make-lan $lans($lan) $OEPC_LINKBW 0ms]
# The default type of link encapsulation for virtual nodes
# (veth-ne) is antiquated and incompatible with modern XEN.
if {[string match -nocase "*vm*" $OEPC_HWTYPE]} {
tb-set-link-encap $nslan "vlan"
}
foreach nent $lanconf($lan) {
set node [lindex $nent 0]
set bw [lindex $nent 1]
set delay [lindex $nent 2]
if {$bw != {}} {
tb-set-node-lan-bandwidth $node $nslan $bw
}
if {$delay != {}} {
tb-set-node-lan-delay $node $nslan $delay
}
}
}
}
# Cut down on the number of nodes required in the topology by using
# end-node traffic shaping.
tb-use-endnodeshaping 1
# Go!
$ns run