node.tcl 8.02 KB
Newer Older
Leigh B. Stoller's avatar
Leigh B. Stoller committed
1 2 3 4 5 6 7 8 9 10 11 12
######################################################################
# node.tcl
#
# This defines the Node class.  Instances of this class are created by
# the 'node' method of Simulator.  A Node is connected to a number of
# LanLinks.  Each such connection is associated with a virtual port,
# an integer.  Each virtual port also has an IP address.  Virtual
# ports start at 0 and go up continuously.  Besides the port
# information each node also has a variety of strings.  These strings
# are set by tb-* commands and dumped to the DB but are otherwise
# uninterpreted.
######################################################################
Mac Newbold's avatar
Mac Newbold committed
13

Leigh B. Stoller's avatar
Leigh B. Stoller committed
14
Class Node -superclass NSObject
Mac Newbold's avatar
Mac Newbold committed
15

Leigh B. Stoller's avatar
Leigh B. Stoller committed
16 17
Node instproc init {s} {
    $self set sim $s
Mac Newbold's avatar
Mac Newbold committed
18

Leigh B. Stoller's avatar
Leigh B. Stoller committed
19 20 21 22 23
    # portlist is a list of connections for the node.  It is sorted
    # by portnumber.  I.e. the ith element of portlist is the connection
    # on port i.
    $self set portlist {}

24 25 26 27 28 29 30
    # A list of agents attached to this node.
    $self set agentlist {}

    # A counter for udp/tcp portnumbers. Assign them in an increasing
    # fashion as agents are assigned to the node.
    $self set next_portnumber_ 5000

Leigh B. Stoller's avatar
Leigh B. Stoller committed
31 32 33 34
    # iplist, like portlist, is supported by portnumber.  An entry of
    # {} indicates an unassigned IP address for that port.
    $self set iplist {}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
35 36 37 38
    # A route list. 
    $self instvar routelist
    array set routelist {}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
39
    # The type of the node.
40
    $self set type "pc" 
Leigh B. Stoller's avatar
Leigh B. Stoller committed
41 42 43 44 45 46 47 48 49 50 51 52

    # If osid remains blank when updatedb is called it is changed
    # to the default OS based on it's type (taken from node_types
    # table).
    $self set osid ""

    # These are just various strings that we pass through to the DB.
    $self set cmdline ""
    $self set rpms ""
    $self set startup ""
    $self set deltas ""
    $self set tarfiles ""
53
    $self set failureaction "fatal"
54
    $self set fixed ""
55 56 57 58 59 60 61 62 63 64 65 66
    $self set nseconfig ""

    var_import ::GLOBALS::simulated
    var_import ::GLOBALS::curnsenode
    if { $simulated == 1 } {
	$self set simulated 1
	$self set nsenode $curnsenode
    } else {
	$self set simulated 0
	$self set nsenode ""
    }
    $self set nsenode_vport ""
Leigh B. Stoller's avatar
Leigh B. Stoller committed
67 68 69 70 71 72 73
}

