node.tcl 6.62 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 ""
Leigh B. Stoller's avatar
Leigh B. Stoller committed
55 56 57 58 59 60 61
}

# 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
62
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
63 64 65 66 67 68 69 70 71 72
    [$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 {
73
	    lappend newportlist $node
Leigh B. Stoller's avatar
Leigh B. Stoller committed
74
	}
Mac Newbold's avatar
Mac Newbold committed
75
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
76
    set portlist $newportlist
Mac Newbold's avatar
Mac Newbold committed
77 78
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
79 80 81 82 83 84 85 86 87 88 89 90
# 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
91
    $self instvar failureaction
92
    $self instvar routertype
93
    $self instvar fixed
94
    $self instvar agentlist
Leigh B. Stoller's avatar
Leigh B. Stoller committed
95 96
    $self instvar routelist
    $self instvar sim
Leigh B. Stoller's avatar
Leigh B. Stoller committed
97 98
    var_import ::GLOBALS::pid
    var_import ::GLOBALS::eid
99
    var_import ::GLOBALS::default_ip_routing_type
Mac Newbold's avatar
Mac Newbold committed
100

Leigh B. Stoller's avatar
Leigh B. Stoller committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    # 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
116

117
    set nseconfig ""
118 119
    foreach agent $agentlist {
	$agent updatedb $DB
120 121

        append nseconfig [$agent get_nseconfig]
122
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
123
    if {$nseconfig != {}} {
124 125 126
        # update the per-node nseconfigs table in the DB
        sql exec $DB "insert into nseconfigs (pid,eid,vname,nseconfig) values ('$pid','$eid','$self','$nseconfig')";
    }
127

Leigh B. Stoller's avatar
Leigh B. Stoller committed
128 129
    $self add_routes_to_DB $DB

Leigh B. Stoller's avatar
Leigh B. Stoller committed
130
    # Update the DB
131
    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
132
}
133

Leigh B. Stoller's avatar
Leigh B. Stoller committed
134 135 136 137 138 139 140 141 142 143
# 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]
}
144

Leigh B. Stoller's avatar
Leigh B. Stoller committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
# 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
    }    
160 161
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
162 163 164 165 166 167
# 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]
}
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

# 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
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243

#
# 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)

	#
	# Convert hop IP address.
	#
	set hopip [$hop ip [$hop find_port [$sim find_link $self $hop]]]

	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"
	    }
	    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')";
    }
}