Simple L2 Switching

This is a brief walk-through of a basic VTS request that will create a topology with several hosts and a DHCP server. This topology will serve as the foundation for several other tutorials that you may also execute, walking you through basic VTS workflows as well as a simple illustration of the power of full control of isolated network topologies.

This tutorial may be executed using the geni-lib suite (see here for installation instructions), either the genish command line tool, or the identically named ipython extension.

For both tools you will need to download your omni.bundle file from the GENI Portal. You can find instructions for doing so in the geni-lib docs.

You can also use VTS with a Cloudlab account (without an omni.bundle), and you can find documentation for acquiring these credentials in the geni-lib docs. If using Cloudlab credentials with geni-lib, please review the geni-lib documentation for using these credentials.

Topology

../_images/simpleovs.png

Build the Request Object

In order to request this topology, we can create a resource request object for VTS using genish (at the command line or in ipython notebooks):

r = VTS.Request()

We then add our switch:

br = r.Datapath(VTS.OVSL2Image(), "br0")

There are a limited number of switch images available in GENI - the two most commonly used are the one above, which is a normal MAC-learning bridge with VLAN support, and an Openflow-supporting image (referenced in geni-lib as VTS.OVSOpenFlowImage, with some required configuration parameters). The second argument to Datapath is the client_id of the bridge, which you will need to know later in order to query it for monitoring and state information. We assign the return from r.Datapath(...) to a variable that we will use later in the request to build links.

Now we add our hosts:

h0 = r.Container(VTS.Image("uh.net-client"), "h0")
h1 = r.Container(VTS.Image("uh.net-client"), "h1")
dhcp = r.Container(VTS.Image("uh.simple-dhcpd"), "dhcp")

Switch images are added using the Datapath constructor, while hosts are added using the Container constructor. As with datapaths there are two arguments - the image object to be used, and the client_id of the resultant host. In the case of hosts, the client_id is also used as the hostname, so it’s preferable to not choose characters that would not be valid in a hostname.

In this case we use two images that are available at all GENI VTS sites - the “uh.net-client” image, which is a basic linux host with networking tools installed (tcpdump, scapy, iperf, etc.), and the “uh.simple-dhcpd” image, which is a trivial DHCP server that supports a single IPv4 subnet. By default the subnet used for DHCP is 192.168.50.0/24, but you can change that value by setting the image attribute subnet if you desire:

dhcp.image.setImageAttribute("subnet", "10.70.10.0/23")

Now we need to add links between our nodes:

VTS.connectInternalCircuit(br, h0)
VTS.connectInternalCircuit(br, h1)
VTS.connectInternalCircuit(br, dhcp)

Now our request is complete, and we can send it to the aggregate manager at a site to reserve our resources.

Make the Reservation

Choose a site, and store it in a short-to-type variable name for later:

SITE = VTSAM.StarLight

You may also want to store your slice name in a short variable name for ease of use or changing later:

SLICE = "my-slice-name"

Of course, change that value to the name of a slice that you control.

Now create the sliver for our resource request, and get the manifest back:

manifest = SITE.createsliver(context, SLICE, r)

If there is an exception, note the problem and either resolve it yourself (if you need to delete an existing sliver, etc.), or send email to geni-users@googlegroups.com to see if someone can help you. Otherwise, proceed with the rest of the tutorial using the manifest that was returned above.

Visualize Reserved Resources

If you are using the genish ipython notebook extension, you can get a visual topology diagram using the built-in manifest renderer:

genish.showtopo(manifest)

If you are using the command line genish shell, you can get dot output, which you can use in graphviz or any other dot supporting tool:

util.builddot([manifest])

Note

util.builddot takes a list of manifests, so if you only have one manifest you still need to put it into a list.

Connect to Topology Hosts

Now that the hosts in this topology have been provisioned, you can get login information in order to configure SSH to access your hosts:

genish.printlogininfo(manifest)

If you are using the genish shell, you can access a similar method in the util module:

util.printlogininfo(manifest=manifest)

Note

The core util.printlogininfo function takes a number of arguments that can be used to get a manifest that you do not already have. Given that you already have a manifest, you can pass it in directly using the manifest argument.

The output comes in 4 pieces - the client_id you requested in your reservation, the username you should use to access this resource, the internet-accessible hostname or IP you can use to reach the resource, and the port number to be used for SSH. It will come in a table in ipython, or in a simple list in the command line output:

[h0][ywauusshw5k] starlight.vts.bsswks.net: 22
[h1][k10172ltax6] starlight.vts.bsswks.net: 22

In this case, if we want to connect to the container representing h0, we have the information that we can give to an SSH client to connect:

ssh -i ~/.ssh/id_geni_ssh_rsa ywauusshw5k@starlight.vts.bsswks.net

Note

Since the default SSH port is 22, we don’t have to provide the port to the client. Also as with all GENI slivers, the SSH public key referenced in your context object is the one used for authentication. By default it is the one used above.

Now that you have a connection to the host, you can run dhclient to get an IP address from the DHCP server that you provisioned in your topology:

/ # dhclient -v eth1

As we asked for verbose output, you should see something like the output below:

Internet Systems Consortium DHCP Client 4.3.4
Copyright 2004-2016 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/eth1/f6:5e:13:3c:0f:7c
Sending on   LPF/eth1/f6:5e:13:3c:0f:7c
Sending on   Socket/fallback
DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 3
DHCPREQUEST on eth1 to 255.255.255.255 port 67
DHCPOFFER from 10.70.10.1
DHCPACK from 10.70.10.1
bound to 10.70.10.10 -- renewal in 375 seconds.

Now that you have established that your topology is working, you can walk through the below sections to view internal network state.

View DHCP Lease State

Many images offer a number of POA (Perform Operational Action) APIs that can be used to gather data about the current image state. In the case of the uh.simple-dhcpd image we can gather information about the leases that the DHCP server has currently allocated:

SITE.getLeaseInfo(context, SLICE, "dhcp")

This will give you a table with the current lease state - allocated IP addresses, MAC addresses, when they expire, and (depending on information offered by the host) the hostname of the requesting host. As long as dhclient continues to run on each host the client process will renew the leases as necessary.

View Switch MAC Table

Similar to the information offered by the uh.simple-dhcpd image, we can inspect the switch state to view learned MAC addresses:

SITE.dumpMACs(context, SLICE, "br")

This will give you table with the current MAC table state on the switch (you can also pass it a list of switches, if your topology has more than one switch). This will include the port number the MAC is learned on, the VLAN if appropriate, the MAC itself, and the current age. The default aging time for the OVSL2Image is 300 seconds, so a MAC not seen for 5 minutes will expire from the table.