# The following procs support renaming (see README)
Node instproc rename {old new} {
    $self instvar portlist
    foreach object $portlist {
	$object rename_node $old $new
Mac Newbold's avatar
Mac Newbold committed
74
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
75 76 77 78 79 80 81 82 83 84
    [$self set sim] rename_node $old $new
}

Node instproc rename_lanlink {old new} {
    $self instvar portlist
    set newportlist {}
    foreach node $portlist {
	if {$node == $old} {
	    lappend newportlist $new
	} else {
85
	    lappend newportlist $node
Leigh B. Stoller's avatar
Leigh B. Stoller committed
86
	}
Mac Newbold's avatar
Mac Newbold committed
87
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
88
    set portlist $newportlist
Mac Newbold's avatar
Mac Newbold committed
89 90
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
91 92 93 94 95 96 97 98 99 100 101 102
# updatedb DB
# This adds a row to the virt_nodes table corresponding to this node.
Node instproc updatedb {DB} {
    $self instvar portlist
    $self instvar type
    $self instvar osid
    $self instvar cmdline
    $self instvar rpms
    $self instvar startup
    $self instvar deltas
    $self instvar iplist
    $self instvar tarfiles
103
    $self instvar failureaction
104
    $self instvar routertype
105
    $self instvar fixed
106
    $self instvar agentlist
Leigh B. Stoller's avatar
Leigh B. Stoller committed
107 108
    $self instvar routelist
    $self instvar sim
109 110
    $self instvar simulated
    $self instvar nseconfig
Leigh B. Stoller's avatar
Leigh B. Stoller committed
111 112
    var_import ::GLOBALS::pid
    var_import ::GLOBALS::eid
113
    var_import ::GLOBALS::default_ip_routing_type
Mac Newbold's avatar
Mac Newbold committed
114

115 116 117 118 119
    # currently we don't want to update the DB for simulated nodes
    if { $simulated == 1 } {
	return
    }

Leigh B. Stoller's avatar
Leigh B. Stoller committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    # If we haven't specified a osid so far then we should fill it
    # with the id from the node_types table now.
    if {$osid == {}} {
	sql query $DB "select osid from node_types where type = \"$type\""
	set osid [sql fetchrow $DB]
	sql endquery $DB
    }

    # We need to generate the IP column from our iplist.
    set ipraw {}
    set i 0
    foreach ip $iplist {
	lappend ipraw $i:$ip
	incr i
    }
Mac Newbold's avatar
Mac Newbold committed
135

136 137
    foreach agent $agentlist {
	$agent updatedb $DB
138 139

        append nseconfig [$agent get_nseconfig]
140
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
141
    if {$nseconfig != {}} {
142 143 144 145 146 147 148

	set nsecfg_script ""
	set simu [lindex [Simulator info instances] 0]
	append nsecfg_script "set $simu \[new Simulator]\n"
	append nsecfg_script "\$$simu use-scheduler RealTime\n\n"
	append nsecfg_script $nseconfig

149
        # update the per-node nseconfigs table in the DB
150
        sql exec $DB "insert into nseconfigs (pid,eid,vname,nseconfig) values ('$pid','$eid','$self','$nsecfg_script')";
151
    }
152

Leigh B. Stoller's avatar
Leigh B. Stoller committed
153 154
    $self add_routes_to_DB $DB

Leigh B. Stoller's avatar
Leigh B. Stoller committed
155
    # Update the DB
156
    sql exec $DB "insert into virt_nodes (pid,eid,vname,type,ips,osname,cmd_line,rpms,deltas,startupcmd,tarfiles,failureaction,routertype,fixed) values (\"$pid\",\"$eid\",\"$self\",\"$type\",\"$ipraw\",\"$osid\",\"$cmdline\",\"$rpms\",\"$deltas\",\"$startup\",\"$tarfiles\",\"$failureaction\",\"$default_ip_routing_type\",\"$fixed\")";
Mac Newbold's avatar
Mac Newbold committed
157
}
158

Leigh B. Stoller's avatar
Leigh B. Stoller committed
159 160 161 162 163 164 165 166 167 168
# add_lanlink lanlink
# This creates a new virtual port and connects the specified LanLink to it.
# The port number is returned.
Node instproc add_lanlink {lanlink} {
    $self instvar portlist
    $self instvar iplist
    lappend portlist $lanlink
    lappend iplist ""
    return [expr [llength $portlist] - 1]
}
169

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
#
# Find the lan that both nodes are attached to. Very bad. If more than
# comman lan, returns the first.
#
Node instproc find_commonlan {node} {
    $self instvar portlist
    set match -1

    foreach ll $portlist {
	set match [$node find_port $ll]
	if {$match != -1} {
	    break
	}
    }
    return $match
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
# ip port
# ip port ip
# In the first form this returns the IP address associated with the port.
# In the second from this sets the IP address of a port.
Node instproc ip {port args} {
    $self instvar iplist
    $self instvar sim
    if {$args == {}} {
	return [lindex $iplist $port]
    } else {
	set ip [lindex $args 0]
	set subnet [join [lrange [split $ip .] 0 2] .]
	set iplist [lreplace $iplist $port $port $ip]
	$sim use_subnet $subnet
    }    
202 203
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
204 205 206 207 208 209
# find_port lanlink
# This takes a lanlink and returns the port it is connected to or 
# -1 if there is no connection.
Node instproc find_port {lanlink} {
    return [lsearch [$self set portlist] $lanlink]
}
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227

# Attach an agent to a node. This mainly a bookkeeping device so
# that the we can update the DB at the end.
Node instproc attach-agent {agent} {
    $self instvar agentlist

    lappend agentlist $agent
    $agent set_node $self
}

#
# Return and bump next agent portnumber,
Node instproc next_portnumber {} {
    $self instvar next_portnumber_
    
    set next_port [incr next_portnumber_]
    return $next_port
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252

#
# Add a route.
# The nexthop to <dst> from this node is <target>.
#
Node instproc add-route {dst nexthop} {
    $self instvar routelist

    if {[info exists routelist($dst)]} {
	perror "\[add-route] route from $self to $dst already exists!"
    }
    set routelist($dst) $nexthop
}

#
# Update DB with routes
#
Node instproc add_routes_to_DB {DB} {
    var_import ::GLOBALS::pid
    var_import ::GLOBALS::eid
    $self instvar routelist
    $self instvar sim

    foreach dst [lsort [array names routelist]] {
	set hop $routelist($dst)
253
	set port -1
Leigh B. Stoller's avatar
Leigh B. Stoller committed
254 255

	#
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
	# Convert hop to IP address. Need to find the link between the
	# the this node and the hop. This is easy if its a link. If its
	# a lan, then its ugly.
	#
	set hoplink [$sim find_link $self $hop]
	if {$hoplink == {}} {
	    set port [$self find_commonlan $hop]
	} else {
	    set port [$hop find_port $hoplink]
	}
	if {$port == -1} {
	    perror "\[add-route] Cannot find a link from $self to $hop!"
	    return
	}
	set hopip [$hop ip $port]
	
	#
	# Convert dst to IP address.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
	#
	switch -- [$dst info class] {
	    "Node" {
		if {[llength [$dst set portlist]] != 1} {
		    perror "\[add-route] $dst must have only one link."
		}
		set dstip [$dst ip 0]
		set type  "host"
	    }
	    "SimplexLink" {
		set link [$dst set mylink]
		set src [$link set src_node]
		set dstip [$src ip [$src find_port $link]]
		set type  "net"
	    }
	    "Link" {
		set dstip [$dst get_subnet]
		set type  "net"
	    }
293 294 295 296
	    "Lan" {
		set dstip [$dst get_subnet]
		set type  "net"
	    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
297 298 299 300 301 302 303 304 305
	    unknown {
		perror "\[add-route] Bad argument. Must be a node or a link."
		return
	    }
	}
	
	sql exec $DB "insert into virt_routes (pid,eid,vname,dst,nexthop,dst_type) values ('$pid','$eid','$self','$dstip','$hopip','$type')";
    }
}