Adding support for unsupported switches to Emulab

Emulab is a popular network testbed for researchers built and maintained by the University of Utah. At the InSPiRe research lab at the University of Victoria we are in the process of building our own Emulab instance to run local experiments and to modify for very specific purposes. This article outlines the process I went through to add support for our switches which were not supported by the Emulab codebase at the time of this writing.

Our Unique Problem

Our switches which are the Nortel Layer 2/3 GBE Switch module for IBM Bladecenters posed an interesting problem. These switches run a completely dead and undocumented operating system with no open SNMP description. One way that this could be reverse-engineered would be to use a proprietary configuration tool and sniff the network packets to determine the internal MIB structure.

The MIB solution would be the best approach, unfortunately the only configuration tool available to us was the command-line interface accessible via remote telnet. For this reason we werent able to use SNMP. Instead of SNMP we used the Perl::Expect module to login via telnet to manipulate the switches.

Note: Using telnet vs SNMP will not affect what needs to be done to emulab in order to support a new switch, only the implementation of the api subroutines discussed below will differ.

Create an internal switch-type name

Come up with a name that you will refer to your new switch as internally, both in the database and in the naming schemes of your supporting perl files. I will use 'mynewswitch' hereafter as our switch model.

Add a switch instance

Assuming you arent working on a live Emulab testbed, you need to add your new switch(es) to database Otherwise you probably want to do this step last once you've tested your code.

Insert a record into the 'nodes' table in the database such that a new switch exists and the 'type' field is set to  'mynewswitch' :
node_id type phys_nodeid role
mynewswitch_1 mynewswitch mynewswitch_1 testswitch

Add a case to handle your new type

When you create an experiment, Emulab will choose a switch from database and pass it's name down through the code until it needs to begin the switch-specific work. The 'snmpit_stack.pm' (located in /usr/testbet/lib/ on boss) seems to be the threshold where the switch specific stuff gets used. I edited this file and added a new case for when it sees the switch type "mynewswitch". Emulab calls the 'new()' subroutine here, which queries the database for the switch's type and then tries to load the correct perl module for that type. In the following code sample from snmpit_stack.pm I've added a new case which passes control to the file we will handle our switch interaction in. Look towards the bottom for my comment:
SWITCH: for ($type) {
    (/cisco/) && do {
        use snmpit_cisco;
        $device = new snmpit_cisco($devicename,$self->{DEBUG});
        last;
        }; # /cisco/

    (/foundry1500/ || /foundry9604/) && do {
        use snmpit_foundry;
        $device = new snmpit_foundry($devicename,$self->{DEBUG});
        last;
        }; # /foundry.*/

    (/nortel1100/ || /nortel5510/) && do {
        use snmpit_nortel;
        $device = new snmpit_nortel($devicename,$self->{DEBUG});
        last;
        }; # /nortel.*/

#------------------------------------------------------------------------

    (/mynewswitch/) && do {     ## Our new case

        use snmpit_mynewswitch;   ## Looks for snmpit_mynewswitch.pm

        $device = new snmpit_mynewswitch($devicename,$self->{DEBUG});
        last;
        }; # /mynewswitch.*/

#------------------------------------------------------------------------

    (/hp/) && do {
        use snmpit_hp;
        $device = new snmpit_hp($devicename,$self->{DEBUG});
        last;
        }; # /hp.*/

    die "Device $devicename is not of a known type, skipping\n";
}

Implement the device-specific subroutines

The previous step will cause Emulab to look for 'snmpit_mynewswitch.pm' in /usr/testbed/lib/ and expect a minimal implementation of the core subroutines to be in place. Because there are so many, Instead of discussing them here individually, I have created a tar file with an unimplemented sample and some comments for what each one does. Find it below. If you find any missing subroutines or unnecessary ones, please let me know.

In order to build our support, I logged in through telnet and ran my functions individually from a test file and watched the changes take effect. A sample test file is included in the tar file.

If you are forced to do something like I did, feel free to contact me if you need some help using the Perl::Expect module for this specific purpose. If you are going to use SNMP, I recommend getting on the emulab-admins google group and talking to the guys at Utah about how they built support for the stuff already in Emulab.

Downloads:

template.tar.gz