Printer FriendlyEmail Article Link

How to build a TCL script to do UDP, TCP, IP, TCP_VLAN with capture on Smartbits

Answer

######################################################################
# This script will build, ip, udp, tcp and tcp vlan packets, transmit
# and capture
# tested 3/16/2012
# Tested with smartlib 6.00 on Termetric 3325 card with ports connected
# Back to Back
#######################################################################
 
source smartlib.tcl

set iHub  0
set iSlot 8
set iPort 0

set iHub2  0
set iSlot2 8
set iPort2 1

 # we will create a total of 10 streams on the card
 # one original and nine copies
set totalStreams 20
 # first stream will be 100 bytes long
set dataLength 80

 # for more readable code below
 # We will use the first stream we create as a
 # blueprint for the copies
set firstStream 1
set Burst 1
set TCPindex 2
set TCP_Vlan_index 1
set UDPindex 5
###############################################################################
###############################################################################
#################   L3_DEFINE_MULTI_IP_STREAM PROCEDURES  #####################
###############################################################################
###############################################################################

###############################################################################
# Creates one stream with DEFINE will create a single stream at index 1
# (stream 0 is resreved)
###############################################################################

proc createOneStream {H S P} {

   struct_new ip StreamIP
    set ip(ucActive) 1
    set ip(ucProtocolType) $::STREAM_PROTOCOL_IP
    set ip(uiFrameLength) $::dataLength
    set ip(ucTagField) 1
    set ip(DestinationMAC.0)  0x00
    set ip(DestinationMAC.1)  0x00
    set ip(DestinationMAC.2)  0x02
    set ip(DestinationMAC.3)  0x02
    set ip(DestinationMAC.4)  0x02
    set ip(DestinationMAC.5)  0x01
    set ip(SourceMAC.0)  0x00
    set ip(SourceMAC.1)  0x00
    set ip(SourceMAC.2)  0x01
    set ip(SourceMAC.3)  0x01
    set ip(SourceMAC.4)  0x01
    set ip(SourceMAC.5)  0x01
    set ip(TimeToLive) 10
    set ip(DestinationIP.0)  10
    set ip(DestinationIP.1)  2
    set ip(DestinationIP.2)  1
    set ip(DestinationIP.3)  1
    set ip(SourceIP.0)  10
    set ip(SourceIP.1)  1
    set ip(SourceIP.2)  1
    set ip(SourceIP.3)  1
    set ip(Netmask.0)  255
    set ip(Netmask.1)  255
    set ip(Netmask.2)  255
    set ip(Netmask.3)  0
    set ip(Gateway.0)  10
    set ip(Gateway.1)  1
    set ip(Gateway.2)  1
    set ip(Gateway.3)  254
   LIBCMD HTSetStructure $::L3_DEFINE_IP_STREAM 0 0 0 ip 0 $H $S $P
}


