How to Script Large Ixia Breaking Point Network Profiles

Background

My team at SealingTech was tasked with testing the performance of a router that would be a tunnel endpoint for many different Site to Site VPN connections from various places. We were given requirements that it needed to support thousands of tunnels and VRFs and lots of bandwidth (upwards of 20 Gb/s). We had an Ixia Traffic Generator (utilizing their Breaking Point Software) to generate the traffic that would be necessary for this. The traffic generation software supports being one end of a tunnel endpoint, but it requires all of the network configuration to be setup via a web GUI.  Naturally, setting up thousands of objects in a web GUI was not something we were interested in doing manually!  We reached out to the vendor to ask if there was any way to support automating the creation of a large test like this one and their response basically amounted to “Good Luck!”

Luckily for us, we had good luck!

The Breaking Point software allows you to export configurations that you have built.  These files, although labeled as “.bpt” files are actually XML files upon closer examination. This means that if the XML schema can be reverse engineered, ALMOST ANY PIECE OF THIS DEVICE’S CONFIGURATION CAN BE AUTOMATED! Woohoo!

The next challenge was to figure out how to automate it. Surely many different programming languages can be used, but we decided on Windows Powershell for the following reasons:

  1. This testing was run in an air-gapped network. This means that it would be kind of a hassle to download the various pieces of software and modules required for some programming languages.
  2. Windows Powershell is installed on nearly every Windows system, and doesn’t really require any internet connectivity for module updates etc.
    • It handles XML natively with some built-in libraries
    • It supports working directly in the command line interactively which makes testing pieces of the script (such as editing specific XML values) very simple

Method 1 Overview

The functionality of the program was very simple. We needed to be able to take a spreadsheet with all of the different IPs used for the test, and use that to create the Breaking Point “Network Neighborhood”. In order to do this, we needed to do the following:

  1. Make a simplified version of the test in the Breaking Point GUI that features 1 of every “element” you might need.
  2. Export the XML from that test and analyze each piece individually. Look at what the values are, what needs to change, and what can stay the same.
  3. Create a spreadsheet with all of the IP addresses, VLAN interfaces, Router Objects etc that are needed. This is much easier than doing it in the Breaking Point GUI because a CSV file can be created by a script, and Excel can also be used to increment and copy and paste large columns of data very easily.
  4. Once the CSV was created, we built the script to read from it and create all of the XML pieces that we determined in Step 2.

When the script runs, it looks something like this:

And when you’ve imported the new file into Breaking Point, the test looks something like this:

Technical Explanations:

This section will attempt to describe each function in detail and how it works. Obviously our scenario was very specific, so if you ever want to do something like this you may want to read how each function works. For many, it could help save time if you have to automate something like this on your own.

Function Get-FileName

This is basically a bunch of technical mumbo-jumbo that opens a prompt to load in a file (CSV or XML). Nothing crazy going on here, but it does set the intial directory to your desktop. Everything else is code that I found somewhere (probably on a Microsoft web page)


