if '/' in component:
addr, mask = component.split('/',1)
else:
- addr, mask = component, 32
+ addr, mask = component, '32'
if mask is not None and not (mask and mask.isdigit()):
# No empty or nonnumeric masks
return False
- if not validation.is_ip4_address(attribute, value):
+ if not validation.is_ip4_address(attribute, addr):
# Address part must be ipv4
return False
# add constraint on number of (real) interfaces
# by counting connected devices
- dev_guids = testbed_instance.get_connected(guid, "node", "devs")
+ dev_guids = testbed_instance.get_connected(guid, "devs", "node")
num_open_ifaces = sum( # count True values
NODEIFACE == testbed_instance._get_factory_id(guid)
for guid in dev_guids )
element.min_num_external_ifaces = num_open_ifaces
+ # require vroute vsys if we have routes to set up
+ routes = testbed_instance._add_route.get(guid)
+ if routes:
+ element.required_vsys.add("vroute")
+
testbed_instance.elements[guid] = element
def create_nodeiface(testbed_instance, guid):
def create_tuniface(testbed_instance, guid):
parameters = testbed_instance._get_parameters(guid)
element = testbed_instance._make_tun_iface(parameters)
+
+ # Set custom addresses, if there are any already
+ # Setting this early helps set up P2P links
+ if guid in testbed_instance._add_address and not (element.address or element.netmask or element.netprefix):
+ addresses = testbed_instance._add_address[guid]
+ for address in addresses:
+ (address, netprefix, broadcast) = address
+ element.add_address(address, netprefix, broadcast)
+
testbed_instance.elements[guid] = element
def create_tapiface(testbed_instance, guid):
parameters = testbed_instance._get_parameters(guid)
element = testbed_instance._make_tap_iface(parameters)
+
+ # Set custom addresses, if there are any already
+ # Setting this early helps set up P2P links
+ if guid in testbed_instance._add_address and not (element.address or element.netmask or element.netprefix):
+ addresses = testbed_instance._add_address[guid]
+ for address in addresses:
+ (address, netprefix, broadcast) = address
+ element.add_address(address, netprefix, broadcast)
+
testbed_instance.elements[guid] = element
def create_application(testbed_instance, guid):
def preconfigure_tuniface(testbed_instance, guid):
element = testbed_instance._elements[guid]
- # Set custom addresses if any
+ # Set custom addresses if any, and if not set already
if guid in testbed_instance._add_address and not (element.address or element.netmask or element.netprefix):
addresses = testbed_instance._add_address[guid]
for address in addresses:
# this call only spawns the process
node.install_dependencies()
+def configure_node_routes(testbed_instance, guid):
+ node = testbed_instance._elements[guid]
+ routes = testbed_instance._add_route.get(guid)
+
+ if routes:
+ devs = [ dev
+ for dev_guid in testbed_instance.get_connected(guid, "devs", "node")
+ for dev in ( testbed_instance._elements.get(dev_guid) ,)
+ if dev and isinstance(dev, testbed_instance._interfaces.TunIface) ]
+
+ node.configure_routes(routes, devs)
+
def configure_application(testbed_instance, guid):
app = testbed_instance._elements[guid]
app.node.wait_dependencies()
# Install stuff
- app.setup()
+ app.async_setup()
def configure_dependency(testbed_instance, guid):
dep = testbed_instance._elements[guid]
dep.node.wait_dependencies()
# Install stuff
- dep.setup()
+ dep.async_setup()
def configure_netpipe(testbed_instance, guid):
netpipe = testbed_instance._elements[guid]
"value": False,
"validation_function": validation.is_bool
}),
+ "pointopoint": dict({
+ "name": "pointopoint",
+ "help": "If the interface is a P2P link, the remote endpoint's IP "
+ "should be set on this attribute.",
+ "type": Attribute.STRING,
+ "flags": Attribute.DesignOnly,
+ "validation_function": validation.is_string
+ }),
"txqueuelen": dict({
"name": "mask",
"help": "Transmission queue length (in packets)",
configure_order = [ INTERNET, NODE, NODEIFACE, TAPIFACE, TUNIFACE, NETPIPE, NEPIDEPENDENCY, NS3DEPENDENCY, DEPENDENCY, APPLICATION ]
+# Start (and prestart) node after ifaces, because the node needs the ifaces in order to set up routes
+start_order = [ INTERNET, NODEIFACE, TAPIFACE, TUNIFACE, NODE, NETPIPE, NEPIDEPENDENCY, NS3DEPENDENCY, DEPENDENCY, APPLICATION ]
+
factories_info = dict({
NODE: dict({
- "allow_routes": False,
+ "allow_routes": True,
"help": "Virtualized Node (V-Server style)",
"category": "topology",
"create_function": create_node,
"preconfigure_function": configure_node,
+ "prestart_function": configure_node_routes,
"box_attributes": [
"forward_X11",
"hostname",
"create_function": create_tuniface,
"preconfigure_function": preconfigure_tuniface,
"configure_function": postconfigure_tuniface,
- "start_function": wait_tuniface,
+ "prestart_function": wait_tuniface,
"box_attributes": [
- "up", "device_name", "mtu", "snat",
+ "up", "device_name", "mtu", "snat", "pointopoint",
"txqueuelen",
"tun_proto", "tun_addr", "tun_port", "tun_key"
],
"create_function": create_tapiface,
"preconfigure_function": preconfigure_tuniface,
"configure_function": postconfigure_tuniface,
- "start_function": wait_tuniface,
+ "prestart_function": wait_tuniface,
"box_attributes": [
- "up", "device_name", "mtu", "snat",
+ "up", "device_name", "mtu", "snat", "pointopoint",
"txqueuelen",
- "tun_proto", "tun_addr", "tun_port"
+ "tun_proto", "tun_addr", "tun_port", "tun_key"
],
"traces": ["packets"],
"connector_types": ["node","udp","tcp","fd->"]
def configure_order(self):
return configure_order
+ @property
+ def prestart_order(self):
+ return start_order
+
+ @property
+ def start_order(self):
+ return start_order
+
@property
def factories_info(self):
return factories_info