###############################################################################
# createMultiCopies
#
# creates numCopies additional new streams using the existing stream at index
# bluePrint as the prototype.
#
# Uses all values set in bluePrint stream unless they are set to something other
# than zero here.  Any field set to a value other than zero in the structure
# sent with the DEFINE_MULTI command will be incremented by that amount in each new
# stream.
# For example suppose a stream is created at stream index 1 with a source IP of
# 10.100.1.5.  This means the orignal structure had the elements SourceIP.0 set
# to 10, SourceIP.1 set to 100, SourceIP.2 set to 1 and SourceIP.3 set to 5.
#
# If a MULTI command was sent to the card with this stream as the blue print and
# it's stream structure had two non-zero elements SourceIP.2 set to 2 and SourceIP.3
# set to 1, then each new stream created would be identical to the blue print stream
# except the source IP for the first copy woul be 10.100.3.6 (IP2 incremented by 2 and
# IP3 incremented by 1) the source IP for the second copy would be 10.100.5.7
# and so on.
#
# Not all fields can be incremented.  Check Appendix C of the SmartLibrary
# Command Reference for a list of the fields that can be incremented in each
# stream type.
###############################################################################
proc createMultiCopies {H S P bluePrint numCopies} {

   struct_new ip StreamIP
     # each sucessive copy will be 10 bytes longer
    set ip(uiFrameLength) 10
     # and the least significant byte of the MAC addresses will be one more
     # than the value in the bluePrint stream
    set ip(DestinationMAC.5)  1
    set ip(SourceMAC.5)  1
     # The destination IP of each new stream will be 2 more for the least significant
     # octet and 4 more for the next most significant octet
    set ip(DestinationIP.2)  4
    set ip(DestinationIP.3)  2
     # the least significant octet of the Source IP will increment by one in each
     # sucessive copy
    set ip(SourceIP.3)  1

   LIBCMD HTSetStructure $::L3_DEFINE_MULTI_IP_STREAM $bluePrint $numCopies 0 ip 0 $H $S $P
}
###############################################################################
# Replace stream at index with new TCP stream.  If index is larger than the number
# of streams on the card a new stream will be appended to the stream list
#
# For example, if there were three streams on the card (at index 1 2 and 3) and
# MOD was used with an index of 24, a new stream would be created at index 4.
# If MOD was called with an index of 2, the existing stream at index 2 would
# be replaced with new stream.
# Stream zero is always reserved, although it can accidentally be overwritten.
# Never use a MOD command with an index of zero.
###############################################################################
proc replaceOneTCPStream {H S P TCPindex} {
   struct_new tcp StreamTCP
    set tcp(ucActive) 1
    set tcp(ucProtocolType) $::STREAM_PROTOCOL_TCP
    set tcp(uiFrameLength) 256
    set tcp(ucTagField) 1
    set tcp(DestinationMAC.0)  0x00
    set tcp(DestinationMAC.1)  0x51
    set tcp(DestinationMAC.2)  0x51
    set tcp(DestinationMAC.3)  0x51
    set tcp(DestinationMAC.4)  0x51
    set tcp(DestinationMAC.5)  0x05
    set tcp(SourceMAC.0)  0x00
    set tcp(SourceMAC.1)  0x61
    set tcp(SourceMAC.2)  0x61
    set tcp(SourceMAC.3)  0x61
    set tcp(SourceMAC.4)  0x61
    set tcp(SourceMAC.5)  0x06
    set tcp(TimeToLive) 10
    set tcp(DestinationIP.0)  5
    set tcp(DestinationIP.1)  5
    set tcp(DestinationIP.2)  5
    set tcp(DestinationIP.3)  10
    set tcp(SourceIP.0)  6
    set tcp(SourceIP.1)  6
    set tcp(SourceIP.2)  6
    set tcp(SourceIP.3)  10
    set tcp(Netmask.0)  255
    set tcp(Netmask.1)  255
    set tcp(Netmask.2)  255
    set tcp(Netmask.3)  0
    set tcp(Gateway.0)  6
    set tcp(Gateway.1)  6
    set tcp(Gateway.2)  6
    set tcp(Gateway.3)  1
    set tcp(InitialSequenceNumber) 1
    set tcp(SourcePort) 32805
      # 80 is httpd
    set tcp(DestPort)    80
    set tcp(TCPAck)      100
    set tcp(TCPSequence) 200
      # set as SYN, ACK packet by ORing constants. Other constants
      # include TCP_FLAG_FIN TCP_FLAG_RST TCP_FLAG_URG and TCP_FLAG_PSH
    set tcp(Flags)       [expr $::TCP_FLAG_SYN + $::TCP_FLAG_ACK]
    set tcp(Window)      10
   LIBCMD HTSetStructure $::L3_MOD_TCP_STREAM $TCPindex 0 0 tcp 0 $H $S $P
}