Function Get-FileName($type)
{
	$username = whoami
	$username = $username.split("\")
	$username = $username[1]
	$initialdirectory = "C:\users\$username\Desktop"
	[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")|out-null
	$OpenFileDialog = new-object system.windows.forms.openfiledialog
	$OpenFileDialog.initialdirectory = $initialDirectory
	if($type -eq "csv"){$OpenFileDialog.filter = "CSV (*.csv)|*.csv"}
	if($type -eq "xml"){$OpenFileDialog.filter = "XML (*.xml)|*.xml"}
	$OpenFileDialog.showHelp = $true
	$OpenFileDialog.showDialog()|out-null
	$OpenFileDialog.filename
}       
       

Functions ImportXML & ImportCSV

These two functions may as well be grouped together. They are complimentary functions to the “Get-Filename” shown above. They’re for importing the CSV and XML files that the script needs.

        
#Can be used to import a CSV of your choosing
1
Function ImportCSV()
{
	$filepath = Get-FileName csv
	$UserCSV = import-csv $filepath
	return $UserCSV
}

#Can be used to import an XML template of your choosing from the Breaking Point
Function ImportXML()
{
	$filepath = Get-FileName xml
	$UserXML = [xml](Get-content $filepath)
	return $UserXML
}
       

Function GetInitialDirectory

This one creates a variable that be used to map different parts of this script to your desktop.


Function GetInitialDirectory()
{
	$username = whoami
	$username = $username.split("\")
	$username = $username[1]
	$initialdirectory = "C:\users\$username\Desktop"
	return $initialdirectory
}
      

Function CreateIPSecRouters

Okay, this function is huge and messy, probably bigger and messier than it has any business being ( I think we can all relate to that!) It may look complicated, but upon close analysis it is actually simpler than it seems. As stated earlier in this post, the configuration file we need to create is all in XML and Powershell can handle XML natively with ease! This function loops through all the lines in a CSV and adds the appropriate pieces of XML. There are some pieces of this that can be particularly confusing, I’ll do my best to explain them here:
If you examine the XML file provided, you’ll find that its got many levels of nesting. This can be done with various different programs, I used Notepad++ for initial analysis and imported the file into Powershell to confirm my code. This line essentially creates a new object variable that is exactly the same as the following location in the XML: ModelExport–>Network–>NetworkModel–>Element[5]
Elements 0-3 are Interfaces, Element 4 is a VLAN, and Element 5 is an IPSec Router! *whew!*


 $newobject = $xml.modelExport.network.networkmodel.element[5].clone()
       

 

Looking at the XML further, you’ll see that this specific element is made up of 7 additional properties:

• String ID
• Reference ID (Container)
• IP Address (IP Address)
• IP Address (Gateway IP Address)
• Netmask
• IP Address (Peer_IP_Address)
• Reference ID (IPSec Configuration)

Examining this even MORE closely (lots of close examination here!) you may notice that some of these elements have the same tags. Everything is hierarchical! Powershell will actually see this as 4 different properties (some of which have multiple sub-properties). This will play into the next piece of our function (line 57-66):


		$Name = $line.name
			$VLAN = $line.container
			$IP = $line.ipaddr
			$Gateway = $line.gateway
			$netmask = $line.count
			
			$newobject.string."#text" = [string]$Name
			$newobject.reference[0]."#text" = [string]"$VLAN"
			$newobject.ip_address[0]."#text" = [string]$gateway
			$newobject.ip_address[1]."#text" = [string]$IP
			$newobject.ip_address[2]."#text" = [string]$IP
    

Notice how the $newobject.string that is being changed looks different than the other changes? That is because it’s the only element listed under “StringID”. The others all need to have an index number specified. As mentioned above, Reference 0 is the “VLAN Container”, and the IP address indexes are the three different IP addresses specified above.

The final piece of this code snippet is to add the new values to the original XML object. This command adds the new values to the XML object.


$xml.modelExport.network.networkmodel.appendchild($newobject)
       

The next section of code creates a different section of XML that is referred to as a “Domain Element” in the schema. There is some neat stuff here, so lets take a look!

This snippet of code is used to create a MAC address that needs to be inserted into the XML. The first line converts an integer into hex and the second line inserts the hex into a properly formatted MAC address.


		$MACKEY = "{0:x2}" -f $x
		$CreateMAC = "02:1a:c5:"+$MACKEY+":00:00" 
     

All of this is basically just formatting text and properly naming things for this section of XML.


		$VLAN = $i.VLAN
		$NetworkAddr = IPSplit $i.ipaddr
		$HostIP = $i.ipaddr
		$splitIP = $i.ipaddr.split(".")
		$splitPort=$splitIP[1]
		$splitHost=$splitIP[2]
		$RouterIP="10.$splitport.$splithost.2"
		$GatewayIP="10.$splitport.$splithost.1"
		if($splitport -eq "1"){$LCNum = "1";$PortNum="1"}
		if($splitport -eq "2"){$LCNum = "1";$PortNum="2"}
		if($splitport -eq "3"){$LCNum = "2";$PortNum="1"}
		if($splitport -eq "4"){$LCNum = "2";$PortNum="2"}
		$RouterName="LC$LCNum-Port$PortNum-CT$SplitHost-RTR"
		$VLANName="VLAN$Splitport$SplitHost"
		$VLANNumber="$Splitport$SplitHost"
		$Interface="interface $splitport"
    

And the rest of the function is following the same pattern we’ve seen before; Clone the template XML, change the values of all relevant parameters, and append it to the original XML object


		If ($i.Type -like "StaticHost" -and $i.container -notlike "VLAN*") 
		{
			$newobject = $xml.modelExport.network.domain[1].clone()
			$newobject.name = [string]$i.Name
			$newobject.endpoints = [string]$i.Name
			$newobject.subnet.router_ip= [string]$RouterIP
			$newobject.subnet.netmask = [string]$i.Count
			$newobject.subnet.netaddr = [string]$networkaddr
			$newobject.subnet.gateway = [string]$GatewayIP
			$newobject.subnet.innervlan = [string]$VLANNumber
			$newobject.subnet.mac_count = "1"
			$newobject.subnet.l2 = $CreateMac
			$newobject.subnet.composition.stack[0].id = [string]$i.Name
			$newobject.subnet.composition.stack[1].id = [string]$i.container
			$newobject.subnet.composition.stack[2].id = [string]$VLANName
			$newobject.subnet.composition.stack[3].id = [string]$Interface
			$newobject.subnet.range.min = [string]$i.ipaddr
			$newobject.subnet.range.max = [string]$i.ipaddr
			
			#Append New Object
			$xml.modelExport.network.appendchild($newobject)
		}
  

Function CreateStaticHostsVlans

This function works just like the others that we’ve seen so far. It clones an existing element, changes the values in it, and appends it to the original XML object. I’ll refrain from doing this one line by line since there isn’t anything new in the code here, just different pieces of XML to adjust


#Creates the static hosts entries in the XML File with VLAN Containers
Function CreateStaticHostsVlans($CSV, $XML)
{
	####Loop to create IPv4 Elements
	Foreach ($i in $csv)
	{
		If ($i.Type -like "StaticHost") 
		{
		
			$newobject = $xml.modelExport.network.networkModel.element[7].clone()														#######Need a better way to select the element
			
			$name = $i.name
			$container = $i.container
			$VLAN = $i."VLAN"
			
			$newobject.tags.tag.id = $i.Name
			$newobject.string."#text" = $name
			$newobject.ip_address."#text" = $i.ipaddr
			$newobject.reference."#text" = [string]$container
			
			
			#Append New Object
			$xml.modelExport.network.networkModel.appendchild($newobject)
		
		}
	}
return $xml
	
}
     

Function CreateVLANs

This function also works like the others so far. It clones an existing object from the XML and edits the values. However there is some cool stuff in it that we will go over. Specifically, the creation of MAC addresses for the VLAN interfaces. These lines are highlighted in yellow, everything else is something that has been seen previously. Again, this code looks confusing, but is actually fairly simple. The variables “counter” and “iteration” are converted into hex and placed into the proper format for a MAC address. Counter is used for the last two digits of the MAC, and Iteration is used for the two digits before that.


#Creates the Vlan entries in the XML File
Function CreateVLANs($CSV, $XML)
{	
	$iteration = 1
	$counter = 1
	$x=6
	$UniqueVLANs = $CSV|where{$_.type -like "VLANInt"}
	#Runs through all Unique VLANs and adds them to the XML
	foreach($Line in $UniqueVLANs)
	{
		#Create Variables from Each Line in the Object and format them properly for the XML
		$VLAN = $Line.Name
		$VLANTag = $VLAN.substring(4)
		$Interface = $Line.Container
		$Interface = $Interface.ToLower()
		
		#Convert the VLAN Value to hex and create a properly formed MAC with the key
		$MACKEY = "{0:x2}" -f $x
		$MACKEY2 = "{0:x2}" -f $counter
		$MACKEY3 = "{0:x2}" -f $iteration
		$CreateMAC = "02:1a:c5:00:"+$MACKEY3+":"+$MacKey2
		
		#Set XML Values for VLANs
		$newobject = $xml.modelExport.network.networkmodel.element[4].clone()
		$newobject.mac_address."#text" = $CreateMac
		$newobject.int[1]."#text" = "$VLANTag"
		$newobject.string."#text" = "$VLAN"	
		$newobject.reference."#text" = $Interface	#Sets the "container" for the VLAN
		
		$xml.modelExport.network.networkmodel.appendchild($newobject)
		$x = $x+1
		if ($counter -ne 200) {$counter = $counter + 1}
		if ($counter -eq 200) {$counter = 1;$iteration = $iteration +1}
	}
	
	#TODO - Currently no good way to enter in Interface Container since it isn't being fed to the ForEach loop. 
	
	return $xml
}
      

Function IPSplit

This function takes a /24 IP Address and converts it into a Network Address (i.e. 192.168.1.5 would be turned into 192.168.1.0). This was needed because our CSV file didn’t list network addresses, it listed gateways and peers.


Function IPSPLIT($IPString) #This takes an IP address and turns it into a Network Address
{
		$splits = $ipstring.split(".")
		$Octet1 = $splits[0]
		$Octet2 = $splits[1]
		$Octet3 = $splits[2]
		$Octet4 = $splits[3]
		$NetworkAddress = $splits[0]+"."+$splits[1]+"."+$splits[2]+".0"
		return $NetworkAddress
}
     

Function “Main”

This isn’t really a function in Powershell, but I’ve seen the terminology used in other programs to describe the parts of the program that actually run. It winds up being pretty simple since we did all of the hard stuff in the functions.

PrintColorLogo and PrintLine are functions that make the Powershell window pretty and display our company logo. They are part of a module I created called “STColorFunctions.psm1” available with this script.

The script then creates popup windows instructing you to give it input files. One for a CSV, one for an XML base file. Once you’ve selected those, it passes those variables into the functions from earlier. After that, it saves the file to your desktop with a “.bpt” extension. This is the extension that Breaking Point requires for uploading the file.


#Makes the window pretty
PrintColorLogo
PrintLine

#Creates an object and a popup window.
$wshell = new-object -ComObject wscript.Shell
$wshell.popup("Please select the CSV to be used",0,"Select a CSV",0x0)

$CSV = ImportCSV
$wshell.popup("Please select the XML to be used",0,"Select a CSV",0x0)
$XML = ImportXML

#Makes changes to the XML Files.
CreateVLANs $CSV $XML
CreateIpsecRouters $CSV $XML
CreateStaticHostsVlans $CSV $XML

#Saves the XML File.
$Desktop = GetInitialDirectory
$FullString = $Desktop + "\test.bpt"
$xml.Save($FullString)
echo 'Your XML file has been saved to your desktop as "test.bpt"'
    

Tips and Tricks

Using Powershell to “Reformat” an exported Breaking Point file

When exporting a Breaking Point configuration file from the Web GUI, the file is exported as a .bpt file. This is just an XML file with a different extension. However, if you try to view it in notepad or notepad++ the contents of the file are all on one line making it very difficult to read. I’ve learned that importing the file into powershell as XML and then re-saving it reformats the file to be properly indented and easily readable.


$file = [xml](get-content FILENAME)
$File.save(“C:\users\USERNAME\desktop\postsavexml.xml”)
    

Using Powershell to “Traverse” an exported Breaking Point File

If you ever have to write one of these of your own, this is a great way to see how the different pieces of the XML schema work and you can also experiment with editing them to see the results. Following this code block, you can see how you can traverse the XML one level at a time and see how each parameter is stored and edited.


$file = [xml](get-content FILENAME)
$File
$file.modelexport
$file.modelexport.network
$file.modelexport.network.networkmodel
$file.modelexport.network.networkmodel.element
$file.modelexport.network.networkmodel.element[0]
    

Q&A

How did you make that giant Excel File?

Great question! We actually did a bit of scripting to make the Excel file as well. It essentially boiled down to using nested loops to print all of the necessary lines to a CSV file. For things that were easy enough to do in excel, we just dragged and had excel either copy the column, or increment the column. The scripts used to do this are attached to this blog post.

What if I need to do something different?

There is a very good chance you WILL need to do something different. My recommendation for the process is as follows:

1. Use this guide as a template for how you can scale your test
2. Make a simplified version of your test in the Breaking Point GUI that features 1 of every “element” you might need.
3. Export the XML from that test and analyze each piece individually. Look at what the values are, what needs to change, and what can stay the same.
4. Now that you know the values of each element, you should be able to clone them, change the relevant values and see if the new XML you’ve created can be imported into BreakingPoint successfully.

Does this really save any time?

Depending on how big your test is, it really could save time. If you have to type in 80 lines into the Breaking Point GUI, maybe it won’t save time. If you would have to type 8000 lines into the GUI, there is a good chance it would save you a lot of time. Additionally, you’re much less likely to have a hard to find mistake if a script is making all of those lines. As with any approach, your mileage may vary.

Interested in using this? Download this zip file– it has all of the different documents needed to edit this script. Happy Automating! 

 

Method 2 Overview

After posting a writeup of Method 1, someone who works for Keysight (Ixia’s parent company) reached out to us to let us know there may be other (and potentially better) ways to solve our problem. Method 2 describes the process we built for doing the exact same thing, only using the built-in Breaking Point Library (written in TCL). It will also discuss the pros and cons we’ve seen of this approach so far.

How to Use the Script

The script and supporting files are available for download here.

1. Import IPSec_Template.bpt into your Breaking Point
  1. Sign into the Breaking Point GUI and do the following
  2. Test–>Import Test
  3. Give it a name, choose the file, and click upload.
  4. Opening the test should give you an empty test, with a network neighborhood that only has 4 interfaces and nothing else
2. Copy the script file and the CSV to the via scp.
  1. Winscp to the device
  2. Copy the files to the proper directory (for me its /home/admin)
3. Run the script.
  1. SSH into the device
  2. Type in “Enter BPS” The shell should now read ” bps> “
  3. From the BPS shell, type in: “bpsh BlogPost_TCLScript.tcl”
  4. This should run the script. The script will save the Network Neighborhood to the name specified in the “newTestName” variable.
  5. The output on your screen should look something like these two screenshots

How Does the Script Work?

At a very high level, this script does the following:

  1. Loads a template test called “IPSec_Template” which needs to exist on the system before this script can be run.
  2. Creates a temporary network neighborhood in memory based on the network neighborhood that was in the “IPSec_Template” test.
  3. Loads a CSV called IPSecScaling_Small.csv from the directory you are in on the Breaking Point. This CSV has values in it that can be used to create a network neighborhood.
  4. The script creates whatever entries are contained in the CSV file and names the new network neighborhood “”TCL_Scripting_IPSecExample” or whatever you decide to change the “newTestName” variable to.

Each function from this script will be explained in this section. Most of them wind up making a list of a certain “type” that needs to be created, and then an accompanying function to import that list, and create it:

proc drawLogo null {

This draws the SealingTech logo! There isn’t really anything out of the ordinary in this function besides this line:

puts \033\[2J

I would be lying to you if I told you I know exactly what it means, but my research told me that it can be used to clear the screen on certain “UNIX Based OSes”. It appears to clear the screen when I use PuTTy from Windows. If it doesn’t work in your environment, everything may wind up looking really ugly when the script runs.

proc createVlanList {csvFilePath}

This process parses a CSV and returns a list that is made up only of entries that had “VlanInt” in the “Type” column


    set vlanLst []
    set file [open $csvFilePath]
    while {[gets $file line] >=0 } {
        set newvar [split $line ,]
        set name [lindex $newvar 0]
        set container [lindex $newvar 1]
        set type [lindex $newvar 5]
        if {$type eq "VLANInt"} {lappend vlanLst "$name,$container,$type"}
    }
    return $vlanLst
}

The way it works is pretty simple, it creates a variable called “file” which is representative of the file that is located at $csvFilePath. For every line in that file, it splits the CSV into several different variables(name, container, and type). If the “type” variable is “VLANInt” it adds the variables to a new list which is composed only of “vlanInt” objects. This list will be used later in the script to actually create the vlan objects

proc createVlanObjects {uniqueVlans newNet}

Remember in that last function when I said the VLAN List would be used later? This is where it gets used! Its worth noting that “uniqueVlans” is a list of vlan objects created in the previous function.

“newNet” is a variable that is created by one of the built-in Breaking Point functions. It represents the network neighborhood from the test that this script uses as a template.

    
    set iteration 1
    set counter 1
    foreach line $uniqueVlans {
        #assigns each CSV column to a variable
        set newvar [split $line ,]
        set vlan [lindex $newvar 0]
        set interface [lindex $newvar 1]
        
        #Formats a proper MAC address for the VLAN Interface.   The Counter and Iteration are used to increment the proper part of the MAC address.   format %02x converts a decimal to hex(with a leading zero if applicable)
        set MACKEY2 [format %02x $counter]
        set MACKEY3 [format %02x $iteration]
        set CreateMAC "02:1a:c5:00:$MACKEY3:$MACKEY2"
        if {$counter !=200} {set counter [expr $counter + 1]}
        if {$counter == 200} {set counter 1;set iteration [expr $iteration + 1]}
        
        #Creates a few more variables needed to create the VLAN interface in the newNet Network neighborhood
        set stringLength [string length $vlan]
        set vlanNumber [string range $vlan 4 $stringLength]
        set interface [string tolower $interface]
        $newNet add vlan -id $vlan -default_container $interface -inner_vlan $vlanNumber -mac_address $CreateMAC
    }
    return $newNet
}

You can see the for-loop in this is very similar to the way we read files in the previous function. It goes through the file line by line and assigns variables from each part of the list.

The next section looks very complicated, but it accomplishes a very simple function. It creates unique mac addresses for each of the VLAN entries. The last part of the hex changes in every iteration of the loop. Every 200 iterations, the second to last part of the hex will change. For example, the MACKEYs will look something like:

 
02:1a:c5:00:01:01
02:1a:c5:00:01:02
02:1a:c5:00:01:03
…
02:1a:c5:00:01:C8
02:1a:c5:00:02:01
02:1a:c5:00:02:02
….
02:1a:c5:00:C7:01
02:1a:c5:00:C7:02
Etc.etc.etc.

From there, this function is fairly straightforward. The remaining parts of the function are used to create the VLAN Objects in a network neighborhood.

$newNet add vlan -id $vlan -default_container $interface -inner_vlan $vlanNumber -mac_address $CreateMAC

You’ll notice that these parameters all match up to something you would see in the Breaking Point GUI in the “VLAN” portion of a network neighborhood.

proc createStaticHostList {csvFilePath}

This function is very similar to “createVlanList”. This does the same thing as that function, but with entries from the CSV that are typed “staticHost”

proc createStaticHosts {staticHosts newNet}

This function is very similar to “createVlanObjects”. There are less formatting things that need to be done in the function, but it eventually creates the static host objects that would be part of the Network Neighborhood in the Breaking Point.

$newNet add ip_static_hosts -id $name -tags $name -default_container $container -ip_address $ipAddr -netmask "" -count $count

Again, you’ll notice that these parameters all match up to something you would see in the Breaking Point GUI in the “VLAN” portion of a network neighborhood.

proc createIPSecRouterList {csvFilePath}

This function is very similar to “createVlanList” and “createStaticHostList”. This does the same thing as those functions, but with entries from the CSV that are typed “IPSecRTR”

proc createIPSecRouterObjects {ipSecRouterList newNet}

This function is very similar to “createVlanObjects” and “createStaticHosts. A notable difference is that this needs to create an IPSec configuration first before the Router objects can be created. We only needed one for our testing so it was hard coded into the code

$newNet add ipsec_config -id "ipsec_config 1" -ike_version "2" -psk "aaa" -ike_dh "5" -ike_encr_alg "ENC_AES256_CBC" -ike_auth_alg "AUTH_HMAC_SHA2_256_128" -ike_prf_alg "PRF_HMAC_SHA2_256" -ike_lifetime "86400" -esp_encr_alg "ENC_AES256_CBC" -esp_auth_alg "AUTH_HMAC_SHA2_256_128" -ipsec_lifetime "86400" -setup_timeout "600" 

Again, you’ll notice that these parameters all match up to what an IPSec configuration looks like within the Breaking Point Network Neighborhood setup.

This piece of the code creates the actual IPSec Router Objects. Notice that it references the ipsec configuration that was created earlier in the function.

$newNet add ipsec_router -id "$name" -default_container $container -ip_address $ipAddr -gateway_ip_address $gateway -netmask $netmask -ike_peer_ip_address $gateway -ipsec "ipsec_config 1"

“Main”

Main isn’t really a function in TCL, but its whatever the script runs automatically when it is called. I put in a commented section to refer to it as “main” but that holds no true significance in the program.

This first section of code uses the built in Breaking Point functions to create some variables necessary for the testing:


set testInstance [$bps createTest -name TCL_Testing -template IPSec_Template]
set templateNetworkName [$testInstance cget -neighborhood]
set newNet [$bps createNetwork -template $templateNetworkName]

When you first type in “enter bps” in the SSH Prompt on the Breaking Point, it automatically creates the “$bps” variable. This variable is actually an “object” . Not sure if objects are a real construct in TCL or not, but that is what I will call them for the remainder of this post. This “object” can be used to implement many functions that can pull information from, or make changes to, the Breaking point device.

createTest

This is a built-in Breaking Point function that can be used to create an object in your shell session that holds all of the values of a created test. The example code creates a new object called “testInstance” which is a copy of a test that already exists on the BreakingPoint device called “IPSec_Template”.

set testInstance [$bps createTest -name TCL_Testing -template IPSec_Template]

cget

This is a built-in Breaking Point function that can be used to grab various objects from a test. I haven’t found a lot of documentation on exactly what this can do, but in this command its used to copy the name of the “network neighborhood” object that was part of the previously defined “testInstance” object. This will be used in the next function to create a copy of whatever network neighborhood was in the originally copied test template

set templateNetworkName [$testInstance cget -neighborhood]

CreateNetwork

This is a built-in Breaking Point function that can be used to create a new Network Neighborhood object within your SSH session. This object can be viewed and edited many times. Once all the changes are made, this object also has a “save” command which will be used to save it to the device.

set newNet [$bps createNetwork -template $templateNetworkName]

This command sets the variable “newNet” to be a copy of the Network Neighborhood that is named in “$templateNetworkName”

Setting some additional variables


#Set the file path for the CSV and the name of the new Network Neighborhood that will be created
set csvFilePath ./IPSecScaling_Small.csv
set newTestName "TCL_Scripting_IPSecExample"

This section creates variables that are used further down in the script.

csvFilePath is the full Linux directory location of the CSV that will be used to generate the Network Neighborhood. We used the relative path here, but it could also be something like : “/home/admin/IPSecScaling_Small.csv”

newTestName is the name that your new Network Neighborhood will have after the test is completed.

Actually Doing Stuff!


#Save the new network with the name described
drawLogo 1
puts "Creating VLAN List.  The current time is [clock format [clock seconds] -format %R]"; set vlanLst [createVlanList $csvFilePath]
puts "Creating Router List.  The current time is [clock format [clock seconds] -format %R]";set ipSecRouterList [createIPSecRouterList $csvFilePath]
puts "Creating Static Host List.  The current time is [clock format [clock seconds] -format %R]";set staticHostList [createStaticHostList $csvFilePath]
puts "Creating VLAN Objects.  The current time is [clock format [clock seconds] -format %R]";set newNet [createVlanObjects $vlanLst $newNet]
puts "Creating IPSecRouterObjects.  The current time is [clock format [clock seconds] -format %R]";set newNet [createIPSecRouterObjects $ipSecRouterList $newNet]
puts "Creating Static Hosts.  The current time is [clock format [clock seconds] -format %R]";set newNet [createStaticHosts $staticHostList $newNet]
puts "Saving the Network Neighborhood.  The current time is [clock format [clock seconds] -format %R]";$newNet save -name $newTestName

This section of code implements the functions that have been described in near excruciating detail further up in this post. Each line pretty much says what its doing.

Some additional notes:

“puts” is the command used to print output to the screen in TCL.

The “clock format [clock seconds] –format %R” portion grabs the current time from the device, then prints it to the screen in a readable format. %R formats the as %H:%M

This line is the most important piece of code in the entire script!

$newNet save -name $newTestName

It saves the network neighborhood that all of the other parts of “Main” have been creating and editing. If you look carefully, you’ll notice this same “$newNet” object is sent to all of the “create” functions in the script. It accumulates the changes, and then the changes are made to the Breaking Point device when the “save” command is implemented.

Pros and Cons

Both this approach, and the approach my team created in our previous blog post have pros and cons. Neither way seems to be without issues. This section will define the pros and cons of this approach vs the original approach my team used.

Pros

  • This method is supported / recommended by Ixia.
  • In theory, this method should continue working between device updates due to utilizing Ixia’s prebuilt commands and APIs to invoke changes.
  • This method is simpler than reverse engineering and re-generating the XML files that contained all of this information previously.
  • Platform-Independent. Our previous approach used Windows Powershell to generate an XML file.
    • If not working from Windows, or a system that implements Powershell in some way, the original approach would not be feasiable.
    • All this approach needs is a system that can SSH into the Breaking Point device. This can be done via PuTTy in Windows, and natively via SSH in Linux.

Cons

  • Speed
    • Our original use case for this script was to generate something like 40 thousand different IPSec VPN connections. When I tried to use this script to generate that amount, it appeared to be doing roughly one static host per second. This would mean it would take about 11 hours to run. The XML generation via Powershell was significantly faster ( I don’t have a benchmark handy but it was probably about 10-15 minutes at the most)
    • If someone has an idea about how to make that portion of this script run fast, please let us know!
      • I experimented a bit with trying to send a list to the “newNet add ip_static_hosts” function but didn’t have much luck.
  • Usability
    • I don’t have any hard data to back this up, but I’m going to go out on a limb and say more people are probably familiar with Powershell and XML than TCL. Despite the task at hand being more difficult to implement in Powershell.
  • Lack of Documentation
    • This is really a con for both approaches I suppose. I had a very difficult time finding any documentation on how to use the built-in Breaking Point functions. There are a few blog posts on their website (linked in this blog post) but not much else that I was able to find.
    • I did find some good documentation on the TCL language although some implementations on the device seemed to vary from what I saw in documentation. (linked in this post)

Additional Notes

  • I knew nothing about TCL going in, but here are some notes about it:
    • It’s a case sensitive language (or at least it is on the Breaking Point)
    • As far as I can tell, processes always need to have a variable sent to them. You’ll see “null” written in some of my functions, and when I call them I just pass them the number 1
    • “puts” is how you print to the screen, but there is some weird behavior with the way printing to the screen works in this language
      • I found it to be interchangeable with “echo” sometimes, but not others
      • Using quotes (i.e. “aslkjd”) prints but also allows things like variable substitutions and newlines (i.e. /n/n)
      • Using curly braces (i.e. {hello}) prints everything inside them literally. I used them for the logo drawing function.
      • When grabbing input, you sometimes need to “flush” the screen or else the prompts you are trying to print will happen after the input grabbing…. I do not know why, but I’m sure someone who is better than me at IT does.
        • This can be done with the command “flush stdout”
    • When declaring variables, don’t use a $. When referencing variables, use the $. Some functions such as “lindex” require to use the $ when referencing the variables. Others like “lappend” don’t.
  • We were also recommended to use some Python scripts that interact with the Breaking Point API. These scripts are provided by Ixia/Breaking Point
    • Unfortunately when I tried these out, it looks like they had options to retrieve, create, and modify objects but not in the way that we needed to do it.
      • Again, there wasn’t a lot of documentation on this, so if someone has had success with this method, please let us know!
  • I am planning on writing a script for my team that will allow easy automation for creation of Network Neighborhoods and Tests, and also allow automation of running tests sequentially and recording the data we need. If that comes to fruition, it may be posted here in another blog post. If anyone is interested in that, please let me know.

References

I did a lot of googling to discover some references and as previously stated was directed to some links by someone who works for Keysight. Links to what I’ve referenced can be found here:

TCL Documentation:

http://tcl.tk/man/tcl8.5/tutorial/tcltutorial.html https://wiki.tcl-lang.org/page/hexadecimal+conversions

Breaking Point Documentation

https://www.ixiacom.com/company/blog/breakingpoint-automation-series-tcl-101

https://www.ixiacom.com/company/blog/automation-101%E2%80%94large-scale-application-testing-needs-diy-build-machine-gun

https://www.ixiacom.com/company/blog/automation-101-rest-future

Supporting Files Download Link

Ixia_Scaling_Blog_Post_Files_Kevin_Roberts.zip

Posted in