###############################################################################
# Will create numStreams streams starting at index 1
# Passing an array to a DEFINE command creates one than one stream
###############################################################################
proc replaceOneTCP_Vlan_Stream {H S P TCP_Vlan_index } {

   struct_new tcpV StreamTCPVLAN
        set tcpV(ucActive) 1
        set tcpV(ucProtocolType) $::STREAM_PROTOCOL_TCP_VLAN
        set tcpV(uiFrameLength) 100
        set tcpV(ucTagField) 1
        set tcpV(DestinationMAC.0)  0x02
        set tcpV(DestinationMAC.1)  0x02
        set tcpV(DestinationMAC.2)  0x02
        set tcpV(DestinationMAC.3)  0x02
        set tcpV(DestinationMAC.4)  0x02
        set tcpV(DestinationMAC.5)  0x02
        set tcpV(SourceMAC.0)  0x20
        set tcpV(SourceMAC.1)  0x20
        set tcpV(SourceMAC.2)  0x20
        set tcpV(SourceMAC.3)  0x20
        set tcpV(SourceMAC.4)  0x20
        set tcpV(SourceMAC.5)  0x20
        set tcpV(TimeToLive) 10
        set tcpV(DestinationIP.0) 10
        set tcpV(DestinationIP.1)  2
        set tcpV(DestinationIP.2)  1
        set tcpV(DestinationIP.3) 10
        set tcpV(SourceIP.0)  10
        set tcpV(SourceIP.1)  1
        set tcpV(SourceIP.2)  1
        set tcpV(SourceIP.3)  0
        set tcpV(Netmask.0)  255
        set tcpV(Netmask.1)  255
        set tcpV(Netmask.2)  255
        set tcpV(Netmask.3)  0
        set tcpV(Gateway.0)  10
        set tcpV(Gateway.1)  1
        set tcpV(Gateway.2)  1
        set tcpV(Gateway.3)  1 
        set tcpV(InitialSequenceNumber) 1
        set tcpV(SourcePort) 32806
        set tcpV(DestPort)    80
        set tcpV(TCPAck)      100
        set tcpV(TCPSequence) 200
          # set as SYN, ACK packet by ORing constants. Other constants
          # include TCP_FLAG_FIN, TCP_FLAG_RST, TCP_FLAG_URG, and TCP_FLAG_PSH
        set tcpV(Flags)       [expr $::TCP_FLAG_SYN + $::TCP_FLAG_ACK]
        set tcpV(Window)     10
        set tcpV(VLAN_Pri)   1
        set tcpV(VLAN_Cfi)   0
        set tcpV(VLAN_Vid)   100
        
   LIBCMD HTSetStructure $::L3_MOD_TCP_STREAM_VLAN 0 0 0 tcpV 0 $H $S $P
}

###############################################################################
# Replace stream at index with new UDP stream.  If index is larger than the number
# of streams on the card a new stream will be appended to the stream list
#
# For example, if there were three streams on the card (at index 1 2 and 3) and
# MOD was used with an index of 24, a new stream would be created at index 4.
# If MOD was called with an index of 2, the existing stream at index 2 would
# be replaced with new stream.
# Stream zero is always reserved, although it can accidentally be overwritten.
# Never use a MOD command with an index of zero.
###############################################################################
proc replaceOneUDPStream {H S P UDPindex} {

   struct_new udp StreamUDP
    set udp(ucActive) 1
    set udp(ucProtocolType) $::STREAM_PROTOCOL_UDP
    set udp(uiFrameLength) 512
    set udp(ucTagField) 1
    set udp(InitialSequenceNumber) 5
    set udp(DestinationMAC.0)  0x00
    set udp(DestinationMAC.1)  0x55
    set udp(DestinationMAC.2)  0x55
    set udp(DestinationMAC.3)  0x55
    set udp(DestinationMAC.4)  0x55
    set udp(DestinationMAC.5)  0x05
    set udp(SourceMAC.0)  0x00
    set udp(SourceMAC.1)  0x66
    set udp(SourceMAC.2)  0x66
    set udp(SourceMAC.3)  0x66
    set udp(SourceMAC.4)  0x66
    set udp(SourceMAC.5)  0x06
    set udp(TimeToLive) 10
    set udp(DestinationIP.0)  5
    set udp(DestinationIP.1)  5
    set udp(DestinationIP.2)  5
    set udp(DestinationIP.3)  10
    set udp(SourceIP.0)  6
    set udp(SourceIP.1)  6
    set udp(SourceIP.2)  6
    set udp(SourceIP.3)  10
    set udp(Netmask.0)  255
    set udp(Netmask.1)  255
    set udp(Netmask.2)  255
    set udp(Netmask.3)  0
    set udp(Gateway.0)  6
    set udp(Gateway.1)  6
    set udp(Gateway.2)  6
    set udp(Gateway.3)  1
     # 68 is bootpc
    set udp(UDPSrc)      68
     # 67 is bootps
    set udp(UDPDest)    67
      #calculated as a global
    #set udp(UDPLen)      $::udpLength
   LIBCMD HTSetStructure $::L3_MOD_UDP_STREAM $UDPindex 0 0 udp 0 $H $S $P
}
###########################################
# Stream extension
# Manipulate mode increments dest IP LSB
# Limit Count sets 254 flows per stream (skips 00 and FF which are normally reserved)
###########################################
proc Extension {H S P} {
struct_new extensionIP L3StreamExtension

   puts "Building extension for frame size, Burst count and frames per second"
   set extensionIP(ulFrameRate) 1000
   set extensionIP(ulTxMode) $::L3_SINGLE_BURST_MODE
   set extensionIP(ulBurstCount) $::Burst
   set extensionIP(ucStepCount) 1
   LIBCMD HTSetStructure $::L3_DEFINE_STREAM_EXTENSION 0 0 0 extensionIP 0 $H $S $P
}
###############################################################################
###############################################################################
########################    OTHER  PROCEDURES  ################################
###############################################################################
###############################################################################

################################################################################
# Check for existing link.  If linked, fall through and return.
# If not linked prompt for SMB Chassis IP.
#
# check_ip procedure is used to validate XXX.XXX.XXX.XXX format of input
# Link with valid IP reserving nothing
################################################################################
proc linkSMB {} {
   if {[ETGetLinkStatus] < 1} {
       puts " Enter SmartBits chassis IP address: "
       gets stdin ipAddr
       set ipAddr "10.98.15.11"
       NSSocketLink $ipAddr 16385 $::RESERVE_ALL
   }
}

###############################################################################
# displayCount
#
# returns number of streams on card.  There is always one hidden stream
# so transmitting count is always one less than returned value.
###############################################################################

proc displayCount {H S P} {
   struct_new DefStreams  ULong
   LIBCMD HTGetStructure $::L3_DEFINED_STREAM_COUNT_INFO 0 0 0 DefStreams 0 $H $S $P
   puts "Number of streams built on transmit card are [expr $DefStreams(ul)-1]"
   return $DefStreams(ul)
}

###############################################################################
# reset_capture
# Restarts capture on target card to capture all received frames
###############################################################################
proc resetCapture {H S P} {
struct_new CapSetup NSCaptureSetup
    set CapSetup(ulCaptureMode) $::CAPTURE_MODE_FILTER_ON_EVENTS
    set CapSetup(ulCaptureEvents) $::CAPTURE_EVENTS_ALL_FRAMES
    LIBCMD HTSetStructure $::NS_CAPTURE_SETUP 0 0 0 CapSetup 0 $H $S $P
    LIBCMD HTSetCommand $::NS_CAPTURE_START 0 0 0 0 $H $S $P
}
###############################################################################
# displayCapture
# displays the first part of packet and protocol decode.  Ethernet only.
# Only works on L3 Ethernet cards. Checks for POS cards and displays an
# error is called with a POS target.  Does not check for other types of
# cards (will error out on unsupported commands rather than giving a nice error).
###############################################################################
proc displayCapture {H S P {output stdout} } {

     LIBCMD HTSetCommand $::NS_CAPTURE_STOP 0 0 0 0 $H $S $P
   set card ""
   set cardType [HTPortProperty card $H $S $P]
   if {$cardType == 11} {
      puts "display_protocapture does not yet support POS decode"
   } else {
      struct_new CapCount NSCaptureCountInfo
      ##################################
      # First get the number of packets
      # in the capture buffer
      # If there aren't any, display an
      # error and exit
      ##################################
      LIBCMD HTGetStructure $::NS_CAPTURE_COUNT_INFO 0 0 0 CapCount 0 $H $S $P
      if {$CapCount(ulCount) < 1} {
          puts $output "No packets captured on Slot $S Port $P"
      } else {
          ####################################
          # We have packets to display
          # Display count and create structure
          # for data
          ####################################
          puts $output "Displaying $CapCount(ulCount) packets captured on card [expr $S + 1]"
          struct_new CapData NSCaptureDataInfo
          #################################
          # from first to as many packets
          # as there are on the card
          #################################
          for {set i 0} {$i < $CapCount(ulCount)} {incr i} {
            set CapData(ulFrameIndex) $i
            set CapData(ulByteOffset) 0
            set CapData(ulRequestedLength) 2048
            LIBCMD HTGetStructure $::NS_CAPTURE_DATA_INFO $i 1 0 CapData 0 $H $S $P
             # display packet number
             puts $output ""
             puts $output "-----------------------"
             puts $output "PACKET $i - "
             puts $output "-----------------------"

             puts $output "=== ETHERNET LAYER DECODE ==="
             puts -nonewline $output  "       Destination MAC ==> "
             for {set p 0} {$p < 5} {incr p} {
                puts  -nonewline $output "[format %02X $CapData(ucData.$p._ubyte_)]:"
             }
             puts $output "[format %02X $CapData(ucData.$p._ubyte_)]"
             puts -nonewline $output "       Source MAC      ==> "
             for {set p 6} {$p < 11} {incr p} {
                puts  -nonewline $output "[format %02X $CapData(ucData.$p._ubyte_)]:"
             }
             puts $output "[format %02X $CapData(ucData.$p._ubyte_)]"
             puts -nonewline $output "       Ethertype       ==> "
             set eType "[format %02X $CapData(ucData.12._ubyte_)][format %02X $CapData(ucData.13._ubyte_)]"
             puts $output "$eType"
             switch $eType {
                0800 {
                     set ipOffset 26
                     puts $output "=== IP LAYER DECODE ==="
                     puts -nonewline $output "       Source IP       ==> "
                     for {set q $ipOffset} {$q < [expr $ipOffset + 3]} {incr q} {
                        puts  -nonewline $output "$CapData(ucData.$q._ubyte_)."
                     }
                     puts $output "$CapData(ucData.$q._ubyte_)"
                     puts -nonewline $output "       Destination IP  ==> "
                     for {set q [expr $ipOffset + 4]} {$q < [expr $ipOffset + 7]} {incr q} {
                        puts  -nonewline $output "$CapData(ucData.$q._ubyte_)."
                     }
                     puts $output "$CapData(ucData.$q._ubyte_)"
                     }
                8100 {
                     set ipOffset 30
                     puts $output "=== IP (VLAN) LAYER DECODE ==="
                     puts -nonewline $output "       Source IP       ==> "
                     for {set q $ipOffset} {$q < [expr $ipOffset + 3]} {incr q} {
                        puts  -nonewline $output "$CapData(ucData.$q._ubyte_)."
                     }
                     puts $output "$CapData(ucData.$q._ubyte_)"
                     puts -nonewline $output "       Destination IP  ==> "
                     for {set q [expr $ipOffset + 4]} {$q < [expr $ipOffset + 7]} {incr q} {
                        puts  -nonewline $output "$CapData(ucData.$q._ubyte_)."
                     }
                     puts $output "$CapData(ucData.$q._ubyte_)"
                     }
                0806 {
                     puts "ARP PACKET"
                     }
                8035 {
                     puts "RARP PACKET"
                     }
                8137 {
                     puts "IPX PACKET"
                     }
                8808 {
                     puts "PAUSE PACKET"
                     }
                default {
                     puts "NO DECODE AVAILABLE FOR THIS PACKET TYPE"
                     }
             }

             ################################################
             # from the first byte to end of packet or 96 bytes
             ################################################
             if {$CapData(ulRetrievedLength) > 128} {
                set pkts2Show 128
             } else {
                set pkts2Show $CapData(ulRetrievedLength)
             }
             for {set j 0} {$j < $pkts2Show} {incr j} {
                ######################################
                # put a newline every 16 bytes
                ######################################
                if {[expr $j % 16] == 0} {
                   puts $output "  "
                   ##################################
                   # put bute number in first column
                   ##################################
                   puts -nonewline $output [format "%4i:   " $j]
                }
                   ##################################
                   # put a space then the byte in hex
                   # with two spaces with leading zero
                   # note _ubyte_  usage
                   ##################################
                   puts -nonewline $output " "
                   puts -nonewline $output [format "%02X" $CapData(ucData.$j._ubyte_)]
             }
           #########################
             # If we're sending to the
             # screen, give the user
             # a chance to quit
             #########################
             puts $output "\n"
             if {$output == "stdout"} {
                puts "Press ENTER key to continue, Q to quit"
                gets stdin response
                if {$response == "Q" || $response == "q"} {
                 break
              }
             }
         }
     }
   }
}
################################################################################
################################################################################
##########################     MAIN  PROGRAM    ################################
################################################################################
################################################################################

# link to SmartBits chassis
linkSMB

# creating one stream
puts "Creating first stream"
createOneStream $iHub $iSlot $iPort
Extension $iHub $iSlot $iPort

# create an array of streams
set copies2Make [expr $totalStreams - 1]
createMultiCopies $iHub $iSlot $iPort $firstStream $copies2Make

replaceOneTCPStream $iHub $iSlot $iPort $TCPindex
replaceOneUDPStream $iHub $iSlot $iPort $UDPindex

replaceOneTCP_Vlan_Stream $iHub $iSlot $iPort $TCP_Vlan_index
displayCount $iHub $iSlot $iPort
#set capture on card 2 send a one second burst and display captured packets
puts "Starting capture and transmitting"
resetCapture $iHub2 $iSlot2 $iPort2
LIBCMD HTRun $HTRUN $iHub $iSlot $iPort
after 1000
LIBCMD HTRun $HTSTOP $iHub $iSlot $iPort
displayCapture $iHub2 $iSlot2 $iPort2

NSUnLink

Attachments


Product : Automation,SmartBits,SmartBits