diff --git a/FT2Classic.tcl b/FT2Classic.tcl new file mode 100644 index 0000000..d77d854 --- /dev/null +++ b/FT2Classic.tcl @@ -0,0 +1,2640 @@ +package provide Ixia 1.0 +global env +source $env(IXIA_LIB) +source $env(ixTclNetwork)/pkgIndex.tcl +if {[info exists env(IxiaLibPath)]} { + set path $env(IxiaLibPath) +} +if {[info exist env(clear_stats)]} { + set apiData(clear_stats) $env(clear_stats) +} + +namespace eval ixia { + set ::ixia::TclInterp [interp create classic] + interp eval $::ixia::TclInterp "package require Ixia" + package require IxTclNetwork +} +array set apiData {} +global env +global stream_name +set stream_name 1 + +if {[info exist env(ixnetwork_tcl_server)]} { + set apiData(tcl_server) $env(ixnetwork_tcl_server) +} else { + error "no tcl_server value given. please set it in env variable \"ixnetwork_tcl_server \"" +} + +proc debug_old {{s {}}} { + if ![info exists ::bp_skip] { + set ::bp_skip [list] + } elseif {[lsearch -exact $::bp_skip $s]>=0} return + if [catch {info level -1} who] {set who ::} + while 1 { + ##puts -nonewline "$who/$s> "; flush stdout + #puts -nonewline "$s> "; flush stdout + gets stdin line + if {$line=="c"} {#puts "continuing.."; break} + if {$line=="i"} {set line "info locals"} + if {$line=="e"} {set line "exit 1"} + catch {uplevel 1 $line} res + #puts $res + } +} + +proc expand_ipv6 {args} { + set ipAddress $args + if {[regexp -nocase {^([a-fA-F0-9]+)::([a-fA-F0-9]+)$} $ipAddress match m11 m12]} { + set ipAddress $m11:0:0:0:0:0:0:$m12 + } elseif {[regexp -nocase {^([a-fA-F0-9]+):([a-fA-F0-9]+)::([a-fA-F0-9]+)$} $ipAddress match m1 m2 m3]} { + set ipAddress $m1:$m2:0:0:0:0:0:$m3 + } elseif {[regexp -nocase {^([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+)::([a-fA-F0-9]+)$} $ipAddress match m1 m2 m3 m4]} { + set ipAddress $m1:$m2:$m3:0:0:0:0:$m4 + } elseif {[regexp -nocase {^([a-fA-F0-9]+):([a-fA-F0-9]+)::([a-fA-F0-9]+):([a-fA-F0-9]+)$} $ipAddress match m1 m2 m3 m4]} { + set ipAddress $m1:$m2:0:0:0:0:$m3:$m4 + } else { + set ipAddress $ipAddress + } + return $ipAddress +} + +proc get_emulation_handle_ipv6 {ipAddress } { + + #package require IxTclNetwork + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + + set handle_list "" + + foreach vport_handle $vports { + set interfaces [interp eval $::ixia::TclInterp " ixNet getList $vport_handle interface"] + if {![string match $interfaces ""]} { + foreach intf $interfaces { + set val [catch {interp eval $::ixia::TclInterp " ixNet getA $intf/ipv6:1 -ip " } getIp] + if {[regexp -nocase {is null} $getIp match]} { + #puts "ip is null" + } else { + + if {[string match $getIp [expand_ipv6 $ipAddress]]} { + #puts "appending handle $intf" + lappend handle_list $intf + } + } + } + } + + set route_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/ospf router"] + if {![string match $route_handles ""]} { + foreach rthdl $route_handles { + set routeRanges_hdls [interp eval $::ixia::TclInterp " ixNet getL $rthdl routeRange"] + if {![string match $routeRanges_hdls ""]} { + foreach rtRangeHdl $routeRanges_hdls { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $rtRangeHdl -networkNumber"] + if {[string match $getIp [expand_ipv6 $ipAddress]]} { + lappend handle_list $rtRangeHdl + } + } + } + } + } + + set route_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/isis router"] + if {![string match $route_handles ""]} { + foreach rthdl $route_handles { + set routeRanges_hdls [interp eval $::ixia::TclInterp " ixNet getL $rthdl routeRange"] + if {![string match $routeRanges_hdls ""]} { + foreach rtRangeHdl $routeRanges_hdls { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $rtRangeHdl -firstRoute"] + if {[string match $getIp [expand_ipv6 $ipAddress]]} { + lappend handle_list $rtRangeHdl + } + } + } + } + } + + + set route_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/bgp neighborRange"] + if {![string match $route_handles ""]} { + foreach rthdl $route_handles { + set routeRanges_hdls [interp eval $::ixia::TclInterp " ixNet getL $rthdl routeRange"] + if {![string match $routeRanges_hdls ""]} { + foreach rtRangeHdl $routeRanges_hdls { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $rtRangeHdl -networkAddress"] + if {[string match $getIp [expand_ipv6 $ipAddress]]} { + lappend handle_list $rtRangeHdl + } + } + } + } + } + } + return $handle_list +} + +proc get_emulation_handle {ipAddress } { + + #package require IxTclNetwork + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + + set handle_list "" + + foreach vport_handle $vports { + set interfaces [interp eval $::ixia::TclInterp " ixNet getList $vport_handle interface"] + if {![string match $interfaces ""]} { + foreach intf $interfaces { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $intf/ipv4 -ip "] + if {[string match $getIp $ipAddress]} { + lappend handle_list $intf + } + } + } + + set route_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/ospf router"] + if {![string match $route_handles ""]} { + foreach rthdl $route_handles { + set routeRanges_hdls [interp eval $::ixia::TclInterp " ixNet getL $rthdl routeRange"] + if {![string match $routeRanges_hdls ""]} { + foreach rtRangeHdl $routeRanges_hdls { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $rtRangeHdl -networkNumber"] + if {[string match $getIp $ipAddress]} { + lappend handle_list $rtRangeHdl + } + } + } + } + } + + set route_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/isis router"] + if {![string match $route_handles ""]} { + foreach rthdl $route_handles { + set routeRanges_hdls [interp eval $::ixia::TclInterp " ixNet getL $rthdl routeRange"] + if {![string match $routeRanges_hdls ""]} { + foreach rtRangeHdl $routeRanges_hdls { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $rtRangeHdl -firstRoute"] + if {[string match $getIp $ipAddress]} { + #puts "getting handle" + lappend handle_list $rtRangeHdl + } + } + } + } + } + + + set route_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/bgp neighborRange"] + if {![string match $route_handles ""]} { + foreach rthdl $route_handles { + set routeRanges_hdls [interp eval $::ixia::TclInterp " ixNet getL $rthdl routeRange"] + if {![string match $routeRanges_hdls ""]} { + foreach rtRangeHdl $routeRanges_hdls { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $rtRangeHdl -networkAddress"] + if {[string match $getIp $ipAddress]} { + lappend handle_list $rtRangeHdl + } + } + } + } + } + + set igmp_host_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/igmp host"] + if {![string match $igmp_host_handles ""]} { + foreach igmp_handle $igmp_host_handles { + set igmp_group_handles [interp eval $::ixia::TclInterp " ixNet getL $igmp_handle group"] + if {![string match $igmp_group_handles ""]} { + foreach igmp_group_handle $igmp_group_handles { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $igmp_group_handles -groupFrom"] + if {[string match $getIp $ipAddress]} { + lappend handle_list $igmp_group_handles + } + } + } + } + } + set igmp_querier_handles [interp eval $::ixia::TclInterp " ixNet getL $vport_handle/protocols/igmp querier"] + if {![string match $igmp_querier_handles ""]} { + foreach igmp_querier_handle $igmp_querier_handles { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $igmp_querier_handle -querierAddress"] + if {[string match $getIp $ipAddress]} { + lappend handle_list $igmp_querier_handle + } + } + } + } + return $handle_list +} + +proc mcastIPv6ToMac { mcastIP } { + + set mcastMac 0000.0000.0000 + set mcastIP [get_ipv6_full_add $mcastIP] + if { ![ regexp {([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+)} \ + $mcastIP dump oct1 oct2 oct3 oct4 oct5 oct6 oct7 oct8] } { + puts "invalid ip format" + return $mcastMac + } + + if { [expr 0x$oct1] < 65281 || [expr 0x$oct1] > 65535 } { + puts "invlaid mcast IPv6" + return $mcastMac + } + catch { unset mcastMac } + + set oct7 [format "%04s" $oct7] + set oct8 [format "%04s" $oct8] + lappend mcastMac 3333 $oct7 $oct8 + regsub -all { } $mcastMac {.} mcastMac + + return $mcastMac +} + +proc get_ipv6_full_add { add } { + set ipv6_split [split $add ":"] + set no_hex 1 + foreach hex $ipv6_split { + if {$no_hex < 8 && $hex != ""} { + incr no_hex + append full_add "$hex:" + } elseif {$hex == ""} { + set empty_idx [lsearch $ipv6_split ""] + set length [llength $ipv6_split] + set rem_hex [expr [expr $length - $empty_idx] - 1] + for {set i $empty_idx} {$i < [expr 8-$rem_hex]} {incr i} { + incr no_hex + append full_add "0:" + } + if {$rem_hex == 1 && \ + [lindex $ipv6_split [expr $length-1]] == ""} { + append full_add "0" + break + } + } else { + append full_add "$hex" + } + } + return $full_add +} + +proc Parse_Dashed_Args {args} { + global apiData + set parse_args "" + regsub -all "^{|}$" $args "" args + set args [split $args " "] + for { set i 0 } { $i < [llength $args]} { incr i } { + set arg [lindex $args $i] + if {$arg != ""} { + set arg [string trim $arg] + switch -regexp -- $arg { + "-reset|-arp" { + if {[regexp -nocase "^-" [lindex $args [expr $i + 1]] match]} { + set $arg "1" + append parse_args " " "$arg 1" + } else { + append parse_args " " $arg + } + } + default { + append parse_args " " "$arg" + } + } + } + } + set parse_args [lsearch -all -inline -not -exact $parse_args {}] + set key "" + set val "" + foreach ele $parse_args { + if {[string equal $ele {}]} { + continue + } + + if {[regexp -nocase "^-" $ele]} { + if {![string equal $key ""]} { + keylset apiData(parse_args) $key $val + set key "" + set val "" + } + } + if {[regexp -nocase "^-" $ele]} { + set key $ele + } else { + lappend val $ele + } + } + keylset apiData(parse_args) $key $val + + return $parse_args +} + + +proc ::ixia::executeInChild {args} { + set api [lindex $args 0] + set args [lindex $args 1] + return [interp eval $::ixia::TclInterp "::ixia::$api $args"] +} + +proc ::ixia::emulation_oam_config_msg {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "emulation_oam_config_msg $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_client_global_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_client_global_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rsvp_tunnel_config {args} { + set api "emulation_rsvp_tunnel_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_eigrp_config {args} { + set api "emulation_eigrp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::uds_filter_pallette_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "uds_filter_pallette_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_stp_control {args} { + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_stp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_efm_config {args} { + set api "emulation_efm_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::interface_config {args} { + puts "inside wrapper ::ixia::interface_config" + global apiData + set args1 $args + Convert_List_To_Keyedlist $args1 + #puts "inside wrapper ::ixia::interface_config" + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split3_width'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split3_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'integrity_signature'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pcs_marker_fields'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_byte_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split1_mask'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'signature_start_offset'} + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + + + # #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_stats'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split3_mask'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'rpr_hec_seed'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'signature_mask'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split2_width'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'tx_lanes'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_pattern_mask'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split3_offset_from'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'sequence_num_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'router_solicitation_retries'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'integrity_signature_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'signature_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pcs_period'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'signature'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_mask'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split2_offset_from'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pcs_sync_bits'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_pattern_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split1_offset_from'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'sequence_checking'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'bert_configuration'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split2_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pcs_period_type'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_packet_type'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_split2_mask'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pgid_128k_bin_enable'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pcs_repeat'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'bert_error_insertion'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pcs_lane'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_pattern_match'} + if {[lsearch $args "-ipv4_prefix_length"] != -1} { + set ipv4_length [keylget apiData(expArgs) -ipv4_prefix_length] + set ipv4PrefixLength [ subnetmaskToCIDR $ipv4_length ] + keyldel apiData(expArgs) -ipv4_prefix_length + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + lappend args -ipv4_prefix_length $ipv4PrefixLength + } + + if {[lsearch $args "-signature"] != -1} { + keyldel apiData(expArgs) -signature + } + if {[lsearch $args "-signature_offset"] != -1} { + keyldel apiData(expArgs) -signature_offset + } + if {[lsearch $args "-pgid_mode"] != -1} { + set pgid_mode [keylget apiData(expArgs) -pgid_mode] + if {[string equal $pgid_mode "custom"]} { + keyldel apiData(expArgs) -pgid_mode + } + } + if {[lsearch $args "-pgid_offset"] != -1} { + set pgid_offset [keylget apiData(expArgs) -pgid_offset] + keyldel apiData(expArgs) -pgid_offset + } + + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + + if {[lsearch $args "-gateway"] == -1} { + if {[lsearch $args "-intf_ip_addr"] != -1} { + set ipv4Address [keylget apiData(expArgs) -intf_ip_addr] + regexp -nocase {^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$} $ipv4Address match m1 m2 m3 m4 + set m5 [expr $m4-1] + set gatewayIp $m1.$m2.$m3.$m5 + lappend args -gateway $gatewayIp + } + } + if {[lsearch $args "-ipv6_gateway"] == -1} { + if {[lsearch $args "-ipv6_intf_addr"] != -1} { + set ipv6Address [keylget apiData(expArgs) -ipv6_intf_addr] + set ipv6 [expand_ipv6 $ipv6Address] + regexp -nocase {^([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+)$} $ipv6 match m1 m2 m3 m4 m5 m6 m7 m8 + if {$m8 == 1} { + set m9 [expr $m8+1] + set gatewayIp $m1:$m2:$m3:$m4:$m5:$m6:$m7:$m9 + lappend args -ipv6_gateway $gatewayIp + } else { + set m9 [expr $m8-1] + set gatewayIp $m1:$m2:$m3:$m4:$m5:$m6:$m7:$m9 + lappend args -ipv6_gateway $gatewayIp + } + } + } + if {[lsearch $args "-arp_send_req"] != -1} { + if {[lsearch $args "-arp"] == -1} { + lappend args -arp 1 + } + if {[lsearch $args "-arp_on_linkup"] == -1} { + lappend args -arp_on_linkup 1 + } + if {[lsearch $args "-arp_req_retries"] == -1} { + lappend args -arp_req_retries "" + } + if {[lsearch $args "-arp_refresh_interval"] == -1} { + lappend args -arp_refresh_interval 60 + } + } + puts $args + set api "interface_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_links_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_links_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_stp_bridge_config {args} { + #Body { Arguments with no mandatory tag argument 'auto_pick_bridge_mac'} + #Body { Arguments with no mandatory tag argument 'port_no_intf_step'} + #Body { Arguments with no mandatory tag argument 'cst_root_priority'} + #Body { Arguments with no mandatory tag argument 'jitter_percentage'} + #Body { Arguments with no mandatory tag argument 'cist_reg_root_mac'} + #Body { Arguments with no mandatory tag argument 'intf_ipv6_addr'} + #Body { Arguments with no mandatory tag argument 'cist_external_root_priority'} + #Body { Arguments with no mandatory tag argument 'intf_ip_addr_bridge_step'} + #Body { Arguments with no mandatory tag argument 'max_age'} + #Body { Arguments with no mandatory tag argument 'intf_count'} + #Body { Arguments with no mandatory tag argument 'auto_pick_port'} + #Body { Arguments with no mandatory tag argument 'override_tracking'} + #Body { Arguments with no mandatory tag argument 'root_priority'} + #Body { Arguments with no mandatory tag argument 'inter_bdpu_gap'} + #Body { Arguments with no mandatory tag argument 'vlan_user_priority'} + #Body { Arguments with no mandatory tag argument 'count'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'bridge_mac_step'} + #Body { Arguments with no mandatory tag argument 'bridge_priority'} + #Body { Arguments with no mandatory tag argument 'cist_external_root_mac'} + #Body { Arguments with no mandatory tag argument 'port_priority'} + #Body { Arguments with no mandatory tag argument 'mstc_name'} + #Body { Arguments with no mandatory tag argument 'intf_ip_addr_step'} + #Body { Arguments with no mandatory tag argument 'bridge_msti_vlan'} + #Body { Arguments with no mandatory tag argument 'intf_ipv6_addr_bridge_step'} + #Body { Arguments with no mandatory tag argument 'mstc_revision'} + #Body { Arguments with no mandatory tag argument 'port_no'} + #Body { Arguments with no mandatory tag argument 'reset'} + #Body { Arguments with no mandatory tag argument 'mac_address_init'} + #Body { Arguments with no mandatory tag argument 'message_age'} + #Body { Arguments with no mandatory tag argument 'cist_remaining_hop'} + #Body { Arguments with no mandatory tag argument 'mtu'} + #Body { Arguments with no mandatory tag argument 'mode'} + #Body { Arguments with no mandatory tag argument 'cist_reg_root_cost'} + #Body { Arguments with no mandatory tag argument 'cist_external_root_cost'} + #Body { Arguments with no mandatory tag argument 'bridge_mac'} + #Body { Arguments with no mandatory tag argument 'intf_gw_ip_addr_step'} + #Body { Arguments with no mandatory tag argument 'override_existence_check'} + #Body { Arguments with no mandatory tag argument 'intf_ip_addr'} + #Body { Arguments with no mandatory tag argument 'port_no_bridge_step'} + #Body { Arguments with no mandatory tag argument 'hello_interval'} + #Body { Arguments with no mandatory tag argument 'cist_reg_root_priority'} + #Body { Arguments with no mandatory tag argument 'mac_address_bridge_step'} + #Body { Arguments with no mandatory tag argument 'intf_ipv6_addr_step'} + #Body { Arguments with no mandatory tag argument 'port_handle'} + #Body { Arguments with no mandatory tag argument 'bridge_system_id'} + #Body { Arguments with no mandatory tag argument 'root_cost'} + #Body { Arguments with no mandatory tag argument 'vlan_id'} + #Body { Arguments with no mandatory tag argument 'cst_root_path_cost'} + #Body { Arguments with no mandatory tag argument 'link_type'} + #Body { Arguments with no mandatory tag argument 'enable_jitter'} + #Body { Arguments with no mandatory tag argument 'root_mac'} + #Body { Arguments with no mandatory tag argument 'vlan_id_intf_step'} + #Body { Arguments with no mandatory tag argument 'cst_root_mac_address'} + #Body { Arguments with no mandatory tag argument 'root_system_id'} + #Body { Arguments with no mandatory tag argument 'vlan'} + #Body { Arguments with no mandatory tag argument 'intf_cost'} + #Body { Arguments with no mandatory tag argument 'cst_vlan_port_priority'} + #Body { Arguments with no mandatory tag argument 'intf_ip_prefix_length'} + #Body { Arguments with no mandatory tag argument 'vlan_id_bridge_step'} + #Body { Arguments with no mandatory tag argument 'intf_ipv6_prefix_length'} + #Body { Arguments with no mandatory tag argument 'intf_gw_ip_addr'} + #Body { Arguments with no mandatory tag argument 'interface_handle'} + #Body { Arguments with no mandatory tag argument 'pvid'} + #Body { Arguments with no mandatory tag argument 'mac_address_intf_step'} + #Body { Arguments with no mandatory tag argument 'intf_gw_ip_addr_bridge_step'} + #Body { Arguments with no mandatory tag argument 'vlan_user_priority_bridge_step'} + #Body { Arguments with no mandatory tag argument 'bridge_mode'} + #Body { Arguments with no mandatory tag argument 'forward_delay'} + set api "emulation_stp_bridge_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_custom_tlv_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_custom_tlv_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pbb_info {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_pbb_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_igmp_info {args} { + set api "emulation_igmp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::get_nodrop_rate {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'run_time_sec'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'stream_mode'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'min_percent'} + #Body { Need to fill equivalent logic in classic for FT Mandatory argument 'max_rate'} + #Body { Need to fill equivalent logic in classic for FT Mandatory argument 'rx_port_handle'} + #Body { Need to fill equivalent logic in classic for FT Mandatory argument 'stream_id'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'poll_timeout_sec'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'tolerance'} + #Body { Need to fill equivalent logic in classic for FT Mandatory argument 'tx_port_handle'} + set api "get_nodrop_rate $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bgp_config {args} { + global apiData + set args1 $args + Convert_List_To_Keyedlist $args1 + if {[lsearch $args "-mac_address_start"] != -1} { + puts "removing -mac_address_start" + keyldel apiData(expArgs) -mac_address_start + } + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + +# if {[lsearch $args "-port_handle"] != -1} { +# set portList [keylget apiData(expArgs) -port_handle] +# if {[llength $portList] > 1} { +# puts "remove port_handle" +# #set args [lreplace $args [lsearch $args $i] [lsearch $args $i]+1] +# #interpreter +# #set args [lreplace $args [lsearch $args "-port_handle"] [lsearch $args "-port_handle"]+1] +# set args [lreplace $args [lsearch $args "-port_handle"] [expr {[lsearch $args "-port_handle"] + 1}]] +# set port [lindex $portList 0] +# lappend args -port_handle $port +# set api "emulation_bgp_config $args" +# return [::ixia::executeInChild $api] +# } else { +# +# if {[lsearch $args "-mac_address_start"] != -1} { +# set srcmac [keylget apiData(expArgs) -mac_address_start] +# set api "interface_config -mode destroy -src_mac_addr $srcmac -port_handle $portList" +# puts "interface_config destroy is $api" +# set ret [::ixia::executeInChild $api] +# puts "return is $ret" +# +# } + + + set api "emulation_bgp_config $args" + return [::ixia::executeInChild $api] +# } +# } +} + +proc ::ixia::emulation_igmp_config {args} { +# puts "inside wrapper ::ixia::emulation_config" +# global apiData +# set args1 $args +# Convert_List_To_Keyedlist $args +# if {[lsearch $args -ipv4_prefix_length ] != -1} { +# set args [lremove $args -ipv4_prefix_length] + +# } + puts $args + global apiData + if {[lsearch $args "-intf_prefix_len"] != -1} { + Convert_List_To_Keyedlist $args + set intf_len [keylget apiData(expArgs) -intf_prefix_len] + set intfPrefixLen [ subnetmaskToCIDR $intf_len ] + keyldel apiData(expArgs) -intf_prefix_len + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + lappend args -intf_prefix_len $intfPrefixLen + } + + if {[lsearch $args "-ipv4_prefix_length"] != -1} { + Convert_List_To_Keyedlist $args + set ipv4_length [keylget apiData(expArgs) -ipv4_prefix_length] + set ipv4PrefixLength [ subnetmaskToCIDR $ipv4_length ] + keyldel apiData(expArgs) -ipv4_prefix_length + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + lappend args -ipv4_prefix_length $ipv4PrefixLength + } + set args1 $args + Convert_List_To_Keyedlist $args1 + if {[lsearch $args "-igmp_version"] !=-1} { + set igmp_version [keylget apiData(expArgs) -igmp_version] + if {[string match $igmp_version "v3"]} { + if {[lsearch $args "-filter_mode"] == -1} { + lappend args -filter_mode include + } + } + } + + if {[lsearch $args "-unsolicited_report_interval"] == -1} { + lappend args -unsolicited_report_interval 120 + } + if {[lsearch $args "-ip_router_alert"] == -1} { + lappend args -ip_router_alert 1 + } else { + set ip_router_alert [keylget apiData(expArgs) -ip_router_alert] + if {[string match $ip_router_alert 0]} { + Convert_List_To_Keyedlist $args + keyldel apiData(expArgs) -ip_router_alert + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + lappend args -ip_router_alert 1 + } + } + + set api "emulation_igmp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_control {args} { + set api "emulation_dhcp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_isis_control {args} { + set api "emulation_isis_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::interface_stats {args} { + #Body { Arguments with no mandatory tag argument 'port_handle'} + set api "interface_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_multicast_source_config {args} { + set api "emulation_multicast_source_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_multicast_group_config {args} { + set api "emulation_multicast_group_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::cleanup_session {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'reset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'port_handle'} + set api "cleanup_session $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ospf_lsa_config {args} { + set api "emulation_ospf_lsa_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_eigrp_control {args} { + set api "emulation_eigrp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::vport_info {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "vport_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bgp_control {args} { + set api "emulation_bgp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rsvp_control {args} { + set api "emulation_rsvp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ospf_topology_route_config {args} { + global apiData + set args_list [Parse_Dashed_Args $args] + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } else { + set mod [keylget apiData(parse_args) -mode] + if {[string equal "create" $mod]} { + if {[lsearch $args "-type"] == -1} { + error "Missing Mandatory Argument \"-type\"" + } + if {[lsearch $args "-handle"] == -1} { + error "Missing Mandatory Argument \"handle\"" + } + } elseif {[string equal "modify" $mod] || [string equal "enable" $mod] || [string equal "disable" $mod]} { + if {[lsearch $args "-type"] == -1} { + error "Missing Mandatory Argument \"-type\"" + } + if {[lsearch $args "-handle"] == -1} { + error "Missing Mandatory Argument \"handle\"" + } + if {[lsearch $args "-elem_handle"] == -1} { + error "Missing Mandatory Argument \"elem_handle\"" + } + + } elseif {[string equal "delete" $mod]} { + if {[lsearch $args "-handle"] == -1} { + error "Missing Mandatory Argument \"handle\"" + } + if {[lsearch $args "-elem_handle"] == -1} { + error "Missing Mandatory Argument \"elem_handle\"" + } + } + } + set api "emulation_ospf_topology_route_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::packet_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'packet_type' + if {[lsearch $args "-packet_type"] == -1} { + #error "Missing Mandatory Argument \"packet_type\"" + lappend args -packet_type both + } + set api "packet_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::traffic_stats {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_counter_vci_data_item_list'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_counter_vpi_type'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_counter_vpi_mode'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_reassembly_enable_iptcpudp_checksum'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_reassembly_encapsulation'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_counter_vci_mode'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_counter_vpi_data_item_list'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_reassembly_enable_ip_qos'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'ignore_rate'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'qos_stats'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci_count'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'packet_group_id'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_counter_vci_type'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci'} + sleep 30 + global env + if {[info exists env(findNdr)]} { + set findndr $env(findNdr) + } else { + set findndr "" + } + global apiData + set args2 $args + Convert_List_To_Keyedlist $args2 + set pgidStr "pgid" + if {[lsearch $args "-packet_group_id"] != -1} { + set pgid [expr [keylget apiData(expArgs) -packet_group_id]-1] + puts "pgid: $pgid" + puts "Removing -packet_group_id " + keyldel apiData(expArgs) -packet_group_id + set pgidStr "pgid" + } + set api "traffic_stats $args" + set stats [::ixia::executeInChild $api] + set ports [list [keylget apiData(expArgs) -port_handle]] + regsub -all "{" $ports {} ports + regsub -all "}" $ports {} ports + set portLength [llength $ports] + set i 1 + foreach port $ports { + if {[catch {keylget stats $port.aggregate.rx.pkt_count} errmsg]} { + puts "This port dont have pkt_count: $port" + #keylset stats $port.aggregate.rx.uds1_count "NA" + } else { + set pkts [keylget stats $port.aggregate.rx.pkt_count] + keylset stats $port.aggregate.rx.uds1_count $pkts + sleep 5 + } + if {[catch {keylget apiData(expArgs) -mode} errmsg]} { + puts "Traffic stats doesn't have mode param" + } else { + set mod [keylget apiData(expArgs) -mode] + if {[string equal $mod "stream"]} { + if {[string match $findndr "ndr"]} { + set streamValues [keylget stats $port.stream] + foreach streamValue $streamValues { + set value [lindex $streamValue 0] + break + } + if {$i<=$portLength} { + set newValue [string trim $value] + regsub -all "$newValue" $stats $i stats + set i [expr {$i + 1}] + } + } + if {[string equal "pgid" $pgidStr]} { + set streamValues [keylget stats $port.stream] + foreach streamValue $streamValues { + set value [lindex $streamValue 0] + break + } + set newValue [string trim $value] + if {[catch {keylget stats $port.stream.$newValue.rx.total_pkts} errmsg]} { + puts "This port $port not have rx details" + } else { + set pktCount [keylget stats $port.stream.$newValue.rx.total_pkts] + keylset stats $port.$pgidStr.rx.pkt_count.$pgid $pktCount + } + } + } + } + } + if {[catch {keylget stats aggregate.rx.uds1_frame_count.max} errmsg]} { + puts "Traffic stats doesn't have User Defined stats" + } else { + set udsmin [keylget stats aggregate.rx.data_int_frames_count.min] + set udsmax [keylget stats aggregate.rx.data_int_frames_count.max] + set udsavg [keylget stats aggregate.rx.data_int_frames_count.avg] + set uds1max [keylget stats aggregate.rx.uds1_frame_count.max] + if {[string equal $uds1max "0"]} { + keylset stats aggregate.rx.uds1_frame_count.min $udsmin + keylset stats aggregate.rx.uds1_frame_count.max $udsmax + keylset stats aggregate.rx.uds1_frame_count.avg $udsavg + } + } + if {0} { + if {[catch {keylget stats $port.aggregate.rx.uds2_frame_count} errmsg]} { + puts "This port dont have uds2_frame_count: $port" + #set udsCount [keylget stats $port.aggregate.rx.uds2_frame_count] + keylset stats $port.aggregate.rx.uds_count2 "NA" + } else { + set udsCount [keylget stats $port.aggregate.rx.uds2_frame_count] + keylset stats $port.aggregate.rx.uds_count2 $udsCount + } + } + return $stats +} + +proc ::ixia::emulation_twamp_test_range_config {args} { + set api "emulation_twamp_test_range_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::pppox_control {args} { + set api "pppox_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_stp_msti_config {args} { + #Body { Arguments with no mandatory tag argument 'msti_mac_step'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'msti_vlan_stop_step'} + #Body { Arguments with no mandatory tag argument 'msti_vlan_start_step'} + #Body { Arguments with no mandatory tag argument 'msti_vlan_start'} + #Body { Arguments with no mandatory tag argument 'msti_wildcard_percent_start'} + #Body { Arguments with no mandatory tag argument 'msti_internal_root_path_cost'} + #Body { Arguments with no mandatory tag argument 'msti_wildcard_percent_enable'} + #Body { Arguments with no mandatory tag argument 'count'} + #Body { Arguments with no mandatory tag argument 'msti_id'} + #Body { Arguments with no mandatory tag argument 'msti_mac'} + #Body { Arguments with no mandatory tag argument 'msti_hops'} + #Body { Arguments with no mandatory tag argument 'msti_port_priority'} + #Body { Arguments with no mandatory tag argument 'msti_id_step'} + #Body { Arguments with no mandatory tag argument 'msti_vlan_stop'} + #Body { Arguments with no mandatory tag argument 'bridge_handle'} + #Body { Arguments with no mandatory tag argument 'msti_priority'} + #Body { Arguments with no mandatory tag argument 'msti_name'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_stp_msti_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_fport_options_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "fc_fport_options_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::pppox_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'protocol' + if {[lsearch $args "-protocol"] == -1} { + error "Missing Mandatory Argument \"protocol\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'encap' + if {[lsearch $args "-encap"] == -1} { + error "Missing Mandatory Argument \"encap\"" + } + set api "pppox_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ospf_control {args} { + set api "emulation_ospf_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bfd_config {args} { + set api "emulation_bfd_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_oam_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'action' + if {[lsearch $args "-action"] == -1} { + error "Missing Mandatory Argument \"action\"" + } + set api "emulation_oam_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_efm_stat {args} { + set api "emulation_efm_stat $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ospf_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'intf_ip_addr_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'loopback_ip_addr'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'neighbor_intf_ip_addr_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'atm_encapsulation'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'neighbor_intf_ip_addr'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'loopback_ip_addr_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vlan_id_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vlan_user_priority'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'intf_ip_addr'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'mac_address_init'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vlan_id_mode'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vlan_id'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'intf_prefix_length'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci'} + + #global connect_output apiData + #set intfArgs {} + #set unconnectedIntfArgs {} + #if {[lsearch $args -reset ] != -1} { + # set args [lremove $args -reset] + #} + # + #set args2 $args + #Convert_List_To_Keyedlist $args2 + + #if {[lsearch $args "-mac_address_init"] != -1} { + # set srcmac [keylget apiData(expArgs) -mac_address_init] + # lappend intfArgs -src_mac_addr $srcmac + # keyldel apiData(expArgs) -mac_address_init + #} + + #if {[lsearch $args "-intf_ip_addr"] != -1} { + # set mac [keylget apiData(expArgs) -intf_ip_addr] + # lappend intfArgs -intf_ip_addr $mac + # lappend unconnectedIntfArgs -gateway $mac + # keyldel apiData(expArgs) -intf_ip_addr + #} + # + #if {[lsearch $args "-neighbor_intf_ip_addr"] != -1} { + # set mac [keylget apiData(expArgs) -neighbor_intf_ip_addr] + # lappend intfArgs -gateway $mac + # keyldel apiData(expArgs) -neighbor_intf_ip_addr + #} + + #if {[lsearch $args "-port_handle"] != -1} { + # set ph [keylget apiData(expArgs) -port_handle] + # lappend intfArgs -port_handle $ph + # lappend unconnectedIntfArgs -port_handle $ph + #} + # + #if {[lsearch $args "-loopback_ip_addr"] != -1} { + # set loopbackAddr [keylget apiData(expArgs) -loopback_ip_addr] + # lappend unconnectedIntfArgs -intf_ip_addr $loopbackAddr + #} + + #set args [Convert_Keyedlist_To_List $apiData(expArgs)] + + + #if {[llength $intfArgs] >= 1} { + + # if {[lsearch $intfArgs "-src_mac_addr"] != -1} { + # set api "interface_config -mode destroy -src_mac_addr $srcmac -port_handle $ph" + # puts "interface_config destroy is $api" + # set ret [::ixia::executeInChild $api] + # puts "return is $ret" + # + # } + + # set api "interface_config $intfArgs -mode config" + # puts "interface_config is $api" + # set ret [::ixia::executeInChild $api] + # puts "return is $ret" + #} + + #if {[lsearch $unconnectedIntfArgs "-intf_ip_addr"] != -1} { + # set api "interface_config $unconnectedIntfArgs -mode config -check_gateway_exists 1" + # puts "interface_config is $api" + # set ret [::ixia::executeInChild $api] + # puts "return is $ret" + #} + + if {[lsearch $args -reset ] != -1} { + set args [lremove $args -reset] + + } + + global apiData + set args1 $args + Convert_List_To_Keyedlist $args1 + if {[lsearch $args "-mac_address_init"] != -1} { + puts "removing -mac_address_init" + set srcmac [keylget apiData(expArgs) -mac_address_init] + set ph [keylget apiData(expArgs) -port_handle] + set api "interface_config -mode destroy -src_mac_addr $srcmac -port_handle $ph" + set ret [::ixia::executeInChild $api] + } + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + + set api "emulation_ospf_config $args -reset 1" + + puts "emulation ospf config is $api" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rip_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_rip_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::dhcp_server_extension_config {args} { + set api "dhcp_server_extension_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_group_config {args} { + #Body { Arguments with no mandatory tag argument 'no_write'} + set api "emulation_dhcp_group_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bfd_session_config {args} { + set api "emulation_bfd_session_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rsvp_info {args} { + set api "emulation_rsvp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::convert_porthandle_to_vport {args} { + set api "convert_porthandle_to_vport $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pim_group_config {args} { + set api "emulation_pim_group_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_mplstp_config {args} { + set api "emulation_mplstp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::connect {args} { + puts "wrapper connect proc ::ixia::connect" + global connect_output apiData + puts "args: $args" + if {[lsearch $args -reset ] != -1} { + set args [lremove $args -reset] + } + + Convert_List_To_Keyedlist $args + if {[lsearch $args "-ixnetwork_tcl_server"] != -1} { + puts "Removing -ixnetwork_tcl_server" + keyldel apiData(expArgs) -ixnetwork_tcl_server + } + if {[lsearch $args "-interactive"] != -1} { + puts "Removing -interactive" + keyldel apiData(expArgs) -interactive + } + if {[lsearch $args "-reset"] != -1} { + puts "Removing -reset" + keyldel apiData(expArgs) -reset + } + + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + set api "connect $args -tcl_server $apiData(tcl_server) -reset 1" + #puts "api : $api" + set connect_output [::ixia::executeInChild $api] + #puts "connect out: $connect_output" + return $connect_output + +} + +proc ::ixia::emulation_mplstp_control {args} { + set api "emulation_mplstp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_fport_vnport_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_fport_vnport_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_lacp_link_config {args} { + #Body { Arguments with no mandatory tag argument 'inter_marker_pdu_delay'} + #Body { Arguments with no mandatory tag argument 'collecting_flag'} + #Body { Arguments with no mandatory tag argument 'collector_max_delay'} + #Body { Arguments with no mandatory tag argument 'actor_system_id'} + #Body { Arguments with no mandatory tag argument 'actor_port_num_step'} + #Body { Arguments with no mandatory tag argument 'actor_port_pri_step'} + #Body { Arguments with no mandatory tag argument 'actor_system_pri'} + #Body { Arguments with no mandatory tag argument 'lacp_activity'} + #Body { Arguments with no mandatory tag argument 'support_responding_to_marker'} + #Body { Arguments with no mandatory tag argument 'port_handle'} + #Body { Arguments with no mandatory tag argument 'lag_count'} + #Body { Arguments with no mandatory tag argument 'actor_key_step'} + #Body { Arguments with no mandatory tag argument 'marker_req_mode'} + #Body { Arguments with no mandatory tag argument 'port_mac_step'} + #Body { Arguments with no mandatory tag argument 'actor_port_num'} + #Body { Arguments with no mandatory tag argument 'marker_res_wait_time'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'actor_system_pri_step'} + #Body { Arguments with no mandatory tag argument 'distributing_flag'} + #Body { Arguments with no mandatory tag argument 'auto_pick_port_mac'} + #Body { Arguments with no mandatory tag argument 'actor_key'} + #Body { Arguments with no mandatory tag argument 'send_marker_req_on_lag_change'} + #Body { Arguments with no mandatory tag argument 'lacpdu_periodic_time_interval'} + #Body { Arguments with no mandatory tag argument 'port_mac'} + #Body { Arguments with no mandatory tag argument 'actor_port_pri'} + #Body { Arguments with no mandatory tag argument 'reset'} + #Body { Arguments with no mandatory tag argument 'actor_system_id_step'} + #Body { Arguments with no mandatory tag argument 'sync_flag'} + #Body { Arguments with no mandatory tag argument 'no_write'} + #Body { Arguments with no mandatory tag argument 'send_periodic_marker_req'} + #Body { Arguments with no mandatory tag argument 'lacp_timeout'} + #Body { Arguments with no mandatory tag argument 'aggregation_flag'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_lacp_link_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ldp_info {args} { + set api "emulation_ldp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rsvp_config {args} { + set api "emulation_rsvp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ancp_config {args} { + set api "emulation_ancp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::convert_portname_to_vport {args} { + set api "convert_portname_to_vport $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_elmi_control {args} { + set api "emulation_elmi_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_efm_org_var_config {args} { + set api "emulation_efm_org_var_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_fport_stats {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_fport_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ldp_control {args} { + set api "emulation_ldp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bgp_info {args} { + set api "emulation_bgp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_twamp_control {args} { + set api "emulation_twamp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::packet_config_buffers {args} { + if {[lsearch $args -data_plane_capture_enable ] != -1} { + set args [lremove $args -data_plane_capture_enable] + + } + set api "packet_config_buffers $args -data_plane_capture_enable 1" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ldp_route_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + set api "emulation_ldp_route_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::session_info {args} { + set api "session_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_efm_control {args} { + set api "emulation_efm_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::find_in_csv {args} { + set api "find_in_csv $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::l2tp_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'action' + if {[lsearch $args "-action"] == -1} { + error "Missing Mandatory Argument \"action\"" + } + set api "l2tp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_mld_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + global connect_output apiData + set args2 $args + Convert_List_To_Keyedlist $args2 + + if {[lsearch $args "-port_handle"] != -1} { + set ph [keylget apiData(expArgs) -port_handle] + } + + if {[lsearch $args "-mac_address_init"] != -1} { + set srcmac [keylget apiData(expArgs) -mac_address_init] + set api "interface_config -mode destroy -src_mac_addr $srcmac -port_handle $ph" + puts "interface_config destroy is $api" + set ret [::ixia::executeInChild $api] + puts "return is $ret" + } + set api "emulation_mld_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_server_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'action' + if {[lsearch $args "-action"] == -1} { + error "Missing Mandatory Argument \"action\"" + } + set api "emulation_dhcp_server_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::pppox_stats {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'handle' + if {[lsearch $args "-handle"] == -1} { + error "Missing Mandatory Argument \"handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "pppox_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::dhcp_extension_stats {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "dhcp_extension_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_oam_info {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_oam_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::packet_config_filter {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gfp_bad_fcs_error'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pattern_atm'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gfp_payload_crc'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pattern_offset_atm'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vci_count'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pattern_mask_atm'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gfp_tHec_error'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gfp_error_condition'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'vpi_count'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gfp_eHec_error'} + set api "packet_config_filter $args " + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pbb_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_pbb_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_stp_info {args} { + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_stp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_client_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_client_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ospf_info {args} { + #Body { Arguments with no mandatory tag argument 'port_handle'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_ospf_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::capture_packets {args} { + set api "capture_packets $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_twamp_info {args} { + set api "emulation_twamp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_mip_mep_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_mip_mep_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pbb_custom_tlv_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'bridge_handle' + if {[lsearch $args "-bridge_handle"] == -1} { + error "Missing Mandatory Argument \"bridge_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_pbb_custom_tlv_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pim_info {args} { } +proc ::ixia::emulation_pbb_trunk_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'bridge_handle' + if {[lsearch $args "-bridge_handle"] == -1} { + error "Missing Mandatory Argument \"bridge_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_pbb_trunk_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::traffic_control {args} { + #set res [::ixia::test_control -action stop_all_protocols] + #sleep 20 + #set res [::ixia::test_control -action start_all_protocols] + #global apiData + #set args2 $args + #Convert_List_To_Keyedlist $args2 + #set args1 $args + #if {[lsearch $args1 "run"] != -1} { + #set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action stop" + #puts $api + #set traffic [::ixia::executeInChild $api] + #set api "reset_port -mode reboot_port_cpu -protocol all -port_handle [keylget apiData(expArgs) -port_handle]" + #puts $api + #set traffic [::ixia::executeInChild $api] + #set api "test_control -action start_all_protocols" + #puts $api + #set traffic [::ixia::executeInChild $api] + #set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action regenerate" + #puts $api + #set traffic [::ixia::executeInChild $api] + #sleep 10 + #set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action apply" + #puts $api + #set traffic [::ixia::executeInChild $api] + #sleep 10 + #} + # if {[lsearch $args1 "sync_run"] != -1} { + # set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action stop" + # puts $api + # set traffic [::ixia::executeInChild $api] + #set api "reset_port -mode reboot_port_cpu -protocol all -port_handle [keylget apiData(expArgs) -port_handle]" + #puts $api + #set traffic [::ixia::executeInChild $api] + #set api "test_control -action start_all_protocols" + #puts $api + #set traffic [::ixia::executeInChild $api] + #} + #set api "traffic_control $args" + #sleep 60 + #puts $api + #set traffic [::ixia::executeInChild $api] + #return $traffic + set res [::ixia::test_control -action start_all_protocols] + sleep 10 + global apiData + set args2 $args + Convert_List_To_Keyedlist $args2 + set args1 $args + if {[lsearch $args1 "run"] != -1} { + set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action stop" + puts $api + set traffic [::ixia::executeInChild $api] + sleep 10 + set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action regenerate" + puts $api + set traffic [::ixia::executeInChild $api] + sleep 10 + set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action apply" + puts $api + set traffic [::ixia::executeInChild $api] + sleep 10 + } + set api "traffic_control $args" + puts $api + set res [::ixia::executeInChild $api] + return $res +} +proc ::ixia::emulation_cfm_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rip_control {args} { + set api "emulation_rip_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pim_control {args} { + set api "emulation_pim_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_elmi_info {args} { + set api "emulation_elmi_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bfd_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "emulation_bfd_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::reboot_port_cpu {args} { + set api "reboot_port_cpu $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_twamp_server_range_config {args} { + set api "emulation_twamp_server_range_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::convert_vport_to_porthandle {args} { + set api "convert_vport_to_porthandle $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_client_stats {args} { + set api "fc_client_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pim_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_ip_addr'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'loopback_ip_address'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_dst_ip_addr'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_key_in_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_ip_addr_cstep'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'loopback_ip_address_cstep'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_count'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_ip_addr_lstep'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'loopback_count'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'loopback_ip_address_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_enable'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_dst_ip_addr_lstep'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_key_out_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_ip_prefix_length'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_unique'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_dst_ip_addr_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_src_ip_addr_mode'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_ip_addr_step'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_dst_ip_addr_cstep'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'gre_seq_enable'} + set api "emulation_pim_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::packet_stats {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'framesize'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'enable_framesize'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'enable_pattern'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pattern_offset'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'chunk_size'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'enable_ethernet_type'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'ethernet_type'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'filename'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'pattern'} + set api "packet_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_fport_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_fport_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_isis_info {args} { + set api "emulation_isis_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::get_port_list_from_connect {args} { + set api "get_port_list_from_connect $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ldp_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'interface_mode'} + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + set api "emulation_ldp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_server_stats {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'action' + if {[lsearch $args "-action"] == -1} { + error "Missing Mandatory Argument \"action\"" + } + set api "emulation_dhcp_server_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_vlan_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_vlan_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_info {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'action' + if {[lsearch $args "-action"] == -1} { + error "Missing Mandatory Argument \"action\"" + } + set api "fc_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_mplstp_info {args} { + set api "emulation_mplstp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_server_config {args} { + set api "emulation_dhcp_server_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_bfd_info {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "emulation_bfd_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::get_packet_content {args} { + set api "get_packet_content $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::uds_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "uds_config $args" + return [::ixia::executeInChild $api] +} + +proc lremove {l p} { + set a [lsearch -all -inline -not -exact $l $p] + return $a +} + +proc get_port_handle_info {ipAddress} { + #package require IxTclNetwork + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + + set handle_list "" + + foreach vport_handle $vports { + set interfaces [interp eval $::ixia::TclInterp " ixNet getList $vport_handle interface"] + if {![string match $interfaces ""]} { + foreach intf $interfaces { + set ipv4Objs [interp eval $::ixia::TclInterp "ixNet getL $intf ipv4"] + if {![string match $ipv4Objs ""]} { + set getIp [interp eval $::ixia::TclInterp " ixNet getA $intf/ipv4 -ip "] + if {[string match $getIp $ipAddress]} { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vport_handle -connectedTo "] + puts "vportobj : $vportObj" + if {$vportObj ne ""} { + regexp -nocase {card:(\d+)\/port:(\d+)} $vportObj match card port + lappend handle_list "1/$card/$port" + } + } + } + set ipv6Objs [interp eval $::ixia::TclInterp "ixNet getL $intf ipv6"] + if {![string match $ipv6Objs ""]} { + set val [catch {interp eval $::ixia::TclInterp " ixNet getA $intf/ipv6:1 -ip " } getIp] + if {![regexp -nocase {is null} $getIp match]} { + if {[string match $getIp [expand_ipv6 $ipAddress]]} { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vport_handle -connectedTo "] + puts "vportobj : $vportObj" + if {$vportObj ne ""} { + regexp -nocase {card:(\d+)\/port:(\d+)} $vportObj match card port + lappend handle_list "1/$card/$port" + } + } + } + } + + } + } + } + puts "handle_list is : $handle_list" + return $handle_list +} + +proc findDstMacForTrafficItem {port} { + + lassign [split $port "/"] sequenceId card port + set vports [interp eval $::ixia::TclInterp "ixNet getList [ixNet getRoot] vport"] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$card\/port:$port" $vportObj match]} { + return [interp eval $::ixia::TclInterp "ixNet getA $vportHdl/discoveredNeighbor:1 -neighborMac"] + } + } +} + +proc ::ixia::traffic_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'command_response'} + global connect_output apiData + global env stream_name + if {[info exists env(findNdr)]} { + set findndr $env(findNdr) + } else { + set findndr "" + } + set dstMac "" + set srcMac "" + set circuitType "" + set args2 $args + Convert_List_To_Keyedlist $args2 + if {[lsearch $args "-port_handle"] != -1} { + set api "traffic_control -port_handle [keylget apiData(expArgs) -port_handle] -action stop" + puts $api + set traffic [::ixia::executeInChild $api] + } + sleep 20 + if {[lsearch $args "-vlan_id"] != -1} { + if {[lsearch $args "-vlan"] == -1} { + lappend args -vlan enable + } + } + if {[lsearch $args "-mac_dst"] != -1} { + set mac [keylget apiData(expArgs) -mac_dst] + set dstMac [format_mac_address $mac] + + } + + if {[lsearch $args "-circuit_endpoint_type"] != -1} { + set circuitType [keylget apiData(expArgs) -circuit_endpoint_type] + } + puts "circuit type is $circuitType" + + if {[lsearch $args "-port_handle2"] == -1} { + #getting port_handle2 info here + if {[lsearch $args "-ip_dst_addr"] != -1 || [lsearch $args "-ipv6_dst_addr"] != -1} { + if {[lsearch $args "-ip_dst_addr"] != -1} { + set ip [keylget apiData(expArgs) -ip_dst_addr] + set port_handle2 [get_port_handle_info $ip] + if { [ regexp {([0-9]+).([0-9]+).([0-9]+).([0-9]+)} $ip dump oct1 oct2 oct3 oct4] } { + if { $oct1 > 224 } { + set temp_mac [mcastIPToMac $ip] + if {[lsearch $args "-mac_dst"] == -1} { + set dstMac_multicast [format_mac_address $temp_mac] + lappend args -mac_dst $dstMac_multicast + } + + } + } + + } elseif {[lsearch $args "-ipv6_dst_addr"] != -1} { + set ip [keylget apiData(expArgs) -ipv6_dst_addr] + set port_handle2 [get_port_handle_info $ip] + set ip [get_ipv6_full_add $ip] + if { [ regexp {([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+)} \ + $ip dump oct1 oct2 oct3 oct4 oct5 oct6 oct7 oct8] } { + if { [expr 0x$oct1] > 65281 || [expr 0x$oct1] < 65535 } { + set temp_mac [mcastIPv6ToMac $ip] + if {[lsearch $args "-mac_dst"] == -1} { + set dstMac_multicast [format_mac_address $temp_mac] + lappend args -mac_dst $dstMac_multicast + } + } + } + + } + if {![string match $port_handle2 ""]} { + lappend args -port_handle2 $port_handle2 + lappend args -convert_to_raw 1 -track_by traffic_item + if {[lsearch $args "-mac_dst"] == -1} { + set macDst "" + foreach vport [keylget apiData(expArgs) -port_handle] { + lappend macDst [findDstMacForTrafficItem $vport] + } + if {$macDst ne ""} { + lappend args -mac_dst $macDst + } + } + } elseif {[string match $port_handle2 ""] && [lsearch $args "-mac_dst"] == -1 } { + set macDst "" + foreach vport [keylget apiData(expArgs) -port_handle] { + lappend macDst [findDstMacForTrafficItem $vport] + } + if {$macDst ne ""} { + lappend args -mac_dst $macDst + } + set port_list [keylget connect_output vport_list] + puts "port_list: $port_list" + set port_list_length [llength [keylget connect_output vport_list]] + + if {$port_list_length == 1} { + lappend args -circuit_type quick_flows + } elseif {$port_list_length >= 2} { + foreach vport [keylget apiData(expArgs) -port_handle] { + regsub -all $vport $port_list {} port_list + } + #set port_handle2 [lindex $port_list {}] + regsub -all "{" $port_list {} port_handle2 + regsub -all "}" $port_handle2 {} port_handle2 + puts "port_handle2 in mac_dst not there : $port_handle2" + + lappend args -port_handle2 $port_handle2 -track_by traffic_item + } + + } elseif {[string match $port_handle2 ""] && [lsearch $args "-mac_dst"] != -1 } { + set port_list [keylget connect_output vport_list] + puts "port_list: $port_list" + set port_list_length [llength [keylget connect_output vport_list]] + + if {$port_list_length == 1} { + lappend args -circuit_type quick_flows + } elseif {$port_list_length >= 2} { + foreach vport [keylget apiData(expArgs) -port_handle] { + regsub -all $vport $port_list {} port_list + } + #set port_handle2 [lindex $port_list {}] + regsub -all "{" $port_list {} port_handle2 + regsub -all "}" $port_handle2 {} port_handle2 + puts "port_handle2 in mac_dst not there : $port_handle2" + + lappend args -port_handle2 $port_handle2 -track_by traffic_item + } + + } else { + if {[lsearch $args "-ip_src_addr"] != -1} { + set ip [keylget apiData(expArgs) -ip_src_addr] + puts "Source ip is $ip" + set handle [get_emulation_handle $ip] + lappend args -emulation_src_handle $handle + lappend args -circuit_endpoint_type ipv4 -track_by traffic_item + + } + + if {[lsearch $args "-ip_dst_addr"] != -1} { + set ip [keylget apiData(expArgs) -ip_dst_addr] + puts "Dest ip is $ip" + set handle [get_emulation_handle $ip] + lappend args -emulation_dst_handle $handle + } + #lappend args -circuit_endpoint_type ipv4 -track_by traffic_item + + if {[lsearch $args "-ipv6_src_addr"] != -1} { + set ip [keylget apiData(expArgs) -ipv6_src_addr] + #puts "source ipv6 is $ip" + set handle [get_emulation_handle_ipv6 $ip] + lappend args -emulation_src_handle $handle + lappend args -circuit_endpoint_type ipv6 -track_by traffic_item + } + if {[lsearch $args "-ipv6_dst_addr"] != -1} { + set ip [keylget apiData(expArgs) -ipv6_dst_addr] + #puts "destination ipv6 is $ip" + set handle [get_emulation_handle_ipv6 $ip] + lappend args -emulation_dst_handle $handle + } + + } + } + } else { + + if {[lsearch $args "-ip_dst_addr"] != -1 || [lsearch $args "-ipv6_dst_addr"] != -1} { + if {[lsearch $args "-ip_dst_addr"] != -1} { + set ip [keylget apiData(expArgs) -ip_dst_addr] + set port_handle2 [get_port_handle_info $ip] + if { [ regexp {([0-9]+).([0-9]+).([0-9]+).([0-9]+)} $ip dump oct1 oct2 oct3 oct4] } { + if { $oct1 > 224 } { + set temp_mac [mcastIPToMac $ip] + if {[lsearch $args "-mac_dst"] == -1} { + set dstMac_multicast [format_mac_address $temp_mac] + lappend args -mac_dst $dstMac_multicast + } + + } + } + + } elseif {[lsearch $args "-ipv6_dst_addr"] != -1} { + set ip [keylget apiData(expArgs) -ipv6_dst_addr] + set port_handle2 [get_port_handle_info $ip] + set ip [get_ipv6_full_add $ip] + if { [ regexp {([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+):([A-Z0-9]+)} \ + $ip dump oct1 oct2 oct3 oct4 oct5 oct6 oct7 oct8] } { + if { [expr 0x$oct1] > 65281 || [expr 0x$oct1] < 65535 } { + set temp_mac [mcastIPv6ToMac $ip] + if {[lsearch $args "-mac_dst"] == -1} { + set dstMac_multicast [format_mac_address $temp_mac] + lappend args -mac_dst $dstMac_multicast + } + } + } + + } + } + } + + set new_args {} + foreach i $args { + if {[regexp {^-\w+$} $i]} { + lappend new_args $i + } + } + + foreach i $new_args { + if {$i == "-no_write"} { + set args [lreplace $args [lsearch $args $i] [lsearch $args $i]+1] + } + } + + if {[lsearch $args "-l3_protocol"] != -1} { + set ip_protocol [keylget apiData(expArgs) -l3_protocol] + if {[lsearch $args "-circuit_endpoint_type"] == -1} { + if {[string match $ip_protocol "arp"]} { + lappend args -circuit_endpoint_type ipv4_arp + } else { + lappend args -circuit_endpoint_type $ip_protocol + } + } + } + + regsub -all "{" $args {} args + regsub -all "}" $args {} args + + puts "args now : $args" + + Convert_List_To_Keyedlist $args + + if {[lsearch $args "-mac_dst_mode"] != -1} { + keyldel apiData(expArgs) -mac_dst_mode + } + + if {[lsearch $args "-mac_src_mode"] != -1} { + keyldel apiData(expArgs) -mac_src_mode + } + + if {[lsearch $args "-signature"] != -1} { + keyldel apiData(expArgs) -signature + } + if {[lsearch $args "-signature_offset"] != -1} { + keyldel apiData(expArgs) -signature_offset + } + + if {[lsearch $args "-pgid_mode"] != -1} { + + set pgid_mode [keylget apiData(expArgs) -pgid_mode] + if {[string match $pgid_mode "custom"]} { + keyldel apiData(expArgs) -pgid_mode + } + } + if {[lsearch $args "-pgid_offset"] != -1} { + + set pgid_offset [keylget apiData(expArgs) -pgid_offset] + keyldel apiData(expArgs) -pgid_offset + } + + if {[lsearch $args "-pgid_value"] != -1} { + puts "Removing -pgid value" + keyldel apiData(expArgs) -pgid_value + } + + if {[lsearch $args "-ethernet_type"] != -1} { + puts "Removing -ethernet_type value" + keyldel apiData(expArgs) -ethernet_type + } + + if {[lsearch $args "-enable_pgid"] != -1} { + puts "Removing -enable_pgid" + keyldel apiData(expArgs) -enable_pgid + } + if {![string match $dstMac ""]} { + puts "removing -mac_dst" + keyldel apiData(expArgs) -mac_dst + } + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + if {![string match $dstMac ""]} { + puts "adding -mac_dst" + lappend args -mac_dst $dstMac + } + if {![string match $circuitType ""]} { + if {[string match $circuitType "arp"]} { + puts "adding -circuit_endpoint_type ipv4_arp" + lappend args -circuit_endpoint_type ipv4_arp + } else { + lappend args -circuit_endpoint_type $circuitType + } + } + if {[lsearch $args "-track_by"] == -1} { + lappend args -track_by traffic_item + } + if {[lsearch $args "-name"] != -1} { + set fragname [keylget apiData(expArgs) -name] + if {[string equal "FragStream1" $fragname]} { + lappend args -ip_fragment_last 0 + } + if {[string equal "FragStream2" $fragname]} { + lappend args -ip_fragment_offset 34 + } + } + + if {[string match $findndr "ndr"]} { + set mod [keylget apiData(expArgs) -mode] + if {[string equal "modify" $mod]} { + set stream [keylget apiData(expArgs) -stream_id] + set traffic [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] traffic "] + set trafficItemList [interp eval $::ixia::TclInterp " ixNet getL $traffic trafficItem "] + foreach trafficItem $trafficItemList { + set result [regexp {::ixNet::OBJ-/traffic/trafficItem:(\d+)} $trafficItem match streamId] + if {[string equal $stream $streamId]} { + set streamName [interp eval $::ixia::TclInterp " ixNet getA $trafficItem -name "] + } + } + keylset apiData(expArgs) -stream_id $streamName + } + set args [Convert_Keyedlist_To_List $apiData(expArgs)] + if {[lsearch $args "-track_by"] == -1} { + lappend args -track_by traffic_item + } + set api "traffic_config $args " + set trafficConfig [::ixia::executeInChild $api] + set mod [keylget apiData(expArgs) -mode] + if {[string equal "create" $mod]} { + keylset trafficConfig stream_id $stream_name + set stream_name [expr {$stream_name + 1}] + } + return $trafficConfig + } else { + set api "traffic_config $args" + return [::ixia::executeInChild $api] + } +} + +proc format_mac_address { macAddr } { + + puts "mac is : $macAddr " + + regsub -all {[.: ]} $macAddr "" macAddr + + regexp -nocase {([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})} $macAddr dummy mac1 mac2 mac3 mac4 mac5 mac6 + set macAddr $mac1:$mac2:$mac3:$mac4:$mac5:$mac6 + + + #if {[string length $macAddr]==12} { + # for {set i 0; set j 1} {$i < 11} {incr i 2; incr j 2} { + # lappend tmp [string range $macAddr $i $j] + # } + # set macAddr $tmp + #} + + return $macAddr + +} + +proc Convert_List_To_Keyedlist {lst} { + global apiData + set apiData(expArgs) "" + + #set expressionList [split $lst "-"] + set newElem [string map {" -" \0} [join [list " " $lst]]] + set expressionList [split $newElem \0] + + foreach value $expressionList { + if { [llength $value] >= 2} { + #regsub -all [lindex $value 0] $value "" val + keylset apiData(expArgs) -[lindex $value 0] [lreplace $value 0 0] + } elseif {[llength $value] == 1} { + keylset apiData(expArgs) -[lindex $value 0] 1 + } + } + + #foreach key [keylkeys keyList] { + # lappend expListArgs $key [keylget keyList $key] + #} + + #foreach {key val} $lst { + # keylset apiData(expArgs) $key $val + #} +} + +proc Convert_Keyedlist_To_List {keyList} { + global apiData + set expListArgs "" + + foreach key [keylkeys keyList] { + lappend expListArgs $key [keylget keyList $key] + } + return $expListArgs +} + +proc ::ixia::emulation_oam_config_topology {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_oam_config_topology $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::test_control {args} { + set api "test_control $args" + return [::ixia::executeInChild $api] +} +proc ::ixia::test_stats {args} { + set api "test_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::l2tp_stats {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'handle' + if {[lsearch $args "-handle"] == -1} { + error "Missing Mandatory Argument \"handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "l2tp_stats $args" + return [::ixia::executeInChild $api] +} +proc ::ixia::increment_ipv6_address {args} { + set ipAddress $args + if {[regexp -nocase {^([a-fA-F0-9]+):([a-fA-F0-9]+):([a-fA-F0-9]+)::([a-fA-F0-9]+)$} $ipAddress match m1 m2 m3 m4]} { + set m5 [expr $m4+1] + set ipAddress $m1:$m2:$m3:0:0:0:0:$m5 + } + return $ipAddress +} + +proc ::ixia::emulation_bgp_route_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + set api "emulation_bgp_route_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::packet_config_triggers {args} { + puts "inside wrapper ::ixia::packet_config_triggers" + global apiData + set args1 $args + Convert_List_To_Keyedlist $args1 + if {[lsearch $args "-port_handle"] != -1} { + set ph [keylget apiData(expArgs) -port_handle] + puts $ph + set res [ixia::packet_config_buffers -port_handle $ph ] + } + set api "packet_config_triggers $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_isis_topology_route_config {args} { + set api "emulation_isis_topology_route_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_stats {args} { + set api "emulation_dhcp_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_twamp_control_range_config {args} { + set api "emulation_twamp_control_range_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::device_info {args} { + set api "device_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "emulation_cfm_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_eigrp_route_config {args} { + set api "emulation_eigrp_route_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::reset_port {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'protocol' + if {[lsearch $args "-protocol"] == -1} { + error "Missing Mandatory Argument \"protocol\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "reset_port $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::dhcp_client_extension_config {args} { + set api "dhcp_client_extension_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::l2tp_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'l2tp_dst_addr' + if {[lsearch $args "-l2tp_dst_addr"] == -1} { + error "Missing Mandatory Argument \"l2tp_dst_addr\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'num_tunnels' + if {[lsearch $args "-num_tunnels"] == -1} { + error "Missing Mandatory Argument \"num_tunnels\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'l2_encap' + if {[lsearch $args "-l2_encap"] == -1} { + error "Missing Mandatory Argument \"l2_encap\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'l2tp_src_addr' + if {[lsearch $args "-l2tp_src_addr"] == -1} { + error "Missing Mandatory Argument \"l2tp_src_addr\"" + } + set api "l2tp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rip_route_config {args} { + set api "emulation_rip_route_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_client_options_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_client_options_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_lacp_info {args} { + #Body { Arguments with no mandatory tag argument 'port_handle'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_lacp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_igmp_querier_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_igmp_querier_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ancp_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'action_control' + if {[lsearch $args "-action_control"] == -1} { + error "Missing Mandatory Argument \"action_control\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'action' + if {[lsearch $args "-action"] == -1} { + error "Missing Mandatory Argument \"action\"" + } + set api "emulation_ancp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::l3vpn_generate_stream {args} { + set api "l3vpn_generate_stream $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_dhcp_config {args} { + #Body { Arguments with no mandatory tag argument 'no_write'} + set api "emulation_dhcp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_eigrp_info {args} { + set api "emulation_eigrp_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::fc_fport_global_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "fc_fport_global_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_mplstp_lsp_pw_config {args} { + set api "emulation_mplstp_lsp_pw_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_twamp_config {args} { + set api "emulation_twamp_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ancp_subscriber_lines_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_ancp_subscriber_lines_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_mld_group_config {args} { + #Body { Need to fill equivalent logic in classic for FT Non-mandatory argument 'no_write'} + set api "emulation_mld_group_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_mld_control {args} { + set api "emulation_mld_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_cfm_md_meg_config {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + set api "emulation_cfm_md_meg_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_rsvp_tunnel_info {args} { + set api "emulation_rsvp_tunnel_info $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_isis_config {args} { + set api "emulation_isis_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_stp_lan_config {args} { + #Body { Arguments with no mandatory tag argument 'count'} + #Body { Arguments with no mandatory tag argument 'mode'} + #Body { Arguments with no mandatory tag argument 'mac_address'} + #Body { Arguments with no mandatory tag argument 'mac_incr_enable'} + #Body { Arguments with no mandatory tag argument 'vlan_enable'} + #Body { Arguments with no mandatory tag argument 'port_handle'} + #Body { Arguments with no mandatory tag argument 'vlan_id'} + set api "emulation_stp_lan_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_stp_vlan_config {args} { + #Body { Arguments with no mandatory tag argument 'count'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'root_priority'} + #Body { Arguments with no mandatory tag argument 'vlan_port_priority'} + #Body { Arguments with no mandatory tag argument 'internal_root_path_cost'} + #Body { Arguments with no mandatory tag argument 'vlan_port_priority_step'} + #Body { Arguments with no mandatory tag argument 'root_mac_address'} + #Body { Arguments with no mandatory tag argument 'bridge_handle'} + #Body { Arguments with no mandatory tag argument 'root_mac_address_step'} + #Body { Arguments with no mandatory tag argument 'vlan_id'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_stp_vlan_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_igmp_control {args} { + set api "emulation_igmp_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_pbb_control {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'mode' + if {[lsearch $args "-mode"] == -1} { + error "Missing Mandatory Argument \"mode\"" + } + #Argument not supported in FT.This argument is Mandatory in Classic 'port_handle' + if {[lsearch $args "-port_handle"] == -1} { + error "Missing Mandatory Argument \"port_handle\"" + } + set api "emulation_pbb_control $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_ancp_stats {args} { + #Argument not supported in FT.This argument is Mandatory in Classic 'reset' + if {[lsearch $args "-reset"] == -1} { + error "Missing Mandatory Argument \"reset\"" + } + set api "emulation_ancp_stats $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_igmp_group_config {args} { + set api "emulation_igmp_group_config $args" + return [::ixia::executeInChild $api] +} + +proc ::ixia::emulation_lacp_control {args} { + #Body { Arguments with no mandatory tag argument 'port_handle'} + #Body { Arguments with no mandatory tag argument 'handle'} + #Body { Arguments with no mandatory tag argument 'mode'} + set api "emulation_lacp_control $args" + return [::ixia::executeInChild $api] +} + + +proc ::ixia::increment_ipv4_net {args} { + set api "increment_ipv4_net $args" + return [::ixia::executeInChild $api] +} + + + +proc ixClearStats {ixPortList} { + set status [::ixia::traffic_control -action clear_stats] +} +proc mcastIPToMac { mcastIP } { + + set mcastMac 0000.0000.0000 + if { ![ regexp {([0-9]+).([0-9]+).([0-9]+).([0-9]+)} $mcastIP dump oct1 oct2 oct3 oct4] } { + puts "invalid ip format" + return $mcastMac + } + if { $oct1 < 224 | $oct1 > 239 } { + puts "invlaid mcast IP" + return $mcastMac + } + catch { unset mcastMac } + set item {} + set oct2 [expr $oct2 & 127] + lappend item 5e [format "%02x" $oct2] + regsub -all { } $item {} item2 + + set item {} + lappend item [format "%02x" $oct3] [format "%02x" $oct4] + regsub -all { } $item {} item3 + + lappend mcastMac 0100 $item2 $item3 + regsub -all { } $mcastMac {.} mcastMac + + return $mcastMac +} + +proc subnetmaskToCIDR { ip } { + set sum 0 + if {[string length $ip]==2} { + return $ip + } else { + foreach i [split $ip "."] { + while { $i !=0} { + set sum [expr $sum + [expr $i & 1]] + set i [expr $i >> 1] + } + } + return $sum + } +} + diff --git a/perfUtils.tcl b/perfUtils.tcl new file mode 100644 index 0000000..94ea941 --- /dev/null +++ b/perfUtils.tcl @@ -0,0 +1,3302 @@ +# $Id: perfUtils.tcl,v 1.9 2019/02/07 14:03:03 kkg Exp $ +# Copyright (c) 2009,2014 by Cisco Systems, Inc. +# +# Name: perfUtils.tcl +# +# Purpose: +# The perfUtils library currently has just one major proc +# for finding NDR (No Drop Rate) and latency. +# This is based on Binary Search algorithm. +# This library can be used for other performance utilities as well. +# +# Author: +# Muhammad A Imam - muimam@cisco.com +# Yuefeng Jiang - yuefjian@cisco.com +# Ruoying Pan - rupan@cisco.com +# +# Usage: +# set auto_path [linsert $auto_path 0 \ +# [file join $env(AUTOTEST) regression lib mid_range_routing]] +# package require perfUtils +# +# Description: +# findNdr - The procedure uses a binary search algorithm to find the NDR +# using the ports and streams information provided by the user. +# The user must provide all of the mandatory argumrnts and +# optionally can provide the optional arguments mentioned below. +# The proc can also obtain latency based on statistical sampling. +# The proc can handle any type of traffic that can be configured +# in IxExplorer as streams. It handles multicast traffic seprately. +# The proc assumes the following: +# 1. The traffic streams will be setup by the user +# 2. On receiving ports packets have to be filtered in UDS1 or UDS2 +# public proc: +# perfUtils::findNdr +# perfUtils::parseNdrResults +# perfUtils::writePerfValues +# perfUtils::writeMyPerfValues +# perfUtils::generate_keyed_result +# private proc: +# perfUtils::_run_IxExplorer_test +# perfUtils::_run_IxNetwork_test +# perfUtils::_run_IxNetwork_test2 +# perfUtils::_get_txPkts_IxExplorer +# perfUtils::_get_rxPkts_IxExplorer +# perfUtils::_get_latency_IxExplorer +# perfUtils::_run_traffic_IxExplorer +# perfUtils::_set_curRate_IxNetwork +# perfUtils::_enable_stats_IxNetwork +# perfUtils::_get_txPkts_IxNetwork +# perfUtils::_get_txPkts_IxNetwork2 +# perfUtils::_get_txRxPkts_IxNetwork +# perfUtils::_get_rxPkts_IxNetwork +# perfUtils::_get_rxPkts_IxNetwork2 +# perfUtils::_get_latency_IxNetwork +# perfUtils::_get_latency_IxNetwork2 +# perfUtils::_run_traffic_IxNetwork +# perfUtils::_maxrate +# perfUtils::_maxrate2 +# perfUtils::_framesize +# perfUtils::_parse_tx_ports +# perfUtils::_parse_rx_ports +# perfUtils::_parse_mtx_ports +# perfUtils::_parse_mrx_ports +# perfUtils::_error +# +# Requirements: +# HLTAPI for generator being used +# +# Bugs: +# Bugs need to fix +# 1. +# +# Limitations: +# 1. All ports involved in the test need to be of the same capacity +# i.e. All of them to be 1Gig or 10Gig. +# The API cannot handle if the situation +# when one port is 1 Gig and the other is 10 Gig +# 2. The API assumes, if there are multiple streams per port, +# all streams have the same frame size defined +# 3. If calculating NDR for IMIX, specify the max_rate, otherwise +# the proc will puick a random max_rate based on the packet sizes +#package provide perfUtils 1.0 +set script_dir [file dirname [info script]] +set sourcefile1 [file join $script_dir "mcpModules.tcl"] +set sourcefile2 [file join $script_dir "constants.h"] +if {[file exists $sourcefile1] && [file exists $sourcefile2]} { + if { [catch { + source [file join $script_dir "mcpModules.tcl"] + source [file join $script_dir "constants.h"] + } errmsg ] } { + set diag "Couldn't source mcpModules.tcl or constants.h, err: $errmsg" + ats_log -error $diag + ats_results -result fail -goto end + } +} else { + set diag "Couldn't source mcpModules.tcl or constants.h, file not exist" + ats_log -error $diag + ats_results -result fail -goto end +} + +namespace eval ::perfUtils { + namespace export * +} + +#################################################### +# Description +#################################################### +procDescr perfUtils::findNdr { + + Description: + The procedure uses a binary search algorithm to find the NDR using the + ports and streams information provided by the user. The user must + provide all of the mandatory argumrnts and optionally can provide the + optional arguments mentioned below. The proc can also obtain latency + based on statistical sampling. The proc can handle any type of traffic + that can be configured in IxExplorer as streams. The proc handles + multicast traffic seprately. + The proc assumes the following: + 1. The traffic streams will be setup by the user + 2. On receiving ports the packets have to be filtered in UDS1 or UDS2 + + Usage: + set result [perfUtils::findNdr \ + -tx_ports \ + -rx_ports \ + -mtx_ports \ + -max_rate \ + -min_rate \ + -threshold \ + -run_time \ + -uds \ + -debug <0|1> \ + -latency <0|1> \ + -uut \ + -tr \ + -exec_cmds ] + + Example: + keylset sendPorts port1.port 1/1/1 + keylset sendPorts port1.streams {1 2 3} + keylset sendPorts port2.port 1/2/1 + keylset sendPorts port2.streams {4 5 6} + + keylset receivePorts port1.port 1/1/1 + keylset receivePorts port2.port 1/2/1 + + set result [perfUtils::findNdr \ + -tx_ports $sendPorts \ + -rx_ports $receivePorts \ + -max_rate 10000000 \ + -min_rate 100000 \ + -threshold 100000 \ + -debug 1 \ + -run_time 100 \ + -latency 1 \ + -uut $UUT ] + + Arguments: + -tx_ports Keyed list in the following format + {port1 {{port 1/1/1} {streams {3 4 1}}}} + {port2 {{port 1/2/1} {streams {23 2 24 25}}}} + Example to define the keyed list: + keylset sendPorts port1.port 1/1/1 + keylset sendPorts port1.streams {1 2 3} + keylset sendPorts port2.port 1/2/1 + keylset sendPorts port2.streams {4 5 6} + Note: You have to give all the transmitting ports info + in a single keyed list as mentioned above in the + example. There is no limit on the number of + transmitting port that you may want to use as + long as all of them are of the same capacity. + e.g. all of them 10Gigs. + You MUST also include the multicast streams + in the tx stream list if you have mcast streams + + -rx_port Keyed list in the following format + {port1 {{port 1/1/1}}} {port2 {{port 1/2/1}}} + Example to define the keyed list: + keylset receivePorts port1.port 1/1/1 + keylset receivePorts port2.port 1/2/1 + Note: You have to give all the receiving ports info + in a single keyed list as mentioned above in the + example. You can receive on any number of ports. + + -mtx_ports Keyed list in the following format + {port2 {{port 1/2/1} {mcast_streams {5 6}} + {mcast_oifs {100 100}}}} + Example to define the keyed list: + keylset mcastPorts port2.port 1/2/1 + keylset mcastPorts port2.mcast_streams {5 6} + keylset mcastPorts port2.mcast_oifs {100 100} + Note: You can have differnt replicas for differnt + streams. Therefore when you mention the multicast + streams you should also mention the number of + replicas you are expecting. If you have two + multicast streams defined you should also mention + the replicas (OIF) respectively. In the above + example stream 5 and 6 and multicast streams. + Each of them are supposed to replicate 100 times. + + -max_rate This is the maximum rate the proc + is going to try on EACH PORT. So the rate you will + mention here will be per port rate in PPS. You should + account for packet size when mentioning the rate. The + procedure tries to find the NDR between the max_rate as + upper bound and min_rate as the lower bound. If you do + not define rate it will calculate the max rate based on + the port capacity and packet size used in the stream. + + -min_rate This is the minimum rate in PPS + the proc is going to try, by default it is 1000 + + -threshold This is the thershold value in PPS. + The proc will not bother the differnce of this value + between the passing and failing NDR. By default is 1000 + + -run_time The proc runs the traffic for this + much amount of time. This is a vlue in seconds. + The default value is 120 seconds + + -uds User can gather recieving traffic + stats on either UDS1 or UDS2. The user has to define + the right filters to cath the interesting traffic. By + default it looks for UDS1. If your traffic stats come + on UDS2 you can select uds2 and provide this argument + + -tx_mode The API supports packet as well as + advanced streams. By default it is packet streams. + if your streams are advanced streams, use this optional + argument to define it is advanced. For advanced streams + the traffic rate will be devided over the number of + streams on each tx port + + -debug by default the debug is OFF (0). + If you enable debug you can get additional log per port + to debug any issues. To enable set -debug value as 1 + + -latency By default the proc does not + calculate latency. If you enable latency by putting + -latency as 1 the proc will give you avg, min and max + latency. To obtain latency you should enable capture + filter and get a reasonable amount of packets in the + buffer (at least 2000) + + -min_cap_pkts By default the value is 20 packets + If this much amount of packet are not there capture + buffer the test is going to fail and will return error + + -uut You must provide the UUT. On this + UUT you can run any commands at half of the run time + for stats or debug. The commands are supplied in the + -exec_cmds argument + + -tr You can provide the TR. On this + RT you can run any commands at half of the run time + for stats or debug. The commands are supplied in the + -exec_cmds argument + + -tgen_app By default its IxExplorer + + -exec_cmds You can provide the list of + show commands to run at half run time. By default + it runs the follwoing three commands + console $uut + EnablePw [test_passwd enable] + $uut exec "show platform hardware qfp active datapath utilization" + $uut exec "show platform hardware qfp active infrastructure exmem statistics" + $uut exec "show platform software status control-processor brief" + $uut exec "show platform hardware qfp active statistics drop" + You should supply as a list e.g. + -exec_cmds {"sh plat hard qfp active data util"\ + "sh plat hard qfp act infra exmem sta"\ + "sh plat soft st control-processor br"} + + -loss_rate loss_rate% number of packets lost + can be acceptable and regard as Non-drop.By default + it's 0.0, indicating the receiving ports shouldn't + lose packets compared with the sending ports. + + Return Value: + Returns a keyed list with structure as follows: + + status <1|0> - 1 for Pass 0 for Fail + <> + ndr - in PPS + numPkts - Number of packets captured on UDS4 for latency. + If latency is not enabled or there is no capture it is 0 + avgLatency - Averege latency in NanoSeconds + minLatency - Minimum Latency in NanoSeconds + maxLatency - Maximum Latency in NanoSeconds + cmd_outputs - Based onm the arguments provided + output1 + output2 + ... + .. + . + <> + log - Message about failure + tclErr - The error thrown by TCL + +} ; # End of procDescr + +####################################################### +#This proc finds the NDR and returns NDR along with latencies and other stats +####################################################### +proc perfUtils::findNdr {args} { + + #mandatory args + set man_args { + -uut ANY + -tx_ports ANY + -rx_ports ANY + } + + #optional_args + set opt_args { + -tr ANY + DEFAULT "" + -mtx_ports ANY + -mrx_ports ANY + -forceTxPorts NUMERIC + DEFAULT 0 + -latency CHOICES 0 1 + DEFAULT 0 + -latency_rates NUMERIC + DEFAULT 95 + -latency_detail CHOICES 0 1 + DEFAULT 0 + -min_cap_pkts NUMERIC + DEFAULT 20 + -run_time NUMERIC + DEFAULT 120 + -max_rate NUMERIC + DEFAULT 0 + -min_rate NUMERIC + DEFAULT 1000 + -threshold NUMERIC + DEFAULT 1000 + -frame_size ANY + -tx_mode CHOICES packet advanced + DEFAULT packet + -exec_cmds ANY + DEFAULT {\ + "show platform hardware qfp active datapath utilization"\ + "show platform hardware qfp active infrastructure exmem statistics"\ + "show platform software status control-processor brief"\ + "show platform hardware qfp active statistics drop"} + -uds CHOICES uds1 uds2 + DEFAULT uds1 + -tgen_app CHOICES IxExplorer IxNetwork + DEFAULT IxNetwork + -ixnetwork_root ANY + -ixnetwork_traffic ANY + -debug CHOICES 0 1 + DEFAULT 0 + -loss_rate ANY + DEFAULT 0.0 + } + + #Parse the dashed arguments + parse_dashed_args -args $args \ + -mandatory_args $man_args -optional_args $opt_args + + ats_log -info "FindNdr args:$args" + + #Define/initialize local variables + set SUCCESS 1 + set FAILURE 0 + set returnList "" + keylset returnList log "" + keylset returnList tclErr "" + append uds_count "$uds" "_count" + append uds_count2 "$uds" "_frame_count" + #debug 1 + #Parse keyed lists + set txPorts ""; set txStreamSets ""; set txStreams ""; set numTxPorts 0 + if {[_parse_tx_ports txPorts txStreamSets txStreams numTxPorts returnList \ + $tx_ports $debug] != $SUCCESS} { + return $returnList + } + + set rxPorts ""; set numRxPorts 0 + if {[_parse_rx_ports rxPorts numRxPorts returnList $rx_ports $debug] \ + != $SUCCESS} { + return $returnList + } + + set mtxPorts ""; set mtxStreamSets ""; + set mtxOifSets ""; set mtxStreams ""; set mtxOifs "" + if {[info exists mtx_ports]} { + if {[_parse_mtx_ports mtxPorts mtxStreamSets mtxOifSets mtxStreams \ + mtxOifs returnList $mtx_ports $debug] != $SUCCESS} { + return $returnList + } + } else { + set mtx_ports "" + } + + set mrxPorts ""; set numMrxPorts 1 + if {[info exists mrx_ports]} { + if {[_parse_mrx_ports mrxPorts numMrxPorts returnList $mrx_ports \ + $debug] != $SUCCESS} { + return $returnList + } + } else { + set mrx_ports "" + } + + if {[info exists max_rate] && $max_rate < 1} { + set maxRatePort [lindex $txPorts 0] + set stream_id [lindex [lindex $txStreamSets 0] 0] + #puts "_maxrate use: $stream_id" + set max_rate [_maxrate2 $maxRatePort $stream_id] + } + + if {[info exists frame_size]} {} else { + set frame_size 0 + if {$tgen_app == "IxExplorer"} { + set frameSizePort [lindex $txPorts 0] + set stream_id [lindex [lindex $txStreamSets 0] 0] + #puts "_framesize use: $stream_id" + set frame_size [_framesize $frameSizePort $stream_id] + } + } + + #Initialize variables for results + set numPkts 0 + set passNdr "NDR not found! Try using lower min_rate and threshold" + set passNumPkts 0 + set passAvgLatency 0 + set passMinLatency 0 + set passMaxLatency 0 + set passCmdOutputs "No Passed Run! All iterations FAILED" + set passCurRate 0 + set everPass 0 + #Initialize variables for while loop + set org_min_rate $min_rate + set nopass_threshold $min_rate + if { $nopass_threshold > $threshold } { + set nopass_threshold $threshold + } + set curRate $max_rate + set iteration 1 + + #start NDR binary search + set latency1 0 + while {($max_rate - $threshold) >= $min_rate || \ + ( $org_min_rate == $min_rate && ($curRate - $nopass_threshold) > $org_min_rate) } { +# note: In original logic, if threshold is much larger than min_rate, and all former +# iteration FAIL, then the condition in while-loop "($max_rate - $threshold) >= $min_rate" +# will lead to break while and not try ~min_rate. +# e.g. min_rate=100, threshold=500, curRate=550 FAIL, set max_rate to 550, then +# max_rate 550 - threshold 500 = 50 < min_rate 100, break while. So only try rate 550, +# much bigger than the set min_rate value 100. +# So this mechanism to handle that if non of the iteration pass, go on try till near min_rate. + set diag "Iteration: $iteration" + ats_log -diag $diag + + #Switch on tgen_app + switch $tgen_app { + IxExplorer { + #Run trafic @ curRate and get results - IxExplorer + if {[_run_IxExplorer_test txPkts rxPkts numPkts avgLatency \ + minLatency maxLatency cmdOutputs returnList $txPorts $txStreams\ + $txStreamSets $tx_mode $rxPorts $mtxPorts $mtxStreams \ + $mtxStreamSets $mtxOifs $mtxOifSets $mtx_ports $run_time \ + $curRate $uds_count $min_cap_pkts $numRxPorts $numMrxPorts \ + $exec_cmds $uut $tr $latency1 0 $debug] != $SUCCESS} { + return $returnList + } + } + + IxNetwork { + #Run trafic @ curRate and get results - IxNetwork +# if {[_run_IxNetwork_test txPkts rxPkts avgLatency minLatency \ +# maxLatency ixNetworkStreamCount cmdOutputs $ixnetwork_root \ +# $curRate $run_time $exec_cmds $uut $latency1 $debug] \ +# != $SUCCESS} { +# return $returnList +# } + #set numPkts $rxPkts + if {[_run_IxNetwork_test2 txPkts rxPkts numPkts avgLatency \ + minLatency maxLatency cmdOutputs returnList $txPorts $txStreams\ + $txStreamSets $tx_mode $rxPorts $mtxPorts $mtxStreams \ + $mtxStreamSets $mtxOifs $mtxOifSets $mtx_ports $run_time \ + $curRate $uds_count2 $min_cap_pkts $numRxPorts $numMrxPorts \ + $exec_cmds $uut $tr $latency1 0 $debug] != $SUCCESS} { + return $returnList + } + } + } + + #Checks for binary search + # $txPkts != $rxPkts + set txPkts [expr {$txPkts*(100.0-$loss_rate)/100}] + if {$debug == 1} { + ats_log -info "loss rate:$loss_rate, txPkts:$txPkts" + } + if {$txPkts > $rxPkts || $rxPkts < $min_rate} { + set result "\n\nFAILED line rate $curRate pps (per port),\ + loss_rate:$loss_rate" + ats_log -result $result + set max_rate $curRate + } else { + set result "\n\nPASSED line rate $curRate pps (per port),\ + loss_rate:$loss_rate" + set everPass 1 + ats_log -result $result + set min_rate $curRate + #NDR if this is the final successful run + if {$forceTxPorts > 0} { + if {$tx_mode == "advanced"} { + set passNdr [expr {$curRate * $numTxPorts * $txStreams}] + } + set passNdr [expr {$curRate * $numTxPorts}] + } else { + if {$tx_mode == "advanced"} { + #Added for IxNetwork + if {$tgen_app == "IxNetwork"} { + set passNdr [expr {$curRate * $numRxPorts}] + # set passNdr [expr {$curRate * $ixNetworkStreamCount}] + # set result "\nPassed line rate $curRate pps (per port),\ + # NDR:$passNdr,ixNetworkStreamCount:$ixNetworkStreamCount" + } else { + set passNdr [expr {$curRate * $numRxPorts}] + } + } else { + set passNdr [expr {$curRate * $numRxPorts}] + } + } + set passNumPkts $numPkts + set passAvgLatency $avgLatency + set passMinLatency $minLatency + set passMaxLatency $maxLatency + set passCmdOutputs $cmdOutputs + set passCurRate $curRate + } + + #Next traffic rate + set curRate [mpexpr ($max_rate+$min_rate)/2] + + #Iteration counter + set iteration [expr {$iteration + 1}] + + } ; # End of While + + # Find latencies at latency_rates + if {$latency == 1} { + foreach rate $latency_rates { + set curRate [expr {($passCurRate*$rate)/100.00}] + if {$latency_detail > 0} {set latency_detail $rate} + switch $tgen_app { + IxExplorer { + #Run trafic @ curRate and get results - IxExplorer + set diag "Post NDR iteration - @ $rate % \ + - $curRate pps (per port)..." + ats_log -diag $diag + if {[_run_IxExplorer_test txPkts rxPkts numPkts avgLatency \ + minLatency maxLatency cmdOutputs returnList $txPorts \ + $txStreams $txStreamSets $tx_mode $rxPorts $mtxPorts \ + $mtxStreams $mtxStreamSets $mtxOifs $mtxOifSets $mtx_ports \ + $run_time $curRate $uds_count $min_cap_pkts $numRxPorts \ + $numMrxPorts $exec_cmds $uut $tr $latency $latency_detail\ + $debug] != $SUCCESS} { + return $returnList + } + } + IxNetwork { + #Run trafic @ curRate and get results - IxNetwork + set diag "Post NDR iteration - @ $rate % \ + - $curRate pps (per port)..." +# ats_log -diag $diag +# if {[_run_IxNetwork_test txPkts rxPkts avgLatency \ +# minLatency maxLatency ixNetworkStreamCount cmdOutputs \ +# $ixnetwork_root $curRate $run_time $exec_cmds $uut \ +# $latency $debug] != $SUCCESS} { +# return $returnList +# } + if {[_run_IxNetwork_test2 txPkts rxPkts numPkts avgLatency\ + minLatency maxLatency cmdOutputs returnList $txPorts \ + $txStreams $txStreamSets $tx_mode $rxPorts $mtxPorts \ + $mtxStreams $mtxStreamSets $mtxOifs $mtxOifSets $mtx_ports \ + $run_time $curRate $uds_count2 $min_cap_pkts $numRxPorts \ + $numMrxPorts $exec_cmds $uut $tr $latency $latency_detail \ + $debug] != $SUCCESS} { + return $returnList + } + } + } + set numPkts $rxPkts + keylset returnList latency($rate) $avgLatency + keylset returnList latency(CUST) $avgLatency + } + } + + #Return keyed list + keylset returnList status $everPass + keylset returnList ndr $passNdr + keylset returnList num_pkts $passNumPkts + keylset returnList latency(NDR) $passAvgLatency + keylset returnList min_latency $passMinLatency + keylset returnList max_latency $passMaxLatency + keylset returnList cmd_outputs $passCmdOutputs + keylset returnList run_time $run_time + keylset returnList frame_size $frame_size + keylset returnList loss_rate $loss_rate + + return $returnList + +} ; # End of Proc findNdr + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_run_IxExplorer_test +# +# Purpose: +# run one iteration of IxExplorer. +# +# Synopsis: +# _run_IxExplorer_test args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc runs IxExplorer test. +###################################################################### +proc perfUtils::_run_IxExplorer_test {txPkts rxPkts numPkts avgLatency \ +minLatency maxLatency cmdOutputs returnList txPorts txStreams txStreamSets \ +tx_mode rxPorts mtxPorts mtxStreams mtxStreamSets mtxOifs mtxOifSets mtx_ports \ +run_time curRate uds_count min_cap_pkts numRxPorts numMrxPorts exec_cmds uut \ +tr latency latency_detail debug} { + + set SUCCESS 1 + upvar $txPkts txPktsLoc + upvar $rxPkts rxPktsLoc + upvar $numPkts numPktsLoc + upvar $avgLatency avgLatencyLoc + upvar $minLatency minLatencyLoc + upvar $maxLatency maxLatencyLoc + upvar $cmdOutputs cmdOutputsLoc + upvar $returnList returnListLoc + + #Set Traffic Rate + if {[_set_curRate_IxExplorer $txPorts $txStreamSets $tx_mode $mtxPorts \ + $mtxStreams $mtxOifs $mtx_ports $numMrxPorts $curRate] != $SUCCESS} { + return $returnList + } + + #Run Traffic + set cmdOuputsLoc "" + if {[_run_traffic_IxExplorer cmdOutputsLoc $txPorts $rxPorts $run_time \ + $exec_cmds $uut $tr] != $SUCCESS} { + return $returnList + } + + #Get Tx Stats + set txPktsLoc [_get_txPkts_IxExplorer $txPorts $txStreamSets $mtxPorts \ + $mtxStreamSets $mtxOifSets $mtx_ports $debug] + + #Get Rx Stats + set rxPktsLoc [_get_rxPkts_IxExplorer $rxPorts $uds_count $debug] + + #Get Latency Stats + set numPktsLoc 0; + set avgLatencyLoc 0; set minLatencyLoc 0; set maxLatencyLoc 0 + if {$latency == 1} { + if {[_get_latency_IxExplorer numPktsLoc avgLatencyLoc minLatencyLoc \ + maxLatencyLoc returnListLoc $rxPorts $min_cap_pkts $numRxPorts\ + $debug $latency_detail] != $SUCCESS} { + return $returnList + } + } + + return 1 +} ; # End of Proc _run_IxExplorer_test + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_run_IxNetwork_test +# +# Purpose: +# run one iteration of IxNetwork. +# +# Synopsis: +# _run_IxNetwork_test args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc runs IxNetwork test. +###################################################################### +proc perfUtils::_run_IxNetwork_test {txPkts rxPkts avgLatency minLatency \ +maxLatency ixNetworkStreamCount cmdOutputs ixnetwork_root curRate run_time \ +exec_cmds uut tr latency debug} { + + set SUCCESS 1 + upvar $txPkts txPktsLoc + upvar $rxPkts rxPktsLoc + upvar $avgLatency avgLatencyLoc + upvar $minLatency minLatencyLoc + upvar $maxLatency maxLatencyLoc + upvar $ixNetworkStreamCount ixNetworkStreamCountLoc + upvar $cmdOutputs cmdOutputsLoc + + #Set Traffic Rate + if {[_set_curRate_IxNetwork $ixnetwork_root $curRate] != $SUCCESS} { + return $returnList + } + + #Enable Stats + set txPkts [_enable_stats_IxNetwork $ixnetwork_root] + + #Run Traffic + set cmdOutputsLoc "" + if {[_run_traffic_IxNetwork cmdOutputsLoc $ixnetwork_root $run_time \ + $exec_cmds $uut $tr] != $SUCCESS} { + return $returnList + } + + #Initialize Variables + set txPktsLoc 0; set rxPktsLoc 0; + set avgLatencyLoc 0; set minLatencyLoc 0; set maxLatencyLoc 0 + + if {0} { + #Get Tx Stats + if {[_get_txPkts_IxNetwork txPktsLoc ixNetworkStreamCountLoc \ + $ixnetwork_root] != $SUCCESS} { + return $returnList + } + + #Get Rx Stats + if {[_get_rxPkts_IxNetwork rxPktsLoc $ixnetwork_root] != $SUCCESS} { + return $returnList + } + } + + # Adding new proc as a work around for Ixia Stats update error + sleep 5 + if {[_get_txRxPkts_IxNetwork txPktsLoc rxPktsLoc ixNetworkStreamCountLoc \ + $ixnetwork_root] != $SUCCESS} { + return $returnList + } + + #Get Latency Stats + if {$latency == 1} { + if {[_get_latency_IxNetwork avgLatencyLoc minLatencyLoc maxLatencyLoc \ + $ixnetwork_root $debug] != $SUCCESS} { + return $returnList + } + } + + return 1 +} ; # End of Proc _run_IxNetwork_test + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_run_IxNetwork_test2 +# +# Purpose: +# run one iteration of IxNetwork, using high-level api +# +# Synopsis: +# _run_IxNetwork_test2 args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc runs IxNetwork test(2). using high-level api +###################################################################### +proc perfUtils::_run_IxNetwork_test2 {txPkts rxPkts numPkts avgLatency \ +minLatency maxLatency cmdOutputs returnList txPorts txStreams txStreamSets \ +tx_mode rxPorts mtxPorts mtxStreams mtxStreamSets mtxOifs mtxOifSets \ +mtx_ports run_time curRate uds_count2 min_cap_pkts numRxPorts numMrxPorts \ +exec_cmds uut tr latency latency_detail debug} { + + set SUCCESS 1 + upvar $txPkts txPktsLoc + upvar $rxPkts rxPktsLoc + upvar $numPkts numPktsLoc + upvar $avgLatency avgLatencyLoc + upvar $minLatency minLatencyLoc + upvar $maxLatency maxLatencyLoc + upvar $cmdOutputs cmdOutputsLoc + upvar $returnList returnListLoc + + #Set Traffic Rate + #Note: can use same _set_curRate proc with IxExplorer method + if {[_set_curRate_IxExplorer $txPorts $txStreamSets $tx_mode $mtxPorts \ + $mtxStreams $mtxOifs $mtx_ports $numMrxPorts $curRate] != $SUCCESS} { + return $returnList + } + + #Run Traffic + set cmdOuputsLoc "" + #Note: can use same _run_traffic proc with IxExplorer method + if {[_run_traffic_IxExplorer cmdOutputsLoc $txPorts $rxPorts $run_time \ + $exec_cmds $uut $tr] != $SUCCESS} { + return $returnList + } + + #sleep 20 second, since ixNetwork seems to have heavy time delay + after 20000 + + #Get Tx Stats + set txPktsLoc [_get_txPkts_IxNetwork2 $txPorts $txStreamSets $mtxPorts \ + $mtxStreamSets $mtxOifSets $mtx_ports $debug] + + #Get Rx Stats + set rxPktsLoc [_get_rxPkts_IxNetwork2 $rxPorts $uds_count2 $debug] + + #Get Latency Stats + set numPktsLoc 0; + set avgLatencyLoc 0; set minLatencyLoc 0; set maxLatencyLoc 0 + if {$latency == 1} { + if {[_get_latency_IxNetwork2 numPktsLoc avgLatencyLoc minLatencyLoc \ + maxLatencyLoc returnListLoc $rxPorts $min_cap_pkts $numRxPorts\ + $debug $latency_detail $txStreamSets $txPorts] != $SUCCESS} { + #return $returnList + #rupan note: here actually should return $returnList; yet if so, + #status of returnList is 0, and the Ndr will not get recorded in + #the script which uses findNdr method. + #so instead we return 1, so latency is 0 in the record, rather than + #expected value, and in the log there is note to explain rx_mode + #should be set capture_and_measure if wanting calculate latency. + return 1 + } + } + + return 1 +} ; # End of Proc _run_IxNetwork_test2 + + +###################################################################### +##Procedure Header +# Name: +# _set_curRate_IxExplorer +# +# Purpose: +# set the traffic rate for the next iteration on IxExplorer. +# +# Synopsis: +# _set_curRate_IxExplorer args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc sets the traffic rate for the next iteration on IxExplorer +###################################################################### +proc _set_curRate_IxExplorer {txPorts txStreamSets tx_mode mtxPorts \ +mtxStreams mtxOifs mtx_ports numMrxPorts curRate} { + #Set traffic rate for all streams + set tempRate $curRate; set SUCCESS 1 + foreach port $txPorts txStreamSet $txStreamSets { + if {$tx_mode == "advanced"} { + set numStreams [llength $txStreamSet] + set curRate [expr {$tempRate/$numStreams}] + } + foreach stream $txStreamSet { + set traffic_status [ixia::traffic_config \ + -mode modify \ + -stream_id $stream \ + -port_handle $port \ + -rate_pps $curRate ] + if {[keylget traffic_status status] != $SUCCESS} { + set diag "Couldn't configure base stream on $port" + ats_log -error $diag + ats_log -error "[keylget traffic_status log]" + ats_results -result fail + } + } + } + + if {[info exists mtx_ports]} { + set numMStreams [llength mtxStreams] + set curRate $tempRate + if {$tx_mode == "advanced"} { + set curRate [expr {$tempRate/$numMStreams}] + } + foreach port $mtxPorts { + foreach stream $mtxStreams oif $mtxOifs { + set traffic_status [ixia::traffic_config \ + -mode modify \ + -stream_id $stream \ + -port_handle $port \ + -rate_pps [expr {($curRate/$oif)*$numMrxPorts}]] + if {[keylget traffic_status status] != $SUCCESS} { + set diag "Couldn't configure base stream on $port" + ats_log -error $diag + ats_log -error "[keylget traffic_status log]" + ats_results -result fail + } + } + } + } + + set diag "Now trying $curRate pps (per port @ each stream)... " + ats_log -diag $diag + + return 1 +} ; # End of Proc _set_curRate_IxExplorer + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_txPkts_IxExplorer +# +# Purpose: +# get the traffic stats for IxExplorer and returns transmitted packets. +# +# Synopsis: +# _get_txPkts_IxExplorer args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the traffic stats for IxExplorer +# and returns transmitted packets +###################################################################### +proc perfUtils::_get_txPkts_IxExplorer {txPorts txStreamSets mtxPorts \ +mtxStreamSets mtxOifSets mtx_ports debug} { + + #Initialize variables + set txPkts 0 + set _txPkts 0 + set mtxPkts 0 + set _mtxPkts 0 + set success 1 + + #Get the total number of packets sent + #here calculate the actual number of packets sent across all streams + foreach txPort $txPorts txStreamSet $txStreamSets { + foreach txStream $txStreamSet { + set txStats [ixia::traffic_stats -port_handle $txPort \ + -mode stream -stream $txStream] + if {[keylget txStats status] != $success} { + set diag "Couldn't get TX stats on $txPort : $txStream" + ats_results -diag $diag + ats_log -diag $diag + if {$debug == 1} { + ats_log -diag "txStats: $txStats" + } + ats_results -result fail + } + if { [catch { + set txPkts [expr { 1.0*$txPkts + \ + [keylget txStats $txPort.stream.$txStream.tx.total_pkts]}] + #For debug only + set _txPkts [expr {1.0*$_txPkts + \ + [keylget txStats $txPort.stream.$txStream.tx.total_pkts]}] + } errmsg ] } { + ats_log -info "txStats: $txStats" + set diag "Couldn't get TX stats on $txPort : $txStream" + ats_results -result fail + } + } + if {$debug == 1} { + ats_log -diag "$txPort - txPkts (mtx pkts included) $_txPkts"; + set _txPkts 0 + } + } + + #If multicast streams exists, adjust the total number of replicated packets + if {[info exists mtx_ports]} { + foreach mtxPort $mtxPorts mtxStreamSet $mtxStreamSets \ + mtxOifSet $mtxOifSets { + foreach mtxStream $mtxStreamSet mtxOif $mtxOifSet { + set mtxStats [ixia::traffic_stats -port_handle $mtxPort \ + -mode stream -stream $mtxStream] + if {[keylget mtxStats status] != $success} { + set diag "Couldn't get TX stats on $mtxPort : $mtxStream" + ats_results -diag $diag + ats_log -diag $diag + if {$debug == 1} { + ats_log -diag "mtxStats: $mtxStats" + } + ats_results -result fail + } + if { [catch { + set extraPkts [keylget mtxStats \ + $mtxPort.stream.$mtxStream.tx.total_pkts] + set mtxPkts [expr {$mtxPkts + (1.0 * $mtxOif * [keylget mtxStats\ + $mtxPort.stream.$mtxStream.tx.total_pkts]) - $extraPkts}] + } errmsg ] } { + ats_log -info "mtxStats: $mtxStats" + set diag "Couldn't get TX stats on $mtxPort : $mtxStream" + ats_results -result fail + } + #For debug only + set _mtxPkts [expr {$_mtxPkts + \ + [keylget mtxStats $mtxPort.stream.$mtxStream.tx.total_pkts]}] + + } + if {$debug == 1} { + ats_log -diag "$mtxPort - mtxPkts x mtxOif - $_mtxPkts x $mtxOif" + set _mtxPkts 0 + } + + } + } + + #Calculate the total number of packets expected to be received on rxPorts, + set txPkts [expr { $txPkts + $mtxPkts}] + if {$txPkts <= 1.0} { + set diag "txPkts 0 - Please check your streams OR API call params " + ats_log -diag $diag + } + + return $txPkts + +} ; # End of Proc _get_rxPkts_IxExplorer + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_rxPkts_IxExplorer +# +# Purpose: +# get the Rx stats for IxExplorer and return pkts received +# +# Synopsis: +# _get_rxPkts_IxExplorer args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the Rx stats for IxExplorer and return pkts received +###################################################################### +proc perfUtils::_get_rxPkts_IxExplorer {rxPorts uds_count debug} { + + #Initialize Rx variables + set rxPkts 0 ; set _rxPkts 0 + set success 1 + + #Get the total number of interesting packets received on RxPorts + foreach rxPort $rxPorts { + set rxStats [ixia::traffic_stats -port_handle $rxPort] + if {[keylget rxStats status] != $success} { + set diag "Couldn't get RX stats on $rxPort" + ats_results -diag $diag + ats_log -diag $diag + if {$debug == 1} { + ats_log -diag "rxStats: $rxStats" + } + } + if { [catch { + set rxPkts [expr {1.0*$rxPkts + \ + [keylget rxStats $rxPort.aggregate.rx.$uds_count]}] + set _rxPkts [expr {1.0* $_rxPkts + \ + [keylget rxStats $rxPort.aggregate.rx.$uds_count]}] + } errmsg ] } { + ats_log -info "rxStats: $rxStats" + set diag "Couldn't get RX stats on $rxPort" + ats_results -result fail + } + if {$debug == 1} { + ats_log -diag "$rxPort - rxPkts - $_rxPkts"; + set _rxPkts 0 + } + } + return $rxPkts + +} ; # End of Proc _get_rxPkts_IxExplorer + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_latency_IxExplorer +# +# Purpose: +# get the latencies on IxExplorer and upvars it +# +# Synopsis: +# _get_latency_IxExplorer args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the latencies on IxExplorer and upvars it +###################################################################### +proc perfUtils::_get_latency_IxExplorer {numPkts avgLatency minLatency \ +maxLatency returnList rxPorts min_cap_pkts numRxPorts debug latency_detail} { + + upvar $numPkts numPktsLocal + upvar $avgLatency avgLatencyLocal + upvar $minLatency minLatencyLocal + upvar $maxLatency maxLatencyLocal + upvar $returnList returnListLocal + set numPktsLocal 0; set _numPkts 0 + set avgLatencyLocal 0; set _avgLatency 0 + set minLatencyLocal 0; set _minLatency 0 + set maxLatencyLocal 0; set _maxLatency 0 + set success 1; set failure 0 + + #puts "enter _get_latency_IxExplorer" + foreach rxPort $rxPorts { + set rxPktStats [ixia::packet_stats -port_handle $rxPort \ + -format none -chunk_size 8000000] + if {[keylget rxPktStats status] != $success} { + set diag "Couldn't get RX packet stats on $rxPort" + ats_results -diag $diag + ats_log -diag $diag + } + #set rxpkt [keylget rxStats $rxPort.aggregate.rx.$uds_count] + ats_log -info "ixia rx_status:$rxPktStats" + if {[keylget rxPktStats $rxPort.aggregate.num_frames] < $min_cap_pkts \ + || [keylget rxPktStats $rxPort.aggregate.num_frames] == "N/A"} { + keylset returnListLocal status $failure + keylset returnListLocal log "[_error 8] - Pkts catured \ + [keylget rxPktStats $rxPort.aggregate.num_frames] \ + Min number of Pkts required $min_cap_pkts" + return 0 + } + set numPktsLocal [expr {$numPktsLocal + \ + [keylget rxPktStats $rxPort.aggregate.num_frames]}] + set _numPkts [expr {$_numPkts + \ + [keylget rxPktStats $rxPort.aggregate.num_frames]}] + set avgLatencyLocal [expr {$avgLatencyLocal + \ + [keylget rxPktStats $rxPort.aggregate.average_latency]}] + set _avgLatency [expr {$_avgLatency + \ + [keylget rxPktStats $rxPort.aggregate.average_latency]}] + set minLatencyLocal [expr {$minLatencyLocal + \ + [keylget rxPktStats $rxPort.aggregate.min_latency]}] + set _minLatency [expr {$_minLatency + \ + [keylget rxPktStats $rxPort.aggregate.min_latency]}] + set maxLatencyLocal [expr {$maxLatencyLocal + \ + [keylget rxPktStats $rxPort.aggregate.max_latency]}] + set _maxLatency [expr {$_maxLatency + \ + [keylget rxPktStats $rxPort.aggregate.max_latency]}] + + if {$debug == 1} { + ats_log -diag "$rxPort- numPkts - $_numPkts\ + avgLatency - $_avgLatency\ + minLatency - $_minLatency\ + maxLatency - $_maxLatency" + set _numPkts 0 + set _avgLatency 0 + set _minLatency 0 + set _maxLatency 0 + } + if {$latency_detail > 0} { + ats_log -diag "Latency detail enabled @ $latency_detail %" + + scan $rxPort "%d/%d/%d" ix_c ix_l ix_p + capture get $ix_c $ix_l $ix_p + + set NOW [clock format [clock seconds] -format {%m%d%y%H%M%S}] + set file_name "Latency_$latency_detail.$ix_c$ix_l$ix_p$NOW.latency" + set fd1 [open $file_name "w"] + + set numCapture [capture cget -nPackets] + if { [captureBuffer get $ix_c $ix_l $ix_p 1 $numCapture] } { + ats_log -diag "Failed to get captureBuffer" + } + captureBuffer getStatistics + puts $fd1 "Per packet latency @ port $ix_c $ix_l $ix_p" + set numFrames [captureBuffer cget -numFrames] + set averageLatency [captureBuffer cget -averageLatency] + set minLatency [captureBuffer cget -minLatency] + set maxLatency [captureBuffer cget -maxLatency] + set standardDeviation [captureBuffer cget -standardDeviation] + set averageDeviation [captureBuffer cget -averageDeviation] + + puts $fd1 "numFrames - $numFrames |\ + averageLatency - $averageLatency |\ + minLatency - $minLatency |\ + maxLatency - $maxLatency |\ + standardDeviation $standardDeviation |\ + averageDeviation $averageDeviation " + + for {set i 1} { $i <= $numFrames } { incr i } { + captureBuffer getframe $i + set frame_latency [captureBuffer cget -latency] + set frame_time [captureBuffer cget -timestamp] + puts $fd1 "$frame_time - $frame_latency" + } + close $fd1 + } + } + + set avgLatencyLocal [expr {$avgLatencyLocal/$numRxPorts}] + set minLatencyLocal [expr {$minLatencyLocal/$numRxPorts}] + set maxLatencyLocal [expr {$maxLatencyLocal/$numRxPorts}] + + return 1 + +} ; # End of Proc _get_latency_IxExplorer + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_run_traffic_IxExplorer +# +# Purpose: +# runs the traffic for the run_time seconds +# and upvars cmd output on IxExplorer +# +# Synopsis: +# _get_latency_IxExplorer args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc runs the traffic for the run_time seconds +# and upvars cmd output on IxExplorer +###################################################################### +proc perfUtils::_run_traffic_IxExplorer {cmdOutputs txPorts rxPorts run_time \ +exec_cmds uut tr} { + + upvar $cmdOutputs cmdOutputsLocal + set allPorts [concat $rxPorts $txPorts] + #Clearing of stats need to be a one statement as below, + #otherwise latency will mess up + #debug 1 + ixia::traffic_control -port_handle $allPorts -action clear_stats + + #start the packet capture + foreach port $rxPorts { + ixia::packet_control -port_handle $port -action start + } + + #start the traffic + set STC_DISABLE_ARP 0 + global env + if { [info exists env(USE_STC)] && $env(USE_STC) } { + if { [info exists env(STC_DISABLE_ARP)] && $env(STC_DISABLE_ARP) } { + set STC_DISABLE_ARP 1 + ats_log -info "run_traffic_IxExplorer: disabling ARP for STC -action run" + } + } + foreach port $txPorts { + if {$STC_DISABLE_ARP} { + ixia::traffic_control -port_handle $port -action run + } else { + ixia::traffic_control -port_handle $port -action run + } + } + + #Wait for half the test run time + sleep [expr {$run_time/2.0}] + + #Execute any commands for debug or results + set cmdOutputsLocal {} + foreach cmd $exec_cmds { + lappend cmdOutputsLocal [$uut exec $cmd] + if { $tr != "" } { + $tr exec $cmd + } + # sleep a while between each show command, + # to reduce the impact on resource using + sleep 3 + } + + #Wait for another half the test run time + sleep [expr {$run_time/2.0}] + + #stop the traffic + foreach port $txPorts { + ixia::traffic_control -port_handle $port -action stop + } + + #stop the packet capture + foreach port $rxPorts { + ixia::packet_control -port_handle $port -action stop + } + + $uut exec "show platform hardware qfp active statistics drop clear" + if { $tr != "" } { + $tr exec "show platform hardware qfp active statistics drop clear" + } + #Wait for 5 seconds before starting to collect data + sleep 5 + + return 1 + +} ; # End of Proc _run_traffic_IxExplorer + + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_set_curRate_IxNetwork +# +# Purpose: +# set the traffic rate for the next iteration on IxNetwork +# +# Synopsis: +# _set_curRate_IxNetwork args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc sets the traffic rate for the next iteration on IxNetwork +###################################################################### +proc perfUtils::_set_curRate_IxNetwork {root curRate} { + + set traffic $root/traffic + #debug 1 + # Set rate + set trafficItems [::ixNet getList $root/traffic trafficItem] + foreach {trafficItem} $trafficItems { + ::ixNet setAttribute $trafficItem/rateOptions -packetsPerSecond $curRate + ::ixNet setAttribute $trafficItem/rateOptions -rateMode packetsPerSecond + } + ::ixNet commit + + #_ixnetwork_set_rate $curRate + set genTraffic [ixNet setAtt $traffic -refreshLearnedInfoBeforeApply true] + ixNet commit + set apply [::ixNet exec apply $traffic] + + return 1 + +} ; # End of Proc _set_curRate_IxNetwork + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_enable_stats_IxNetwork +# +# Purpose: +# enable traffic stats on IxNetwork +# +# Synopsis: +# _enable_stats_IxNetwork args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc enables traffic stats on IxNetwork +###################################################################### +proc perfUtils::_enable_stats_IxNetwork {root} { + + # Enable stats + #debug 1 + set statistic $root/statistics + set statViewList [ixNet getList $statistic trafficStatViewBrowser] + set indexOftraffStats [lsearch -regexp $statViewList "Traffic Statistics"] + set trafficStats [lindex $statViewList $indexOftraffStats] + ixNet setAttr $trafficStats -enabled true + ixNet commit + + return 1 + +} ; # End of Proc _enable_stats_IxNetwork + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_txPkts_IxNetwork +# +# Purpose: +# get the Tx stats for IxNetwork and return transmitted pkts +# +# Synopsis: +# _get_txPkts_IxNetwork args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the Tx stats for IxNetwork and return transmitted pkts +###################################################################### +proc perfUtils::_get_txPkts_IxNetwork {txPkts ixNetworkStreamCount root} { + + upvar $txPkts txPktsLocal + upvar $ixNetworkStreamCount ixNetworkStreamCountLoc + + #Initialize Rx variables + set txPkts 0 + set success 1 + + set statistic $root/statistics + set statViewList [ixNet getList $statistic trafficStatViewBrowser] + set indexOftraffStats [lsearch -regexp $statViewList "Traffic Statistics"] + set trafficStats [lindex $statViewList $indexOftraffStats] + ixNet setAttr $trafficStats -enabled true + ixNet commit + + # Get stats + set rows [ixNet getList $trafficStats row] + set framesDelta 0 + set totalLat 0 + set ixNetworkStreamCountLoc 0 + + foreach row $rows { + set stats [ixNet getList $row cell] + set curTxFrames [ixNet getAttr \ + [lindex $stats [lsearch -regexp $stats {Tx Frames}]] -statValue] + set txPktsLocal [mpexpr $txPktsLocal + $curTxFrames] + incr ixNetworkStreamCountLoc + } + + #puts "txPkts $txPktsLocal" + #puts "ixNetworkStreamCountLoc $ixNetworkStreamCountLoc" + + return 1 + +} ; # End of Proc _get_txPkts_IxNetwork + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_txPkts_IxNetwork2 +# +# Purpose: +# get the Tx stats for IxNetwork and return transmitted pkts +# using high-level api +# +# Synopsis: +# _get_txPkts_IxNetwork2 args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the Tx stats for IxNetwork and return transmitted pkts +# using high-level api +###################################################################### +proc perfUtils::_get_txPkts_IxNetwork2 {txPorts txStreamSets mtxPorts \ +mtxStreamSets mtxOifSets mtx_ports debug} { + + #Initialize variables + set txPkts 0 + set _txPkts 0 + set mtxPkts 0 + set _mtxPkts 0 + set success 1 + + #Get the total number of packets sent, + #here calculate the actual number of packets sent across all streams + foreach txPort $txPorts txStreamSet $txStreamSets { + #IxNetwork can only get aggregate count with this method, + #so not "foreach txStream $txStreamSet", but just one + #foreach txStream $txStreamSet { + set txStats [ixia::traffic_stats -port_handle $txPort \ + -traffic_generator ixnetwork_540] + if {$debug == 1} { + set key $txPort.aggregate.tx + set aggregate_keys [keylkeys txStats $key] + foreach aggregate_key $aggregate_keys { + ats_log -info "[format "%5s %10s" $aggregate_key \ + [keylget txStats $key.$aggregate_key]]" + } + } + set txPkts [expr {$txPkts + \ + [keylget txStats $txPort.aggregate.tx.scheduled_pkt_count]}] + #For debug only + set _txPkts [expr {$_txPkts + \ + [keylget txStats $txPort.aggregate.tx.scheduled_pkt_count]}] + if {[keylget txStats status] != $success} { + set diag "Couldn't get TX stats on $txPort (aggregate)" + ats_results -diag $diag + ats_log -diag $diag + ats_results -result fail + } + #} + if {$debug == 1} { + ats_log -diag "$txPort - txPkts (mtx pkts included) $_txPkts"; + set _txPkts 0 + } + } + + #If multicast streams exists, adjust the total number of replicated packets + if {[info exists mtx_ports]} { + foreach mtxPort $mtxPorts mtxStreamSet $mtxStreamSets \ + mtxOifSet $mtxOifSets { + #IxNetwork can only get aggregate count with this method, + #so not "foreach txStream $txStreamSet", but just one + set firstTime 1 + foreach mtxStream $mtxStreamSet mtxOif $mtxOifSet { + if { $firstTime == 1 } { + set mtxStats [ixia::traffic_stats -port_handle $mtxPort \ + -traffic_generator ixnetwork_540] + set extraPkts [keylget mtxStats \ + $mtxPort.aggregate.tx.scheduled_pkt_count] + set mtxPkts [expr {$mtxPkts + (1.0 * $mtxOif * [keylget mtxStats \ + $mtxPort.aggregate.tx.scheduled_pkt_count]) - $extraPkts}] + #For debug only + set _mtxPkts [expr {$_mtxPkts + \ + [keylget mtxStats $mtxPort.aggregate.tx.scheduled_pkt_count]}] + + if {[keylget mtxStats status] != $success} { + set diag "Couldn't get TX stats on $mtxPort (aggregate)" + ats_results -diag $diag + ats_log -diag $diag + ats_results -result fail + } + } + set firstTime 0 + } + if {$debug == 1} { + ats_log -diag "$mtxPort - mtxPkts x mtxOif - $_mtxPkts x $mtxOif"; + set _mtxPkts 0 + } + } + } + + #Calculate the total number of packets expected to be received on rxPorts, + set txPkts [expr { $txPkts + $mtxPkts}] + if {$txPkts <= 1.0} { + set diag "txPkts 0 - Please check your streams OR API call params " + ats_log -diag $diag + } + return $txPkts + +} ; # End of Proc _get_txPkts_IxNetwork2 + + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_txRxPkts_IxNetwork +# +# Purpose: +# get the Rx and TX stats for IxNetwork and return pkts received +# +# Synopsis: +# _get_txPkts_IxNetwork2 args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the Rx and TX stats for IxNetwork and return pkts received +# This proc is workaround for IxNW status update error +# The code s for one port 10 GE card. For the XM8 cards, +# you don't need the workaround code. +# The old one port 10GE card does not support the port level filtering +# for the stats, so the stats update maybe lagging. +###################################################################### +proc perfUtils::_get_txRxPkts_IxNetwork {txPkts rxPkts ixNetworkStreamCount \ +root} { + + upvar $txPkts txPktsLocal + upvar $rxPkts rxPktsLocal + upvar $ixNetworkStreamCount ixNetworkStreamCountLoc + + #Initialize Rx variables + set txPkts 0 + set rxPkts 0 + set success 1 + + set statistic $root/statistics + set statViewList [ixNet getList $statistic trafficStatViewBrowser] + set indexOftraffStats [lsearch -regexp $statViewList "Traffic Statistics"] + set trafficStats [lindex $statViewList $indexOftraffStats] + ixNet setAttr $trafficStats -enabled true + ixNet commit + + + ### TK debug + set timeout 0 + set error "false" + set continueFlag "true" + + while {$continueFlag == "true"} { + set continueFlag "false" + set rows [ixNet getList $trafficStats row] + set ixNetworkStreamCountLoc 0 + + foreach row $rows { + set stats [ixNet getList $row cell] + set curTxFrames [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Tx Frames}]] -statValue] + set curRxFrames [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Rx Frames}]] -statValue] + set curTxFrameRate [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Tx Frame Rate}]] -statValue] + set curRxFrameRate [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Rx Frame Rate}]] -statValue] + set curLossPercent [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Loss %}]] -statValue] + #puts "curTxFrameRate = $curTxFrameRate \ + #curRxFrameRate = $curRxFrameRate curLossPercent = $curLossPercent" + + if { $curTxFrameRate != 0 || $curRxFrameRate != 0 } { + set continueFlag "true" + after 1000 + incr timeout + if {$timeout == 240} { + set continueFlag "false" + set error "true" + } + } else { + + if {$curTxFrames == {} || $curRxFrames == {} || \ + $curTxFrameRate == {} || $curRxFrameRate == {} || \ + $curLossPercent == {} } { + ### pause for 1 second + set continueFlag "true" + after 1000 + incr timeout + if {$timeout == 240} { + set continueFlag "false" + set error "true" + } + } else { + set txPktsLocal [expr {$txPktsLocal + $curTxFrames}] + set rxPktsLocal [expr {$rxPktsLocal + $curRxFrames}] + incr ixNetworkStreamCountLoc + + } + } + } + } + if {$error == "true"} { + #puts "Ixia Error: failed to get either Tx Frames or Rx Frames count \ + # after 180 seconds" + } + + #puts "txPkts $txPktsLocal rxPkts $rxPktsLocal" + #puts "ixNetworkStreamCountLoc $ixNetworkStreamCountLoc" + + return 1 + +} ; # End of Proc _get_txPkts_IxNetwork + + + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_rxPkts_IxNetwork +# +# Purpose: +# get the Rx stats for IxNetwork and return pkts received +# +# Synopsis: +# _get_rxPkts_IxNetwork args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the Rx stats for IxNetwork and return pkts received +###################################################################### +proc perfUtils::_get_rxPkts_IxNetwork {rxPkts root} { + + upvar $rxPkts rxPktsLocal + + #Initialize Rx variables + set rxPkts 0 + set success 1 + + set statistic $root/statistics + set statViewList [ixNet getList $statistic trafficStatViewBrowser] + set indexOftraffStats [lsearch -regexp $statViewList "Traffic Statistics"] + set trafficStats [lindex $statViewList $indexOftraffStats] + ixNet setAttr $trafficStats -enabled true + ixNet commit + + # Get stats + set rows [ixNet getList $trafficStats row] + set framesDelta 0 + set totalLat 0 + set ixNetworkStreamCount 0 + + foreach row $rows { + set stats [ixNet getList $row cell] + set curRxFrames [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Rx Frames}]] -statValue] + set rxPktsLocal [mpexpr $rxPktsLocal + $curRxFrames] + incr ixNetworkStreamCount + } + + #puts "rxPkts $rxPktsLocal" + return 1 + +} ; # End of Proc _get_rxPkts_IxNetwork + + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_rxPkts_IxNetwork2 +# +# Purpose: +# get the Rx stats for IxNetwork and return pkts received +# using high-level api +# +# Synopsis: +# _get_rxPkts_IxNetwork2 args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the Rx stats for IxNetwork and return pkts received +# using high-level api +###################################################################### +proc perfUtils::_get_rxPkts_IxNetwork2 {rxPorts uds_count2 debug} { + #Initialize Rx variables + set rxPkts 0 ; set _rxPkts 0 + set success 1 + set uds_count2 "uds2_frame_count" + #debug 1 + #Get the total number of interesting packets received on RxPorts + foreach rxPort $rxPorts { + set rxStats [ixia::traffic_stats -port_handle $rxPort \ + -traffic_generator ixnetwork_540] + if { $debug == 1 } { + set key $rxPort.aggregate.rx + set aggregate_keys [keylkeys rxStats $key] + foreach aggregate_key $aggregate_keys { + ats_log -info "[format "%5s %10s" $aggregate_key \ + [keylget rxStats $key.$aggregate_key]]" + } + } + + if {[keylget rxStats status] != $success} { + set diag "Couldn't get RX stats on $rxPort" + ats_results -diag $diag + ats_log -diag $diag + } + set rxPkts [expr {1.0*$rxPkts + \ + [keylget rxStats $rxPort.aggregate.rx.$uds_count2]}] + set _rxPkts [expr {1.0* $_rxPkts + \ + [keylget rxStats $rxPort.aggregate.rx.$uds_count2]}] + if {$debug == 1} { + ats_log -diag "$rxPort - rxPkts - $_rxPkts"; + set _rxPkts 0 + } + } + return $rxPkts + +} ; # End of Proc _get_rxPkts_IxNetwork2 + + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_latency_IxNetwork +# +# Purpose: +# get the latencies on IxNetwork and upvars it +# +# Synopsis: +# _get_latency_IxNetwork args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the latencies on IxNetwork and upvars it +###################################################################### +proc perfUtils::_get_latency_IxNetwork {avgLatency minLatency maxLatency root \ +debug} { + + upvar $avgLatency avgLatencyLocal + upvar $minLatency minLatencyLocal + upvar $maxLatency maxLatencyLocal + + set avgLatencyLocal 0 + set minLatencyLocal 0 + set maxLatencyLocal 0 + + #Initialize Rx variables + set avgLatency 0 + set success 1 + + set statistic $root/statistics + set statViewList [ixNet getList $statistic trafficStatViewBrowser] + set indexOftraffStats [lsearch -regexp $statViewList "Traffic Statistics"] + set trafficStats [lindex $statViewList $indexOftraffStats] + ixNet setAttr $trafficStats -enabled true + ixNet commit + + # Get stats + set rows [ixNet getList $trafficStats row] + set framesDelta 0 + set totalLat 0; set curMinLat 0; set curMaxLat 0; set curAvgLat 0 + set ixNetworkStreamCount 0 + set rx_pkt 0 + + + foreach row $rows { + set stats [ixNet getList $row cell] + set rx_pkts [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Rx Frames}]] -statValue] + if {$rx_pkts != 0 } { + set curAvgLat [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Avg Latency \(ns\)}]] -statValue] + set curMinLat [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Min Latency \(ns\)}]] -statValue] + set curMaxLat [ixNet getAttr [lindex $stats \ + [lsearch -regexp $stats {Max Latency \(ns\)}]] -statValue] + set avgLatencyLocal [mpexpr $avgLatencyLocal + $curAvgLat] + set minLatencyLocal [mpexpr $minLatencyLocal + $curMinLat] + set maxLatencyLocal [mpexpr $maxLatencyLocal + $curMaxLat] + incr ixNetworkStreamCount + #puts "Stream: $ixNetworkStreamCount curMinLat:$curMinLat \ + # curMaxLat:$curMaxLat curAvgLat:$curAvgLat" + #puts "Stream:$ixNetworkStreamCount minLatencyLocal:$minLatencyLocal\ + #maxLatencyLocal:$maxLatencyLocal avgLatencyLocal:$avgLatencyLocal" + } + } + set avgLatencyLocal [{expr $avgLatencyLocal / $ixNetworkStreamCount}] + set minLatencyLocal [{expr $minLatencyLocal / $ixNetworkStreamCount}] + set maxLatencyLocal [{expr $maxLatencyLocal / $ixNetworkStreamCount}] + + #puts "Final Stream: $ixNetworkStreamCount minLatencyLocal:$minLatencyLocal\ + # maxLatencyLocal:$maxLatencyLocal avgLatencyLocal:$avgLatencyLocal" + ### + if {$debug == 1} { + ats_log -diag "\ + avgLatency - $avgLatencyLocal\ + minLatency - $minLatencyLocal\ + maxLatency - $maxLatencyLocal" + set _avgLatency 0 + set _minLatency 0 + set _maxLatency 0 + } + ### + + #puts "AvgLatency $avgLatencyLocal" + + return 1 + +} ; # End of Proc _get_latency_IxNetwork + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_get_latency_IxNetwork2 +# +# Purpose: +# get the latencies on IxNetwork and upvars it using high-level api +# +# Synopsis: +# _get_latency_IxNetwork2 args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc gets the latencies on IxNetwork and upvars it +# using high-level api +###################################################################### +proc perfUtils::_get_latency_IxNetwork2 {numPkts avgLatency minLatency \ +maxLatency returnList rxPorts min_cap_pkts numRxPorts debug latency_detail \ +txStreamSets txPorts} { + upvar $numPkts numPktsLocal + upvar $avgLatency avgLatencyLocal + upvar $minLatency minLatencyLocal + upvar $maxLatency maxLatencyLocal + upvar $returnList returnListLocal + set numPktsLocal 0; set _numPkts 0 + set avgLatencyLocal 0; set _avgLatency 0 + set minLatencyLocal 0; set _minLatency 0 + set maxLatencyLocal 0; set _maxLatency 0 + set success 1; set failure 0 + + set traffic_status [::ixia::traffic_control \ + -action run \ + -traffic_generator ixnetwork_540 \ + ] + after 5000 + set traffic_status [::ixia::traffic_control \ + -action stop \ + -traffic_generator ixnetwork_540 \ + ] + after 15000 + + set flow_traffic_status [::ixia::traffic_stats \ + -mode flow \ + -traffic_generator ixnetwork_540 \ + ] + set num_flow 0 + if { [ catch { + set flows [keylget flow_traffic_status flow] + } err_msg ] } { + keylset returnListLocal status $failure + ats_log -info "[_error 10] - fail to get avg_delay without measure flow" + return 0 + } + foreach flow [keylkeys flows] { + set num_flow [expr {$num_flow + 1}] + set flow_key [keylget flow_traffic_status flow.$flow] + if { [keylget flow_traffic_status flow.$flow.rx.avg_delay] == "N/A" } { + keylset returnListLocal status $failure + ats_log -info "[_error 10] - \ + fail to get avg_delay without measure flow" + return 0 + } + set numPktsLocal [expr {$numPktsLocal + \ + [keylget flow_traffic_status flow.$flow.rx.total_pkts]}] + set _numPkts [expr {$_numPkts + \ + [keylget flow_traffic_status flow.$flow.rx.total_pkts]}] + set avgLatencyLocal [expr {$avgLatencyLocal + \ + [keylget flow_traffic_status flow.$flow.rx.avg_delay]}] + set _avgLatency [expr {$_avgLatency + \ + [keylget flow_traffic_status flow.$flow.rx.avg_delay]}] + set minLatencyLocal [expr {$minLatencyLocal + \ + [keylget flow_traffic_status flow.$flow.rx.min_delay]}] + set _minLatency [expr {$_minLatency + \ + [keylget flow_traffic_status flow.$flow.rx.min_delay]}] + set maxLatencyLocal [expr {$maxLatencyLocal + \ + [keylget flow_traffic_status flow.$flow.rx.max_delay]}] + set _maxLatency [expr {$_maxLatency + \ + [keylget flow_traffic_status flow.$flow.rx.max_delay]}] + + if {$debug == 1} { + ats_log -diag "numPkts - $_numPkts\ + avgLatency - $_avgLatency\ + minLatency - $_minLatency\ + maxLatency - $_maxLatency" + set _numPkts 0 + set _avgLatency 0 + set _minLatency 0 + set _maxLatency 0 + } + if {$latency_detail > 0} { + ats_log -diag "Latency detail enabled @ $latency_detail %" + + foreach rxPort $rxPorts { + scan $rxPort "%d/%d/%d" ix_c ix_l ix_p + capture get $ix_c $ix_l $ix_p + + set NOW [clock format [clock seconds] -format {%m%d%y%H%M%S}] + set file_name "Latency_$latency_detail.$ix_c$ix_l$ix_p$NOW.latency" + set fd1 [open $file_name "w"] + puts $fd1 "Per packet latency @ port $ix_c $ix_l $ix_p" + set flow_results [list \ + "Tx Port" tx.port \ + "Rx Port" rx.port \ + "Tx Frames" tx.total_pkts \ + "Tx Frame Rate" tx.total_pkt_rate \ + "Rx Frames" rx.total_pkts \ + "Frames Delta" rx.loss_pkts \ + "Rx Frame Rate" rx.total_pkt_rate \ + "Loss %" rx.loss_percent \ + "Rx Bytes" rx.total_pkts_byte \ + "Rx Rate (Bps)" rx.total_pkt_byte_rate \ + "Rx Rate (bps)" rx.total_pkt_bit_rate \ + "Rx Rate (Kbps)" rx.total_pkt_kbit_rate \ + "Rx Rate (Mbps)" rx.total_pkt_mbit_rate \ + "Avg Latency (ns)" rx.avg_delay \ + "Min Latency (ns)" rx.min_delay \ + "Max Latency (ns)" rx.max_delay \ + "First Timestamp" rx.first_tstamp \ + "Last Timestamp" rx.last_tstamp \ + ] + set flows [keylget flow_traffic_status flow] + foreach flow [keylkeys flows] { + set flow_key [keylget flow_traffic_status flow.$flow] + puts $fd1 "\tFlow $flow" + foreach {name key} [subst $[subst flow_results]] { + puts $fd1 "\t\t$name: \ + [keylget flow_traffic_status flow.$flow.$key]" + } + } + + close $fd1 + } + } + } + + set avgLatencyLocal [expr {$avgLatencyLocal/$num_flow}] + set minLatencyLocal [expr {$minLatencyLocal/$num_flow}] + set maxLatencyLocal [expr {$maxLatencyLocal/$num_flow}] + + return 1 + +} ; # End of Proc _get_latency_IxNetwork2 + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_run_traffic_IxNetwork +# +# Purpose: +# run the traffic for the run_time seconds +# and upvars cmd output on IxExplorer +# +# Synopsis: +# _run_traffic_IxNetwork args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc runs the traffic for the run_time seconds +# and upvars cmd output on IxExplorer +###################################################################### +proc perfUtils::_run_traffic_IxNetwork {cmdOutputs root run_time exec_cmds \ +uut tr} { + + upvar $cmdOutputs cmdOutputsLocal + set traffic $root/traffic + + # Send traffic + set startTraffic [::ixNet exec start $traffic] + + #Wait for half the test run time + sleep [expr {$run_time/2.0}] + + #Execute any commands for debug or results + set cmdOutputsLocal {} + foreach cmd $exec_cmds { + lappend cmdOutputsLocal [$uut exec $cmd] + if { $tr != "" } { + $tr exec $cmd + } + # sleep a while between each show command, + # to reduce the impact on resource using + sleep 3 + } + + #Wait for another half the test run time + sleep [expr {$run_time/2.0}] + + set stopTraffic [::ixNet exec stop $traffic] + + $uut exec "show platform hardware qfp active statistics drop clear" + if { $tr != "" } { + $tr exec "show platform hardware qfp active statistics drop clear" + } + sleep 5 + + return 1 + +} ; # End of Proc _run_traffic_IxNetwork + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_maxrate +# +# Purpose: +# return the maxRate on a port +# +# Synopsis: +# _maxrate args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc returns the maxRate on a port +###################################################################### +proc perfUtils::_maxrate {port, stream_id} { + set maxRate 0; set success 1 + regexp {(\d+)/(\d+)/(\d+)} $port - chas card port + stream get $chas $card $port 1 + set stream_type [stream cget -frameSizeType] + if {$stream_type == $::sizeRandom} { + weightedRandomFramesize get $chas $card $port + if {[weightedRandomFramesize cget -randomType] == $::randomWeightedPair} { + set pairList [weightedRandomFramesize cget -pairList] + } + set total_weight 0 + set total_framesize 0 + foreach pair $pairList { + set framesize [lindex $pair 0] + set weight [lindex $pair 1] + set total_framesize [mpexpr $total_framesize + $framesize * $weight] + set total_weight [mpexpr $total_weight + $weight] + } + set frame_size [mpexpr $total_framesize / $total_weight] + } else { + set frame_size [stream cget -framesize] + } + capture get $chas $card $port + set maxRate [calculateMaxRate $chas $card $port $frame_size] + + set diag "Calculated max_rate - $maxRate" + ats_results -diag $diag + ats_log -diag $diag + + return $maxRate +} + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_maxrate2 +# +# Purpose: +# return the maxRate on a port using specific stream to calculate +# +# Synopsis: +# _maxrate2 args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc returns the maxRate on a port using specific stream to calculate +###################################################################### +proc perfUtils::_maxrate2 {port stream_id} { + set maxRate 0; set success 1 + + #capture get $chas $card $port + #set maxRate [calculateMaxRate $chas $card $port $frame_size] + #set maxRate 320513 + #set maxRate 335121 + #set maxRate $maxrate + + set diag "Calculated max_rate - $maxRate" + ats_results -diag $diag + ats_log -diag $diag + + return $maxRate +} + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_framesize +# +# Purpose: +# return the framesize configured on the port +# +# Synopsis: +# _framesize args +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc returns the framesize configured on the port +###################################################################### + +proc perfUtils::_framesize {port stream_id} { + set frameSize 0; set success 1 + regexp {(\d+)/(\d+)/(\d+)} $port - chas card port + #stream get $chas $card $port 1 + stream get $chas $card $port $stream_id + set stream_type [stream cget -frameSizeType] + if {$stream_type == $::sizeRandom} { + weightedRandomFramesize get $chas $card $port + if {[weightedRandomFramesize cget -randomType] \ + == $::randomWeightedPair} { + set pairList [weightedRandomFramesize cget -pairList] + #puts "weighted pairs: $pairList" + } + set total_weight 0 + set total_framesize 0 + foreach pair $pairList { + set framesize [lindex $pair 0] + set weight [lindex $pair 1] + set total_framesize [mpexpr $total_framesize + $framesize * $weight] + set total_weight [mpexpr $total_weight + $weight] + } + set frame_size [mpexpr $total_framesize / $total_weight] + } else { + set frame_size [stream cget -framesize] + } + set frameSize $frame_size + set diag "Calculated frame_size - $frameSize" + ats_results -diag $diag + ats_log -diag $diag + return $frameSize +} + +###################################################################### +###Procedure Header +## Name: +## perfUtils::_framesize2 +## +## Purpose: +## return the framesize configured on the port +## +## Synopsis: +## _framesize2 args +## +## Arguments: +## too much to be listed +## +## Return Values: +## 1 - Success +## 0 - failure +## +## Description: +## This Proc returns the framesize configured on the port +####################################################################### + +proc perfUtils::_framesize2 {port stream_id} { + + set frameSize 0; set success 1 + + regexp {(\d+)/(\d+)/(\d+)} $port - chas card port + + #stream get $chas $card $port 1 + #stream get $chas $card $port $stream_id + set streamList [interp eval $::ixia::TclInterp " ixNet getL ::ixNet::OBJ-/traffic trafficItem "] + puts "streamList: $streamList" + foreach stream $streamList { + if {[regexp -nocase $stream_id [interp eval $::ixia::TclInterp " ixNet getA ::ixNet::OBJ-/traffic/trafficItem:1 -name"]]} { + set trafficStream $stream + } + } + set weightedFrame [interp eval $::ixia::TclInterp " ixNet getA $trafficStream/highLevelStream:1/frameSize -weightedPairs "] + puts "weightedFrame: $weightedFrame" + set pairList [interp eval $::ixia::TclInterp " ixNet getA $trafficStream/configElement:0/frameSize -weightedPairs "] + puts "pairList: $pairList" + set total_weight 0 + set total_framesize 0 + for {set i 0} {$i < [llength $pairList]} {incr i +2} { + set framesize [lindex $pairList $i] + set weight [lindex $pairList [expr $i+1]] + set total_framesize [mpexpr $total_framesize + $framesize * $weight] + set total_weight [mpexpr $total_weight + $weight] + } + puts "total_weight: $total_weight" + puts "total_framesize: $total_framesize" + set frame_size [mpexpr $total_framesize / $total_weight] + set frameSize $frame_size + + set diag "Calculated frame_size - $frameSize" + ats_results -diag $diag + ats_log -diag $diag + + return $frameSize +} + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_parse_tx_ports +# +# Purpose: +# parse the tx_port data and upvar the variables +# +# Synopsis: +# _parse_tx_ports +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc parses the tx_port data and upvar the variables +###################################################################### +proc perfUtils::_parse_tx_ports {txPorts txStreamSets txStreams numTxPorts \ +returnList tx_ports debug} { + + set success 1; set failure 0 + upvar $txPorts txPortsLocal + upvar $txStreamSets txStreamSetsLocal + upvar $txStreams txStreamsLocal + upvar $numTxPorts numTxPortsLocal + upvar $returnList returnListLocal + + #Parse Tx ports and all Tx streams + ### + if {$debug == 1} {ats_log -diag "tx_ports - $tx_ports"} + ### + if {[catch {set portKeys [keylkeys tx_ports]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 1] + keylset returnListLocal tclErr $tclErr + return 0 + } + set numTxPortsLocal 0 + foreach portKey $portKeys { + if {[catch { \ + lappend txPortsLocal [keylget tx_ports $portKey.port]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 1] + keylset returnListLocal tclErr $tclErr + return 0 + } + if {[catch { \ + lappend txStreamSetsLocal [keylget tx_ports $portKey.streams]\ + } tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 1] + keylset returnListLocal tclErr $tclErr + return 0 + } + incr numTxPortsLocal + } + foreach txStreamSet $txStreamSetsLocal { + if {$debug == 1} {ats_log -diag "txStreamSet - $txStreamSet"} + foreach txStream $txStreamSet { + if {[catch {lappend txStreamsLocal $txStream} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 1] + keylset returnListLocal tclErr $tclErr + return 0 + } + } + } + if {$debug == 1} {ats_log -diag "txStreamsLocal - $txStreamsLocal"} + + return 1 + +} ; # End of proc _parse_tx_ports + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_parse_rx_ports +# +# Purpose: +# parse the rx_port data and upvar the variables +# +# Synopsis: +# _parse_rx_ports +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc parses the rx_port data and upvar the variables +###################################################################### +proc perfUtils::_parse_rx_ports {rxPorts numRxPorts returnList rx_ports debug} { + + set success 1; set failure 0 + upvar $rxPorts rxPortsLocal + upvar $numRxPorts numRxPortsLocal + + #Parse Rx ports + if {$debug == 1} {ats_log -diag "rx_ports - $rx_ports"} + + if {[catch {set portKeys [keylkeys rx_ports]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 2] + keylset returnListLocal tclErr $tclErr + return 0 + } + + set numRxPortsLocal 0 + foreach portKey $portKeys { + if {[catch {lappend rxPortsLocal [keylget rx_ports $portKey.port]} \ + tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 2] + keylset returnListLocal tclErr $tclErr + return 0 + } + incr numRxPortsLocal + } + return 1 + +} ; # End of proc _parse_rx_ports + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_parse_mtx_ports +# +# Purpose: +# parse the mtx_port data and upvar the variables +# +# Synopsis: +# _parse_mtx_ports +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc parses the mtx_port data and upvar the variables +###################################################################### +proc perfUtils::_parse_mtx_ports {mtxPorts mtxStreamSets mtxOifSets \ +mtxStreams mtxOifs returnList mtx_ports debug} { + + set success 1; set failure 0 + upvar $mtxPorts mtxPortsLocal + upvar $mtxStreamSets mtxStreamSetsLocal + upvar $mtxOifSets mtxOifSetsLocal + upvar $mtxStreams mtxStreamsLocal + upvar $mtxOifs mtxOifsLocal + + #Parse MTx ports streams and OIF + if {[info exists mtx_ports]} { + if {$debug == 1} {ats_log -diag "mtx_ports - $mtx_ports"} + + if {[catch {set portKeys [keylkeys mtx_ports]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 3] + keylset returnListLocal tclErr $tclErr + return $returnList + } + + foreach portKey $portKeys { + if {[catch {lappend mtxPortsLocal [keylget \ + mtx_ports $portKey.port]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 3] + keylset returnListLocal tclErr $tclErr + return $returnList + } + if {[catch {lappend mtxStreamSetsLocal [keylget mtx_ports \ + $portKey.mcast_streams]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 3] + keylset returnListLocal tclErr $tclErr + return $returnList + } + if {[catch {lappend mtxOifSetsLocal [keylget mtx_ports \ + $portKey.mcast_oifs]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 3] + keylset returnListLocal tclErr $tclErr + return $returnList + } + } + + foreach mtxStreamSet $mtxStreamSetsLocal { + foreach mtxStream $mtxStreamSet { + if {[catch {lappend mtxStreamsLocal $mtxStream} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 3] + keylset returnListLocal tclErr $tclErr + return $returnList + } + } + } + + foreach mtxOifSet $mtxOifSetsLocal { + foreach mtxOif $mtxOifSet { + if {[catch {lappend mtxOifsLocal $mtxOif} tclErr]} { + #puts $mtxOif + keylset returnListLocal status $failure + keylset returnListLocal log [_error 3] + keylset returnListLocal tclErr $tclErr + return $returnList + } + } + } + }; # End of if + + return 1 + +} ; # End of proc _parse_mtx_ports + + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_parse_mrx_ports +# +# Purpose: +# parse the mrx_port data and upvar the variables +# +# Synopsis: +# _parse_mrx_ports +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc parses the mrx_port data and upvar the variables +###################################################################### +proc perfUtils::_parse_mrx_ports {mrxPorts numMrxPorts returnList mrx_ports \ +debug} { + + set success 1; set failure 0 + upvar $mrxPorts mrxPortsLocal + upvar $numMrxPorts numMrxPortsLocal + #Parse Rx ports + if {$debug == 1} {ats_log -diag "mrx_ports - $mrx_ports"} + + if {[catch {set portKeys [keylkeys mrx_ports]} tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 2] + keylset returnListLocal tclErr $tclErr + return 0 + } + + set numMrxPortsLocal 0 + foreach portKey $portKeys { + if {[catch {lappend mrxPortsLocal [keylget mrx_ports $portKey.port]} \ + tclErr]} { + keylset returnListLocal status $failure + keylset returnListLocal log [_error 2] + keylset returnListLocal tclErr $tclErr + return 0 + } + incr numMrxPortsLocal + } + return 1 + +} ; # End of proc _parse_mrx_ports + +###################################################################### +##Procedure Header +# Name: +# perfUtils::_error +# +# Purpose: +# define the errors and returns respective error msg +# +# Synopsis: +# _parse_rx_ports +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc defines the errors and returns respective error msg +###################################################################### +proc perfUtils::_error {id} { + + set success 1 + + #Define error messages + set err(1) "ERROR-1: incorrect tx_port format. Expecting keyed list e.g.\ + {port1 {{port 1/6/1} {streams {3 4 1}}}}\ + {port2 {{port 1/12/1} {streams {23 2 24 25}}}}" + set err(2) "ERROR-2: incorrect rx_port format. Expecting keyed list e.g. \ + {port1 {{port 1/6/1}}} {port2 {{port 1/12/1}}}" + set err(3) "ERROR-3: incorrect mtx_port format. Expecting keyed list e.g. \ + {port2 {{port 1/12/1} {mcast_streams {24 25}}\ + {mcast_oifs {100 100}}}}" + set err(4) "ERROR (findNdr argument): -max_rate must be a positive value \ + greater than 1" + set err(5) "ERROR (findNdr argument): -min_rate must be a positive value" + set err(6) "ERROR (findNdr argument): -threshold must be a positive value" + set err(7) "ERROR (findNdr argument): -uds must be either uds1 or uds2" + set err(8) "ERROR (findNdr): Check your capture buffer filter" + set err(9) "ERROR (findNdr argument): -tx_mode must be \ + either packet or advanced" + set err(10) "ERROR (findNdr): Check your port_rx_mode, should be \ + capture_and_measure with IxNetwork" + + return $err($id) + +} ; # End of proc _error + +#################################################### +# Description +#################################################### +procDescr perfUtils::parseNdrResults { + Description: + Usage: + Example: + Arguments: + Return Value: +} + +####################################################### +#This proc finds the NDR and returns NDR along with latencies and other stats +####################################################### +proc perfUtils::parseNdrResults {args} { + + #mandatory args + set man_args { + -result ANY + } + + #optional_args + set opt_args { + -dashboard CHOICES 0 1 + DEFAULT 0 + } + + #Parse the dashed arguments + parse_dashed_args -args $args \ + -mandatory_args $man_args -optional_args $opt_args + + #Initialize variables + set ndr_mpps 0 + set avg_ndr_latency 0 + set avg_cust_latency 0 + set avg_95_latency 0 + set avg_75_latency 0 + set avg_50_latency 0 + set frame_size 0 + set test_run_time 0 + set cpp_util 0 + set cpp_mem 0 + set fp_util 0 + set fp_mem 0; set fp_mem_value 0; set fp_mem_perc_value 0 + set rp_util 0; set rp_mem_value 0; set rp_mem_perc_value 0 + set rp_mem 0 + set cmdOutputs [keylget result cmd_outputs] + set numPkts [keylget result num_pkts] + set frame_size [keylget result frame_size] + if { [catch { + set ndr_mpps [mpexpr [keylget result ndr]/1000000.00] + set ndr_bps [mpexpr [keylget result ndr] * $frame_size * 8.0] + set ndr_gbps [mpexpr $ndr_bps/1000000000.00] + } errmsg ] } { + set ndr_mpps 0 + set ndr_bps 0 + set ndr_gbps 0 + ats_log -diag "parseNdrResults: failed to get NDR" + } + + + if {$numPkts >= 0} { + catch { + set avg_ndr_latency [expr {[keylget result latency(NDR)]/1000.00}] + set avg_cust_latency [expr {[keylget result latency(CUST)]/1000.00}] + #set avg_ndr_latency [expr {[keylget result latency(100)]/1000.00}] + set avg_95_latency [expr {[keylget result latency(95)]/1000.00}] + set avg_75_latency [expr {[keylget result latency(75)]/1000.00}] + set avg_50_latency [expr {[keylget result latency(50)]/1000.00}] + } + } + if {[catch { + set test_run_time [keylget result run_time] + if {$cmdOutputs != ""} { + set cpp_util [parseCppUtil $cmdOutputs] + set cpp_mem [parseCppMem $cmdOutputs] + set rp_util [parseRpUtil $cmdOutputs] + set rp_mem [parseRpMem $cmdOutputs] + set fp_util [parseFpUtil $cmdOutputs] + set fp_mem [parseFpMem $cmdOutputs] + + regexp -nocase "(\[0-9\]+)\[ \]+\\(\[ \]*\[0-9\]+%\\)" $fp_mem \ + dummy fp_mem_value + regexp -nocase "\[0-9\]+\[ \]+\\(\[ \]*(\[0-9\]+)%\\)" $fp_mem \ + dummy fp_mem_perc_value + regexp -nocase "(\[0-9\]+)\[ \]+\\(\[ \]*\[0-9\]+%\\)" $rp_mem \ + dummy rp_mem_value + regexp -nocase "\[0-9\]+\[ \]+\\(\[ \]*(\[0-9\]+)%\\)" $rp_mem \ + dummy rp_mem_perc_value + } + } errmsg] } { + ats_log -info "parseNdrResults catch errmsg:$errmsg" + } + + if {$dashboard == 0} { + set parsedResults "===>> NDR - $ndr_mpps Mpps | NDR - $ndr_gbps Gbps \ + | Latency@NDR - $avg_ndr_latency us | Latency@95% - $avg_95_latency us \ + | Latency@75% - $avg_75_latency us | Latency@50% - $avg_50_latency us \ + | Latency@CUST - $avg_cust_latency us \ + | Frame Size - $frame_size bytes | Runtime - $test_run_time ms \ + | CPP CPU Utilization $cpp_util % | CPP Memory Utilization $cpp_mem B \ + | FP CPU Utilization $fp_util % | FP Memory Utilization $fp_mem kB \ + | RP CPU Utilization $rp_util % | RP Memory Utilization $rp_mem kB <<===" + return $parsedResults + } else { + #NDR + keylset perfvalues $frame_size.measure1.name NDR + keylset perfvalues $frame_size.measure1.order 1 + keylset perfvalues $frame_size.measure1.desc N/A + keylset perfvalues $frame_size.measure1.unit Mpps + keylset perfvalues $frame_size.measure1.value $ndr_mpps + keylset perfvalues $frame_size.measure1.perc_value "N/A" + #NDR + keylset perfvalues $frame_size.measure12.name NDR + keylset perfvalues $frame_size.measure12.order 1 + keylset perfvalues $frame_size.measure12.desc N/A + keylset perfvalues $frame_size.measure12.unit Gbps + keylset perfvalues $frame_size.measure12.value $ndr_gbps + keylset perfvalues $frame_size.measure12.perc_value "N/A" + if {$numPkts >= 0} { + #Latency@NDR + keylset perfvalues $frame_size.measure2.name Latency@NDR + keylset perfvalues $frame_size.measure2.order 1 + keylset perfvalues $frame_size.measure2.desc N/A + keylset perfvalues $frame_size.measure2.unit us + keylset perfvalues $frame_size.measure2.value $avg_ndr_latency + keylset perfvalues $frame_size.measure2.perc_value "N/A" + #Latency@CUST + keylset perfvalues $frame_size.measure22.name Latency@CUST + keylset perfvalues $frame_size.measure22.order 1 + keylset perfvalues $frame_size.measure22.desc N/A + keylset perfvalues $frame_size.measure22.unit us + keylset perfvalues $frame_size.measure22.value $avg_cust_latency + keylset perfvalues $frame_size.measure22.perc_value "N/A" + #Latency@95% + keylset perfvalues $frame_size.measure3.name Latency@95% + keylset perfvalues $frame_size.measure3.order 1 + keylset perfvalues $frame_size.measure3.desc N/A + keylset perfvalues $frame_size.measure3.unit us + keylset perfvalues $frame_size.measure3.value $avg_95_latency + keylset perfvalues $frame_size.measure3.perc_value "N/A" + #Latency@75% + keylset perfvalues $frame_size.measure4.name Latency@75% + keylset perfvalues $frame_size.measure4.order 1 + keylset perfvalues $frame_size.measure4.desc N/A + keylset perfvalues $frame_size.measure4.unit us + keylset perfvalues $frame_size.measure4.value $avg_75_latency + keylset perfvalues $frame_size.measure4.perc_value "N/A" + #Latency@50% + keylset perfvalues $frame_size.measure5.name Latency@50% + keylset perfvalues $frame_size.measure5.order 1 + keylset perfvalues $frame_size.measure5.desc N/A + keylset perfvalues $frame_size.measure5.unit us + keylset perfvalues $frame_size.measure5.value $avg_50_latency + keylset perfvalues $frame_size.measure5.perc_value "N/A" + } + #CPP Utilization + keylset perfvalues $frame_size.measure6.name "QFP Utilization" + keylset perfvalues $frame_size.measure6.order 1 + keylset perfvalues $frame_size.measure6.desc N/A + keylset perfvalues $frame_size.measure6.unit "%" + keylset perfvalues $frame_size.measure6.value $cpp_util + keylset perfvalues $frame_size.measure6.perc_value "N/A" + #CPP Memory + keylset perfvalues $frame_size.measure7.name "QFP Memory" + keylset perfvalues $frame_size.measure7.order 1 + keylset perfvalues $frame_size.measure7.desc N/A + keylset perfvalues $frame_size.measure7.unit B + keylset perfvalues $frame_size.measure7.value $cpp_mem + keylset perfvalues $frame_size.measure7.perc_value "N/A" + #FP Utilization + keylset perfvalues $frame_size.measure8.name "ESP Utilization" + keylset perfvalues $frame_size.measure8.order 1 + keylset perfvalues $frame_size.measure8.desc N/A + keylset perfvalues $frame_size.measure8.unit "%" + keylset perfvalues $frame_size.measure8.value $fp_util + keylset perfvalues $frame_size.measure8.perc_value "N/A" + #FP Memory + keylset perfvalues $frame_size.measure9.name "ESP Memory" + keylset perfvalues $frame_size.measure9.order 1 + keylset perfvalues $frame_size.measure9.desc N/A + keylset perfvalues $frame_size.measure9.unit "kB" + keylset perfvalues $frame_size.measure9.value $fp_mem_value + keylset perfvalues $frame_size.measure9.perc_value $fp_mem_perc_value + #RP Utilization + keylset perfvalues $frame_size.measure10.name "RP Utilization" + keylset perfvalues $frame_size.measure10.order 1 + keylset perfvalues $frame_size.measure10.desc N/A + keylset perfvalues $frame_size.measure10.unit "%" + keylset perfvalues $frame_size.measure10.value $rp_util + keylset perfvalues $frame_size.measure10.perc_value "N/A" + #RP Memory + keylset perfvalues $frame_size.measure11.name "RP Memory" + keylset perfvalues $frame_size.measure11.order 1 + keylset perfvalues $frame_size.measure11.desc N/A + keylset perfvalues $frame_size.measure11.unit "kB" + keylset perfvalues $frame_size.measure11.value $rp_mem_value + keylset perfvalues $frame_size.measure11.perc_value $rp_mem_perc_value + + return $perfvalues + } + +} ; # End of parseNdrResults + +#################################################### +# Description +#################################################### +procDescr perfUtils::writePerfValues { + Description: + Usage: + Example: + Arguments: + Return Value: +} + +proc perfUtils::writePerfValues {args} { + + set man_args { + -uut ANY + -image_type ANY + -protocol ANY + -file_name ANY + -keylist ANY + -packet_sizes ANY + -profile ANY + -functional_area ANY + -feature ANY + -feature_order ANY + -scale_size ANY + -a_flag ANY + } + + set opt_args { + -feat_comments ANY + DEFAULT N/A + -cat_name ANY + DEFAULT N/A + -tid ANY + DEFAULT N/A + -cid ANY + DEFAULT N/A + -image_branch ANY + DEFAULT IMAGE_BRANCH + -image_name ANY + DEFAULT RLS + } + + parse_dashed_args -args $args -mandatory_args $man_args \ + -optional_args $opt_args -return_direct + + if {$image_type == "BiWeekly"} { + set image_name [getImageName $uut] + set image_name "$image_name\($image_branch\)" + } else { + #set image_name $rls_name + set image_name [getImageName $uut] + set image_name "$image_name\($image_branch\)" + } + set image_date [getImageDate $uut] + set run_date [clock format [clock seconds] -format {%m-%d-%y}] + set hardware [getHardware $uut] + + if {$a_flag} { + set fd1 [open $file_name "a+"] + } else { + set fd1 [open $file_name "w"] + set content "ASR,Hardware,FunctionalArea,Profile,Feature," + append content "Feature_Comments,Feature_Order,Protocol,ImageName," + append content "ImageDate,ImageType,PacketSize,ScaleSize,CategoryName," + append content "MeasureName,Measure_Order,MeasureDesc,MeasureUnit," + append content "MeasureValue,PercentageValue,TopologyFileID," + append content "ConfigurationFileID" + puts $fd1 "$content" + } + #$feat_comments + foreach pkt $packet_sizes { + # Get the measure keyes like measure1,measure2... etc. for the packet size + set keys [keylkeys keylist $pkt] + foreach key $keys { + set content "ASR1K,$hardware,$functional_area,$profile," + append content "$feature,$feat_comments,$feature_order," + append content "$protocol,$image_name,$image_date,$image_type," + append content "$pkt Bytes,$scale_size,$cat_name," + append content "[keylget keylist $pkt.$key.name]," + append content "[keylget keylist $pkt.$key.order]," + append content "[keylget keylist $pkt.$key.desc]," + append content "[keylget keylist $pkt.$key.unit]," + append content "[keylget keylist $pkt.$key.value]," + append content "[keylget keylist $pkt.$key.perc_value],$tid,$cid" + puts $fd1 "$content" + aetest::action -diag "$content" + } ; # end of foreach_keys_loop + } ;# End of forach_pkt_loop + close $fd1 +} + + +#################################################### +# Description +#################################################### +procDescr perfUtils::writeMyPerfValues { + Description: + Usage: + Example: + Arguments: + Return Value: +} + +proc perfUtils::writeMyPerfValues {args} { + + set man_args { + -uut ANY + -file_name ANY + -keylist ANY + -packet_sizes ANY + -feature ANY + -profile ANY + -scale_size ANY + -a_flag ANY + } + + set opt_args { + -profile2 ANY + DEFAULT N/A + -extra_data ANY + DEFAULT "" + } + + parse_dashed_args -args $args -mandatory_args $man_args \ + -optional_args $opt_args -return_direct + + set image_date [getImageDate $uut] + set image_branch [getImageBranch $uut] + set run_date [clock format [clock seconds] -format {%m-%d-%y}] + set hardware [getHardware $uut] + + if {$a_flag} { + set fd1 [open $file_name "a+"] + } else { + set fd1 [open $file_name "w"] + } + #$feat_comments + foreach pkt $packet_sizes { + # Get the measure keyes like measure1,measure2... etc. for the packet size + set keys [keylkeys keylist $pkt] + set rp_util 0 + set rp_mem 0 + set fp_util 0 + set fp_mem 0 + set qfp_util 0 + set qfp_mem 0 + set Mpps 0 + set Gbps 0 + set Latency 0 + catch { + set rp_util [keylget keylist $pkt.measure10.value] + set rp_mem [keylget keylist $pkt.measure11.value] + set fp_util [keylget keylist $pkt.measure8.value] + set fp_mem [keylget keylist $pkt.measure9.value] + set qfp_util [keylget keylist $pkt.measure6.value] + set qfp_mem [keylget keylist $pkt.measure7.value] + set Mpps [keylget keylist $pkt.measure1.value] + set Gbps [keylget keylist $pkt.measure12.value] + #set Latency [keylget keylist $pkt.measure3.value] + set Latency [keylget keylist $pkt.measure22.value] + } + if {$extra_data == "" } { + puts $fd1 "exec_date,$run_date,hardware,$hardware,image_branch,\ + $image_branch,image_date,$image_date,scale_size,$scale_size,\ + rp_util,$rp_util,fp_util,$fp_util,qfp_util,$qfp_util,rp_mem,\ + $rp_mem,fp_mem,$fp_mem,qfp_mem,$qfp_mem,Mpps,$Mpps,Gbps,$Gbps,\ + Latency,$Latency,packet_size,$pkt,feature,$feature,profile1,\ + $profile,profile2,$profile2" + } else { + puts $fd1 "exec_date,$run_date,hardware,$hardware,image_branch,\ + $image_branch,image_date,$image_date,scale_size,$scale_size,\ + rp_util,$rp_util,fp_util,$fp_util,qfp_util,$qfp_util,rp_mem,\ + $rp_mem,fp_mem,$fp_mem,qfp_mem,$qfp_mem,Mpps,$Mpps,Gbps,$Gbps,\ + Latency,$Latency,packet_size,$pkt,feature,$feature,profile1,\ + $profile,profile2,$profile2,$extra_data" + } + + } ;# End of forach_pkt_l + close $fd1 +} + +###################################################################### +##Procedure Header +# Name: +# perfUtils::generate_keyed_result +# +# Purpose: +# generate keyed result +# +# Synopsis: +# generate_keyed_result +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc generates keyed result +###################################################################### +proc perfUtils::generate_keyed_result {args} { + + set man_args { + -uut ANY + -tx_ports ANY + -pps ANY + -frame_size ANY + } + set opt_args { + + } + set ret {} + parse_dashed_args -args $args -mandatory_args $man_args \ + -optional_args $opt_args -return_direct + + set portKeys [keylkeys tx_ports] + set port_list "" + set stream_list "" + foreach portKey $portKeys { + lappend port_list [keylget tx_ports $portKey.port] + lappend stream_list [keylget tx_ports $portKey.streams] + } + + set result [ixia::traffic_control -port_handle $port_list -action stop] + ats_log -info "ixia stop traffic: $result" + foreach handle $port_list streams $stream_list { + foreach stream $streams { + set traffic_status [ixia::traffic_config \ + -port_handle $handle \ + -mode modify \ + -stream_id $stream \ + -rate_pps $pps \ + -frame_size $frame_size ] + ats_log -info "modify $handle stream: $traffic_status" + if {[keylget traffic_status status] == 0 } { + aetest::action -diag "modify traffic failed:$traffic_status" + return $ret + } + } + } + set traffic_status [ixia::traffic_control -port_handle $port_list \ + -action run] + ats_log -info "start ixia traffic: $traffic_status" + if {[keylget traffic_status status] == 0 } { + aetest::action -diag "start traffic failed:$traffic_status" + return $ret + } + + sleep 60 + ats_log -info "collect the asr1k cpu and memory data" + set exec_cmds "" + lappend exec_cmds "show platform hardware qfp active data util" + lappend exec_cmds "show platform hardware qfp active infrastructure exmem \ + statistics" + lappend exec_cmds "show platform software status control-processor brief" + set cmdOutputsLocal {} + foreach cmd $exec_cmds { + lappend cmdOutputsLocal [$uut exec $cmd] + # sleep a while between each show command, + # to reduce the impact on resource using + sleep 3 + } + sleep 10 + set result [ixia::traffic_control -port_handle $port_list -action stop] + ats_log -info "ixia stop traffic: $result" + + keylset output status 1 + keylset output ndr $pps + keylset output num_pkts 0 + keylset output latency(NDR) 0 + keylset output min_latency 0 + keylset output max_latency 0 + keylset output cmd_outputs $cmdOutputsLocal + keylset output run_time 60 + keylset output frame_size $frame_size + + set ret [perfUtils::parseNdrResults -result $output -dashboard 1] + return $ret +} + +###################################################################### +##Procedure Header +# Name: +# perfUtils::calculate_latency +# +# Purpose: +# calculate latency value +# +# Synopsis: +# calculate_latency +# +# Arguments: +# too much to be listed +# +# Return Values: +# 1 - Success +# 0 - failure +# +# Description: +# This Proc calculates latency value +###################################################################### +proc perfUtils::calculate_latency {args} { + + set man_args { + -tx_ports ANY + -rx_ports ANY + -ndr ANY + -frame_size ANY + } + set opt_args { + -uds ANY + default uds1 + } + ats_log -info "start to calculate_latency" + set ret {} + keylset ret status 0 + parse_dashed_args -args $args -mandatory_args $man_args \ + -optional_args $opt_args -return_direct + + set portKeys [keylkeys tx_ports] + set tx_port_list "" + set tx_stream_list "" + foreach portKey $portKeys { + lappend tx_port_list [keylget tx_ports $portKey.port] + lappend tx_stream_list [keylget tx_ports $portKey.streams] + } + + set portKeys [keylkeys tx_ports] + set rx_port_list "" + set rx_stream_list "" + foreach portKey $portKeys { + lappend rx_port_list [keylget rx_ports $portKey.port] + lappend rx_stream_list [keylget rx_ports $portKey.streams] + } + + set result [ixia::traffic_control -port_handle $tx_port_list -action stop] + ats_log -info "ixia stop traffic: $result" + foreach handle $tx_port_list streams $tx_stream_list { + foreach stream $streams { + set traffic_status [ixia::traffic_config -port_handle $port \ + -mode modify \ + -stream_id $stream \ + -rate_pps [expr {$pps/2}] \ + ] + ats_log -info "modify $handle stream: $traffic_status" + if {[keylget traffic_status status] == 0 } { + aetest::action -diag "modify traffic failed:$traffic_status" + keylset ret log "modify traffic failed:$traffic_status" + return $ret + } + } + } + + + ixia::interface_config -port_handle $rx_port_list \ + -port_rx_mode capture + + ixia::traffic_control -port_handle $tx_port_list -action clear_stats + ixia::traffic_control -port_handle $rx_port_list -action clear_stats + + ats_log -info "config packet buffer" + ixia::packet_control -port_handle $rx_port_list -action stop + set result [ixia::packet_config_buffers -port_handle $rx_port_list \ + -slice_size 100 -capture_mode continuous -continuous_filter filter] + ats_log -info "result is $result" + + ats_log -info "start packet capture" + set result [ixia::packet_control -port_handle $rx_port_list -action start] + ats_log -info "start packet_control:$result" + + set tr_stat [ixia::traffic_control -action run \ + -duration 30 -port_handle $tx_port_list] + + if {[keylget tr_stat status] == 0} { + aetest::action -diag "Ixia up Traffic start failed:$tr_stat" + keylset ret log "Ixia up Traffic start failed:$tr_stat" + return $ret + } + + sleep 30 + set result [ixia::packet_control -port_handle $tx_port_list -action stop] + + sleep 3 + #stop the packet capture + ats_log -info "stop packet capture" + set result [ixia::packet_control -port_handle $rx_port_list -action stop] + ats_log -info "stop packet_control:$result" + + get the Rx packet stats (Capture Buffer), enable capture on the Rx port + set rx_pkt_stats [ixia::packet_stats -port_handle $rx_port_list \ + -chunk_size 8000000] + + if {[keylget rx_pkt_stats status] != $SUCCESS} { + set diag "Couldn't get RX packet stats on $rx_port_list" + ats_results -diag $diag + keylset ret log $diag + return $ret + } + + set count [llength rx_port_list] + set numPkts 0 + set max_latency 0 + set min_latency 0 + set avg_latency 0 + foreach port $rx_port_list { + set numPkts [expr {$numPkts+\ + [keylget rx_pkt_stats $port.aggregate.num_frames]}] + set max_latency [expr {$max_latency+\ + [keylget rx_pkt_stats $port.aggregate.max_latency]}] + set min_latency [expr {$min_latency+\ + [keylget rx_pkt_stats $port.aggregate.min_latency]}] + set avg_latency [expr {$avg_latency+\ + [keylget rx_pkt_stats $port.aggregate.average_latency]}] + } + keylset ret status 1 numPkts $numPkts \ + max_latency [expr {$max_latency/$count}] \ + min_latency [expr {$min_latency/$count}] \ + avg_latency [expr {$avg_latency/$count}] + + return $ret +} + +########################## STANDARD SCRIPT FOOTER ########################### +# $Log: perfUtils.tcl,v $ +# Revision 1.9 2019/02/07 14:03:03 kkg +# add control on ARP/ND via environment variable when using Spirent STC +# +# Revision 1.8 2017/10/31 18:26:44 kkg +# change cpp to qfp references due to the hidden CLi removal +# +# Revision 1.7 2015/05/06 02:15:36 rupan +# modify according to CSCut92600: (1) main logic enhancement; (2) latency +# hardcode issue +# +# Revision 1.6 2015/04/09 20:03:00 kkg +# fixed typo in catch +# +# Revision 1.5 2015/04/02 17:40:46 kkg +# fixed a syntax error in parseNDR +# +# Revision 1.4 2015/02/11 21:29:23 kkg +# Currently parseNdrResults will error out and abort a test when ndr is not found.Adding a catch to protect it from happening... +# +# Revision 1.3 2014/11/03 07:20:15 rupan +# set mtxPkts float rather than original int in order to avoid out-of-bound +# issue +# +# Revision 1.2 2014/09/26 08:13:34 rupan +# add -tr param to support show info on other routers besides uut; modify +# remove undefined variable "rls_name" in writePerfValues proc +# +# Used for emacs +# Local Variables: +# mode:tcl +# indent-tabs-mode:nil +# End: + diff --git a/vtmsIxiaUtils.lib b/vtmsIxiaUtils.lib new file mode 100644 index 0000000..33bb3ad --- /dev/null +++ b/vtmsIxiaUtils.lib @@ -0,0 +1,9316 @@ +# $Id: vtmsIxiaUtils.lib,v 1.9 2010/07/21 22:39:40 kvieira Exp $ +# Copyright (c) 2005 by Cisco Systems, Inc. +# +# Author: Michael Fingleton +# +# Support Alias: +# mrr-scripting@cisco.com +# +# Usage: +# set auto_path [linsert $auto_path 0 \ +# [file join $env(AUTOTEST) regression lib mid_range_routing]] +# package require VtmsIxiaUtils +# namespace import vtmsIxiaUtils::* +# +# +# Purpose / Description : +# This file contains common procedures used in VTMS test scripts +# It also contains the definitions for various MyMIX distributions +# These are variations on the IMIX theme - sequences of packets with +# various average datagram lengths from 100 bytes -> 700 bytes +# +# Any changes to procedures in this file must be cleared with +# mfinglet@cisco.com and/or mrr-scripting@cisco.com +# +# Note: +# This library contains a lot of functionality that should now +# be available through the HLTAPI. +# I am committing this library so I can start to commit VTMS +# scripts that have been sitting around for a while. +# New users should look to use the IXIA HLTAPI rather than procedures +# in this library to avoid future support issues. +# +# +# List of Procedures in this file: +# +# For Receiving Port +# ------------------ +# IXIA_GE_Basic_Config +# IXIA_POS_Basic_Config +# +# +# For Sending Port +# ---------------- +# IXIA_Create_IMIX_GE +# IXIA_Update_IPG_IMIX_GE +# +# IXIA_Create_Bursty_GE +# IXIA_Update_IBG_Bursty_GE +# +# IXIA_Create_BasicStream_GE +# IXIA_Add_BasicStream_GE +# IXIA_Update_IPG_BasicStream_GE +# IXIA_Simply_Update_IPG_BasicStream_GE +# +# IXIA_Create_IMIX_POS +# IXIA_Update_IPG_IMIX_POS +# +# IXIA_Create_BasicStream_POS +# IXIA_Update_IPG_BasicStream_POS +# +# IXIA_Create_MyMIX_GE +# IXIA_Update_IPG_MyMIX_GE +# +# Filters / Rates and Stats +# ------------------------- +# ixia_measure_rates +# ixia_measure_vc_rates +# ixia_add_rx_filter +# ixia_read_stats +# pps2bps +# + +namespace eval vtmsIxiaUtils { + namespace export * +} + +########################################################################## +#MyMIX Definitions +set Definition(MyMIX335) {46 138 167 412 992 94 239 418 691 83 142 671 50 \ + 263 416 288 1500 876 312 57 93 241 52 102 52} + +set Definition(MyMIX100) {46 52 70 52 62 54 101 72 51 56 72 51 50 \ + 45 52 89 1100 76 52 47 53 46 47 52 52} + +set Definition(MyMIX200) {46 72 91 412 62 94 201 52 571 83 142 71 50 \ + 63 312 189 1500 76 312 67 93 241 46 102 52} + +set Definition(MyMIX300) {46 172 91 592 162 94 501 52 871 53 176 91 120 \ + 163 311 188 1500 274 342 167 93 841 146 302 152} + +set Definition(MyMIX400) {46 272 91 792 131 64 591 52 1071 153 176 191 170 \ + 263 371 288 1500 774 342 637 193 841 446 393 152} + +set Definition(MyMIX500) {46 472 91 828 331 64 591 352 1371 253 176 191 170 \ + 477 371 488 1500 774 592 837 193 1041 546 393 352} + +set Definition(MyMIX600) {46 609 93 951 311 162 591 391 1301 503 106 391 291 \ + 499 632 688 1500 1074 504 891 293 1412 596 483 682} + +set Definition(MyMIX700) {46 812 203 1051 311 162 591 409 1250 782 191 492 491 \ + 499 1002 688 1500 1074 819 891 503 1412 596 813 912} + +set Definition(IMIX_A) {46 46 46 46 46 46 46 552 552 552 552 1500} +set Definition(IMIX_B) {46 46 46 552 552 552 552 46 46 46 46 1500} +set Definition(IMIX_C) {46 46 46 46 46 46 46 552 552 1500 552 552} + +set Definition(MyMIX_PQ) {59 64 59 63 63 55 64 62 62 69 59 65} +set Definition(MyMIX_BT) {46 46 552 552 1500 46 46 46 552 1500 552 46 1500} + +########################################################################## + +procDescr vtmsIxiaUtils::get_avg_mymix_length { + Description: + Returns the average datagram length for a given mymix distribution. + + Usage: get_avg_mymix_length +} + +proc vtmsIxiaUtils::get_avg_mymix_length {mymix_definition} { + set total_length 0 + set number_of_packets [llength $mymix_definition] + + foreach packet_length $mymix_definition { + set total_length [expr $total_length + $packet_length] + } + + set avg_length [mpexpr $total_length.0 / $number_of_packets.0] + + return $avg_length +} + + + +########################################################################## + +procDescr vtmsIxiaUtils::getmaskfromBits { + Procedure pulled from pimlib.exp - thanks.. + Duplicated here to ensure it's always available in it's current + form for VTMS scripts. + + Description: + Converts a mask from a number of bits format to a dotted decimal format. + + Usage: gatmaskfromBits + + Returns: mask in dotted decimal format +} + +proc vtmsIxiaUtils::getmaskfromBits { bits } { + + if { $bits >= 24 } { + + set byte1 255 + set byte2 255 + set byte3 255 + set byte4 [expr [expr 0xff << [expr 32 - $bits]] & 0xff] + + } elseif { $bits >= 16 } { + + set byte1 255 + set byte2 255 + set byte3 [expr [expr 0xff << [expr 24 - $bits]] & 0xff] + set byte4 0 + + } elseif { $bits >= 8 } { + + set byte1 255 + set byte2 [expr [expr 0xff << [expr 16 - $bits]] & 0xff] + set byte3 0 + set byte4 0 + + } else { + + set byte1 [expr [expr 0xff << [expr 8 - $bits]] & 0xff] + set byte2 0 + set byte3 0 + set byte4 0 + + } + + return "$byte1.$byte2.$byte3.$byte4" + +} + + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Create_IMIX_GE { + + Description: + This procedure creates an IMIX stream on an IXIA GE port + It will start by resetting the port to ensure we're starting + with a clean slate. + + Usage: + IXIA_Create_IMIX_GE $port -dstIp \ + -dstMac \ + -isg \ + [-srcIp ] \ + [-srcMac ] \ + [-prec <0|1|2|3|4|5|6|7|ATM>] \ + [-latencyStamp ] \ + [-autoNegotiation ] \ + [-mediaType ] + + Example: + IXIA_Create_IMIX_GE {1 5 1} -srcIp 10.0.0.2 -dstIp 12.2.1.2 \ + -isg 10000000 \ + -srcMac {00 c0 10 00 00 02} \ + -dstMac {22 22 22 22 22 22} -prec 4 + + Arguments are self explainatory except for -prec + If this is set to ATM then each packet size in an IMIX distribution is + marked with a different precedence value. + This is required to when figuring how many of each size packets were + received / dropped when the interface under test is ATM. + If set to a numeric value all packets are marked with that same + precedence. + + The value configured for ISG is not that important - it should be modified + later by IXIA_Update_IPG_IMIX_GE. + + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_Create_IMIX_GE {IXIA_Port args} { + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #Source MAC Address + if {[lsearch $args -srcMac] != -1} { + set variable_position [lsearch $args -srcMac] + set SourceMAC [lindex $args [expr $variable_position +1]] + } else { + #Source MAC doesn't really matter so I'll arbitrarily pick a default + set SourceMAC "00 c0 01 01 01 01" + } + + #Destination MAC Address + if {[lsearch $args -dstMac] != -1} { + set variable_position [lsearch $args -dstMac] + set DestinationMAC [lindex $args [expr $variable_position +1]] + } + + #Inter Stream Gap + if {[lsearch $args -isg] != -1} { + set variable_position [lsearch $args -isg] + set InterStreamGap [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + #For ATM IMIX Tests Precedence is used to differentiate number of packet of + #each size that are received - this is necessary as the cell tax + #(L2 overhead) is different for each packet size. + + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + #GE Autonegotiation + if {[lsearch $args -autoNegotiation] != -1} { + set variable_position [lsearch $args -autoNegotiation] + set autonegotiation [lindex $args [expr $variable_position +1]] + } else { + #Negotiation will usually + set autonegotiation false + } + + #Media Type - GBIC or RJ45 + #Need to keep autonegotiation enabled for RJ45 / limit speed to 1000 + if {[lsearch $args -mediaType] != -1} { + set variable_position [lsearch $args -mediaType] + set mediaType [lindex $args [expr $variable_position +1]] + } else { + set mediaType GBIC + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + + + #IMIX Packet Lengths on GE + #0 is just so lengths are in positions 1 - 12 + set IMIX_Packet_Length { 0 64 64 570 64 64 570 64 1518 570 64 64 570 } + set ATM_Precedence_Distribution { 0 1 1 2 1 1 2 1 3 2 1 1 2 } + + #Return the Ports to Factory Defaults + if {$tgen_app == "IxExplorer"} { + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + + # #For new dual phy mode interfaces set phy mode first + # if {[string match $mediaType "fiber"]} { + # port setPhyMode portPhyModeFiber $chassis $card $port + # } + + + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + port setPhyMode portPhyModeFiber $Chassis $Card $Port + port config -autonegotiate $autonegotiation + port config -duplex full + } else { + port config -autonegotiate true + port config -advertise1000FullDuplex true + port config -advertise100FullDuplex false + port config -advertise100HalfDuplex false + port config -advertise10FullDuplex false + port config -advertise10HalfDuplex false + + } + port config -numAddresses 1 + port config -MacAddress $SourceMAC + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + + for {set looper 1} {$looper <= 12} {incr looper} { + + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass classA + ip config -sourceClass classA + if {[string match $IPprecedence "ATM"]} { + ip config -precedence [lindex $ATM_Precedence_Distribution $looper] + } else { + ip config -precedence $IPprecedence + } + ip set $Chassis $Card $Port + + protocol config -ethernetType EthernetII + protocol config -name ipV4 + + stream config -sa $SourceMAC + stream config -da $DestinationMAC + stream config -name IMIX_Stream + stream config -framesize [lindex $IMIX_Packet_Length $looper] + if {$looper < 12} { + stream config -dma advance + } else { + stream config -dma gotoFirst + } + stream config -numFrames 1 + stream config -gapUnit gapNanoSeconds + stream config -enableIbg false + stream config -enableIsg true + stream config -isg $InterStreamGap + if {[string match $enable_latency "true"]} { + stream config -enableTimestamp true + } + stream config -patternType repeat + stream config -dataPattern xAAAA + stream set $Chassis $Card $Port $looper + stream write $Chassis $Card $Port $looper + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + # - using same groupID for all streams + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port $looper + } + } + } + if {$tgen_app == "IxNetwork"} { + + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$Card\/port:$Port" $vportObj match]} { + set vportHandle $vportHdl + } + } + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -media fiber " + set setPhyMode [interp eval $::ixia::TclInterp " ixNet getA $vportHandle/l1Config/ethernet -media "] + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate $autonegotiation " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto all " + interp eval $::ixia::TclInterp " ixNet commit " + + } else { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate true " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto speed1000 " + interp eval $::ixia::TclInterp " ixNet commit " + + } + set interfaceObj [interp eval $::ixia::TclInterp " ixNet getL $vportHandle interface "] + interp eval $::ixia::TclInterp " ixNet setA [lindex $interfaceObj 0]/ethernet -macAddress $SourceMAC " + interp eval $::ixia::TclInterp " ixNet commit " + set port1 $Chassis/$Card/$Port + + for {set looper 1} {$looper <= 12} {incr looper} { + + if {[string match $IPprecedence "ATM"]} { + #ip config -precedence [lindex $ATM_Precedence_Distribution $looper] + set IpPrecedence [lindex $ATM_Precedence_Distribution $looper] + } else { + #ip config -precedence $IPprecedence + set IpPrecedence $IPprecedence + } + + if {[string match $enable_latency "true"]} { + #stream config -enableTimestamp true + set enableTimestamp 1 + } else { + set enableTimestamp 0 + } + + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + # - using same groupID for all streams + #packetGroup setDefault + #packetGroup config -insertSignature true + #packetGroup config -groupId 1 + #packetGroup setTx $Chassis $Card $Port $looper + puts "Not required" + } + set frameSize [lindex $IMIX_Packet_Length $looper] + if {[regexp {(\.)} $SourceIP matched]} { + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv4 -ip_src_addr $SourceIP -ip_dst_addr $DestinationIP -ip_precedence $IpPrecedence \ + -ethernet_type ethernetII -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $frameSize -length_mode imix -inter_burst_gap $InterStreamGap -inter_stream_gap 1 \ + -transmit_mode continuous_burst -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA] + } + if {[regexp {(\:)} $SourceIP matched]} { + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv6 -ipv6_src_addr $SourceIP -ipv6_dst_addr $DestinationIP -ip_precedence $IpPrecedence \ + -ethernet_type ethernetII -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $frameSize -length_mode imix -inter_burst_gap $InterStreamGap -inter_stream_gap 1 \ + -transmit_mode continuous_burst -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA] + } + } + } +} + + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Update_IPG_IMIX_GE { + + Description: + This procedure changes the ISG for each stream in an IMIX + packet distribution on a GE port based on the required packets + per second. + + The stream should first be configured using IXIA_Create_IMIX_GE + + Usage: IXIA_Update_IPG_IMIX_GE $port -sendPps + + Example: IXIA_Update_IPG_IMIX_GE {1 1 2} -sendPps 100 + + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_Update_IPG_IMIX_GE {IXIA_Port args} { + + #Desired PPS send rate + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set SendPPS [lindex $args [expr $variable_position +1]] + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Need to calculate the Inter Stream Gap for IMIX Traffic + set AvgIMIXDatagramSize 335.83 + + #Knowing how many pps translate this to GE bps (note on GE it takes 1 nS to + #transmit 1 bit. + #For some reason with IMIX calculation are not acheiving the rates I desire + #The 60 in the equation below is a penalty to make things work properly + #This effectively decreases the IPG on IXIA - seems to make everything work + #as expected. + #The value 60 was achieved through experimentation + # + #Also note that with IMIX IXIA can't send more than 83% linerate on IXIA + #Removing 60 byte penalty doesn't get you beyond 83% + + set GESendBPS [expr $SendPPS * ($AvgIMIXDatagramSize + 38 + 60) * 8] + + #Calculate the GE Gaps (ie time not being used by above + set GETotalGap [expr 1000000000.0 - $GESendBPS] + + #Need to avoid /0 errors when a stream has 0 percent load + if {$SendPPS == 0 } { + set SendPPS .001 + } + + #Inter Packet Gap + set IPG [expr $GETotalGap / $SendPPS] + + if {$tgen_app == "IxExplorer"} { + for {set StreamID 1} {$StreamID <= 12} {incr StreamID} { + stream get $Chassis $Card $Port $StreamID + stream config -isg $IPG + stream set $Chassis $Card $Port $StreamID + stream write $Chassis $Card $Port $StreamID + } + } + + if {$tgen_app == "IxNetwork"} { + set port1 $Chassis/$Card/$Port + for {set StreamID 1} {$StreamID <= 12} {incr StreamID} { + set trafficConfig [::ixia::traffic_config -mode modify -port_handle $port1 -inter_burst_gap $IPG -stream_id $StreamID] + } + } +} + + + +########################################################################## + + procDescr vtmsIxiaUtils::IXIA_GE_Basic_Config { + + Description: + This procedure creates resets a GE port to it's basic config + and then removes autonegotiation / sets duplex etc. + Creates basic config needed to bring GE up so it can be used + to count pkts. + + Usage: + IXIA_GE_Basic_Config port [-autoNegotiation ] \ + [-macAddress ] \ + [-qosStatsMode ] \ + [-packetGroupMode ] \ + [-mediaType ] + Defaults: + -autonegotiation : false = no autonegotiation + -macAddress : {00 c0 ab ad ca fe} - doesn't really matter what this is + -qosStatsMode : false + -packetGroupMode : false + -mediaType : GBIC + + Example: + IXIA_GE_Basic_Config {1 1 2} -MACaddress {00 c0 12 01 00 02} \ + -packetgroupmode true + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_GE_Basic_Config {IXIA_Port args} { + + #IXIA MAC Address + if {[lsearch $args -macAddress] != -1} { + set variable_position [lsearch $args -macAddress] + set IXIA_MAC [lindex $args [expr $variable_position +1]] + } else { + #Makey upey address + set IXIA_MAC {00 c0 ab ad ca fe} + } + + #Enable Packet Groups Mode + if {[lsearch $args -packetGroupMode] != -1} { + set variable_position [lsearch $args -packetGroupMode] + set EnablePacketGroupMode [lindex $args [expr $variable_position +1]] + } else { + set EnablePacketGroupMode false + } + + #Enable QOS Stats Mode + if {[lsearch $args -qosStatsMode] != -1} { + set variable_position [lsearch $args -qosStatsMode] + set EnableQOSStatsMode [lindex $args [expr $variable_position +1]] + } else { + set EnableQOSStatsMode false + } + + #GE Autonegotiation + if {[lsearch $args -autoNegotiation] != -1} { + set variable_position [lsearch $args -autoNegotiation] + set autonegotiation [lindex $args [expr $variable_position +1]] + } else { + #Negotiation will usually + set autonegotiation false + } + + #Media Type - GBIC or RJ45 + #Need to keep autonegotiation enabled for RJ45 / limit speed to 1000 + if {[lsearch $args -mediaType] != -1} { + set variable_position [lsearch $args -mediaType] + set mediaType [lindex $args [expr $variable_position +1]] + } else { + set mediaType GBIC + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + if {$tgen_app == "IxExplorer"} { + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + #Configure the Receiving GE Port + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + port setPhyMode portPhyModeFiber $Chassis $Card $Port + port config -autonegotiate $autonegotiation + port config -duplex full + } else { + port config -autonegotiate true + port config -advertise1000FullDuplex true + port config -advertise100FullDuplex false + port config -advertise100HalfDuplex false + port config -advertise10FullDuplex false + port config -advertise10HalfDuplex false + + } + port config -numAddresses 1 + port config -MacAddress $IXIA_MAC + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + + if {[string match $EnablePacketGroupMode "true"]} { + packetGroup setDefault + packetGroup config -latencyControl cutThrough + packetGroup setRx $Chassis $Card $Port + port setReceiveMode portPacketGroup $Chassis $Card $Port + port set $Chassis $Card $Port + } + + if {[string match $EnableQOSStatsMode "true"]} { + port setReceiveMode portCapture $Chassis $Card $Port + port set $Chassis $Card $Port + stat config -mode statQos + stat set $Chassis $Card $Port + stat write $Chassis $Card $Port + } + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + } + if {$tgen_app == "IxNetwork"} { + #port setFactoryDefaults $Chassis $Card $Port + #sleep 2 + #Configure the Receiving GE Port + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$card\/port:$port" $vportObj match]} { + set vportHandle $vportHdl + } + } + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -media fiber " + set setPhyMode [interp eval $::ixia::TclInterp " ixNet getA $vportHandle/l1Config/ethernet -media "] + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate $autonegotiation " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto all " + interp eval $::ixia::TclInterp " ixNet commit " + + #port setPhyMode portPhyModeFiber $Chassis $Card $Port + #port config -autonegotiate $autonegotiation + #port config -duplex full + } else { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate true " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto speed1000 " + interp eval $::ixia::TclInterp " ixNet commit " + #port config -autonegotiate true + #port config -advertise1000FullDuplex true + #port config -advertise100FullDuplex false + #port config -advertise100HalfDuplex false + #port config -advertise10FullDuplex false + #port config -advertise10HalfDuplex false + + } + set interfaceObj [interp eval $::ixia::TclInterp " ixNet getL $vportHandle interface "] + interp eval $::ixia::TclInterp " ixNet setA [lindex $interfaceObj 0]/ethernet -macAddress $IXIA_MAC " + interp eval $::ixia::TclInterp " ixNet commit " + #port config -numAddresses 1 + #port config -MacAddress $IXIA_MAC + #port set $Chassis $Card $Port + #port write $Chassis $Card $Port + + + if {[string match $EnablePacketGroupMode "true"]} { + interp eval $::ixia::TclInterp " ixNet setA $vportHdl -rxMode captureAndMeasure " + interp eval $::ixia::TclInterp " ixNet commit " + #packetGroup setDefault + #packetGroup config -latencyControl cutThrough + #packetGroup setRx $Chassis $Card $Port + #port setReceiveMode portPacketGroup $Chassis $Card $Port + #port set $Chassis $Card $Port + } + + if {[string match $EnableQOSStatsMode "true"]} { + interp eval $::ixia::TclInterp " ixNet setA $vportHdl -rxMode captureAndMeasure " + interp eval $::ixia::TclInterp " ixNet commit " + #port setReceiveMode portCapture $Chassis $Card $Port + #port set $Chassis $Card $Port + #stat config -mode statQos + #stat set $Chassis $Card $Port + #stat write $Chassis $Card $Port + } + #stream set $Chassis $Card $Port 1 + #stream write $Chassis $Card $Port 1 + } +} + + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Create_Bursty_GE { + + Description: + This procedure creates an Bursty stream on an IXIA GE port + It will start by resetting the port to ensure we're starting + with a clean slate. + + Usage: + IXIA_Create_Bursty_GE $port -dstIp \ + -dstMac \ + [-srcIp ] \ + [-srcMac ] \ + [-ibg ] \ + [-prec ] \ + [-latencyStamp ] \ + [-datagramLength ] \ + [-packetsPerBurst ] \ + [-autoNegotiation ] \ + [-mediaType ] + + Defaults: + -srcMac : "00 c0 01 01 01 01" - generally doesn't matter what this is + -srcIp : 10.10.10.1 - often doesn't matter what this is + -ibg : 200000000 - will be changed later using IXIA_Update_IBG_Bursty_GE + -prec : 0 + -latencyStamp : false + -datagramLength : 62 (80 byte GE frame) + -packetsPerBurst : 20 + -autoNegotiation : false => no autonegotiation + -mediaType : GBIC + + Example: + IXIA_Create_Bursty_GE {1 1 1} -srcIP 10.1.0.2 -dstIP 12.1.0.2 \ + -ibg 200000000 -latency_stamp true \ + -srcMAC {00 c0 10 01 00 02} \ + -dstMAC {00 c0 10 01 00 01} -prec 5 \ + -Packets_Per_Burst 20 \ + -DatagramLength 100 + + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_Create_Bursty_GE {IXIA_Port args} { + + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #Source MAC Address + if {[lsearch $args -srcMac] != -1} { + set variable_position [lsearch $args -srcMac] + set SourceMAC [lindex $args [expr $variable_position +1]] + } else { + #Source MAC doesn't really matter so I'll arbitrarily pick a default + set SourceMAC "00 c0 01 01 01 01" + } + + #Destination MAC Address + if {[lsearch $args -dstMac] != -1} { + set variable_position [lsearch $args -dstMac] + set DestinationMAC [lindex $args [expr $variable_position +1]] + } + + #Inter Burst Gap + if {[lsearch $args -ibg] != -1} { + set variable_position [lsearch $args -ibg] + set InterBurstGap [lindex $args [expr $variable_position +1]] + } else { + set InterBurstGap 200000000 + } + + #IP Precedence + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + #How Many Packets Should be in each Burst + if {[lsearch $args -packetsPerBurst] != -1} { + set variable_position [lsearch $args -packetsPerBurst] + set PacketsPerBurst [lindex $args [expr $variable_position +1]] + } else { + set PacketsPerBurst 20 + } + + #Datagram Length for all packets to be used in burst + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set DatagramLength [lindex $args [expr $variable_position +1]] + set GE_PacketSize [expr $DatagramLength + 18] + } else { + set GE_PacketSize 80 + } + #GE Autonegotiation + if {[lsearch $args -autoNegotiation] != -1} { + set variable_position [lsearch $args -autoNegotiation] + set autonegotiation [lindex $args [expr $variable_position +1]] + } else { + #Negotiation will usually + set autonegotiation false + } + + #Media Type - GBIC or RJ45 + #Need to keep autonegotiation enabled for RJ45 / limit speed to 1000 + if {[lsearch $args -mediaType] != -1} { + set variable_position [lsearch $args -mediaType] + set mediaType [lindex $args [expr $variable_position +1]] + } else { + set mediaType GBIC + } + + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Return the Ports to Factory Defaults + if {$tgen_app == "IxExplorer"} { + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + port setPhyMode portPhyModeFiber $Chassis $Card $Port + port config -autonegotiate $autonegotiation + port config -duplex full + } else { + port config -autonegotiate true + port config -advertise1000FullDuplex true + port config -advertise100FullDuplex false + port config -advertise100HalfDuplex false + port config -advertise10FullDuplex false + port config -advertise10HalfDuplex false + + } + port config -numAddresses 1 + port config -MacAddress $SourceMAC + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + #Create 1 Streams with 0 IPG and calculated ISG + + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass classA + ip config -sourceClass classA + ip config -precedence $IPprecedence + ip set $Chassis $Card $Port + + protocol config -ethernetType EthernetII + protocol config -name ipV4 + + stream config -sa $SourceMAC + stream config -da $DestinationMAC + stream config -name Bursty_Stream + stream config -framesize $GE_PacketSize + + stream config -dma gotoFirst + stream config -numFrames 20 + stream config -gapUnit gapNanoSeconds + stream config -enableIbg false + stream config -enableIsg true + stream config -rateMode useGap + stream config -ifg 1 + stream config -isg $InterBurstGap + if {[string match $enable_latency "true"]} { + stream config -enableTimestamp true + } + stream config -patternType repeat + stream config -dataPattern xAAAA + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + # - using same groupID for all streams + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port 1 + } + } + if {$tgen_app == "IxNetwork"} { + #port setFactoryDefaults $Chassis $Card $Port + #sleep 2 + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$Card\/port:$Port" $vportObj match]} { + set vportHandle $vportHdl + } + } + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -media fiber " + set setPhyMode [interp eval $::ixia::TclInterp " ixNet getA $vportHandle/l1Config/ethernet -media "] + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate $autonegotiation " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto all " + interp eval $::ixia::TclInterp " ixNet commit " + #port setPhyMode portPhyModeFiber $Chassis $Card $Port + #port config -autonegotiate $autonegotiation + #port config -duplex full + } else { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate true " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto speed1000 " + interp eval $::ixia::TclInterp " ixNet commit " + #port config -autonegotiate true + #port config -advertise1000FullDuplex true + #port config -advertise100FullDuplex false + #port config -advertise100HalfDuplex false + #port config -advertise10FullDuplex false + #port config -advertise10HalfDuplex false + + } + set interfaceObj [interp eval $::ixia::TclInterp " ixNet getL $vportHandle interface "] + interp eval $::ixia::TclInterp " ixNet setA [lindex $interfaceObj 0]/ethernet -macAddress $SourceMAC " + interp eval $::ixia::TclInterp " ixNet commit " + #port config -numAddresses 1 + #port config -MacAddress $SourceMAC + #port set $Chassis $Card $Port + #port write $Chassis $Card $Port + + #Create 1 Streams with 0 IPG and calculated ISG + set port1 $Chassis/$Card/$Port + set enableTimestamp 1 + + #ip config -sourceIpAddr $SourceIP + #ip config -destIpAddr $DestinationIP + #ip config -destClass classA + #ip config -sourceClass classA + #ip config -precedence $IPprecedence + #ip set $Chassis $Card $Port + + #protocol config -ethernetType EthernetII + #protocol config -name ipV4 + + #stream config -sa $SourceMAC + #stream config -da $DestinationMAC + #stream config -name Bursty_Stream + #stream config -framesize $GE_PacketSize + + #stream config -dma gotoFirst + #stream config -numFrames 20 + #stream config -gapUnit gapNanoSeconds + #stream config -enableIbg false + #stream config -enableIsg true + #stream config -rateMode useGap + #stream config -ifg 1 + #stream config -isg $InterBurstGap + if {[string match $enable_latency "true"]} { + #stream config -enableTimestamp true + set enableTimestamp 1 + } else { + set enableTimestamp 0 + } + #stream config -patternType repeat + #stream config -dataPattern xAAAA + #stream set $Chassis $Card $Port 1 + #stream write $Chassis $Card $Port 1 + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + # - using same groupID for all streams + #packetGroup setDefault + #packetGroup config -insertSignature true + #packetGroup config -groupId 1 + #packetGroup setTx $Chassis $Card $Port 1 + puts "Not required" + } + #dont have support in IxNetwork "-inter_burst_gap_unit gapNanoSeconds", default it will take. + if {[regexp {(\.)} $SourceIP matched]} + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv4 -ip_src_addr $SourceIP -ip_dst_addr $DestinationIP -ip_precedence $IPprecedence \ + -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $GE_PacketSize -inter_burst_gap $InterBurstGap -inter_stream_gap 1 \ + -pkts_per_burst 20 -transmit_mode continuous_burst -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA] + } + if {[regexp {(\:)} $SourceIP matched]} + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv6 -ipv6_src_addr $SourceIP -ipv6_dst_addr $DestinationIP -ip_precedence $IPprecedence \ + -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $GE_PacketSize -inter_burst_gap $InterBurstGap -inter_stream_gap 1 \ + -pkts_per_burst 20 -transmit_mode continuous_burst -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA] + } + } +} + + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Update_IBG_Bursty_GE { + + Description: + This procedure changes the IBG for a bursty stream on GE that was + previously created using IXIA_Create_Bursty_GE. + Given the datagram length, packets per burst and send rate in pps + the procedure will calculate and configure the IBG for the IXIA to + achieve that rate. + + Usage: + IXIA_Update_IBG_Bursty_GE $port -datagramLength \ + -packetsPerBurst \ + -sendPps + + Example: + IXIA_Update_IBG_Bursty_GE {1 1 1} -packetsPerBurst 20 \ + -datagramLength 100 \ + -pps 5000 + + Returns: Nothing +} + +proc vtmsIxiaUtils::IXIA_Update_IBG_Bursty_GE {IXIA_Port args} { + + #Datagram Length for all packets + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set datagramLength [lindex $args [expr $variable_position +1]] + } + #How Many Packets Should be in each Burst + if {[lsearch $args -packetsPerBurst] != -1} { + set variable_position [lsearch $args -packetsPerBurst] + set packetsPerBurst [lindex $args [expr $variable_position +1]] + } + #Desired PPS send rate + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set requestedPps [lindex $args [expr $variable_position +1]] + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + + #requestedPps may be zero which would result in a divide by zero + #error below. Avoid by setting pps really small + if {$requestedPps == "0"} { + set requestedPps .000000001 + } + + #To calculate the IPG first calculate interval + #(time between starting to send two consequative packets) + #From this I then subtract the time to transmit one packet. + set BasicIPG [expr \ + ( 1000000000.0 / $requestedPps) - (($datagramLength.0 + 18 + 20) * 8)] + + set TotalGapPerBurst [expr $BasicIPG * $packetsPerBurst] + if {$tgen_app == "IxExplorer"} { + stream get $Chassis $Card $Port 1 + stream config -isg $TotalGapPerBurst + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + } + if {$tgen_app == "IxNetwork"} { + set streamId 1 + set port1 $Chassis/$Card/$Port + set trafficConfig [::ixia::traffic_config -mode modify -port_handle $port1 -inter_burst_gap $TotalGapPerBurst -stream_id $streamId] + } +} + + + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Create_BasicStream_GE { + + Description: + This procedure creates a basic stream with one fixed sized + packet continuously played + It will start by resetting the port to ensure we're starting + with a clean slate. + The ipg configured here will generally be updated later using + IXIA_Update_IPG_BasicStream_GE + + Usage: + IXIA_Create_BasicStream_GE $port -dstIp \ + -dstMac \ + -ipg \ + [-srcIp ] \ + [-srcMac ] \ + [-prec ] \ + [-latencyStamp ] \ + [-datagramLength ] \ + [-autoNegotiation ] \ + [-mediaType ] \ + [-vlanId ] \ + [-increaseNetwork ] \ + [-increaseHost ] \ + [-prefixLength ] \ + [-class ] \ + [-increaseVlan ] + + Notes: + Configuring the -increaseNetwork option will increase the network portion + of the destination IP address by 1 the number of times requested by this + option. Currently it supports values in the range 1-254 + The class option is used in conjunction with this option to determine + where the network portion begins. The operation is classful - i.e. must + be A,B or C and defaults to A + + Configuring the -increaseHost option is similar but increase the host + portion of the destination IP addr. + This is used in conjunction with the -prefixLength option. + Using the -prefixLength option gives better control on where the host + portion starts. Due to IXIA funkyness prefix length must be used with + increaseHost and class must be used with increaseNetwork. + + Configuring the -vlanId option will insert a vlan tag in all generated + packets. + Configuring the -increaseVlan option will cause the vlanId in this + tag to increase by one each time up to the number of times requested. + + Example: + IXIA_Create_BasicStream_GE {1 1 1} -srcIp 8.0.1.2 -dstIp 11.0.1.2 \ + -ipg 10000000 \ + -srcMac {00 00 00 00 11 11} \ + -dstMac {10 10 10 10 10 10} \ + -datagramLength 400 -prec 1 \ + -class C -increaseNetwork 60 \ + -vlanId 1 -increaseVlan 60 + Returns: Nothing + +} + +proc vtmsIxiaUtils::IXIA_Create_BasicStream_GE {IXIA_Port args} { + + #This flag will be used to know if incrementing either network or host req'd + set multiple_streams 0 + + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #Source MAC Address + if {[lsearch $args -srcMac] != -1} { + set variable_position [lsearch $args -srcMac] + set SourceMAC [lindex $args [expr $variable_position +1]] + } else { + #Source MAC doesn't really matter so I'll arbitrarily pick a default + set SourceMAC "00 c0 01 01 01 01" + } + + #Destination MAC Address + if {[lsearch $args -dstMac] != -1} { + set variable_position [lsearch $args -dstMac] + set DestinationMAC [lindex $args [expr $variable_position +1]] + } + + #Inter Packet Gap + if {[lsearch $args -ipg] != -1} { + set variable_position [lsearch $args -ipg] + set InterPacketGap [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Datagram Length for all packets + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set datagramLength [lindex $args [expr $variable_position +1]] + } else { + set datagramLength 62 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + #Increase Network + if {[lsearch $args -increaseNetwork] != -1} { + set variable_position [lsearch $args -increaseNetwork] + set increase_network [lindex $args [expr $variable_position +1]] + if {($increase_network < 1) || ($increase_network > 255) } { + set increase_network 1 + } else { + set multiple_streams 1 + } + } else { + set increase_network 1 + } + + #Increase Host + if {[lsearch $args -increaseHost] != -1} { + set variable_position [lsearch $args -increaseHost] + set increase_host [lindex $args [expr $variable_position +1]] + if {($increase_host < 1) || ($increase_host > 255) } { + set increase_host 1 + } else { + #increase_network and increase_host are mutually exclusive + #if user requests both this line means increase_network will + #be ignored + set increase_network 1 + set multiple_streams 1 + } + } else { + set increase_host 1 + } + + #Prefix Length + #NOTE IXIA will use prefix length if increase_host is selected + #if increase_network is selected you MUST use class type instead + if {[lsearch $args -prefixLength] != -1} { + set variable_position [lsearch $args -prefixLength] + set prefix_length [lindex $args [expr $variable_position +1]] + if {($prefix_length < 1) || ($prefix_length > 32) } { + set prefix_length 8 + } + } else { + set prefix_length 8 + } + + if {[lsearch $args -class] != -1} { + set variable_position [lsearch $args -class] + set class [lindex $args [expr $variable_position +1]] + if {($class != "A") && ($class != "B") && ($class != "C") } { + set classToUse classA + } else { + set classToUse class$class + } + } else { + set classToUse classA + } + + #GE Autonegotiation + if {[lsearch $args -autoNegotiation] != -1} { + set variable_position [lsearch $args -autoNegotiation] + set autonegotiation [lindex $args [expr $variable_position +1]] + } else { + #Negotiation will usually + set autonegotiation false + } + + #Media Type - GBIC or RJ45 + #Need to keep autonegotiation enabled for RJ45 / limit speed to 1000 + if {[lsearch $args -mediaType] != -1} { + set variable_position [lsearch $args -mediaType] + set mediaType [lindex $args [expr $variable_position +1]] + } else { + set mediaType GBIC + } + + # -vlanId VLAN header added with this ID - must be > 0 + if {[lsearch $args -vlanId] != -1} { + set variable_position [lsearch $args -vlanId] + set vlanId [lindex $args [expr $variable_position +1]] + if {$vlanId <= 0} { + error "Vlan Id must be greater than 0" + } + } else { + set vlanId 0 + } + + #-increaseVlan vlanId must have been previously specified + if {[lsearch $args -increaseVlan] != -1} { + set variable_position [lsearch $args -increaseVlan] + set increaseVlan [lindex $args [expr $variable_position +1]] + if {$vlanId <= 0} { + error "Vlan Id must set before you use -increaseVlan" + } + } else { + set increaseVlan 0 + } + + + if {$vlanId} { + set GE_PacketSize [expr $datagramLength + 22] + } else { + set GE_PacketSize [expr $datagramLength + 18] + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + + #Return the Ports to Factory Defaults + if {$tgen_app == "IxExplorer"} { + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + + + + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"])} { + port setPhyMode portPhyModeFiber $Chassis $Card $Port + port config -autonegotiate $autonegotiation + port config -duplex full + } else { + port config -autonegotiate true + port config -advertise1000FullDuplex true + port config -advertise100FullDuplex false + port config -advertise100HalfDuplex false + port config -advertise10FullDuplex false + port config -advertise10HalfDuplex false + + } + port config -numAddresses 1 + port config -MacAddress $SourceMAC + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass classA + ip config -sourceClass classA + ip config -precedence $IPprecedence + #Handle the case of multiple streams + if {$multiple_streams} { + if {$increase_host > 1} { + ip config -destIpAddrMode ipIncrHost + ip config -destIpAddrRepeatCount $increase_host + ip config -destIpMask [getmaskfromBits $prefix_length] + } + if {$increase_network > 1} { + ip config -destIpAddrMode ipIncrNetwork + ip config -destIpAddrRepeatCount $increase_network + ip config -destClass $classToUse + } + } + ip set $Chassis $Card $Port + + protocol config -ethernetType EthernetII + protocol config -name ipV4 + if {$vlanId} { + protocol config -enable802dot1qTag true + } + + if {$vlanId} { + vlan config -vlanID $vlanId + vlan set $Chassis $Card $Port + } + if {$increaseVlan} { + vlan config -mode vIncrement + vlan config -step 1 + vlan config -repeat $increaseVlan + vlan set $Chassis $Card $Port + } + + stream config -sa $SourceMAC + stream config -da $DestinationMAC + stream config -name Basic_Stream + stream config -framesize $GE_PacketSize + stream config -gapUnit gapNanoSeconds + stream config -rateMode useGap + stream config -enableIbg false + stream config -ifg $InterPacketGap + stream config -dma contPacket + stream config -patternType repeat + stream config -dataPattern xAAAA + if {[string match $enable_latency "true"]} { + stream config -enableTimestamp true + } + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + #Note - this only inserts packetgroups signature + #Actual timestamp is 'stream config fir' above + # - using same groupID for all streams + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port 1 + } + } + if {$tgen_app == "IxNetwork"} { + + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$Card\/port:$Port" $vportObj match]} { + set vportHandle $vportHdl + } + } + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"])} { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -media fiber " + set setPhyMode [interp eval $::ixia::TclInterp " ixNet getA $vportHandle/l1Config/ethernet -media "] + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate $autonegotiation " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto all " + interp eval $::ixia::TclInterp " ixNet commit " + + } else { + interp eval $::ixia::TclInterp " ixNet setAttribute $vportHandle/l1Config/ethernet -autoNegotiate true " + interp eval $::ixia::TclInterp " ixNet setA $vportHandle/l1Config/ethernet -speedAuto speed1000 " + interp eval $::ixia::TclInterp " ixNet commit " + + } + set interfaceObj [interp eval $::ixia::TclInterp " ixNet getL $vportHandle interface "] + interp eval $::ixia::TclInterp " ixNet setA [lindex $interfaceObj 0]/ethernet -macAddress $SourceMAC " + interp eval $::ixia::TclInterp " ixNet commit " + + set port1 $Chassis/$Card/$Port + #set enableTimestamp 1 + + #Handle the case of multiple streams + if {$multiple_streams} { + if {$increase_host > 1} { + set ipDstMode increment + set ipDstCount $increase_host + set ipDstMask [getmaskfromBits $prefix_length] + + } + if {$increase_network > 1} { + set ipDstMode increment + set ipDstCount $increase_network + + } + } else { + set ipDstMode increment + set ipDstCount 1 + } + + if {$vlanId} { + #protocol config -enable802dot1qTag true + set enableVlan enable + } + + if {$vlanId} { + set vlanID $vlanId + + } + if {$increaseVlan} { + set vlanMode increment + set vlanStep 1 + set vlanRepeatcount $increaseVlan + + } else { + set vlanMode increment + set vlanStep 1 + set vlanRepeatcount 1 + } + + if {[string match $enable_latency "true"]} { + #stream config -enableTimestamp true + set enableTimestamp 1 + } else { + set enableTimestamp 0 + } + + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + #Note - this only inserts packetgroups signature + #Actual timestamp is 'stream config fir' above + # - using same groupID for all streams + #packetGroup setDefault + #packetGroup config -insertSignature true + #packetGroup config -groupId 1 + #packetGroup setTx $Chassis $Card $Port 1 + puts "Not required" + } + #dont have support in IxNetwork "-inter_burst_gap_unit gapNanoSeconds", default it will take. + if {$vlanId} { + if {[regexp {(\.)} $SourceIP matched]} { + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv4 -ip_src_addr $SourceIP -ip_dst_addr $DestinationIP -ip_precedence $IPprecedence \ + -ethernet_type ethernetII -ip_dst_mode $ipDstMode -ip_dst_count $ipDstCount -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $GE_PacketSize -enforce_min_gap $InterPacketGap -tx_delay $InterPacketGap -tx_delay_unit ns \ + -transmit_mode continuous -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA -vlan $enableVlan -vlan_id $vlanID -vlan_id_mode $vlanMode -vlan_id_step $vlanStep -vlan_id_count $vlanRepeatcount] + } + if {[regexp {(\:)} $SourceIP matched]} { + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv6 -ipv6_src_addr $SourceIP -ipv6_dst_addr $DestinationIP -ip_precedence $IPprecedence \ + -ethernet_type ethernetII -ipv6_dst_mode $ipDstMode -ipv6_dst_count $ipDstCount -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $GE_PacketSize -enforce_min_gap $InterPacketGap -tx_delay $InterPacketGap -tx_delay_unit ns \ + -transmit_mode continuous -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA -vlan $enableVlan -vlan_id $vlanID -vlan_id_mode $vlanMode -vlan_id_step $vlanStep -vlan_id_count $vlanRepeatcount] + } + } else { + if {[regexp {(\.)} $SourceIP matched]} { + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv4 -ip_src_addr $SourceIP -ip_dst_addr $DestinationIP -ip_precedence $IPprecedence \ + -ethernet_type ethernetII -ip_dst_mode $ipDstMode -ip_dst_count $ipDstCount -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $GE_PacketSize -tx_delay $InterPacketGap -tx_delay_unit ns \ + -enforce_min_gap $InterPacketGap -transmit_mode continuous -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA] + } + if {[regexp {(\:)} $SourceIP matched]} { + set trafficConfig [::ixia::traffic_config -mode create -port_handle $port1 -l3_protocol ipv6 -ipv6_src_addr $SourceIP -ipv6_dst_addr $DestinationIP -ip_precedence $IPprecedence \ + -ethernet_type ethernetII -ipv6_dst_mode $ipDstMode -ipv6_dst_count $ipDstCount -mac_src $SourceMAC -mac_dst $DestinationMAC -frame_size $GE_PacketSize -tx_delay $InterPacketGap -tx_delay_unit ns \ + -enforce_min_gap $InterPacketGap -transmit_mode continuous -enable_time_stamp $enableTimestamp -data_pattern_mode repeating -data_pattern xAAAA] + } + } + } +} + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Add_BasicStream_GE { + + Description + This procedure adds a basic stream with one fixed sized + packet continuously played + It assumes at least one stream already exists (created using + IXIA_Create_BasicStream_GE) + + The ipg configured here will generally be updated later using + IXIA_Simply_Update_IPG_BasicStream_GE + In a time crunch IXIA_Simply_Update_IPG_BasicStream_GE was created + rather than adding functionality to IXIA_Update_IPG_BasicStream_GE + + Usage: + IXIA_Add_BasicStream_GE $port -dstIp \ + -dstMac \ + -ipg \ + [-srcIp ] \ + [-srcMac ] \ + [-prec ] \ + [-latencyStamp ] \ + [-datagramLength ] \ + [-autoNegotiation ] \ + [-mediaType ] \ + [-vlanId ] \ + [-increaseNetwork ] \ + [-increaseHost ] \ + [-prefixLength ] \ + [-class ] \ + [-increaseVlan ] + + Notes: + Configuring the -increaseNetwork option will increase the network portion + of the destination IP address by 1 the number of times requested by this + option. Currently it supports values in the range 1-254 + The class option is used in conjunction with this option to determine + where the network portion begins. The operation is classful - i.e. must + be A,B or C and defaults to A + + Configuring the -increaseHost option is similar but increase the host + portion of the destination IP addr. + This is used in conjunction with the -prefixLength option. + Using the -prefixLength option gives better control on where the host + portion starts. Due to IXIA funkyness prefix length must be used with + increaseHost and class must be used with increaseNetwork. + + Configuring the -vlanId option will insert a vlan tag in all generated + packets. + Configuring the -increaseVlan option will cause the vlanId in this + tag to increase by one each time up to the number of times requested. + + Example: + IXIA_Add_BasicStream_GE {1 1 1} -srcIp 8.0.1.2 -dstIp 11.0.1.2 \ + -ipg 10000000 \ + -srcMac {00 00 00 00 11 11} \ + -dstMac {10 10 10 10 10 10} \ + -datagramLength 400 -prec 1 \ + -class C -increaseNetwork 60 \ + -vlanId 1 -increaseVlan 60 + Returns: Nothing +} + +proc vtmsIxiaUtils::IXIA_Add_BasicStream_GE {IXIA_Port args} { + + #This flag will be used to know if incrementing either network or host req'd + set multiple_streams 0 + + #Stream ID + if {[lsearch $args -streamId] != -1} { + set variable_position [lsearch $args -streamId] + set streamId [lindex $args [expr $variable_position +1]] + } else { + #Can't continue without a stream ID + error "You must pass a streamId when calling IXIA_Add_BasicStream_GE" + } + #Packets Per Burst + if {[lsearch $args -pktsPerBurst] != -1} { + set variable_position [lsearch $args -pktsPerBurst] + set pktsPerBurst [lindex $args [expr $variable_position +1]] + } else { + set pktsPerBurst 1 + } + + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #Source MAC Address + if {[lsearch $args -srcMac] != -1} { + set variable_position [lsearch $args -srcMac] + set SourceMAC [lindex $args [expr $variable_position +1]] + } else { + #Source MAC doesn't really matter so I'll arbitrarily pick a default + set SourceMAC "00 c0 01 01 01 01" + } + + #Destination MAC Address + if {[lsearch $args -dstMac] != -1} { + set variable_position [lsearch $args -dstMac] + set DestinationMAC [lindex $args [expr $variable_position +1]] + } + + #Inter Packet Gap + if {[lsearch $args -ipg] != -1} { + set variable_position [lsearch $args -ipg] + set InterPacketGap [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Datagram Length for all packets + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set datagramLength [lindex $args [expr $variable_position +1]] + } else { + set datagramLength 62 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + #Increase Network + if {[lsearch $args -increaseNetwork] != -1} { + set variable_position [lsearch $args -increaseNetwork] + set increase_network [lindex $args [expr $variable_position +1]] + if {($increase_network < 1) || ($increase_network > 255) } { + set increase_network 1 + } else { + set multiple_streams 1 + } + } else { + set increase_network 1 + } + + #Increase Host + if {[lsearch $args -increaseHost] != -1} { + set variable_position [lsearch $args -increaseHost] + set increase_host [lindex $args [expr $variable_position +1]] + if {($increase_host < 1) || ($increase_host > 255) } { + set increase_host 1 + } else { + #increase_network and increase_host are mutually exclusive + #if user requests both this line means increase_network will + #be ignored + set increase_network 1 + set multiple_streams 1 + } + } else { + set increase_host 1 + } + + #Prefix Length + #NOTE IXIA will use prefix length if increase_host is selected + #if increase_network is selected you MUST use class type instead + if {[lsearch $args -prefixLength] != -1} { + set variable_position [lsearch $args -prefixLength] + set prefix_length [lindex $args [expr $variable_position +1]] + if {($prefix_length < 1) || ($prefix_length > 32) } { + set prefix_length 8 + } + } else { + set prefix_length 8 + } + + if {[lsearch $args -class] != -1} { + set variable_position [lsearch $args -class] + set class [lindex $args [expr $variable_position +1]] + if {($class != "A") && ($class != "B") && ($class != "C") } { + set classToUse classA + } else { + set classToUse class$class + } + } else { + set classToUse classA + } + + + # -vlanId VLAN header added with this ID - must be > 0 + if {[lsearch $args -vlanId] != -1} { + set variable_position [lsearch $args -vlanId] + set vlanId [lindex $args [expr $variable_position +1]] + if {$vlanId <= 0} { + error "Vlan Id must be greater than 0" + } + } else { + set vlanId 0 + } + + #-increaseVlan vlanId must have been previously specified + if {[lsearch $args -increaseVlan] != -1} { + set variable_position [lsearch $args -increaseVlan] + set increaseVlan [lindex $args [expr $variable_position +1]] + if {$vlanId <= 0} { + error "Vlan Id must set before you use -increaseVlan" + } + } else { + set increaseVlan 0 + } + + + if {$vlanId} { + set GE_PacketSize [expr $datagramLength + 22] + } else { + set GE_PacketSize [expr $datagramLength + 18] + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + + + + + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass classA + ip config -sourceClass classA + ip config -precedence $IPprecedence + #Handle the case of multiple streams + if {$multiple_streams} { + if {$increase_host > 1} { + ip config -destIpAddrMode ipIncrHost + ip config -destIpAddrRepeatCount $increase_host + ip config -destIpMask [getmaskfromBits $prefix_length] + } + if {$increase_network > 1} { + ip config -destIpAddrMode ipIncrNetwork + ip config -destIpAddrRepeatCount $increase_network + ip config -destClass $classToUse + } + } + ip set $Chassis $Card $Port + + protocol config -ethernetType EthernetII + protocol config -name ipV4 + if {$vlanId} { + protocol config -enable802dot1qTag true + } + + if {$vlanId} { + vlan config -vlanID $vlanId + vlan set $Chassis $Card $Port + } + if {$increaseVlan} { + vlan config -mode vIncrement + vlan config -step 1 + vlan config -repeat $increaseVlan + vlan set $Chassis $Card $Port + } + + stream config -sa $SourceMAC + stream config -da $DestinationMAC + stream config -name Basic_Stream + stream config -framesize $GE_PacketSize + stream config -gapUnit gapNanoSeconds + stream config -rateMode useGap + stream config -enableIbg false + stream config -ifg $InterPacketGap + stream config -dma contPacket + stream config -patternType repeat + stream config -dataPattern xAAAA + if {[string match $enable_latency "true"]} { + stream config -enableTimestamp true + } + stream set $Chassis $Card $Port $streamId + stream write $Chassis $Card $Port $streamId + + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + #Note - this only inserts packetgroups signature + #Actual timestamp is 'stream config fir' above + # - using same groupID for all streams + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port $streamId + } + + #Change Advance mode for streams - return to 1 for last stream + for {set looper 1} {$looper <= $streamId} {incr looper} { + stream get $Chassis $Card $Port $looper + if {$looper < $streamId} { + stream config -dma advance + } else { + stream config -dma gotoFirst + } + stream config -numFrames $pktsPerBurst + stream config -gapUnit gapNanoSeconds + stream config -enableIbg false + stream config -enableIsg true + stream config -isg $InterPacketGap + stream set $Chassis $Card $Port $looper + stream write $Chassis $Card $Port $looper + } +} + + + + +########################################################################## + +procDescr vtmsIxiaUtils::IXIA_Update_IPG_BasicStream_GE { + + Description: + This procedure changes the IPG for a basic stream that was previously + created using IXIA_Create_BasicStream_GE + + Usage: + IXIA_Update_IPG_BasicStream_GE $port -sendPps \ + [-dstIp ] \ + [-datagramLength ] \ + [-vlanId ] \ + [-increaseNetwork ] \ + [-increaseHost ] \ + [-prefixLength ] \ + [-class ] + + Note - -class must be passed if increase network is required + -prefixLength must be passed if increase host is set (IXIA issue) + + Note - If multiple streams are configured and you want to revert to one + then request -increaseNetwork 1 or -increaseHost 1 + + Example: + IXIA_Update_IPG_BasicStream_GE {1 1 1} -datagramLength 100 \ + -sendPps 5000 + + Returns: Nothing +} + +proc vtmsIxiaUtils::IXIA_Update_IPG_BasicStream_GE {IXIA_Port args} { + + #sendPPS + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set SendPPS [lindex $args [expr $variable_position +1]] + } else { + error "You must specify a send rate in PPS" + } + + #datagramLength + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set DatagramLength [lindex $args [expr $variable_position +1]] + } else { + error "You must specify a datagram length in bytes" + } + + #This flag will be used to know if incrementing either network or host req'd + set multiple_streams 0 + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + set ChangeDestIp 1 + } else { + set ChangeDestIp 0 + } + #Increase Network + if {[lsearch $args -increaseNetwork] != -1} { + set variable_position [lsearch $args -increaseNetwork] + set increase_network [lindex $args [expr $variable_position +1]] + if {($increase_network < 1) || ($increase_network > 255) } { + set increase_network 1 + } else { + set multiple_streams 1 + } + } else { + set increase_network 1 + } + + #Increase Host + if {[lsearch $args -increaseHost] != -1} { + set variable_position [lsearch $args -increaseHost] + set increase_host [lindex $args [expr $variable_position +1]] + if {($increase_host < 1) || ($increase_host > 255) } { + set increase_host 1 + } else { + # increase_network and increase_host are mutually exclusive + # if user requests both this line means increase_network + # will be ignored + set increase_network 1 + set multiple_streams 1 + } + } else { + set increase_host 1 + } + + # Prefix Length + # NOTE IXIA will use prefix length if increase_host is selected + # if increase_network is selected you MUST use class type instead + if {[lsearch $args -prefixLength] != -1} { + set variable_position [lsearch $args -prefixLength] + set prefix_length [lindex $args [expr $variable_position +1]] + if {($prefix_length < 1) || ($prefix_length > 32) } { + set prefix_length 8 + } + } else { + set prefix_length 8 + } + + #Class + if {[lsearch $args -class] != -1} { + set variable_position [lsearch $args -class] + set class [lindex $args [expr $variable_position +1]] + if {($class != "A") && ($class != "B") && ($class != "C") } { + set classToUse classA + } else { + set classToUse class$class + } + } else { + set classToUse classA + } + + # -vlanId VLAN header added with this ID - must be > 0 + if {[lsearch $args -vlanId] != -1} { + set variable_position [lsearch $args -vlanId] + set vlanId [lindex $args [expr $variable_position +1]] + if {$vlanId <= 0} { + error "Vlan Id must be greater than 0" + } + } else { + set vlanId 0 + } + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Amount of overhead depends on whether VLAN id is present + if {$vlanId} { + set packetOverHead 42.0 + set packetL2HeaderLength 22.0 + } else { + set packetOverHead 38.0 + set packetL2HeaderLength 18.0 + } + + + #Knowing datagram size and PPS requested calculate what percentage of GE + #should be sent + set GESendBPS [expr $SendPPS * ($DatagramLength.0 + $packetOverHead) * 8.0] + set SendPercent [expr ($GESendBPS / 1000000000) * 100] + + set GE_PacketSize [expr $DatagramLength + $packetL2HeaderLength] + + #Figure out what kind of card we are portMode = 1 for GE / 4 for 10GE + if {$tgen_app == "IxExplorer"} { + port get $Chassis $Card $Port + set current_port_mode [port cget -portMode] + + #If 10GE port scale SendPErcent accordingly + if {$current_port_mode == 4} { + set SendPercent [expr $SendPercent / 10] + } + + #Do the config + + stream get $Chassis $Card $Port 1 + + if {$vlanId} { + vlan get $Chassis $Card $Port + vlan config -vlanID $vlanId + vlan set $Chassis $Card $Port + } + + ip get $Chassis $Card $Port + #Only change the destination IP if an address was passed + if {$ChangeDestIp} { + ip config -destIpAddr $DestinationIP + } + #Change back & forth between multiple IP destination / single depending + #on whether or not an option was passed + if {$multiple_streams} { + if { ($increase_host > 1) || ($increase_network > 1)} { + if {$increase_host > 1} { + ip config -destIpAddrMode ipIncrHost + ip config -destIpAddrRepeatCount $increase_host + ip config -destIpMask [getmaskfromBits $prefix_length] + } + if {$increase_network > 1} { + ip config -destIpAddrMode ipIncrNetwork + ip config -destIpAddrRepeatCount $increase_network + ip config -destClass $classToUse + } + } else { + ip config -destIpAddrMode ipIdle + } + } + ip set $Chassis $Card $Port + + + #stream get $Chassis $Card $Port 1 - stream get here was wipes out IP set ^^ + #Note - had problems using IPG on basic stream - using + #percent mode instead + stream config -framesize $GE_PacketSize + stream config -rateMode usePercentRate + stream config -percentPacketRate $SendPercent + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + + sleep 2 + } + + if {$tgen_app == "IxNetwork"} { + + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$Card\/port:$Port" $vportObj match]} { + #interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHdl/capture -hardwareEnabled true " + set vportHandle $vportHdl + } + } + #port get $Chassis $Card $Port + #set current_port_mode [port cget -portMode] + set current_int_type_name [interp eval $::ixia::TclInterp " ixNet getA $vportHandle -actualSpeed "] + if {$current_int_type_name == 1000} { + set current_port_mode 1 + } + if {$current_int_type_name == 10000} { + set current_port_mode 4 + } + + #If 10GE port scale SendPErcent accordingly + if {$current_port_mode == 4} { + set SendPercent [expr $SendPercent / 10] + } + + #Do the config + + #stream get $Chassis $Card $Port 1 + set streamID 1 + + #Change back & forth between multiple IP destination / single depending + #on whether or not an option was passed + if {$multiple_streams} { + if { ($increase_host > 1) || ($increase_network > 1)} { + if {$increase_host > 1} { + set ipDstMode increment + set ipDstCount $increase_host + set ipDstMask [getmaskfromBits $prefix_length] + } + if {$increase_network > 1} { + set ipDstMode increment + set ipDstCount $increase_network + } + } else { + set ipDstMode increment + set ipDstCount 1 + } + } + + #stream get $Chassis $Card $Port 1 - stream get here was wipes out IP set ^^ + #Note - had problems using IPG on basic stream - using + #percent mode instead + + #Only change the destination IP if an address was passed + set port1 $Chassis/$Card/$Port + if {$vlanId && $ChangeDestIp} { + set trafficConfig [::ixia::traffic_config -mode modify -port_handle $port1 -stream_id $streamID -frame_size $GE_PacketSize -rate_mode percent -rate_percent $SendPercent \ + -ip_dst_addr $DestinationIP -ip_dst_mode $ipDstMode -ip_dst_count $ipDstCount -vlan_id $vlanId] + } elseif {$vlanId} { + set trafficConfig [::ixia::traffic_config -mode modify -port_handle $port1 -stream_id $streamID -frame_size $GE_PacketSize -rate_mode percent -rate_percent $SendPercent -vlan_id $vlanId] + } elseif {$ChangeDestIp} { + set trafficConfig [::ixia::traffic_config -mode modify -port_handle $port1 -stream_id $streamID -frame_size $GE_PacketSize -rate_mode percent -rate_percent $SendPercent \ + -ip_dst_addr $DestinationIP -ip_dst_mode $ipDstMode -ip_dst_count $ipDstCount] + } else { + set trafficConfig [::ixia::traffic_config -mode modify -port_handle $port1 -stream_id $streamID -frame_size $GE_PacketSize -rate_mode percent -rate_percent $SendPercent ] + } + #sleep 2 + } +} + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Simply_Update_IPG_BasicStream_GE { + + Description: + This procedure changes the IPG for basic streams that were previously + created using the combination of IXIA_Create_BasicStream_GE and + IXIA_Add_BasicStream_GE + + Usage: + IXIA_Simply_Update_IPG_BasicStream_GE $port \ + -sendPps \ + -datagramLength \ + [-vlanId <1|0>] \ + [-numberOfStreams ] + + Note - vlanId is a flag - if 1 a vlan tag is assumed present in calculations + for the IPG / ISG to configer. Defaults to 0 + Note - If multiple streams are present it's up to the caller to pass the + number of streams - defaults to 1. + + Example: + IXIA_Simply_Update_IPG_BasicStream_GE {1 1 1} -datagramLength 100 \ + -sendPps 5000 + + Returns: Nothing + +} + +proc vtmsIxiaUtils::IXIA_Simply_Update_IPG_BasicStream_GE {IXIA_Port args} { + + #sendPPS + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set SendPPS [lindex $args [expr $variable_position +1]] + } else { + error "You must specify a send rate in PPS" + } + + #datagramLength + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set DatagramLength [lindex $args [expr $variable_position +1]] + } else { + error "You must specify a datagram length in bytes" + } + + #number of streams + if {[lsearch $args -numberOfStreams] != -1} { + set variable_position [lsearch $args -numberOfStreams] + set numberOfStreams [lindex $args [expr $variable_position +1]] + } else { + set numberOfStreams 1 + } + + # -vlanId VLAN header added with this ID - must be > 0 + if {[lsearch $args -vlanId] != -1} { + set variable_position [lsearch $args -vlanId] + set vlanId [lindex $args [expr $variable_position +1]] + if {$vlanId <= 0} { + error "Vlan Id must be greater than 0" + } + } else { + set vlanId 0 + } + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Amount of overhead depends on whether VLAN id is present + if {$vlanId} { + set packetOverHead 42.0 + set packetL2HeaderLength 22.0 + } else { + set packetOverHead 38.0 + set packetL2HeaderLength 18.0 + } + + + #Knowing datagram size and PPS requested calculate what percentage of GE + #should be sent + set GESendBPS [expr $SendPPS * ($DatagramLength.0 + $packetOverHead) * 8.0] + set SendPercent [expr ($GESendBPS / 1000000000) * 100] + + set GE_PacketSize [expr $DatagramLength + $packetL2HeaderLength] + + #Knowing how many pps translate this to GE bps (note on GE it takes + # 1 nS to transmit 1 bit + + #Note - as usual IXIA is not behaving and sending at the correct rate based + #on IPG I request. It is oversending + #To compensate I subtract some size from each packet + #I suspect that the IXIA IPG doesn't allow for the minimum required + #ifg but does expect you to allow for preamble / flag hence + #I remove 12 bytes from each packet - seems to work fine. + + #Calculate the GE Gaps (ie time not being used by above + set GETotalGap [expr 1000000000.0 - $GESendBPS] + #Need to avoid /0 errors when a stream has 0 percent load + if {$SendPPS == 0 } { + set SendPPS .00001 + } + #Inter Packet Gap + set IPG [expr $GETotalGap / $SendPPS] + #Why the following - don't know - allow for IXIA funkyness.. + #Penalty of 100 was reached through experimentation. + set IPG [expr $IPG + 100] + + if {$numberOfStreams == 1} { + stream get $Chassis $Card $Port 1 + #Note - had problems using IPG on basic stream - using + #percent mode instead + stream config -framesize $GE_PacketSize + stream config -rateMode usePercentRate + stream config -percentPacketRate $SendPercent + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + sleep 2 + } else { + #Need to use IPG & ISG + for {set currentStream 1} {$currentStream <= $numberOfStreams} \ + {incr currentStream} { + stream get $Chassis $Card $Port $currentStream + stream config -framesize $GE_PacketSize + stream config -rateMode useGap + stream config -enableIbg false + stream config -gapUnit gapNanoSeconds + stream config -ifg $IPG + stream config -isg $IPG + stream set $Chassis $Card $Port $currentStream + stream write $Chassis $Card $Port $currentStream + } + } +} + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_POS_Basic_Config { + + Description: + This procedure resets a POS port to it's basic config + and then sets CF flag, interface speed, CRC etc.. + It creates basic config needed to bring an IXIA POS port up so + that it can be used to count packets. + + Usage: + IXIA_POS_Basic_Config port [-posSpeed ] \ + [-crcLength <2|4>] \ + [-packetGroupMode ] \ + [-qosStatsMode ] + + Defaults: + -posSpeed : oc3 + -crcLength : 2 + -packetGroupMode : false + -qosStatsMode : false + + Example: + IXIA_POS_Basic_Config {1 1 1} -posSpeed oc3 -packetGroupMode true + + Returns: Nothing +} + +proc vtmsIxiaUtils::IXIA_POS_Basic_Config {IXIA_Port args} { + + #POS Speed + if {[lsearch $args -posSpeed] != -1} { + set variable_position [lsearch $args -posSpeed] + set POS_Speed [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to oc3 + set POS_Speed OC3 + } + + #CRC Length + if {[lsearch $args -crcLength] != -1} { + set variable_position [lsearch $args -crcLength] + set CRC_Length [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to 2 bytes + set CRC_Length 2 + } + + #Enable Packet Groups Mode + if {[lsearch $args -packetGroupMode] != -1} { + set variable_position [lsearch $args -packetGroupMode] + set EnablePacketGroupMode [lindex $args [expr $variable_position +1]] + } else { + set EnablePacketGroupMode false + } + + #Enable QOS Stats Mode + if {[lsearch $args -qosStatsMode] != -1} { + set variable_position [lsearch $args -qosStatsMode] + set EnableQOSStatsMode [lindex $args [expr $variable_position +1]] + } else { + set EnableQOSStatsMode false + } + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + if {$tgen_app == "IxExplorer"} { + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + + #Configure the Receiving POS Port + sonet get $Chassis $Card $Port + sonet config -interfaceType $POS_Speed + if {$CRC_Length == 4} { + sonet config -rxCrc sonetCrc32 + sonet config -txCrc sonetCrc32 + } else { + sonet config -rxCrc sonetCrc16 + sonet config -txCrc sonetCrc16 + } + + sonet config -header sonetCiscoHdlc + sonet config -C2byteExpected 0xCF + sonet config -C2byteTransmit 0xCF + sonet config -dataScrambling false + sonet config -useRecoveredClock true + + sonet set $Chassis $Card $Port + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + if {[string match $EnablePacketGroupMode "true"]} { + packetGroup setDefault + packetGroup config -latencyControl cutThrough + packetGroup setRx $Chassis $Card $Port + port setReceiveMode portPacketGroup $Chassis $Card $Port + port set $Chassis $Card $Port + } + + if {[string match $EnableQOSStatsMode "true"]} { + port setReceiveMode portCapture $Chassis $Card $Port + port set $Chassis $Card $Port + stat config -mode statQos + stat set $Chassis $Card $Port + stat write $Chassis $Card $Port + } + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + } + if {$tgen_app == "IxNetwork"} { + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$Card\/Port:$port" $vportObj match]} { + set vportHandle $vportHdl + } + } + #Configure the Receiving POS Port (sonet will not work in IxNetwork so removed) + + } +} + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Create_IMIX_POS { + + Description: + This procedure creates an IMIX stream on an IXIA POS port + It will start by resetting the port to ensure we're starting + with a clean slate. + + Usage: + IXIA_Create_IMIX_POS $port -dstIp \ + -isg \ + [-srcIp ] \ + [-srcMac ] \ + [-prec <0|1|2|3|4|5|6|7|ATM>] \ + [-latencyStamp ] \ + [-posSpeed ] \ + [-crcLength <2|4>] \ + [-increaseNetwork ] \ + [-increaseHost ] \ + [-prefixLength ] \ + [-class ] + + Note - -class must be passed if increase network is required + -prefixLength must be passed if increase host is set (IXIA issue) + + Arguments are self explainatory except for -prec + If this is set to ATM then each packet size in an IMIX distribution is + marked with a different precedence value. + This is required to when figuring how many of each size packets were + received / dropped when the interface under test is ATM. + If set to a numeric value all packets are marked with that same + precedence. + + The value configured for ISG is not that important - it should be modified + later by IXIA_Update_IPG_IMIX_GE. + + Defaults : + -posSpeed : oc3 + -crcLength : 2 + -srcIp : 10.10.10.1 - generally don't care what this is + -prec : 0 + -latencyStamp : false + -increaseNetwork : 1 + -increaseHost : 1 + -prefixLength : 8 + -class : A + + Example : + IXIA_Create_IMIX_POS {1 7 1} -srcIP 10.2.1.2 -dstIP 12.2.0.2 \ + -isg 10000000 \ + -posSpeed oc12 -crcLength 2 \ + -latency_stamp true -DatagramLength 62 \ + -increaseNetwork 2 -class B + Returns: Nothing + +} + + +proc vtmsIxiaUtils::IXIA_Create_IMIX_POS {IXIA_Port args} { + + #This flag will be used to know if incrementing either network or host req'd + set multiple_streams 0 + + #POS Speed + if {[lsearch $args -posSpeed] != -1} { + set variable_position [lsearch $args -posSpeed] + set POS_Speed [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to oc3 + set POS_Speed oc3 + } + + #CRC Length + if {[lsearch $args -crcLength] != -1} { + set variable_position [lsearch $args -crcLength] + set CRC_Length [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to 2 bytes + set CRC_Length 2 + } + + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + + #Inter Stream Gap + if {[lsearch $args -isg] != -1} { + set variable_position [lsearch $args -isg] + set InterStreamGap [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + #For ATM IMIX Tests Precedence is used to differentiate number of packet + #of each size that are received - this is necessary as the cell tax + #(L2 overhead) is different for each packet size. + + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + #Increase Network + if {[lsearch $args -increaseNetwork] != -1} { + set variable_position [lsearch $args -increaseNetwork] + set increase_network [lindex $args [expr $variable_position +1]] + if {($increase_network < 1) || ($increase_network > 255) } { + set increase_network 1 + } else { + set multiple_streams 1 + } + } else { + set increase_network 1 + } + + #Increase Host + if {[lsearch $args -increaseHost] != -1} { + set variable_position [lsearch $args -increaseHost] + set increase_host [lindex $args [expr $variable_position +1]] + if {($increase_host < 1) || ($increase_host > 255) } { + set increase_host 1 + } else { + # increase_network and increase_host are mutually exclusive + # if user requests both this line means increase_network + # will be ignored + set increase_network 1 + set multiple_streams 1 + } + } else { + set increase_host 1 + } + + #Prefix Length + #NOTE IXIA will use prefix length if increase_host is selected + #if increase_network is selected you MUST use class type instead + if {[lsearch $args -prefixLength] != -1} { + set variable_position [lsearch $args -prefixLength] + set prefix_length [lindex $args [expr $variable_position +1]] + if {($prefix_length < 1) || ($prefix_length > 32) } { + set prefix_length 8 + } + } else { + set prefix_length 8 + } + + #Class + if {[lsearch $args -class] != -1} { + set variable_position [lsearch $args -class] + set class [lindex $args [expr $variable_position +1]] + if {($class != "A") && ($class != "B") && ($class != "C") } { + set classToUse classA + } else { + set classToUse class$class + } + } else { + set classToUse classA + } + + #IMIX Packet Lengths on POS + #0 is just so lengths are in positions 1 - 12 + set IMIX_Packet_Length { 0 52 52 558 52 52 558 52 1506 558 52 52 558 } + set ATM_Precedence_Distribution { 0 1 1 2 1 1 2 1 3 2 1 1 2 } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Return the Ports to Factory Defaults + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + + sonet get $Chassis $Card $Port + sonet config -interfaceType $POS_Speed + if {$CRC_Length == 4} { + sonet config -rxCrc sonetCrc32 + sonet config -txCrc sonetCrc32 + } else { + sonet config -rxCrc sonetCrc16 + sonet config -txCrc sonetCrc16 + } + sonet config -header sonetCiscoHdlc + sonet config -C2byteExpected 0xCF + sonet config -C2byteTransmit 0xCF + sonet config -dataScrambling false + sonet config -useRecoveredClock true + sonet set $Chassis $Card $Port + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + for {set looper 1} {$looper <= 12} {incr looper} { + + stream get $Chassis $Card $Port $looper + + protocol config -name ipV4 + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass $classToUse + ip config -sourceClass classA + #Handle the case of multiple streams + if {$multiple_streams} { + if {$increase_host > 1} { + ip config -destIpAddrMode ipIncrHost + ip config -destIpAddrRepeatCount $increase_host + ip config -destIpMask [getmaskfromBits $prefix_length] + } + if {$increase_network > 1} { + ip config -destIpAddrMode ipIncrNetwork + ip config -destIpAddrRepeatCount $increase_network + ip config -destClass $classToUse + } + } + if {[string match $IPprecedence "ATM"]} { + ip config -precedence [lindex $ATM_Precedence_Distribution $looper] + } else { + ip config -precedence $IPprecedence + } + ip set $Chassis $Card $Port + stream config -name IMIX_Stream + stream config -framesize [lindex $IMIX_Packet_Length $looper] + if {$looper < 12} { + stream config -dma advance + } else { + stream config -dma gotoFirst + } + if {$multiple_streams} { + stream config -rateMode usePercentRate + stream config -percentPacketRate 100 + if {$increase_host > $increase_network} { + stream config -numFrames $increase_host + } else { + stream config -numFrames $increase_network + } + } else { + stream config -numFrames 1 + } + stream config -enableIbg false + stream config -enableIsg true + stream config -gapUnit gapNanoSeconds + stream config -isg $InterStreamGap + if {[string match $enable_latency "true"]} { + stream config -enableTimestamp true + } + stream config -patternType repeat + stream config -dataPattern xAAAA + stream set $Chassis $Card $Port $looper + stream write $Chassis $Card $Port $looper + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + # - using same groupID for all streams + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port $looper + } + } +} + + + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Update_IPG_IMIX_POS { + + Description: + This procedure changes the ISG for each packet in an IMIX + packet distribution on a POS port that was previously created + using IXIA_Create_IMIX_POS + + + Usage: IXIA_Update_IPG_IMIX_POS $port -sendPps \ + [-dstIp ] \ + [-posSpeed ] \ + [-crcLength <2|4>] \ + [-prec <0-8|ATM>] + + Defaults: + -posSpeed : oc12 + -crcLength : 2 + + Example: IXIA_Update_IPG_IMIX_POS {1 1 2} -sendPps 100 + + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_Update_IPG_IMIX_POS {IXIA_Port args } { + + #Desired PPS send rate + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set pps [lindex $args [expr $variable_position +1]] + } + + #POS Speed + if {[lsearch $args -posSpeed] != -1} { + set variable_position [lsearch $args -posSpeed] + set POS_Speed [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to oc12 + set POS_Speed oc12 + } + + #CRC Length + if {[lsearch $args -crcLength] != -1} { + set variable_position [lsearch $args -crcLength] + set CRC_Length [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to 2 bytes + set CRC_Length 2 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Need to calculate the Inter Stream Gap for IMIX Traffic + set AvgIMIXDatagramSize 335.83 + + #1.) Calculate actual busy time + set POSSendBPS [expr $SendPPS \ + * ($AvgIMIXDatagramSize + 5 + $CRC_Length) * 8] + + #2.)From this calculat ethe gap time in nanoseconds + if {[string match $POS_Speed "oc3"]} { + set TotalTransmitTime [expr 1000000000.0 * ($POSSendBPS / 149760000)] + set TotalGapTime [expr 1000000000.0 - $TotalTransmitTime] + } + + if {[string match $POS_Speed "oc12"]} { + set TotalTransmitTime [expr 1000000000.0 * ($POSSendBPS / 599040000)] + set TotalGapTime [expr 1000000000.0 - $TotalTransmitTime] + } + + #Need to avoid /0 errors when a stream has 0 percent load + if {$SendPPS == 0 } { + set SendPPS .1 + } + + #Inter Packet Gap + set IPG [expr $TotalGapTime / $SendPPS] + + # + #Remove the pause that will be there because I'm only sending + #one packet per stream + #set IPG [expr $IPG - 60] + + for {set StreamID 1} {$StreamID <= 12} {incr StreamID} { + stream get $Chassis $Card $Port $StreamID + + if {[lsearch $args -dstIp] || [lsearch $args -prec]} { + ip get $Chassis $Card $Port + if {[lsearch $args -dstIp]} { + ip config -destIpAddr $DestinationIP + } + if {[lsearch $args -prec]} { + ip config -precedence $IPprecedence + } + ip set $Chassis $Card $Port + } + stream config -isg $IPG + stream set $Chassis $Card $Port $StreamID + stream write $Chassis $Card $Port $StreamID + } +} + + + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Create_BasicStream_POS { + + Description: + This procedure creates a basic stream with one fixed sized + packet continuously played + It will start by resetting the port to ensure we're starting + with a clean slate. + The ipg configured here will generally be updated later using + IXIA_Update_IPG_BasicStream_GE + + Usage: + IXIA_Create_BasicStream_GE $port -dstIp \ + -dstMac \ + -ipg \ + [-srcIp ] \ + [-prec ] \ + [-latencyStamp ] \ + [-datagramLength ] \ + [-posSpeed ] \ + [-crcLength <2|4>] + + Defaults: + -srcIp : 10.10.10.1 - generally doesn't matter + -prec : 0 + -latencyStamp : false + -datagramLength : 74 + -posSpeed :oc12 + -crcLength : 2 + + Example: + IXIA_Create_BasicStream_POS {1 1 1} -srcIp 5.1.0.2 -dstIp 5.2.0.2 \ + -posSpeed oc3 -crcLength 2 \ + -ipg 10000000 -prec 6 \ + -datagramLength 100 + + Returns: Nothing +} + +proc vtmsIxiaUtils::IXIA_Create_BasicStream_POS {IXIA_Port args} { + + #POS Speed + if {[lsearch $args -posSpeed] != -1} { + set variable_position [lsearch $args -posSpeed] + set POS_Speed [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to oc3 + set POS_Speed oc3 + } + + #CRC Length + if {[lsearch $args -crcLength] != -1} { + set variable_position [lsearch $args -crcLength] + set CRC_Length [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to 2 bytes + set CRC_Length 2 + } + + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #Inter Packet Gap + if {[lsearch $args -ipg] != -1} { + set variable_position [lsearch $args -ipg] + set InterPacketGap [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Datagram Length for all packets + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set DatagramLength [lindex $args [expr $variable_position +1]] + set POS_PacketSize [expr $DatagramLength + 4 + $CRC_Length] + } else { + set POS_PacketSize 80 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Return the Ports to Factory Defaults + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + + sonet get $Chassis $Card $Port + sonet config -interfaceType $POS_Speed + if {$CRC_Length == 4} { + sonet config -rxCrc sonetCrc32 + sonet config -txCrc sonetCrc32 + } else { + sonet config -rxCrc sonetCrc16 + sonet config -txCrc sonetCrc16 + } + sonet config -header sonetCiscoHdlc + sonet config -C2byteExpected 0xCF + sonet config -C2byteTransmit 0xCF + sonet config -dataScrambling false + sonet config -useRecoveredClock true + sonet set $Chassis $Card $Port + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + #Seems I need to get stream first with POS... + stream get $Chassis $Card $Port 1 + + + protocol config -name ipV4 + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass classA + ip config -sourceClass classA + ip config -precedence $IPprecedence + ip set $Chassis $Card $Port + + stream config -name Basic_Stream + stream config -framesize $POS_PacketSize + stream config -gapUnit gapNanoSeconds + stream config -rateMode useGap + stream config -enableIbg false + stream config -ifg $InterPacketGap + stream config -dma contPacket + stream config -patternType repeat + stream config -dataPattern xAAAA + + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements (using same + #groupID for all streams) + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port 1 + } + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 +} + + + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Update_IPG_BasicStream_POS { + + Description: + This procedure changes the IPG for POS basic streams that were + created using IXIA_Create_BasicStream_POS + + Usage: + IXIA_Update_IPG_BasicStream_POS port -sendPps \ + -datagramLength \ + -posSpeed \ + -crcLength <2|4> + + Defaults: + -posSpeed : oc12 + -crcLength : 2 + + Example: + IXIA_Update_IPG_BasicStream_POS {1 1 1} -sendPps 1000 \ + -datagramLength 100 + + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_Update_IPG_BasicStream_POS {IXIA_Port args} { + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #sendPPS + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set SendPPS [lindex $args [expr $variable_position +1]] + } + + #POS Speed + if {[lsearch $args -posSpeed] != -1} { + set variable_position [lsearch $args -posSpeed] + set POS_Speed [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to oc12 + set POS_Speed oc12 + } + + #CRC Length + if {[lsearch $args -crcLength] != -1} { + set variable_position [lsearch $args -crcLength] + set CRC_Length [lindex $args [expr $variable_position +1]] + } else { + #Defaulting to 2 bytes + set CRC_Length 2 + } + + #Datagram Length for all packets + if {[lsearch $args -datagramLength] != -1} { + set variable_position [lsearch $args -datagramLength] + set DatagramLength [lindex $args [expr $variable_position +1]] + set POS_PacketSize [expr $DatagramLength + 4 + $CRC_Length] + } else { + set POS_PacketSize 80 + } + + + + #1.) Calculate actual bbs to send including hdlc flag + set POSSendBPS [expr $SendPPS * ($POS_PacketSize + 1) * 8] + + #2.)From this calculate the gap time in nanoseconds + if {[string match $POS_Speed "oc3"]} { + set TotalTransmitTime [expr 1000000000.0 * ($POSSendBPS / 149760000)] + set TotalGapTime [expr 1000000000.0 - $TotalTransmitTime] + set PosLinkRate 149760000 + } + if {[string match $POS_Speed "oc12"]} { + set TotalTransmitTime [expr 1000000000.0 * ($POSSendBPS / 599040000)] + set TotalGapTime [expr 1000000000.0 - $TotalTransmitTime] + set PosLinkRate 599040000 + } + if {[string match $POS_Speed "oc48"]} { + set TotalTransmitTime [expr 1000000000.0 * ($POSSendBPS / 2396160000 )] + set TotalGapTime [expr 1000000000.0 - $TotalTransmitTime] + set PosLinkRate 2396160000 + } + + #Knowing datagram size and PPS requested calculate what percentage of POS + #should be sent + set POSSendBPS [expr $SendPPS * ($DatagramLength.0 + 7.0) * 8.0] + set SendPercent [expr ($POSSendBPS / $PosLinkRate) * 100] + + #Need to avoid /0 errors when a stream has 0 percent load + if {$SendPPS == 0 } { + set SendPPS .00001 + } + #Inter Packet Gap + set IPG [expr $TotalGapTime / $SendPPS] + + + stream get $Chassis $Card $Port 1 + stream config -framesize $POS_PacketSize + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 + sleep 2 + stream get $Chassis $Card $Port 1 + #Note - had problems using IPG on basic stream - using + #percent mode instead + stream config -rateMode usePercentRate + stream config -percentPacketRate $SendPercent + #puts "Result of setting IFG is:" + #puts [stream config -ifg $IPG] + stream set $Chassis $Card $Port 1 + stream write $Chassis $Card $Port 1 +} + + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Create_MyMIX_GE { + + Description: + This procedure creates an MyMIX stream on an IXIA GE port + It will start by resetting the port to ensure we're starting + with a clean slate. + MyMIX is basically configuring a predetermined sequence of packets + that will repeat much like is done with IMIX. + The reasoning behind MyMIX is that we were tuning VTMS with IMIX + and were concerned we were tuning for just that particular sequence. + MyMIX allows longer sequences with more variance. + + MyMIX definitions are basically a list of the datagram sizes to be + configured. MyMIX definitions appear at the top of this file and the + number associated with each is the average datagram length for that + sequence (e.g. MyMIX(200) has an average datagram length of 200 bytes) + + The required packet distribution is passed as one of the parameters + + The isg passed to IXIA_Create_MyMIX_GE generally doesn't matter as it + is usually updated later using IXIA_Update_IPG_MyMIX_GE based on the + required pps rate. + + + Usage: + IXIA_Create_MyMIX_GE $port -dstIp \ + -dstMac \ + -isg \ + -MyMIX \ + [-srcIp ] \ + [-srcMac ] \ + [-prec <0-7>] \ + [-latencyStamp ] \ + [-autoNegotiation ] \ + [-mediaType ] + Defaults: + -srcIp : 10.10.10.1 - generally doesn't matter what this is + -srcMac : "00 c0 01 01 01 01" - generally doesn't matter what this is + -prec : 0 + -latencyStamp : false + -autonegotiation : false => no autonegotiation + -mediaType: GBIC + + Example: + IXIA_Create_MyMIX_GE {1 16 1} -srcIp 10.0.0.2 -dstIp 12.2.1.2 \ + -isg 10000000 \ + -srcMac {00 c0 10 00 00 02} \ + -dstMac {00 c0 22 22 22 22} -prec 4 \ + -MyMIX $Definition(MyMIX200) + + Returns: Nothing +} + + +proc vtmsIxiaUtils::IXIA_Create_MyMIX_GE {IXIA_Port args} { + + #Source IP + if {[lsearch $args -srcIp] != -1} { + set variable_position [lsearch $args -srcIp] + set SourceIP [lindex $args [expr $variable_position +1]] + } else { + #Source IP doesn't really matter so I'll arbitrarily pick a default + set SourceIP 10.10.10.1 + } + + #Destination IP + if {[lsearch $args -dstIp] != -1} { + set variable_position [lsearch $args -dstIp] + set DestinationIP [lindex $args [expr $variable_position +1]] + } + + #Source MAC Address + if {[lsearch $args -srcMac] != -1} { + set variable_position [lsearch $args -srcMac] + set SourceMAC [lindex $args [expr $variable_position +1]] + } else { + #Source MAC doesn't really matter so I'll arbitrarily pick a default + set SourceMAC "00 c0 01 01 01 01" + } + + #Destination MAC Address + if {[lsearch $args -dstMac] != -1} { + set variable_position [lsearch $args -dstMac] + set DestinationMAC [lindex $args [expr $variable_position +1]] + } + + #Inter Stream Gap + if {[lsearch $args -isg] != -1} { + set variable_position [lsearch $args -isg] + set InterStreamGap [lindex $args [expr $variable_position +1]] + } + + #IP Precedence + #For ATM IMIX Tests Precedence is used to differentiate number of packet of + #each size that are received - this is necessary as the cell tax + #(L2 overhead) is different for each packet size. + + if {[lsearch $args -prec] != -1} { + set variable_position [lsearch $args -prec] + set IPprecedence [lindex $args [expr $variable_position +1]] + } else { + set IPprecedence 0 + } + + #Enable_Latency + if {[lsearch $args -latencyStamp] != -1} { + set variable_position [lsearch $args -latencyStamp] + set enable_latency [lindex $args [expr $variable_position +1]] + } else { + set enable_latency false + } + + #MyMIX - A list of packet sizes to be configured + if {[lsearch $args -MyMIX] != -1} { + set variable_position [lsearch $args -MyMIX] + set MyMIX_Packet_Lengths [lindex $args [expr $variable_position +1]] + } else { + error "You must pass a packet distribution" + } + #GE Autonegotiation + if {[lsearch $args -autoNegotiation] != -1} { + set variable_position [lsearch $args -autoNegotiation] + set autonegotiation [lindex $args [expr $variable_position +1]] + } else { + #Negotiation will usually + set autonegotiation false + } + + #Media Type - GBIC or RJ45 + #Need to keep autonegotiation enabled for RJ45 / limit speed to 1000 + if {[lsearch $args -mediaType] != -1} { + set variable_position [lsearch $args -mediaType] + set mediaType [lindex $args [expr $variable_position +1]] + } else { + set mediaType GBIC + } + + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + + set NumberOfPackets [llength $MyMIX_Packet_Lengths] + + #Return the Ports to Factory Defaults + port setFactoryDefaults $Chassis $Card $Port + sleep 2 + + if {([string match $mediaType "GBIC"]) || \ + ([string match $mediaType "fiber"]) } { + port setPhyMode portPhyModeFiber $Chassis $Card $Port + port config -autonegotiate $autonegotiation + port config -duplex full + } else { + port config -autonegotiate true + port config -advertise1000FullDuplex true + port config -advertise100FullDuplex false + port config -advertise100HalfDuplex false + port config -advertise10FullDuplex false + port config -advertise10HalfDuplex false + + } + port config -numAddresses 1 + port config -MacAddress $SourceMAC + port set $Chassis $Card $Port + port write $Chassis $Card $Port + + + for {set looper 1} {$looper <= $NumberOfPackets} {incr looper} { + set packetIndex [expr $looper - 1] + set currentDatagramLength [lindex $MyMIX_Packet_Lengths $packetIndex] + set currentFrameLength [expr $currentDatagramLength + 18] + + ip config -sourceIpAddr $SourceIP + ip config -destIpAddr $DestinationIP + ip config -destClass classA + ip config -sourceClass classA + ip config -precedence $IPprecedence + ip set $Chassis $Card $Port + + protocol config -ethernetType EthernetII + protocol config -name ipV4 + + stream config -sa $SourceMAC + stream config -da $DestinationMAC + stream config -name IMIX_Stream + stream config -framesize $currentFrameLength + if {$looper < $NumberOfPackets} { + stream config -dma advance + } else { + stream config -dma gotoFirst + } + stream config -numFrames 1 + stream config -gapUnit gapNanoSeconds + stream config -enableIbg false + stream config -enableIsg true + stream config -isg $InterStreamGap + if {[string match $enable_latency "true"]} { + stream config -enableTimestamp true + } + stream config -patternType repeat + stream config -dataPattern xAAAA + stream set $Chassis $Card $Port $looper + stream write $Chassis $Card $Port $looper + if {[string match $enable_latency "true"]} { + #Enable TimeStamps for latency measurements + # - using same groupID for all streams + packetGroup setDefault + packetGroup config -insertSignature true + packetGroup config -groupId 1 + packetGroup setTx $Chassis $Card $Port $looper + } + } +} + + +###################################################################### + +procDescr vtmsIxiaUtils::IXIA_Update_IPG_MyMIX_GE { + + Description: + This procedure changes the IPG for each packet in an IMIX + packet distribution on a GE port that was previously configured using + IXIA_Create_MyMIX_GE + + The required send rate is usally calculated in a script based on the + average datagram length in the MyMIX distribution + + Usage: + IXIA_Update_IPG_MyMIX_GE port -sendPps \ + -MyMIX + + Returns: Nothing +} + +proc vtmsIxiaUtils::IXIA_Update_IPG_MyMIX_GE {IXIA_Port args} { + + #SendPPS + if {[lsearch $args -sendPps] != -1} { + set variable_position [lsearch $args -sendPps] + set SendPPS [lindex $args [expr $variable_position +1]] + } + + #MyMIX - A list of packet sizes to be configured + if {[lsearch $args -MyMIX] != -1} { + set variable_position [lsearch $args -MyMIX] + set MyMIX_Packet_Lengths [lindex $args [expr $variable_position +1]] + } else { + error "You must pass a packet distribution" + } + + + set Chassis [lindex $IXIA_Port 0] + set Card [lindex $IXIA_Port 1] + set Port [lindex $IXIA_Port 2] + + #Need to calculate the Inter Stream Gap for IMIX Traffic + set AvgMyMIXDatagramSize [get_avg_mymix_length $MyMIX_Packet_Lengths] + + set NumberOfStreams [llength $MyMIX_Packet_Lengths] + + #Knowing how many pps translate this to GE bps (note on GE it takes 1 nS to + #transmit 1 bit. + #For some reason with IMIX calculation are not acheiving the rates I desire + #The 60 in the equation below is a penalty to make things work properly + #This effectively decreases the IPG on IXIA - seems to make everything work + #as expected. + #The value 60 was achieved through experimentation + # + #Also note that with IMIX IXIA can't send more than 83% linerate on IXIA + #Removing 60 bye penalty doesn't get you beyond 83% + + set GESendBPS [expr $SendPPS * ($AvgMyMIXDatagramSize + 38 + 60) * 8] + + #Calculate the GE Gaps (ie time not being used by above + set GETotalGap [expr 1000000000.0 - $GESendBPS] + + #Need to avoid /0 errors when a stream has 0 percent load + if {$SendPPS == 0 } { + set SendPPS .001 + } + + #Inter Packet Gap + set IPG [expr $GETotalGap / $SendPPS] + + for {set StreamID 1} {$StreamID <= $NumberOfStreams} {incr StreamID} { + stream get $Chassis $Card $Port $StreamID + stream config -isg $IPG + stream set $Chassis $Card $Port $StreamID + stream write $Chassis $Card $Port $StreamID + } +} + +###################################################################### + +procDescr vtmsIxiaUtils::ixia_measure_rates { + + Author: Michael Fingleton + Date: May 2005 + + Usage: + ixia_measure_rates [-tx_ports <{list of tx ports}>] \ + [-per_tx_port_labels <{list of tx label counts}>] \ + [-rx_ports <{list of rx ports}>] \ + [-rx_port_encaps <{list of rx port encaps}>] \ + [-per_rx_port_labels <{list of rx label counts}>] \ + [-iut_encaps ] \ + [-iut_crc_len ] \ + [-iut_num_labels ] \ + [-measure_interval ] \ + [-statgroup_exists] \ + [-atm_imix] + + Example: + set procReturned [ ixia_measure_rates \ + -tx_ports {{1 12 1} {1 16 1}} \ + -per_tx_port_labels {3 0} \ + -rx_ports {{1 12 2} {1 16 1}} \ + -rx_port_encaps {hdlc dot1q} \ + -per_rx_port_labels {0 1} \ + -iut_encaps dot1q \ + -measure_interval 7 ] + + Description / Arguments: + + -tx_ports : List of ports on which we will measure / calculate tx rates + + -per_tx_port_labels: If any of the tx ports have MPLS labels you need + to provide a count of the number of labels being + transmitted on EVERY port. + If no ports are transmitting with labels you just + ommit this option. + On the tx side I detect from Ixia if labels are + being transmitted but can't get read the number of + labels. If labels are being transmitted and you fail + to provide details an error will result. + + -rx_ports : List of ports on which we will measure / calculate rx rates + + -rx_encaps : List of encaps for each of the rx ports. + This list must be a one to one mapping to the rx_ports list. + The known encaps are listed below. + Rx encaps defaults to arpa for ethernet type interfaces. + On the tx side I can read the tx encaps from Ixia - not + possible on the rx side which means you must specify the + rx encaps if it's not hdlc / arpa. + + -per_rx_port_labels: If any of the tx ports have MPLS labels you need + to provide a count of the number of labels expected + to be received on EVERY port. + If no ports are transmitting with labels you just + ommit this option. + Unlike the tx side there is no sanity checking. + + + -iut_encaps: If specified calculations will be done to give rate values + as would have been seen on the interface under test. + Example: + Ixia_GE--Router--HDLC--Router--Ixia_GE + iut_encaps would be set to hdlc + + + -iut_crc_len: Defaults to 2 for if the iut_encaps is hdlc, ppp or fr + and to 4 if the iut_encaps is arpa or dot1q. + Default values can be overwritten by setting this option + + -iut_num_labels: If you expect labels on the link under test you + should pass the number of labels here. Defaults to 0 + + + -measure_interval : If specified the tx and rx rates are calculated over + this interval. + If not specified Ixia rate counters are used. + The Ixia rate counters are calculated over a very + short interval (eg 400mS on GE) and are not useful + when measuring very low rates. + + -statgroup_exists : When measuring rates we want to grab all the desired + stats in one shot. If this flag is set we will assume + all ports in the tx_ports and rx_ports lists are + already in a stats group - i.e. done once in script + rather than each time this proc is called. + + -datagram_length: When calculating throughput for atm interfaces we need + the datagram length to determine how much cell tax needs + to be included when calculating rates. + + -tx_datagram_list / rx_datagram_list: + This option is used when sending imix traffic over atm + interfaces. In this scenario each packet size is subject + to a different amount of cell tax. We need to know + how many packet of each imix size were received so we + can calculate rates on IUT. + This proc assumed true Cisco IMIX created with the procs + in this library. It assumes 46 byte datagrams are marked + with precedence 1, 552 byte datagrams are marked with + precedence 2 and 1500 byte datagrams are marked with + precedence 3. + Proc will also assume receiving port is in QOS_Stats mode + when measuring imix throughput for ATM interfaces. + In this mode we will get only packet stats (no byte stats) + but will get packet stats per precedence value thus + allowing us to calculate throughput at IUT. + The reason for a list is that in PQ type tests PQ traffic + may be fixed length and background traffic may be imix. + If you use atm you must supply values (numeric or 'imix') + for each sending / receiving port + + + Notes:- + - Proc assumes that ports are already owned by script / we already have + a session with the ixia + + - rx_ports & tx_ports are both optional but one or the other must + be passed + + - An interface under test (IUT) need not exist - proc can be used to + just measure tx / rx rates on ixia ports. + + - If an ixia port is transmitting and receiving it should appear in both + tx_ports and rx_ports lists + + - If iut_encaps is atm (aal5snap|aal5nlpid) and traffic type is imix + then receiving port must be in qos_stats mode - otherwise we assume + normal stats mode + + + + Meaning of Results Returned (Normal Interfaces): + + When specifying traffic rates in bps there are numerous ways people use + to specify rates. + The goal here is to return send and receive rates in all the usable formats + + To clarrify what each of the returned results really means refer to the + diagram below which uses ethernet/arpa as an example. + + + 14 X 4 20 14 Y 4 20 + +------+----------+---+/////////+------+---------------+---+///////// + | L2 | L3 |CRC| Per Pkt | L2 | L3 |CRC| Per Pkt + |Header| Datagram | |Overhead |Header| Datagram | |Overhead + +------+----------+---+/////////+------+---------------+---+///////// + + + |< l2_header_bps->| + |< l2_frame_bps------>| + |< l2_all_bps----------------->| + |< >| + l3_datagram_bps + + + l2_header_bps: This includes the L3 Datagram and L2 header (including MPLS + labels, NLPID etc..) + Generally Cisco QOS only counts the IP datagram and L2 header + as CRC and any inter packet overhead are stripped before the + packet is passed to IOS. + This rate is generally used when testing functionality of + policing / shaping / stats etc.. + + l2_frame_bps: This includes the L2 header, L3 datagram and L2 CRC - i.e. all + that constitutes a L2 frame. + This is what is reported by IXIA rate counters / some low + level interface counters. + Generally it's not used that often elsewhere.. + + l2_all_bps: This includes the entire frame (as in l2_frame_bps) plus any + mandatory interpacket overhead. + E.g. on ethernet there is a mandatory silence equal to the + time taken to transmit 12 bytes plus a mandatory 8 bytes + preamble. + E.g.2. on serial interfaces there is a mandatory hdlc flag + 1 byte long between each packet. + + This rate should be used when calculating what percentage of + a physical line is consumed by traffic (note - you also + need to account for static framing overheads) + VTMS implementations also count all overhead so this rate + should also be used when checking VTMS accuracy (eg bandwidth + guarantee or shaping accuracy with VTMS) + + l3_datagram_bps: This includes only the L3 datagram. This is useful because + it is the only thing that stays constant as you traverse + a network and add / strip different L2 encaps. + + + + + Meaning of Results Returned (ATM Interfaces): + + With ATM interfaces what's included will be quite different to other + interface types. We may look at the AAL5 pdu or we may look at + entire cell tax meaning we must include any padding & ATM cell headers. + + + Looking at AAL5 PDU + ------------------- + |-- ATM CPCS Trailer --| + + 2 or 8 X 1 1 2 4 + +----------+---------------+----+-----+------+------+ + | AAL5 | L3 | UU | CPI |Length| CRC | + | Header | Datagram | | | | | + +----------+---------------+----+-----+------+------+ + + + |< aal5_header_bps-------->| + |< aal5_pdu_no_crc-------------------------->| + |< aal5_pdu----------------------------------------->| + |< >| + l3_datagram_bps + + + + Looking at Cell Tax + ------------------- + + In this case we take the complete AAL5 PDU, calculate how many ATM cells + are required to carry this and include the padding & 5 bytes ATM header + per cell in throughput. + + +---+-------+---+-------+---+-------+---+-------+ + | 5 | 48 | 5 | 48 | 5 | 48 | 5 | 48 | + +---+-------+---+-------+---+-------+---+-------+ + ATM CELL ATM CELL ATM CELL ATM CELL + + |< cell_tax------------------------------------>| + + + + aal5_header_bps: This includes the L3 Datagram, the AAL5 header and MPLS + labels (if any). The AAL5 header length will depend on the + encapsulation - 2 bytes for AAL5_NLPID and 8 bytes for + AAL5_SNAP + Some platform use this for atm policer calculations + + aal5_pdu_bps: This includes the AAL5 header, L3 datagram and the 8 byte + AAL5 trailer. + Not sure if this is used on any platforms today + + aal_5_pdu_no_crc_bps: This is very similar to aal5_pdu_bps above except that + we do not include the 4 byte CRC in the CPCS trailer + This rate seems to be used for policing and scheduling + on pure IOS platforms (i.e. 7200) + + cell_tax_bps_bps: This rate includes all ATM overhead.i.e. We take the + AAL5 PDU and calculate how many cells will be required to + transport that PDU (allowing for padding we round up to + multiple of 48 bytes). We then add 5 bytes for each ATM + cell header. + This rate will always be used when calculating link + utilization or atm SAR shaping accuracy. It will + also be used for MQC QOS scheduling on some platforms. + + + l3_datagram_bps: This includes only the L3 datagram. This is useful because + it is the only thing that stays constant as you traverse + a network and add / strip different L2 encaps. + + + Returns a keyed list with structure as folows: + + iut + crc_bytes + l2_header_len + inter_frame_overhead + mpls_label_bytes + tx_port + $chassis_$card_$port + chassis + card + port + port_type_name + port_mode + port_mode_name + crc_bytes + l2_header_len + inter_frame_overhead + mpls_label_bytes + l2_frame_bytes_per_sec + pps + l2_frame_bps + l3_datagram_bps + l2_header_bps + l2_all_bps + iut + l2_frame_bps + l3_datagram_bps + l2_header_bps + l2_all_bps + aal5_header_bps + aal5_pdu_bps + aal5_pdu_no_crc_bps + cell_tax_bps + rx_port + $chassis_$card_$port + chassis + card + port + port_type_name + port_mode + port_mode_name + crc_bytes + l2_header_len + inter_frame_overhead + mpls_label_bytes + l2_frame_bytes_per_sec + pps + stat1_pps + stat2_pps + l2_frame_bps + l3_datagram_bps + l2_header_bps + l2_all_bps + iut + l2_frame_bps + l3_datagram_bps + l2_header_bps + l2_all_bps + aal5_header_bps + aal5_pdu_bps + aal5_pdu_no_crc_bps + cell_tax_bps + tx_aggregate + pps + l3_datagram_bps + iut + l2_frame_bps + l3_datagram_bps + l2_header_bps + l2_all_bps + aal5_header_bps + aal5_pdu_bps + aal5_pdu_no_crc_bps + cell_tax_bps + rx_aggregate + pps + l3_datagram_bps + iut + l2_frame_bps + l3_datagram_bps + l2_header_bps + l2_all_bps + aal5_header_bps + aal5_pdu_bps + aal5_pdu_no_crc_bps + cell_tax_bps + + Notes on returned values: + + - some of the returned values are not necessarily that useful to + the caller but rather were used internally within the proc and are + returned to allow sanity checking of results. + - Only l2_XX or aal5_XX/cell_tax values will be returned for iut + bps rates - only one or the other will make sense depending on + type of IUT. + +} + + + +proc vtmsIxiaUtils::ixia_measure_rates {args} { + + # optional_args + set opt_args { + -tx_ports SHIFT + -per_tx_port_labels NUMERIC + -rx_ports SHIFT + -rx_port_encaps CHOICES arpa dot1q hdlc ppp fr + -per_rx_port_labels NUMERIC + -iut_encaps CHOICES arpa dot1q hdlc ppp fr aal5snap aal5mux + -iut_crc_len NUMERIC + -iut_num_labels RANGE 0-4 + DEFAULT 0 + -measure_interval RANGE 5-300 + -statgroup_exists FLAG + -tx_datagram_list SHIFT + -rx_datagram_list SHIFT + -tgen_app CHOICES IxExplorer IxNetwork + DEFAULT IxNetwork + } + + parse_dashed_args -args $args -optional_args $opt_args + + #limit output to 2 decimal places + global mp_precision + set original_mp_precision $mp_precision + set mp_precision 2 + + #Sanity checking of passed values + #1. Either tx_ports OR rx_ports OR both must exist + if { (![info exists tx_ports]) && (![info exists rx_ports])} { + error "You must specify tx_ports or rx_ports when calling\ + ixia_measure_rates" + } + #2. If per_tx_port_labels exists it must be a list the same length as the + # tx_ports list + if {[info exists per_tx_port_labels]} { + if {[llength $per_tx_port_labels] != [llength $tx_ports]} { + error "If you pass tx port label info to ixia_measure_rates you\ + \nmust pass a value for each port in the tx_ports list" + } + } + #3. If per_rx_port_labels exists it must be a list the same length as the + # rx_ports list + if {[info exists per_rx_port_labels]} { + if {[llength $per_rx_port_labels] != [llength $rx_ports]} { + error "If you pass rx port label info to ixia_measure_rates you\ + \nmust pass a value for each port in the rx_ports list" + } + } + #4. If rx_port_encaps exists it must be a list the same length as the + # rx_ports list + if {[info exists rx_port_encaps]} { + if {[llength $rx_port_encaps] != [llength $rx_ports]} { + error "If you pass rx port encaps info to ixia_measure_rates you\ + \nmust pass a value for each port in the rx_ports list" + } + } + + #Determine if atm mode or normal mode + if {([info exists iut_encaps]) && ([regexp {aal5} $iut_encaps])} { + set int_mode atm + } else { + set int_mode normal + } + + #if atm you must supply datagram length per tx and rx port + if {$int_mode == "atm"} { + if {(![info exists tx_datagram_list]) && ([info exists tx_ports])} { + error "If using atm you must provide tx_datagram_list" + } + + if {[info exists tx_ports] && \ + ([llength $tx_datagram_list] != [llength $tx_ports])} { + + error "tx_datagram_list must contain a list of datagram length and\ + the number of entries must match the number of tx ports" + } + + if {(![info exists rx_datagram_list]) && ([info exists rx_ports])} { + error "If using atm you must provide rx_datagram_list" + } + + if {[info exists rx_ports] && \ + ([llength $rx_datagram_list] != [llength $rx_ports])} { + error "rx_datagram_list must contain a list of datagram length and\ + the number of entries must match the number of rx ports" + } + } ;#end if $int_mode == atm + + #iut_encaps may not exist (ie we only want IXIA tx/tx rates) + #If it does we need to figure out IUT encaps length / transmission overhead + if {[info exists iut_encaps]} { + #Figure out the IUT L2 header length from the encaps / number of flags + #Also default the IUT CRC length if it's not set + switch $iut_encaps { + arpa { + set iut_l2_header_len 14 + if {![info exists iut_crc_len]} { + set iut_crc_len 4 + } + set iut_inter_frame_overhead 20 + } + dot1q { + set iut_l2_header_len 18 + if {![info exists iut_crc_len]} { + set iut_crc_len 4 + } + set iut_inter_frame_overhead 20 + } + hdlc { + set iut_l2_header_len 4 + if {![info exists iut_crc_len]} { + set iut_crc_len 2 + } + set iut_inter_frame_overhead 1 + } + ppp { + set iut_l2_header_len 4 + if {![info exists iut_crc_len]} { + set iut_crc_len 2 + } + set iut_inter_frame_overhead 1 + } + fr { + set iut_l2_header_len 4 + if {![info exists iut_crc_len]} { + set iut_crc_len 2 + } + set iut_inter_frame_overhead 1 + } + aal5snap { + set aal_header_len 8 + set aal_trailer_len 8 + } + aal5nlpid { + set aal_header_len 2 + set aal_trailer_len 8 + } + default { + error "iut encaps passed to ixia_measure_rates is not supported" + } + } ;# end switch iut_encaps + + #Add interface under test info to keyed list + if {$int_mode == "normal"} { + keylset ret_list iut.crc_bytes $iut_crc_len + keylset ret_list iut.l2_header_len $iut_l2_header_len + keylset ret_list iut.inter_frame_overhead $iut_inter_frame_overhead + } + if {$int_mode == "atm"} { + keylset ret_list iut.aal_header_len $aal_header_len + keylset ret_list iut.aal_trailer_len $aal_trailer_len + } + keylset ret_list iut.mpls_label_bytes [expr $iut_num_labels * 4] + + } ;#End if info exists iut_encaps + + + + #Figure out the encaps length / crc length and label stack for the tx ports + #Note - user may only be looking for rx rates so need to check if $tx_ports + if {$tgen_app == "IxExplorer"} { + + if {[info exists tx_ports]} { + #Format will be like {1 5 1} - extract card / port / chassis + set tx_ports_list_offset 0 + + foreach ixia_port $tx_ports { + if {![regexp {(\d+) +(\d+) +(\d+)} $ixia_port \ + - chassis card port]} { + error "tx_port format should be like {1 5 1} \ + - was passed $ixia_port" + } + keylset ret_list tx_port.$chassis\_$card\_$port.chassis $chassis + keylset ret_list tx_port.$chassis\_$card\_$port.card $card + keylset ret_list tx_port.$chassis\_$card\_$port.port $port + + #Figure out what kind of card we are.. + port get $chassis $card $port + set current_int_type_name [port cget -typeName] + set current_port_mode [port cget -portMode] + + + keylset ret_list tx_port.$chassis\_$card\_$port.port_type_name \ + $current_int_type_name + keylset ret_list tx_port.$chassis\_$card\_$port.port_mode \ + $current_port_mode + + + #Calcualte Overheads for POS (pos => portMode = 0) + if {$current_port_mode == 0} { + keylset ret_list \ + tx_port.$chassis\_$card\_$port.port_mode_name pos + #CRC - 2 or 4 Bytes + sonet get $chassis $card $port + if {[sonet cget -txCrc]} { + keylset ret_list tx_port.$chassis\_$card\_$port.crc_bytes 4 + } else { + keylset ret_list tx_port.$chassis\_$card\_$port.crc_bytes 2 + } + #Assume 4 Bytes L2 HEader (HDLC,PPP or FR the same) + keylset \ + ret_list tx_port.$chassis\_$card\_$port.l2_header_len 4 + #assume 1 hdlc flag for per pkt inter frame overhead + keylset ret_list \ + tx_port.$chassis\_$card\_$port.inter_frame_overhead 1 + + } + + + #Calculate Overheads for Ethernet + #(GE => portMode = 1, 10GE => portMode = 4) + if {($current_port_mode == 1) || ($current_port_mode == 4)} { + keylset ret_list \ + tx_port.$chassis\_$card\_$port.port_mode_name ethernet + #CRC - 4 Bytes + keylset ret_list tx_port.$chassis\_$card\_$port.crc_bytes 4 + + #L2 Header - depends on whether vlan tag or not + stream get $chassis $card $port 1 + if {[protocol cget -enable802dot1qTag]} { + keylset \ + ret_list tx_port.$chassis\_$card\_$port.l2_header_len 18 + } else { + keylset \ + ret_list tx_port.$chassis\_$card\_$port.l2_header_len 14 + } + #assume 20 bytes for per pkt inter frame overhead + keylset ret_list \ + tx_port.$chassis\_$card\_$port.inter_frame_overhead 20 + } + + #Check for MPLS Tags on Tx Pkts (same logic all port types) + stream get $chassis $card $port 1 + #If MPLS is enabled but we haven't been told about labels error + if {([protocol cget -enableMPLS]) \ + && (![info exists per_tx_port_labels])} { + error "MPLS is enabled on tx port $card\/$port \ + and you haven't passed any label info" + } + + if {[protocol cget -enableMPLS]} { + #How many labels - cant get this from IXIA + #Need to figure it out from per_tx_port_labes list + set num_labels \ + [lindex $per_tx_port_labels $tx_ports_list_offset] + if {$num_labels == 0} { + error "You passed ixia_measure_rates 0 labels for IXIA\ + port $card\/$port \ + \nbut this port has MPLS configured" + } + if {$num_labels > 4} { + error "You passed ixia_measure_rates $num_labels labels\ + for IXIA tx port $card\/$port \ + \nbut this isn't possible. Remember this is the\ + \nnumber of labels - not the bytes consumed by\ + labels" + } + keylset ret_list \ + tx_port.$chassis\_$card\_$port.mpls_label_bytes \ + [expr $num_labels * 4] + } else { + keylset \ + ret_list tx_port.$chassis\_$card\_$port.mpls_label_bytes 0 + } + + #if atm_mode put the tx_datagram_len into keyed list + if {$int_mode == "atm"} { + set tx_datagram_len [lindex $tx_datagram_list \ + $tx_ports_list_offset] + + keylset ret_list tx_port.$chassis\_$card\_$port.tx_datagram_len\ + $tx_datagram_len + } + + incr tx_ports_list_offset + + } ;#End foreach ixia_port $tx_ports + } ;#End if info exists tx_ports + } + if {$tgen_app == "IxNetwork"} { + if {[info exists tx_ports]} { + #Format will be like {1 5 1} - extract card / port / chassis + set tx_ports_list_offset 0 + + foreach ixia_port $tx_ports { + if {![regexp {(\d+) +(\d+) +(\d+)} $ixia_port \ + - chassis card port]} { + error "tx_port format should be like {1 5 1} \ + - was passed $ixia_port" + } + keylset ret_list tx_port.$chassis\_$card\_$port.chassis $chassis + keylset ret_list tx_port.$chassis\_$card\_$port.card $card + keylset ret_list tx_port.$chassis\_$card\_$port.port $port + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$card\/port:$port" $vportObj match]} { + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHdl/capture -hardwareEnabled true " + set vportHandle $vportHdl + } + } + #Figure out what kind of card we are.. + #port get $chassis $card $port + #set current_int_type_name [port cget -typeName] + #set current_port_mode [port cget -portMode] + set current_int_type_name [interp eval $::ixia::TclInterp " ixNet getA $vportHandle -actualSpeed "] + if {$current_int_type_name == 1000} { + set current_port_mode 1 + } + if {$current_int_type_name == 10000} { + set current_port_mode 4 + } + + keylset ret_list tx_port.$chassis\_$card\_$port.port_type_name \ + $current_int_type_name + keylset ret_list tx_port.$chassis\_$card\_$port.port_mode \ + $current_port_mode + + #Removed Calcualte Overheads for POS (pos => portMode = 0) (Not support for IxNetwork) + + #Calculate Overheads for Ethernet + #(GE => portMode = 1, 10GE => portMode = 4) + if {($current_port_mode == 1) || ($current_port_mode == 4)} { + keylset ret_list \ + tx_port.$chassis\_$card\_$port.port_mode_name ethernet + #CRC - 4 Bytes + keylset ret_list tx_port.$chassis\_$card\_$port.crc_bytes 4 + + #L2 Header - depends on whether vlan tag or not + stream get $chassis $card $port 1 + if {[protocol cget -enable802dot1qTag]} { + keylset \ + ret_list tx_port.$chassis\_$card\_$port.l2_header_len 18 + } else { + keylset \ + ret_list tx_port.$chassis\_$card\_$port.l2_header_len 14 + } + #assume 20 bytes for per pkt inter frame overhead + keylset ret_list \ + tx_port.$chassis\_$card\_$port.inter_frame_overhead 20 + } + + #Check for MPLS Tags on Tx Pkts (same logic all port types) + stream get $chassis $card $port 1 + #If MPLS is enabled but we haven't been told about labels error + set enableMpls [interp eval $::ixia::TclInterp " ixNet getA $vportHandle/protocols/mplsOam -enabled "] + if {($enableMpls) \ + && (![info exists per_tx_port_labels])} { + error "MPLS is enabled on tx port $card\/$port \ + and you haven't passed any label info" + } + + if {$enableMpls} { + #How many labels - cant get this from IXIA + #Need to figure it out from per_tx_port_labes list + set num_labels \ + [lindex $per_tx_port_labels $tx_ports_list_offset] + if {$num_labels == 0} { + error "You passed ixia_measure_rates 0 labels for IXIA\ + port $card\/$port \ + \nbut this port has MPLS configured" + } + if {$num_labels > 4} { + error "You passed ixia_measure_rates $num_labels labels\ + for IXIA tx port $card\/$port \ + \nbut this isn't possible. Remember this is the\ + \nnumber of labels - not the bytes consumed by\ + labels" + } + keylset ret_list \ + tx_port.$chassis\_$card\_$port.mpls_label_bytes \ + [expr $num_labels * 4] + } else { + keylset \ + ret_list tx_port.$chassis\_$card\_$port.mpls_label_bytes 0 + } + + #if atm_mode put the tx_datagram_len into keyed list + if {$int_mode == "atm"} { + set tx_datagram_len [lindex $tx_datagram_list \ + $tx_ports_list_offset] + + keylset ret_list tx_port.$chassis\_$card\_$port.tx_datagram_len\ + $tx_datagram_len + } + + incr tx_ports_list_offset + + } ;#End foreach ixia_port $tx_ports + } ;#End if info exists tx_ports + } + #Figure out the encaps length / crc length and label stack for the rx ports + #Note - user may only be looking for tx rates so need to check if $rx_ports + if {$tgen_app == "IxExplorer"} { + if {[info exists rx_ports]} { + #Format will be like {1 5 1} - extract card / port / chassis + set rx_ports_list_offset 0 + + foreach ixia_port $rx_ports { + if {![regexp {(\d+) +(\d+) +(\d+)} $ixia_port \ + - chassis card port]} { + error "rx_port format should be like {1 5 1} \ + - was passed $ixia_port" + } + keylset ret_list rx_port.$chassis\_$card\_$port.chassis $chassis + keylset ret_list rx_port.$chassis\_$card\_$port.card $card + keylset ret_list rx_port.$chassis\_$card\_$port.port $port + + #Figure out what kind of card we are.. + port get $chassis $card $port + set current_int_type_name [port cget -typeName] + set current_port_mode [port cget -portMode] + + #see if we're in packetGroup mode or portCapture mode + set current_port_rx_mode [port cget -receiveMode] + + #See if capture or packet group mode (may not need this) + if {$current_port_rx_mode == 1} { + set current_port_rx_mode portCapture + } + if {$current_port_rx_mode == 2} { + set current_port_rx_mode portPacketGroup + } + + #Get the stats mode for rx port + stat get statMode $chassis $card $port + set current_stats_mode [stat cget -mode] + + #puts "Current Stats Mode: $current_stats_mode" + if {$current_stats_mode == 0} { + set current_stats_mode normal + } + if {$current_stats_mode == 1} { + set current_stats_mode statQos + } + + keylset ret_list rx_port.$chassis\_$card\_$port.port_type_name \ + $current_int_type_name + keylset ret_list rx_port.$chassis\_$card\_$port.port_mode \ + $current_port_mode + keylset ret_list rx_port.$chassis\_$card\_$port.port_rx_mode \ + $current_port_rx_mode + keylset ret_list rx_port.$chassis\_$card\_$port.port_stats_mode \ + $current_stats_mode + + + #Calcualte Overheads for POS (pos => portMode = 0) + if {$current_port_mode == 0} { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.port_mode_name pos + #CRC - 2 or 4 Bytes + sonet get $chassis $card $port + if {[sonet cget -rxCrc]} { + keylset ret_list rx_port.$chassis\_$card\_$port.crc_bytes 4 + } else { + keylset ret_list rx_port.$chassis\_$card\_$port.crc_bytes 2 + } + #Assume 4 Bytes L2 HEader (HDLC,PPP or FR the same) + keylset \ + ret_list rx_port.$chassis\_$card\_$port.l2_header_len 4 + #assume 1 hdlc flag for per pkt inter frame overhead + keylset ret_list \ + rx_port.$chassis\_$card\_$port.inter_frame_overhead 1 + + } + + + #Calculate Overheads for Ethernet (GE portMode = 1 , TE portMode=4) + if {($current_port_mode == 1) ||($current_port_mode == 4) } { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.port_mode_name ethernet + #CRC - 4 Bytes + keylset ret_list rx_port.$chassis\_$card\_$port.crc_bytes 4 + + #L2 header depends on whether vlan tag or not + #If no rx_port_encaps is passed we'll asume arpa + if {[info exists rx_port_encaps]} { + set current_encaps \ + [lindex $rx_port_encaps $rx_ports_list_offset] + } else { + set current_encaps arpa + } + + switch $current_encaps { + arpa { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.l2_header_len 14 + } + dot1q { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.l2_header_len 18 + } + default { + error "IXIA port $card\/$port is of type ethernet but\ + you passed unsupported $current_encaps as the encaps" + } + } ;#end switch $current_encaps + + + #assume 20 bytes for per pkt inter frame overhead + keylset ret_list \ + rx_port.$chassis\_$card\_$port.inter_frame_overhead 20 + } + + #Check for MPLS Tags on Rx Pkts (same logic all port types) + if {[info exists per_rx_port_labels]} { + set num_labels \ + [lindex $per_rx_port_labels $rx_ports_list_offset] + if {$num_labels > 4} { + error "You passed ixia_measure_rates $num_labels labels\ + for IXIA rx port $card\/$port \ + \nbut this isn't possible. Remember this is the\ + \nnumber of labels - not the bytes consumed by\ + labels" + } + keylset ret_list \ + rx_port.$chassis\_$card\_$port.mpls_label_bytes \ + [expr $num_labels * 4] + } else { + keylset \ + ret_list rx_port.$chassis\_$card\_$port.mpls_label_bytes 0 + } + + #if atm_mode put the rx_datagram_len into keyed list + if {$int_mode == "atm"} { + set rx_datagram_len [lindex $rx_datagram_list \ + $rx_ports_list_offset] + + keylset ret_list rx_port.$chassis\_$card\_$port.rx_datagram_len\ + $rx_datagram_len + } + + incr rx_ports_list_offset + + } ;#End foreach ixia_port $rx_ports + } ;#End if info exists rx_ports + } + if {$tgen_app == "IxNetwork"} { + if {[info exists rx_ports]} { + #Format will be like {1 5 1} - extract card / port / chassis + set rx_ports_list_offset 0 + + foreach ixia_port $rx_ports { + if {![regexp {(\d+) +(\d+) +(\d+)} $ixia_port \ + - chassis card port]} { + error "rx_port format should be like {1 5 1} \ + - was passed $ixia_port" + } + keylset ret_list rx_port.$chassis\_$card\_$port.chassis $chassis + keylset ret_list rx_port.$chassis\_$card\_$port.card $card + keylset ret_list rx_port.$chassis\_$card\_$port.port $port + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$card\/port:$port" $vportObj match]} { + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHdl/capture -hardwareEnabled true " + set vportHandle $vportHdl + } + } + #Figure out what kind of card we are.. + #port get $chassis $card $port + #set current_int_type_name [port cget -typeName] + #set current_port_mode [port cget -portMode] + #see if we're in packetGroup mode or portCapture mode + set captureMode [interp eval $::ixia::TclInterp " ixNet getA $vportHandle -rxMode "] + if {$captureMode == "capture"} { + set current_port_rx_mode 1 + } + if {$captureMode == "captureAndMeasure"} { + set current_port_rx_mode 2 + } + + #set current_port_rx_mode [port cget -receiveMode] + + #See if capture or packet group mode (may not need this) + if {$current_port_rx_mode == 1} { + set current_port_rx_mode portCapture + } + if {$current_port_rx_mode == 2} { + set current_port_rx_mode portPacketGroup + } + + #Get the stats mode for rx port + #stat get statMode $chassis $card $port + #set current_stats_mode [stat cget -mode] + + #puts "Current Stats Mode: $current_stats_mode" + #if {$current_stats_mode == 0} { + # set current_stats_mode normal + #} + #if {$current_stats_mode == 1} { + # set current_stats_mode statQos + #} + + keylset ret_list rx_port.$chassis\_$card\_$port.port_type_name \ + $current_int_type_name + keylset ret_list rx_port.$chassis\_$card\_$port.port_mode \ + $current_port_mode + keylset ret_list rx_port.$chassis\_$card\_$port.port_rx_mode \ + $current_port_rx_mode + keylset ret_list rx_port.$chassis\_$card\_$port.port_stats_mode \ + $current_stats_mode + + + #Removed "Calcualte Overheads for POS (pos => portMode = 0)" Not support for IxNetwork + + set current_int_type_name [interp eval $::ixia::TclInterp " ixNet getA $vportHandle -actualSpeed "] + if {$current_int_type_name == 1000} { + set current_port_mode 1 + } + if {$current_int_type_name == 10000} { + set current_port_mode 4 + } + #Calculate Overheads for Ethernet (GE portMode = 1 , TE portMode=4) + if {($current_port_mode == 1) ||($current_port_mode == 4) } { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.port_mode_name ethernet + #CRC - 4 Bytes + keylset ret_list rx_port.$chassis\_$card\_$port.crc_bytes 4 + + #L2 header depends on whether vlan tag or not + #If no rx_port_encaps is passed we'll asume arpa + if {[info exists rx_port_encaps]} { + set current_encaps \ + [lindex $rx_port_encaps $rx_ports_list_offset] + } else { + set current_encaps arpa + } + + switch $current_encaps { + arpa { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.l2_header_len 14 + } + dot1q { + keylset ret_list \ + rx_port.$chassis\_$card\_$port.l2_header_len 18 + } + default { + error "IXIA port $card\/$port is of type ethernet but\ + you passed unsupported $current_encaps as the encaps" + } + } ;#end switch $current_encaps + + + #assume 20 bytes for per pkt inter frame overhead + keylset ret_list \ + rx_port.$chassis\_$card\_$port.inter_frame_overhead 20 + } + + #Check for MPLS Tags on Rx Pkts (same logic all port types) + if {[info exists per_rx_port_labels]} { + set num_labels \ + [lindex $per_rx_port_labels $rx_ports_list_offset] + if {$num_labels > 4} { + error "You passed ixia_measure_rates $num_labels labels\ + for IXIA rx port $card\/$port \ + \nbut this isn't possible. Remember this is the\ + \nnumber of labels - not the bytes consumed by\ + labels" + } + keylset ret_list \ + rx_port.$chassis\_$card\_$port.mpls_label_bytes \ + [expr $num_labels * 4] + } else { + keylset \ + ret_list rx_port.$chassis\_$card\_$port.mpls_label_bytes 0 + } + + #if atm_mode put the rx_datagram_len into keyed list + if {$int_mode == "atm"} { + set rx_datagram_len [lindex $rx_datagram_list \ + $rx_ports_list_offset] + + keylset ret_list rx_port.$chassis\_$card\_$port.rx_datagram_len\ + $rx_datagram_len + } + + incr rx_ports_list_offset + + } ;#End foreach ixia_port $rx_ports + } ;#End if info exists rx_ports + } + + #Finally we get to the good stuff - start measuring what we need + + #Create a new statgroup if it doesn't already exist + if {![info exists statgroup_exists]} { + + statGroup setDefault + + if {[info exists tx_ports]} { + set tx_port_keys [keylkeys ret_list tx_port] + foreach tx_port_key $tx_port_keys { + statGroup add [keylget ret_list tx_port.$tx_port_key.chassis] \ + [keylget ret_list tx_port.$tx_port_key.card] \ + [keylget ret_list tx_port.$tx_port_key.port] + } + } + + if {[info exists rx_ports]} { + set rx_port_keys [keylkeys ret_list rx_port] + foreach rx_port_key $rx_port_keys { + statGroup add [keylget ret_list rx_port.$rx_port_key.chassis] \ + [keylget ret_list rx_port.$rx_port_key.card] \ + [keylget ret_list rx_port.$rx_port_key.port] + } + } + #Sleep 2 secs to allow statGroup creation + after 2000 + } + + + #Read rates from IXIA + + #Use ixia rate counters if no test interval set + if {$tgen_app == "IxExplorer"} { + if {![info exists measure_interval]} { + statList setDefault + statGroup get + + #If Tx ports get the tx port rates + if {[info exists tx_ports]} { + set tx_port_keys [keylkeys ret_list tx_port] + foreach tx_port_key $tx_port_keys { + set chassis [keylget ret_list tx_port.$tx_port_key.chassis] + set card [keylget ret_list tx_port.$tx_port_key.card] + set port [keylget ret_list tx_port.$tx_port_key.port] + + statList getRate $chassis $card $port + + #Raw IXIA Results + set tx_bytes_per_sec [statList cget -bytesSent] + set tx_frames_per_sec [statList cget -framesSent] + + keylset ret_list \ + tx_port.$tx_port_key.l2_frame_bytes_per_sec $tx_bytes_per_sec + + keylset ret_list tx_port.$tx_port_key.pps $tx_frames_per_sec + } + } + + #If Rx ports get the rx port rates + if {[info exists rx_ports]} { + + set rx_port_keys [keylkeys ret_list rx_port] + + foreach rx_port_key $rx_port_keys { + set chassis [keylget ret_list rx_port.$rx_port_key.chassis] + set card [keylget ret_list rx_port.$rx_port_key.card] + set port [keylget ret_list rx_port.$rx_port_key.port] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + + statList getRate $chassis $card $port + + #Raw IXIA Results + + #If normal mode we have packet and byte stats + if {$stats_mode == "normal"} { + set rx_bytes_per_sec [statList cget -bytesReceived] + set rx_frames_per_sec [statList cget -framesReceived] + set stat1_pps [statList cget -userDefinedStat1] + set stat2_pps [statList cget -userDefinedStat2] + + keylset ret_list \ + rx_port.$rx_port_key.l2_frame_bytes_per_sec \ + $rx_bytes_per_sec + + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + + keylset ret_list rx_port.$rx_port_key.stat1_pps $stat1_pps + keylset ret_list rx_port.$rx_port_key.stat2_pps $stat2_pps + } + + #If statQos mode we only get packet stats but we do get per + #precedence value stats + if {$stats_mode == "statQos"} { + + set rx_frames_per_sec [statList cget -framesReceived] + set prec0_pps [statList cget -qualityOfService0] + set prec1_pps [statList cget -qualityOfService1] + set prec2_pps [statList cget -qualityOfService2] + set prec3_pps [statList cget -qualityOfService3] + set prec4_pps [statList cget -qualityOfService4] + set prec5_pps [statList cget -qualityOfService5] + set prec6_pps [statList cget -qualityOfService6] + set prec7_pps [statList cget -qualityOfService7] + + + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + keylset ret_list rx_port.$rx_port_key.prec0_pps $prec0_pps + keylset ret_list rx_port.$rx_port_key.prec1_pps $prec1_pps + keylset ret_list rx_port.$rx_port_key.prec2_pps $prec2_pps + keylset ret_list rx_port.$rx_port_key.prec3_pps $prec3_pps + keylset ret_list rx_port.$rx_port_key.prec4_pps $prec4_pps + keylset ret_list rx_port.$rx_port_key.prec5_pps $prec5_pps + keylset ret_list rx_port.$rx_port_key.prec6_pps $prec6_pps + keylset ret_list rx_port.$rx_port_key.prec7_pps $prec7_pps + } + + } ;#end foreach rx_port_key + } ;# end if info exists rx_ports + } ;# end if ![info exists measure_interval] + } + if {$tgen_app == "IxNetwork"} { + if {![info exists measure_interval]} { + #statList setDefault + #statGroup get + + #If Tx ports get the tx port rates + if {[info exists tx_ports]} { + set tx_port_keys [keylkeys ret_list tx_port] + foreach tx_port_key $tx_port_keys { + set chassis [keylget ret_list tx_port.$tx_port_key.chassis] + set card [keylget ret_list tx_port.$tx_port_key.card] + set port [keylget ret_list tx_port.$tx_port_key.port] + + #statList getRate $chassis $card $port + + #Raw IXIA Results + set port1 $chassis/$card/$port + set txStats [::ixia::traffic_stats -port_handle $port1] + #set tx_bytes_per_sec [statList cget -bytesSent] + set tx_bytes_per_sec [keylget txStats $port1.aggregate.tx.pkt_byte_count] + #set tx_frames_per_sec [statList cget -framesSent] + set tx_frames_per_sec [keylget txStats $port1.aggregate.tx.tx_aal5_scheduled_frames_count] + + keylset ret_list \ + tx_port.$tx_port_key.l2_frame_bytes_per_sec $tx_bytes_per_sec + + keylset ret_list tx_port.$tx_port_key.pps $tx_frames_per_sec + } + } + + #If Rx ports get the rx port rates + if {[info exists rx_ports]} { + + set rx_port_keys [keylkeys ret_list rx_port] + + foreach rx_port_key $rx_port_keys { + set chassis [keylget ret_list rx_port.$rx_port_key.chassis] + set card [keylget ret_list rx_port.$rx_port_key.card] + set port [keylget ret_list rx_port.$rx_port_key.port] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + #set stats_mode "normal" + + #statList getRate $chassis $card $port + + #Raw IXIA Results + set port2 $chassis/$card/$port + set rxStats [::ixia::traffic_stats -port_handle $port2] + #If normal mode we have packet and byte stats + if {$stats_mode == "normal"} { + #set rx_bytes_per_sec [statList cget -bytesReceived] + set rx_bytes_per_sec [keylget rxStats $port2.aggregate.rx.pkt_byte_count] + #set rx_frames_per_sec [statList cget -framesReceived] + set rx_frames_per_sec [keylget rxStats $port1.aggregate.rx.raw_pkt_count] + set stat1_pps [keylget rxStats $port1.aggregate.rx.uds1_frame_count] + set stat2_pps [keylget rxStats $port1.aggregate.rx.uds2_frame_count] + + keylset ret_list \ + rx_port.$rx_port_key.l2_frame_bytes_per_sec \ + $rx_bytes_per_sec + + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + + keylset ret_list rx_port.$rx_port_key.stat1_pps $stat1_pps + keylset ret_list rx_port.$rx_port_key.stat2_pps $stat2_pps + } + + #If statQos mode we only get packet stats but we do get per + #precedence value stats + if {$stats_mode == "statQos"} { + set rx_frames_per_sec [keylget rxStats $port1.aggregate.rx.raw_pkt_count] + #set rx_frames_per_sec [statList cget -framesReceived] + #set prec0_pps [statList cget -qualityOfService0] + #set prec1_pps [statList cget -qualityOfService1] + #set prec2_pps [statList cget -qualityOfService2] + #set prec3_pps [statList cget -qualityOfService3] + #set prec4_pps [statList cget -qualityOfService4] + #set prec5_pps [statList cget -qualityOfService5] + #set prec6_pps [statList cget -qualityOfService6] + #set prec7_pps [statList cget -qualityOfService7] + + + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + #keylset ret_list rx_port.$rx_port_key.prec0_pps $prec0_pps + #keylset ret_list rx_port.$rx_port_key.prec1_pps $prec1_pps + #keylset ret_list rx_port.$rx_port_key.prec2_pps $prec2_pps + #keylset ret_list rx_port.$rx_port_key.prec3_pps $prec3_pps + #keylset ret_list rx_port.$rx_port_key.prec4_pps $prec4_pps + #keylset ret_list rx_port.$rx_port_key.prec5_pps $prec5_pps + #keylset ret_list rx_port.$rx_port_key.prec6_pps $prec6_pps + #keylset ret_list rx_port.$rx_port_key.prec7_pps $prec7_pps + } + + } ;#end foreach rx_port_key + } ;# end if info exists rx_ports + } ;# end if ![info exists measure_interval] + } + + + + #Calculate our own rates if test interval is set + if {$tgen_app == "IxExplorer"} { + if {[info exists measure_interval]} { + statList setDefault + statGroup get + + #If Tx ports get the initial tx port values + if {[info exists tx_ports]} { + set tx_port_keys [keylkeys ret_list tx_port] + foreach tx_port_key $tx_port_keys { + set chassis [keylget ret_list tx_port.$tx_port_key.chassis] + set card [keylget ret_list tx_port.$tx_port_key.card] + set port [keylget ret_list tx_port.$tx_port_key.port] + + statList get $chassis $card $port + + #Raw IXIA Results + set initial_tx_bytes [statList cget -bytesSent] + set initial_tx_frames [statList cget -framesSent] + + keylset ret_list \ + tx_port.$tx_port_key.initial_tx_bytes $initial_tx_bytes + + keylset ret_list \ + tx_port.$tx_port_key.initial_tx_pkts $initial_tx_frames + } + } + + #If Rx ports get the initial rx port values + if {[info exists rx_ports]} { + set rx_port_keys [keylkeys ret_list rx_port] + foreach rx_port_key $rx_port_keys { + set chassis [keylget ret_list rx_port.$rx_port_key.chassis] + set card [keylget ret_list rx_port.$rx_port_key.card] + set port [keylget ret_list rx_port.$rx_port_key.port] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + statList get $chassis $card $port + + #Raw IXIA Results + + #If normal mode we have packet and byte stats + if {$stats_mode == "normal"} { + + set initial_rx_bytes [statList cget -bytesReceived] + set initial_rx_frames [statList cget -framesReceived] + set initial_stat1_pkts [statList cget -userDefinedStat1] + set initial_stat2_pkts [statList cget -userDefinedStat2] + + keylset ret_list \ + rx_port.$rx_port_key.initial_rx_bytes $initial_rx_bytes + + keylset ret_list \ + rx_port.$rx_port_key.initial_rx_pkts $initial_rx_frames + + keylset ret_list rx_port.$rx_port_key.initial_stat1_pkts \ + $initial_stat1_pkts + + keylset ret_list rx_port.$rx_port_key.initial_stat2_pkts \ + $initial_stat2_pkts + } + + #If statQos mode we only get packet stats but we do get per + #precedence value stats + if {$stats_mode == "statQos"} { + set initial_rx_frames [statList cget -framesReceived] + set initial_prec0_pkts [statList cget -qualityOfService0] + set initial_prec1_pkts [statList cget -qualityOfService1] + set initial_prec2_pkts [statList cget -qualityOfService2] + set initial_prec3_pkts [statList cget -qualityOfService3] + set initial_prec4_pkts [statList cget -qualityOfService4] + set initial_prec5_pkts [statList cget -qualityOfService5] + set initial_prec6_pkts [statList cget -qualityOfService6] + set initial_prec7_pkts [statList cget -qualityOfService7] + + keylset ret_list \ + rx_port.$rx_port_key.initial_rx_pkts $initial_rx_frames + keylset ret_list \ + rx_port.$rx_port_key.initial_prec0_pkts \ + $initial_prec0_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec1_pkts \ + $initial_prec1_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec2_pkts \ + $initial_prec2_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec3_pkts \ + $initial_prec3_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec4_pkts \ + $initial_prec4_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec5_pkts \ + $initial_prec5_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec6_pkts \ + $initial_prec6_pkts + keylset ret_list \ + rx_port.$rx_port_key.initial_prec7_pkts \ + $initial_prec7_pkts + } + } + } + + + + + #Sleep for the test interval + after [mpexpr $measure_interval * 1000] + + statList setDefault + statGroup get + + #If Tx ports get the final tx port values + if {[info exists tx_ports]} { + + set tx_port_keys [keylkeys ret_list tx_port] + + foreach tx_port_key $tx_port_keys { + + set chassis [keylget ret_list tx_port.$tx_port_key.chassis] + set card [keylget ret_list tx_port.$tx_port_key.card] + set port [keylget ret_list tx_port.$tx_port_key.port] + + statList get $chassis $card $port + + #Raw IXIA Results + set final_tx_bytes [statList cget -bytesSent] + set final_tx_frames [statList cget -framesSent] + + keylset ret_list \ + tx_port.$tx_port_key.final_tx_bytes $final_tx_bytes + + keylset ret_list \ + tx_port.$tx_port_key.final_tx_pkts $final_tx_frames + + #Calculate the rates + set total_tx_bytes [mpexpr $final_tx_bytes - \ + [keylget ret_list tx_port.$tx_port_key.initial_tx_bytes]] + + set total_tx_frames [mpexpr $final_tx_frames - \ + [keylget ret_list tx_port.$tx_port_key.initial_tx_pkts]] + + + set tx_bytes_per_sec \ + [mpexpr $total_tx_bytes / $measure_interval.0] + + set tx_frames_per_sec \ + [mpexpr $total_tx_frames / $measure_interval.0] + + keylset ret_list \ + tx_port.$tx_port_key.l2_frame_bytes_per_sec $tx_bytes_per_sec + + keylset ret_list tx_port.$tx_port_key.pps $tx_frames_per_sec + + } + } + + #If Rx ports get the final rx port values + if {[info exists rx_ports]} { + + set rx_port_keys [keylkeys ret_list rx_port] + + foreach rx_port_key $rx_port_keys { + + set chassis [keylget ret_list rx_port.$rx_port_key.chassis] + set card [keylget ret_list rx_port.$rx_port_key.card] + set port [keylget ret_list rx_port.$rx_port_key.port] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + statList get $chassis $card $port + + #If normal mode we have packet and byte stats + if {$stats_mode == "normal"} { + #Raw IXIA Results + set final_rx_bytes [statList cget -bytesReceived] + set final_rx_frames [statList cget -framesReceived] + set final_stat1_pkts [statList cget -userDefinedStat1] + set final_stat2_pkts [statList cget -userDefinedStat2] + + keylset ret_list \ + rx_port.$rx_port_key.final_tx_bytes $final_rx_bytes + + keylset ret_list \ + rx_port.$rx_port_key.final_tx_pkts $final_rx_frames + + keylset ret_list rx_port.$rx_port_key.final_stat1_pkts \ + $final_stat1_pkts + + keylset ret_list rx_port.$rx_port_key.final_stat2_pkts \ + $final_stat2_pkts + + #Calculate the rates + set total_rx_bytes [mpexpr $final_rx_bytes - [keylget \ + ret_list rx_port.$rx_port_key.initial_rx_bytes]] + + set total_rx_frames [mpexpr $final_rx_frames - [keylget \ + ret_list rx_port.$rx_port_key.initial_rx_pkts]] + + set total_stat1_pkts [mpexpr $final_stat1_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_stat1_pkts]] + + set total_stat2_pkts [mpexpr $final_stat2_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_stat2_pkts]] + + + set rx_bytes_per_sec \ + [mpexpr $total_rx_bytes / $measure_interval.0] + + set rx_frames_per_sec \ + [mpexpr $total_rx_frames / $measure_interval.0] + + set stat1_pps [mpexpr $total_stat1_pkts \ + / $measure_interval.0] + set stat2_pps [mpexpr $total_stat2_pkts \ + / $measure_interval.0] + + keylset ret_list \ + rx_port.$rx_port_key.l2_frame_bytes_per_sec \ + $rx_bytes_per_sec + + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + keylset ret_list rx_port.$rx_port_key.stat1_pps $stat1_pps + keylset ret_list rx_port.$rx_port_key.stat2_pps $stat2_pps + } + + #If statQos mode we only get packet stats but we do get per + #precedence value stats + if {$stats_mode == "statQos"} { + set final_rx_frames [statList cget -framesReceived] + set final_prec0_pkts [statList cget -qualityOfService0] + set final_prec1_pkts [statList cget -qualityOfService1] + set final_prec2_pkts [statList cget -qualityOfService2] + set final_prec3_pkts [statList cget -qualityOfService3] + set final_prec4_pkts [statList cget -qualityOfService4] + set final_prec5_pkts [statList cget -qualityOfService5] + set final_prec6_pkts [statList cget -qualityOfService6] + set final_prec7_pkts [statList cget -qualityOfService7] + + keylset ret_list \ + rx_port.$rx_port_key.final_rx_pkts $final_rx_frames + keylset ret_list \ + rx_port.$rx_port_key.final_prec0_pkts \ + $final_prec0_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec1_pkts \ + $final_prec1_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec2_pkts \ + $final_prec2_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec3_pkts \ + $final_prec3_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec4_pkts \ + $final_prec4_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec5_pkts \ + $final_prec5_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec6_pkts \ + $final_prec6_pkts + keylset ret_list \ + rx_port.$rx_port_key.final_prec7_pkts \ + $final_prec7_pkts + + + set total_rx_frames [mpexpr $final_rx_frames - [keylget \ + ret_list rx_port.$rx_port_key.initial_rx_pkts]] + set rx_frames_per_sec \ + [mpexpr $total_rx_frames / $measure_interval.0] + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + + + set total_prec0_pkts [mpexpr $final_prec0_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec0_pkts]] + set total_prec1_pkts [mpexpr $final_prec1_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec1_pkts]] + set total_prec2_pkts [mpexpr $final_prec2_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec2_pkts]] + set total_prec3_pkts [mpexpr $final_prec3_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec3_pkts]] + set total_prec4_pkts [mpexpr $final_prec4_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec4_pkts]] + set total_prec5_pkts [mpexpr $final_prec5_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec5_pkts]] + set total_prec6_pkts [mpexpr $final_prec6_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec6_pkts]] + set total_prec7_pkts [mpexpr $final_prec7_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_prec7_pkts]] + + + set prec0_pps [mpexpr $total_prec0_pkts \ + / $measure_interval.0] + set prec1_pps [mpexpr $total_prec1_pkts \ + / $measure_interval.0] + set prec2_pps [mpexpr $total_prec2_pkts \ + / $measure_interval.0] + set prec3_pps [mpexpr $total_prec3_pkts \ + / $measure_interval.0] + set prec4_pps [mpexpr $total_prec4_pkts \ + / $measure_interval.0] + set prec5_pps [mpexpr $total_prec5_pkts \ + / $measure_interval.0] + set prec6_pps [mpexpr $total_prec6_pkts \ + / $measure_interval.0] + set prec7_pps [mpexpr $total_prec7_pkts \ + / $measure_interval.0] + + keylset ret_list rx_port.$rx_port_key.prec0_pps $prec0_pps + keylset ret_list rx_port.$rx_port_key.prec1_pps $prec1_pps + keylset ret_list rx_port.$rx_port_key.prec2_pps $prec2_pps + keylset ret_list rx_port.$rx_port_key.prec3_pps $prec3_pps + keylset ret_list rx_port.$rx_port_key.prec4_pps $prec4_pps + keylset ret_list rx_port.$rx_port_key.prec5_pps $prec5_pps + keylset ret_list rx_port.$rx_port_key.prec6_pps $prec6_pps + keylset ret_list rx_port.$rx_port_key.prec7_pps $prec7_pps + } + } + } + + } ;#End if [info exists measure_interval] + } + + if {$tgen_app == "IxNetwork"} { + if {[info exists measure_interval]} { + #statList setDefault + #statGroup get + + #If Tx ports get the initial tx port values + if {[info exists tx_ports]} { + set tx_port_keys [keylkeys ret_list tx_port] + foreach tx_port_key $tx_port_keys { + set chassis [keylget ret_list tx_port.$tx_port_key.chassis] + set card [keylget ret_list tx_port.$tx_port_key.card] + set port [keylget ret_list tx_port.$tx_port_key.port] + + #statList get $chassis $card $port + set port1 $chassis/$card/$port + set txStats [::ixia::traffic_stats -port_handle $port1] + #Raw IXIA Results + set initial_tx_bytes [keylget txStats $port1.aggregate.tx.pkt_byte_count] + set initial_tx_frames [keylget txStats $port1.aggregate.tx.tx_aal5_scheduled_frames_count] + + keylset ret_list \ + tx_port.$tx_port_key.initial_tx_bytes $initial_tx_bytes + + keylset ret_list \ + tx_port.$tx_port_key.initial_tx_pkts $initial_tx_frames + } + } + + #If Rx ports get the initial rx port values + if {[info exists rx_ports]} { + set rx_port_keys [keylkeys ret_list rx_port] + foreach rx_port_key $rx_port_keys { + set chassis [keylget ret_list rx_port.$rx_port_key.chassis] + set card [keylget ret_list rx_port.$rx_port_key.card] + set port [keylget ret_list rx_port.$rx_port_key.port] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + #statList get $chassis $card $port + + #Raw IXIA Results + set port2 $chassis/$card/$port + set rxStats [::ixia::traffic_stats -port_handle $port2] + #If normal mode we have packet and byte stats + if {$stats_mode == "normal"} { + + set initial_rx_bytes [keylget rxStats $port2.aggregate.rx.pkt_byte_count] + set initial_rx_frames [keylget rxStats $port2.aggregate.rx.raw_pkt_count] + set initial_stat1_pkts [keylget rxStats $port2.aggregate.rx.uds1_frame_count] + set initial_stat2_pkts [keylget rxStats $port2.aggregate.rx.uds2_frame_count] + + keylset ret_list \ + rx_port.$rx_port_key.initial_rx_bytes $initial_rx_bytes + + keylset ret_list \ + rx_port.$rx_port_key.initial_rx_pkts $initial_rx_frames + + keylset ret_list rx_port.$rx_port_key.initial_stat1_pkts \ + $initial_stat1_pkts + + keylset ret_list rx_port.$rx_port_key.initial_stat2_pkts \ + $initial_stat2_pkts + } + + #If statQos mode we only get packet stats but we do get per + #precedence value stats + if {$stats_mode == "statQos"} { + set initial_rx_frames [keylget rxStats $port2.aggregate.rx.raw_pkt_count] + #set initial_prec0_pkts [statList cget -qualityOfService0] + #set initial_prec1_pkts [statList cget -qualityOfService1] + #set initial_prec2_pkts [statList cget -qualityOfService2] + #set initial_prec3_pkts [statList cget -qualityOfService3] + #set initial_prec4_pkts [statList cget -qualityOfService4] + #set initial_prec5_pkts [statList cget -qualityOfService5] + #set initial_prec6_pkts [statList cget -qualityOfService6] + #set initial_prec7_pkts [statList cget -qualityOfService7] + + keylset ret_list \ + rx_port.$rx_port_key.initial_rx_pkts $initial_rx_frames + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec0_pkts \ + # $initial_prec0_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec1_pkts \ + # $initial_prec1_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec2_pkts \ + # $initial_prec2_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec3_pkts \ + # $initial_prec3_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec4_pkts \ + # $initial_prec4_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec5_pkts \ + # $initial_prec5_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec6_pkts \ + # $initial_prec6_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.initial_prec7_pkts \ + # $initial_prec7_pkts + } + } + } + + #Sleep for the test interval + after [mpexpr $measure_interval * 1000] + + #statList setDefault + #statGroup get + + #If Tx ports get the final tx port values + if {[info exists tx_ports]} { + + set tx_port_keys [keylkeys ret_list tx_port] + + foreach tx_port_key $tx_port_keys { + + set chassis [keylget ret_list tx_port.$tx_port_key.chassis] + set card [keylget ret_list tx_port.$tx_port_key.card] + set port [keylget ret_list tx_port.$tx_port_key.port] + + #statList get $chassis $card $port + set port1 $chassis/$card/$port + set txStats [::ixia::traffic_stats -port_handle $port1] + #Raw IXIA Results + set final_tx_bytes [keylget txStats $port1.aggregate.tx.pkt_byte_count] + set final_tx_frames [keylget txStats $port1.aggregate.tx.tx_aal5_scheduled_frames_count] + + keylset ret_list \ + tx_port.$tx_port_key.final_tx_bytes $final_tx_bytes + + keylset ret_list \ + tx_port.$tx_port_key.final_tx_pkts $final_tx_frames + + #Calculate the rates + set total_tx_bytes [mpexpr $final_tx_bytes - \ + [keylget ret_list tx_port.$tx_port_key.initial_tx_bytes]] + + set total_tx_frames [mpexpr $final_tx_frames - \ + [keylget ret_list tx_port.$tx_port_key.initial_tx_pkts]] + + + set tx_bytes_per_sec \ + [mpexpr $total_tx_bytes / $measure_interval.0] + + set tx_frames_per_sec \ + [mpexpr $total_tx_frames / $measure_interval.0] + + keylset ret_list \ + tx_port.$tx_port_key.l2_frame_bytes_per_sec $tx_bytes_per_sec + + keylset ret_list tx_port.$tx_port_key.pps $tx_frames_per_sec + + } + } + + #If Rx ports get the final rx port values + if {[info exists rx_ports]} { + + set rx_port_keys [keylkeys ret_list rx_port] + + foreach rx_port_key $rx_port_keys { + + set chassis [keylget ret_list rx_port.$rx_port_key.chassis] + set card [keylget ret_list rx_port.$rx_port_key.card] + set port [keylget ret_list rx_port.$rx_port_key.port] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + #statList get $chassis $card $port + set port2 $chassis/$card/$port + set rxStats [::ixia::traffic_stats -port_handle $port2] + #If normal mode we have packet and byte stats + if {$stats_mode == "normal"} { + #Raw IXIA Results + set final_rx_bytes [keylget rxStats $port2.aggregate.rx.pkt_byte_count] + set final_rx_frames [keylget rxStats $port2.aggregate.rx.raw_pkt_count] + set final_stat1_pkts [keylget rxStats $port2.aggregate.rx.uds1_frame_count] + set final_stat2_pkts [keylget rxStats $port2.aggregate.rx.uds2_frame_count] + + keylset ret_list \ + rx_port.$rx_port_key.final_tx_bytes $final_rx_bytes + + keylset ret_list \ + rx_port.$rx_port_key.final_tx_pkts $final_rx_frames + + keylset ret_list rx_port.$rx_port_key.final_stat1_pkts \ + $final_stat1_pkts + + keylset ret_list rx_port.$rx_port_key.final_stat2_pkts \ + $final_stat2_pkts + + #Calculate the rates + set total_rx_bytes [mpexpr $final_rx_bytes - [keylget \ + ret_list rx_port.$rx_port_key.initial_rx_bytes]] + + set total_rx_frames [mpexpr $final_rx_frames - [keylget \ + ret_list rx_port.$rx_port_key.initial_rx_pkts]] + + set total_stat1_pkts [mpexpr $final_stat1_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_stat1_pkts]] + + set total_stat2_pkts [mpexpr $final_stat2_pkts - [keylget \ + ret_list rx_port.$rx_port_key.initial_stat2_pkts]] + + + set rx_bytes_per_sec \ + [mpexpr $total_rx_bytes / $measure_interval.0] + + set rx_frames_per_sec \ + [mpexpr $total_rx_frames / $measure_interval.0] + + set stat1_pps [mpexpr $total_stat1_pkts \ + / $measure_interval.0] + set stat2_pps [mpexpr $total_stat2_pkts \ + / $measure_interval.0] + + keylset ret_list \ + rx_port.$rx_port_key.l2_frame_bytes_per_sec \ + $rx_bytes_per_sec + + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + keylset ret_list rx_port.$rx_port_key.stat1_pps $stat1_pps + keylset ret_list rx_port.$rx_port_key.stat2_pps $stat2_pps + } + + #If statQos mode we only get packet stats but we do get per + #precedence value stats + if {$stats_mode == "statQos"} { + set final_rx_frames [keylget rxStats $port2.aggregate.rx.raw_pkt_count] + #set final_prec0_pkts [statList cget -qualityOfService0] + #set final_prec1_pkts [statList cget -qualityOfService1] + #set final_prec2_pkts [statList cget -qualityOfService2] + #set final_prec3_pkts [statList cget -qualityOfService3] + #set final_prec4_pkts [statList cget -qualityOfService4] + #set final_prec5_pkts [statList cget -qualityOfService5] + #set final_prec6_pkts [statList cget -qualityOfService6] + #set final_prec7_pkts [statList cget -qualityOfService7] + + keylset ret_list \ + rx_port.$rx_port_key.final_rx_pkts $final_rx_frames + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec0_pkts \ + # $final_prec0_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec1_pkts \ + # $final_prec1_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec2_pkts \ + # $final_prec2_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec3_pkts \ + # $final_prec3_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec4_pkts \ + # $final_prec4_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec5_pkts \ + # $final_prec5_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec6_pkts \ + # $final_prec6_pkts + #keylset ret_list \ + # rx_port.$rx_port_key.final_prec7_pkts \ + # $final_prec7_pkts + + + set total_rx_frames [mpexpr $final_rx_frames - [keylget \ + ret_list rx_port.$rx_port_key.initial_rx_pkts]] + set rx_frames_per_sec \ + [mpexpr $total_rx_frames / $measure_interval.0] + keylset ret_list rx_port.$rx_port_key.pps $rx_frames_per_sec + + + #set total_prec0_pkts [mpexpr $final_prec0_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec0_pkts]] + #set total_prec1_pkts [mpexpr $final_prec1_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec1_pkts]] + #set total_prec2_pkts [mpexpr $final_prec2_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec2_pkts]] + #set total_prec3_pkts [mpexpr $final_prec3_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec3_pkts]] + #set total_prec4_pkts [mpexpr $final_prec4_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec4_pkts]] + #set total_prec5_pkts [mpexpr $final_prec5_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec5_pkts]] + #set total_prec6_pkts [mpexpr $final_prec6_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec6_pkts]] + #set total_prec7_pkts [mpexpr $final_prec7_pkts - [keylget \ + # ret_list rx_port.$rx_port_key.initial_prec7_pkts]] + + + #set prec0_pps [mpexpr $total_prec0_pkts \ + # / $measure_interval.0] + #set prec1_pps [mpexpr $total_prec1_pkts \ + # / $measure_interval.0] + #set prec2_pps [mpexpr $total_prec2_pkts \ + # / $measure_interval.0] + #set prec3_pps [mpexpr $total_prec3_pkts \ + # / $measure_interval.0] + #set prec4_pps [mpexpr $total_prec4_pkts \ + # / $measure_interval.0] + #set prec5_pps [mpexpr $total_prec5_pkts \ + # / $measure_interval.0] + #set prec6_pps [mpexpr $total_prec6_pkts \ + # / $measure_interval.0] + #set prec7_pps [mpexpr $total_prec7_pkts \ + # / $measure_interval.0] + + #keylset ret_list rx_port.$rx_port_key.prec0_pps $prec0_pps + #keylset ret_list rx_port.$rx_port_key.prec1_pps $prec1_pps + #keylset ret_list rx_port.$rx_port_key.prec2_pps $prec2_pps + #keylset ret_list rx_port.$rx_port_key.prec3_pps $prec3_pps + #keylset ret_list rx_port.$rx_port_key.prec4_pps $prec4_pps + #keylset ret_list rx_port.$rx_port_key.prec5_pps $prec5_pps + #keylset ret_list rx_port.$rx_port_key.prec6_pps $prec6_pps + #keylset ret_list rx_port.$rx_port_key.prec7_pps $prec7_pps + } + } + } + + } ;#End if [info exists measure_interval] + } + + + + #Calculations - convert raw IXIA results into useful info + + #Tx Port Calculations + if {[info exists tx_ports]} { + + set tx_port_keys [keylkeys ret_list tx_port] + + foreach tx_port_key $tx_port_keys { + + set tx_bytes_per_sec [keylget ret_list \ + tx_port.$tx_port_key.l2_frame_bytes_per_sec] + + set tx_frames_per_sec [keylget ret_list \ + tx_port.$tx_port_key.pps] + + + #bps results for l2_frame, l2_header, l2_all and l3_datagram + + #l2_frame + set tx_l2_frame_bps [mpexpr $tx_bytes_per_sec * 8] + keylset ret_list tx_port.$tx_port_key.l2_frame_bps $tx_l2_frame_bps + + #l3_datagram (remove l2header, mpls labels and crc) + set tx_l3_datagram_bps [mpexpr $tx_l2_frame_bps - \ + ($tx_frames_per_sec * 8 * ( \ + [keylget ret_list tx_port.$tx_port_key.l2_header_len] + \ + [keylget ret_list tx_port.$tx_port_key.mpls_label_bytes] + \ + [keylget ret_list tx_port.$tx_port_key.crc_bytes]))] + + keylset ret_list \ + tx_port.$tx_port_key.l3_datagram_bps $tx_l3_datagram_bps + + #l2_header + set tx_l2_header_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * \ + ([keylget ret_list tx_port.$tx_port_key.l2_header_len] + \ + [keylget ret_list tx_port.$tx_port_key.mpls_label_bytes]))] + + keylset ret_list \ + tx_port.$tx_port_key.l2_header_bps $tx_l2_header_bps + + #l2 all + set tx_l2_all_bps [mpexpr $tx_l2_frame_bps + \ + ($tx_frames_per_sec * 8 * [keylget \ + ret_list tx_port.$tx_port_key.inter_frame_overhead])] + + keylset ret_list tx_port.$tx_port_key.l2_all_bps $tx_l2_all_bps + + + #Similar values per the perspective of the interface under test + if {[info exists iut_encaps]} { + + #iut_l3_datagram_bps (same as tx_l3_datagram_bps + #return as second key anyway.. + keylset ret_list tx_port.$tx_port_key.iut.l3_datagram_bps \ + $tx_l3_datagram_bps + + + if {$int_mode == "normal"} { + #iut_l2_frame_bps + set iut_l2_frame_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * (\ + [keylget ret_list iut.l2_header_len] +\ + [keylget ret_list iut.crc_bytes] +\ + [keylget ret_list iut.mpls_label_bytes]))] + + keylset ret_list tx_port.$tx_port_key.iut.l2_frame_bps \ + $iut_l2_frame_bps + + #iut_l2_header_bps + set iut_l2_header_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * \ + ([keylget ret_list iut.l2_header_len] + \ + [keylget ret_list iut.mpls_label_bytes]))] + + keylset ret_list tx_port.$tx_port_key.iut.l2_header_bps \ + $iut_l2_header_bps + + #iut_l2_all_bps + set iut_l2_all_bps [mpexpr $iut_l2_frame_bps + \ + ($tx_frames_per_sec * 8 * \ + [keylget ret_list iut.inter_frame_overhead])] + + keylset ret_list \ + tx_port.$tx_port_key.iut.l2_all_bps $iut_l2_all_bps + } ;#end if int_mode == normal + + if {$int_mode == "atm"} { + + #pull the tx_datagram_len for this port from keyed list + set datagram_len [keylget ret_list \ + tx_port.$tx_port_key.tx_datagram_len] + + #iut_aal5_header_bps + set iut_aal5_header_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * \ + [keylget ret_list iut.aal_header_len])] + + keylset ret_list tx_port.$tx_port_key.iut.aal5_header_bps \ + $iut_aal5_header_bps + + #iut_aal5_pdu_bps + set iut_aal5_pdu_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * \ + ([keylget ret_list iut.aal_header_len] + \ + [keylget ret_list iut.aal_trailer_len]))] + + keylset ret_list tx_port.$tx_port_key.iut.aal5_pdu_bps \ + $iut_aal5_pdu_bps + + + #iut_aal5_pdu_no_crc_bps + set iut_aal5_pdu_no_crc_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * \ + ([keylget ret_list iut.aal_header_len] + \ + [keylget ret_list iut.aal_trailer_len] - 4))] + + keylset ret_list \ + tx_port.$tx_port_key.iut.aal5_pdu_no_crc_bps \ + $iut_aal5_pdu_no_crc_bps + + #iut_aal5_pdu_no_crc_bps + set iut_cell_tax_bps [mpexpr $tx_l3_datagram_bps + \ + ($tx_frames_per_sec * 8 * [_calc_per_pkt_cell_tax \ + -datagram_len $datagram_len \ + -aal_header_len [keylget ret_list iut.aal_header_len] \ + -aal_trailer_len [keylget ret_list iut.aal_trailer_len]\ + ])] + + keylset ret_list tx_port.$tx_port_key.iut.cell_tax_bps \ + $iut_cell_tax_bps + + + } ;#End if $int_mode == atm + + } ;#end if info exists iut_encaps + + } ;#enf foreach tx_port_key + } ;#End if info exists tx_ports + + + #Build an aggregate tx summary + if {[info exists tx_ports]} { + #Initialize summary stats - note - no aggregate tx_port_l2 stats + #as there may be multiple port types in the tx list + set tx_aggregate_pps 0 + set tx_aggregate_l3_datagram_bps 0 + #Following may or may not be used.. + set tx_iut_aggregate_l3_datagram_bps 0 + set tx_iut_aggregate_l2_frame_bps 0 + set tx_iut_aggregate_l2_header_bps 0 + set tx_iut_aggregate_l2_all_bps 0 + set tx_iut_aggregate_aal5_header_bps 0 + set tx_iut_aggregate_aal5_pdu_bps 0 + set tx_iut_aggregate_aal5_pdu_no_crc_bps 0 + set tx_iut_aggregate_cell_tax_bps 0 + + + set tx_port_keys [keylkeys ret_list tx_port] + + foreach tx_port_key $tx_port_keys { + + set tx_aggregate_pps [mpexpr $tx_aggregate_pps \ + + [keylget ret_list tx_port.$tx_port_key.pps]] + + set tx_aggregate_l3_datagram_bps \ + [mpexpr $tx_aggregate_l3_datagram_bps \ + + [keylget ret_list tx_port.$tx_port_key.l3_datagram_bps]] + + + if {[info exists iut_encaps]} { + + set tx_iut_aggregate_l3_datagram_bps [mpexpr \ + $tx_iut_aggregate_l3_datagram_bps + [keylget \ + ret_list tx_port.$tx_port_key.iut.l3_datagram_bps]] + + if {$int_mode == "normal"} { + set tx_iut_aggregate_l2_frame_bps [mpexpr \ + $tx_iut_aggregate_l2_frame_bps + \ + [keylget ret_list tx_port.$tx_port_key.iut.l2_frame_bps]] + + set tx_iut_aggregate_l2_header_bps [mpexpr \ + $tx_iut_aggregate_l2_header_bps + \ + [keylget ret_list tx_port.$tx_port_key.iut.l2_header_bps]] + + set tx_iut_aggregate_l2_all_bps [mpexpr \ + $tx_iut_aggregate_l2_all_bps + \ + [keylget ret_list tx_port.$tx_port_key.iut.l2_all_bps]] + } ;# end if int_mode == normal + + + if {$int_mode == "atm"} { + set tx_iut_aggregate_aal5_header_bps [mpexpr \ + $tx_iut_aggregate_aal5_header_bps + [keylget \ + ret_list tx_port.$tx_port_key.iut.aal5_header_bps]] + + set tx_iut_aggregate_aal5_pdu_bps [mpexpr \ + $tx_iut_aggregate_aal5_pdu_bps + [keylget \ + ret_list tx_port.$tx_port_key.iut.aal5_pdu_bps]] + + set tx_iut_aggregate_aal5_pdu_no_crc_bps [mpexpr \ + $tx_iut_aggregate_aal5_pdu_no_crc_bps + [keylget \ + ret_list tx_port.$tx_port_key.iut.aal5_pdu_no_crc_bps]] + + set tx_iut_aggregate_cell_tax_bps [mpexpr \ + $tx_iut_aggregate_cell_tax_bps + [keylget \ + ret_list tx_port.$tx_port_key.iut.cell_tax_bps]] + } ;# end if int_mode == normal + + } ;# end if info exists iut_encaps + } ;#end foreach tx_port_key + + keylset ret_list tx_aggregate.pps $tx_aggregate_pps + keylset ret_list \ + tx_aggregate.l3_datagram_bps $tx_aggregate_l3_datagram_bps + + if {[info exists iut_encaps]} { + + if {$int_mode == "normal"} { + keylset ret_list tx_aggregate.iut.l3_datagram_bps \ + $tx_iut_aggregate_l3_datagram_bps + + keylset ret_list tx_aggregate.iut.l2_frame_bps \ + $tx_iut_aggregate_l2_frame_bps + + keylset ret_list tx_aggregate.iut.l2_header_bps \ + $tx_iut_aggregate_l2_header_bps + + keylset ret_list tx_aggregate.iut.l2_all_bps \ + $tx_iut_aggregate_l2_all_bps + } ;# end if int_mode == normal + + if {$int_mode == "atm"} { + keylset ret_list tx_aggregate.iut.aal5_header_bps \ + $tx_iut_aggregate_aal5_header_bps + + keylset ret_list tx_aggregate.iut.aal5_pdu_bps \ + $tx_iut_aggregate_aal5_pdu_bps + + keylset ret_list tx_aggregate.iut.aal5_pdu_no_crc_bps \ + $tx_iut_aggregate_aal5_pdu_no_crc_bps + + keylset ret_list tx_aggregate.iut.cell_tax_bps \ + $tx_iut_aggregate_cell_tax_bps + } ;# end if int_mode == atm + + } ;#End if info exists iut_encaps + + } ;#End if info exists tx_ports - build aggregate tx summary + + + + #Rx Port Calculations + if {[info exists rx_ports]} { + + set rx_port_keys [keylkeys ret_list rx_port] + + foreach rx_port_key $rx_port_keys { + + set rx_frames_per_sec [keylget ret_list \ + rx_port.$rx_port_key.pps] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + #bps results for l2_frame, l2_header, l2_all and l3_datagram + + #Will only get bytes/per sec / be able to calculate rx rates + #when we are not in qos_stats mode + if {$stats_mode == "normal"} { + + #this stat only available if normal stats mode + set rx_bytes_per_sec [keylget ret_list \ + rx_port.$rx_port_key.l2_frame_bytes_per_sec] + + #l2_frame + set rx_l2_frame_bps [mpexpr $rx_bytes_per_sec * 8] + + keylset ret_list \ + rx_port.$rx_port_key.l2_frame_bps $rx_l2_frame_bps + + #l3_datagram (remove l2header, mpls labels and crc) + set rx_l3_datagram_bps [mpexpr $rx_l2_frame_bps - \ + ($rx_frames_per_sec * 8 * ( \ + [keylget ret_list rx_port.$rx_port_key.l2_header_len] + \ + [keylget ret_list rx_port.$rx_port_key.mpls_label_bytes] +\ + [keylget ret_list rx_port.$rx_port_key.crc_bytes]))] + + keylset ret_list \ + rx_port.$rx_port_key.l3_datagram_bps $rx_l3_datagram_bps + + #l2_header + set rx_l2_header_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * \ + ([keylget ret_list rx_port.$rx_port_key.l2_header_len] + \ + [keylget ret_list rx_port.$rx_port_key.mpls_label_bytes]))] + + keylset ret_list \ + rx_port.$rx_port_key.l2_header_bps $rx_l2_header_bps + + #l2 all + set rx_l2_all_bps [mpexpr $rx_l2_frame_bps + \ + ($rx_frames_per_sec * 8 * [keylget ret_list \ + rx_port.$rx_port_key.inter_frame_overhead])] + + keylset ret_list rx_port.$rx_port_key.l2_all_bps $rx_l2_all_bps + } + + if {$stats_mode == "qos_stats"} { + keylset ret_list rx_port.$rx_port_key.l2_frame_bps not_available + keylset ret_list rx_port.$rx_port_key.l3_datagram_bps \ + not_available + keylset ret_list rx_port.$rx_port_key.l2_header_bps \ + not_available + keylset ret_list rx_port.$rx_port_key.l2_all_bps not_available + } + + #Similar values per the perspective of the interface under test + if {[info exists iut_encaps]} { + + if {$int_mode == "normal"} { + + #iut_l2_frame_bps + set iut_l2_frame_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * (\ + [keylget ret_list iut.l2_header_len] +\ + [keylget ret_list iut.crc_bytes] +\ + [keylget ret_list iut.mpls_label_bytes]))] + + keylset ret_list rx_port.$rx_port_key.iut.l2_frame_bps \ + $iut_l2_frame_bps + + #iut_l3_datagram_bps (same as rx_l3_datagram_bps + #return as second key anyway.. + keylset ret_list rx_port.$rx_port_key.iut.l3_datagram_bps \ + $rx_l3_datagram_bps + + #iut_l2_header_bps + set iut_l2_header_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * \ + ([keylget ret_list iut.l2_header_len] + \ + [keylget ret_list iut.mpls_label_bytes]))] + + keylset ret_list rx_port.$rx_port_key.iut.l2_header_bps \ + $iut_l2_header_bps + + #iut_l2_all_bps + set iut_l2_all_bps [mpexpr $iut_l2_frame_bps + \ + ($rx_frames_per_sec * 8 * \ + [keylget ret_list iut.inter_frame_overhead])] + + keylset ret_list rx_port.$rx_port_key.iut.l2_all_bps \ + $iut_l2_all_bps + } ;# end if int_mode == normal + + + + #pull the tx_datagram_len for this port from keyed list + #Currently only required for ATM interfaces + if {($int_mode == "atm")} { + set datagram_len [keylget ret_list \ + rx_port.$rx_port_key.rx_datagram_len] + } + + + #if mode is atm and receiving fixed type traffic + if {($int_mode == "atm") && ($datagram_len != "imix")} { + + #The non-imix atm assumption is that port is *NOT* in qos + #stats mode - ie we get packet and byte stats + + #iut_aal5_header_bps + set iut_aal5_header_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * \ + [keylget ret_list iut.aal_header_len])] + + keylset ret_list rx_port.$rx_port_key.iut.aal5_header_bps \ + $iut_aal5_header_bps + + #iut_aal5_pdu_bps + set iut_aal5_pdu_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * \ + ([keylget ret_list iut.aal_header_len] + \ + [keylget ret_list iut.aal_trailer_len]))] + + keylset ret_list rx_port.$rx_port_key.iut.aal5_pdu_bps \ + $iut_aal5_pdu_bps + + + #iut_aal5_pdu_no_crc_bps + set iut_aal5_pdu_no_crc_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * \ + ([keylget ret_list iut.aal_header_len] + \ + [keylget ret_list iut.aal_trailer_len] - 4))] + + keylset ret_list \ + rx_port.$rx_port_key.iut.aal5_pdu_no_crc_bps \ + $iut_aal5_pdu_no_crc_bps + + #iut_cell_tax_bps + set iut_cell_tax_bps [mpexpr $rx_l3_datagram_bps + \ + ($rx_frames_per_sec * 8 * [_calc_per_pkt_cell_tax \ + -datagram_len $datagram_len \ + -aal_header_len [keylget ret_list iut.aal_header_len] \ + -aal_trailer_len [keylget ret_list iut.aal_trailer_len]\ + ])] + + keylset ret_list rx_port.$rx_port_key.iut.cell_tax_bps \ + $iut_cell_tax_bps + + } ;# end if mode == atm && not imix + + + + #if mode is atm and receiving imix type traffic + if {($int_mode == "atm") && ($datagram_len == "imix")} { + + #The imix atm assumption is that port **IS** in qos + #stats mode. In this mode we only get packet counters + #Assumption is that prec1 => 46 byte datagram + # prec2 => 552 byte datagram + # prec3 => 1500 byte datagram + + set num_46byte_pps [keylget ret_list \ + rx_port.$rx_port_key.prec1_pps] + set num_552byte_pps [keylget ret_list \ + rx_port.$rx_port_key.prec2_pps] + set num_1500byte_pps [keylget ret_list \ + rx_port.$rx_port_key.prec3_pps] + + + #iut_aal5_header_bps + set iut_aal5_header_bps [mpexpr \ + ($num_46byte_pps * 8 * \ + (46 + [keylget ret_list iut.aal_header_len])) \ + + ($num_552byte_pps * 8 * \ + (552 + [keylget ret_list iut.aal_header_len])) \ + + ($num_1500byte_pps * 8 * \ + (1500 + [keylget ret_list iut.aal_header_len])) ] + + keylset ret_list rx_port.$rx_port_key.iut.aal5_header_bps \ + $iut_aal5_header_bps + + + #iut_aal5_pdu_bps + set iut_aal5_pdu_bps [mpexpr \ + ($num_46byte_pps * 8 * \ + (46 + [keylget ret_list iut.aal_header_len] \ + + [keylget ret_list iut.aal_trailer_len])) \ + + ($num_552byte_pps * 8 * \ + (552 + [keylget ret_list iut.aal_header_len] \ + + [keylget ret_list iut.aal_trailer_len])) \ + + ($num_1500byte_pps * 8 * \ + (1500 + [keylget ret_list iut.aal_header_len] \ + + [keylget ret_list iut.aal_trailer_len])) ] + + keylset ret_list rx_port.$rx_port_key.iut.aal5_pdu_bps \ + $iut_aal5_pdu_bps + + + #iut_aal5_pdu_no_crc_bps + set iut_aal5_pdu_no_crc_bps [mpexpr \ + ($num_46byte_pps * 8 * \ + (46 + [keylget ret_list iut.aal_header_len] \ + + [keylget ret_list iut.aal_trailer_len] - 4)) \ + + ($num_552byte_pps * 8 * \ + (552 + [keylget ret_list iut.aal_header_len] \ + + [keylget ret_list iut.aal_trailer_len] - 4)) \ + + ($num_1500byte_pps * 8 * \ + (1500 + [keylget ret_list iut.aal_header_len] \ + + [keylget ret_list iut.aal_trailer_len] - 4)) ] + + keylset ret_list \ + rx_port.$rx_port_key.iut.aal5_pdu_no_crc_bps \ + $iut_aal5_pdu_no_crc_bps + + + + #iut_cell_tax_bps + set iut_cell_tax_bps [mpexpr \ + ($num_46byte_pps * 8 * (46 + [_calc_per_pkt_cell_tax \ + -datagram_len 46 \ + -aal_header_len [keylget ret_list iut.aal_header_len] \ + -aal_trailer_len [keylget ret_list iut.aal_trailer_len] \ + ])) \ + + ($num_552byte_pps * 8 * (552 + [_calc_per_pkt_cell_tax \ + -datagram_len 552 \ + -aal_header_len [keylget ret_list iut.aal_header_len] \ + -aal_trailer_len [keylget ret_list iut.aal_trailer_len] \ + ])) \ + + ($num_1500byte_pps * 8 * (1500 + [_calc_per_pkt_cell_tax\ + -datagram_len 1500 \ + -aal_header_len [keylget ret_list iut.aal_header_len] \ + -aal_trailer_len [keylget ret_list iut.aal_trailer_len] \ + ])) ] + + keylset ret_list rx_port.$rx_port_key.iut.cell_tax_bps \ + $iut_cell_tax_bps + + } ;#End if mode == atm && traffic == imix + + } ;#end if info exists iut_encaps + + } ;# end foreach rx_port_key + } ;#End if info exists rx_ports + + + #Build an aggregate rx summary + if {[info exists rx_ports]} { + #Initialize summary stats - note - no aggregate rx_port_l2 stats + #as there may be multiple port types in the rx list + set rx_aggregate_pps 0 + set rx_aggregate_l3_datagram_bps 0 + #Following may or may not be used.. + set rx_iut_aggregate_l2_frame_bps 0 + set rx_iut_aggregate_l3_datagram_bps 0 + set rx_iut_aggregate_l2_header_bps 0 + set rx_iut_aggregate_l2_all_bps 0 + set rx_iut_aggregate_aal5_header_bps 0 + set rx_iut_aggregate_aal5_pdu_bps 0 + set rx_iut_aggregate_aal5_pdu_no_crc_bps 0 + set rx_iut_aggregate_cell_tax_bps 0 + + set rx_port_keys [keylkeys ret_list rx_port] + + foreach rx_port_key $rx_port_keys { + + set rx_aggregate_pps [mpexpr $rx_aggregate_pps \ + + [keylget ret_list rx_port.$rx_port_key.pps]] + + set stats_mode [keylget ret_list \ + rx_port.$rx_port_key.port_stats_mode] + + if {$stats_mode == "normal"} { + set rx_aggregate_l3_datagram_bps \ + [mpexpr $rx_aggregate_l3_datagram_bps \ + + [keylget ret_list rx_port.$rx_port_key.l3_datagram_bps]] + } + + + if {[info exists iut_encaps]} { + + if {$int_mode == "normal"} { + set rx_iut_aggregate_l2_frame_bps [mpexpr \ + $rx_iut_aggregate_l2_frame_bps + \ + [keylget ret_list rx_port.$rx_port_key.iut.l2_frame_bps]] + + set rx_iut_aggregate_l3_datagram_bps [mpexpr \ + $rx_iut_aggregate_l3_datagram_bps + [keylget \ + ret_list rx_port.$rx_port_key.iut.l3_datagram_bps]] + + set rx_iut_aggregate_l2_header_bps [mpexpr \ + $rx_iut_aggregate_l2_header_bps + \ + [keylget ret_list rx_port.$rx_port_key.iut.l2_header_bps]] + + set rx_iut_aggregate_l2_all_bps [mpexpr \ + $rx_iut_aggregate_l2_all_bps + \ + [keylget ret_list rx_port.$rx_port_key.iut.l2_all_bps]] + } ;# end if int_mode == normal + + if {$int_mode == "atm"} { + set rx_iut_aggregate_aal5_header_bps [mpexpr \ + $rx_iut_aggregate_aal5_header_bps + [keylget \ + ret_list rx_port.$rx_port_key.iut.aal5_header_bps]] + + set rx_iut_aggregate_aal5_pdu_bps [mpexpr \ + $rx_iut_aggregate_aal5_pdu_bps + [keylget \ + ret_list rx_port.$rx_port_key.iut.aal5_pdu_bps]] + + set rx_iut_aggregate_aal5_pdu_no_crc_bps [mpexpr \ + $rx_iut_aggregate_aal5_pdu_no_crc_bps + [keylget \ + ret_list rx_port.$rx_port_key.iut.aal5_pdu_no_crc_bps]] + + set rx_iut_aggregate_cell_tax_bps [mpexpr \ + $rx_iut_aggregate_cell_tax_bps + [keylget \ + ret_list rx_port.$rx_port_key.iut.cell_tax_bps]] + } ;# end if int_mode == atm + } ;# end if info exists iut_encaps + } ;#end foreach rx_port_key + + + + keylset ret_list rx_aggregate.pps $rx_aggregate_pps + + if {$stats_mode == "normal"} { + keylset ret_list \ + rx_aggregate.l3_datagram_bps $rx_aggregate_l3_datagram_bps + } + + if {[info exists iut_encaps]} { + + keylset ret_list rx_aggregate.iut.l3_datagram_bps \ + $rx_iut_aggregate_l3_datagram_bps + + if {$int_mode == "normal"} { + keylset ret_list rx_aggregate.iut.l2_frame_bps \ + $rx_iut_aggregate_l2_frame_bps + + keylset ret_list rx_aggregate.iut.l2_header_bps \ + $rx_iut_aggregate_l2_header_bps + + keylset ret_list rx_aggregate.iut.l2_all_bps \ + $rx_iut_aggregate_l2_all_bps + } ;#end if int_mode == normal + + if {$int_mode == "atm"} { + keylset ret_list rx_aggregate.iut.aal5_header_bps \ + $rx_iut_aggregate_aal5_header_bps + + keylset ret_list rx_aggregate.iut.aal5_pdu_bps \ + $rx_iut_aggregate_aal5_pdu_bps + + keylset ret_list rx_aggregate.iut.aal5_pdu_no_crc_bps \ + $rx_iut_aggregate_aal5_pdu_no_crc_bps + + keylset ret_list rx_aggregate.iut.cell_tax_bps \ + $rx_iut_aggregate_cell_tax_bps + } ;# end if int_mode == atm + + } ;#End if info exists iut_encaps + + } ;#End if info exists rx_ports - build aggregate rx summary + + #restore mp_precision + set mp_precision $original_mp_precision + + return $ret_list +} + + +########################################################################## + + +procDescr vtmsIxiaUtils::ixia_add_rx_filter { + + Author: Michael Fingleton + Date: May 2005 + + Description: + This proc is used to configure the User Defined Statistics on an Ixia + port. + + Depending on the receive mode of the port one or two user defined filters + are available to users. 2 are available when the port is in capture mode + but only one when packet groups mode is used (required when measuring + latency). + + With this procedure if 2 filters are available the user can choose to use + these for two separate User Defined Statistics or combine them for a + single User Defined Stat that only counts when both conditions are met. + + When the user requests filtering based on source and destination IP these + are concatenated into one block and therefore consume only one filter. + These means combinations of source and destination IP and some other field + such as precedence or DSCP are possible or if using two stats each can + match based on a different source / destination IP pair. + + Note: The offset for all filters are calculated within this procedure. + This allows new filter types to be easily added and allows us to + look inside MPLS packets for IP values once the number of labels + is known. + + Usage: + + ixia_add_rx_filter -rx_port \ + -rx_port_encaps \ + -stat_key1 \ + [-rx_port_labels ] \ + [-src_ip1 ] \ + [-dst_ip1 ] \ + [-dscp1 ] \ + [-prec1 ] \ + [-tos1 ] \ + [-cos1 ] \ + [-fr_de1 ] \ + [-mpls_exp1 ]\ + [-mpls_exp1_label2 ] \ + [-stat_key2 ] \ + [-src_ip2 ] \ + [-dst_ip2 ] \ + [-dscp2 ] \ + [-prec2 ] \ + [-tos2 ] \ + [-cos2 ] \ + [-fr_de2 ] \ + [-mpls_exp2 ] + + Examples: + set procReturned [ ixia_add_rx_filter -rx_port {1 16 1} \ + -rx_port_encaps arpa \ + -stat_key1 src_dst_ip_dscp \ + -src_ip1 10.0.0.1 \ + -dst_ip1 100.100.100.100 \ + -dscp1 1 ] + + + set procReturned [ ixia_add_rx_filter -rx_port {1 16 1} \ + -rx_port_encaps arpa \ + -stat_key1 src_ip \ + -src_ip1 10.0.0.1 \ + -stat_key2 src_ip \ + -src_ip2 20.0.0.1 ] + + Example: Say you want to check MPLS EXP values in each of two labels and + precedence value in encapsulated IP datagram. Looking for Exp 7 + in outer label, Exp 3 in inner label and Prec 3 in IP datagram. + With following stat1 will show all packets with Exp 7 in outer + *AND* Exp 3 in inner label. stat2 will show all packets that have + prec 3 in the encapsulated datagram. + + set ret [ ixia_add_rx_filter -rx_port [list $old_rx_port] \ + -rx_port_encaps arpa \ + -rx_port_labels 2 \ + -stat_key1 mpls_exp \ + -mpls_exp1 7 \ + -mpls_exp1_label2 3 \ + -stat_key2 prec \ + -prec2 3 ] + + + + Returns: + A keyed list with the filter type (stat_key) and filter values for + each User Defined Statistic. + + e.g. (from second usage example above): + + stat1 + type = src_ip + src_ip = 10.0.0.1 + stat2 + type = src_ip + src_ip = 20.0.0.1 + +} + + + + +proc vtmsIxiaUtils::ixia_add_rx_filter {args} { + + #mandatory args + set man_args { + -rx_port SHIFT + LIST_SIZE 1 + -rx_port_encaps CHOICES arpa dot1q hdlc ppp fr + -stat_key1 CHOICES src_ip dst_ip src_dst_ip prec dscp tos \ + fr_de mpls_exp src_ip_prec dst_ip_prec \ + src_dst_ip_prec src_ip_dscp dst_ip_dscp \ + src_dst_ip_dscp cos ecn pgid + } + + # optional_args + set opt_args { + -stat_key2 CHOICES src_ip dst_ip src_dst_ip prec dscp tos \ + cos fr_de mpls_exp ecn + -rx_port_labels NUMERIC + DEFAULT 0 + -src_ip1 IPV4 + -dst_ip1 IPV4 + -dscp1 RANGE 0-63 + -prec1 RANGE 0-7 + -tos1 RANGE 0-255 + -cos1 RANGE 0-7 + -ecn1 RANGE 0-3 + -fr_de1 RANGE 0-1 + -mpls_exp1 RANGE 0-7 + -mpls_exp1_label2 RANGE 0-7 + -src_ip2 IPV4 + -dst_ip2 IPV4 + -dscp2 RANGE 0-63 + -prec2 RANGE 0-7 + -tos2 RANGE 0-255 + -cos2 RANGE 0-7 + -ecn2 RANGE 0-3 + -fr_de2 RANGE 0-1 + -tgen_app CHOICES IxExplorer IxNetwork + DEFAULT IxNetwork + -mpls_exp2 RANGE 0-7 + -mpls_exp2_label2 RANGE 0-7 + -pgid1 NUMERIC + -pgid_offset NUMERIC + DEFAULT 52 + + } + + parse_dashed_args -args $args -mandatory_args $man_args \ + -optional_args $opt_args + + + #Will return filter details in a keyed list + set return_list {} + if {$tgen_app == "IxExplorer"} { + #Grep port info + if {![regexp {(\d+) +(\d+) +(\d+)} $rx_port - chassis card port]} { + error "rx_port format should be like {1 5 1} - was passed $rx_port" + } + + + #Read current port info to ensure we don't accidently change anything + #Note - don't think this is really necessary but it's the kind of thing + #ixia may change version to version.. + port get $chassis $card $port + port config -receiveMode portCapture + #Receive mode '1' = capture mode => 2 filters available + if {[port cget -receiveMode] == 1} { + set filters_available 2 + } else { + set filters_available 1 + } + + #Error out straight away if 2 stat_keys are passed but only one + #user defined filter is available + if {[info exists stat_key1] && [info exists stat_key2] && + ($filters_available == 1)} { + error "\nYou requested ixia_add_rx_filter to configure 2 statistic\ + \nfilters but since the port is not in capture mode only one\ + \nuser defined filter is available\n\n" + } + + #following will be used to track number of filters consumed by first stat + set filters_used 0 + + #Figure out the L2 header length from the encaps / number of flags + #Will need this when calculating offsets + switch $rx_port_encaps { + arpa { + set rx_port_l2_header_len 14 + } + dot1q { + set rx_port_l2_header_len 18 + } + hdlc { + set rx_port_l2_header_len 4 + } + ppp { + set rx_port_l2_header_len 4 + } + fr { + set rx_port_l2_header_len 4 + } + default { + error "rx_port encaps \'$rx_port_encaps\' passed to\ + ixia_add_rx_filter is not supported" + } + } ;# end switch rx_port_encaps + + #Remember This offset as it will be the outer label offset + set mpls_offset $rx_port_l2_header_len + + #fr de offset will always be zero - point at fr header + set fr_de_offset 0 + + #For dot1q COS always look in the dot1q header at offset 14 + # +------+------+------+-----+-----+------+-------+-------------+-----+ + # | DMAC | SMAC | 8100 | QOS | CFI | VLID | 0x800 | IP Datagram | CRC | + # +------+------+------+-----+-----+------+-------+-------------+-----+ + # 6byte 6byte 2byte 3bit 1bit 12bit 2byte + set cos_offset 14 + + #Allow for any label expected on the rx port + if {[info exists rx_port_labels]} { + set rx_port_l2_header_len [expr $rx_port_l2_header_len \ + + ($rx_port_labels * 4) ] + } + + #Define Offsets for Other fields we're interested in + set ip_src_offset [expr $rx_port_l2_header_len + 12] + set ip_dst_offset [expr $rx_port_l2_header_len + 16] + set ip_tos_offset [expr $rx_port_l2_header_len + 1] + set ip_tcp_src_port_offset [expr $rx_port_l2_header_len + 20] + set ip_tcp_dst_port_offset [expr $rx_port_l2_header_len + 22] + set ip_udp_src_port_offset [expr $rx_port_l2_header_len + 20] + set ip_udp_dst_port_offset [expr $rx_port_l2_header_len + 22] + + #vlan tag is right after src mac + set vlan_tag_offset 12 + + + + + #Configure the first stat requested + switch $stat_key1 { + pgid { + #Ensure pgid1 was passed + if {![info exists pgid1]} { + error "\nYou need to pass pgid1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for pgid + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $pgid_offset + #Pad hex value with zeros as needed + if {$pgid1 < 16 } { + #convert pgid1 decimal to hex + set inhex_pgid 000[dectohex $pgid1] + } elseif {$pgid1 < 256 } { + #convert pgid1 decimal to hex + set inhex_pgid 00[dectohex $pgid1] + } elseif {$pgid1 < 4096} { + #convert pgid1 decimal to hex + set inhex_pgid 0[dectohex $pgid1] + } else { + #convert pgid1 decimal to hex + set inhex_pgid [dectohex $pgid1] + } + #putting in a work around for a bug with ixia low level calls + #output is now expected to have a space between each 2 number set + if {![regexp {(\w\w)(\w\w)} $inhex_pgid - num_group_a num_group_b]} { + error "Did not match PGID hex value in regular expression\n\n" + } else { + set inhex_pgid "$num_group_a $num_group_b" + } + + filterPallette config -patternMask1 {00 00} + filterPallette config -pattern1 $inhex_pgid + filterPallette set $chassis $card $port + + keylset return_list stat1.type pgid + keylset return_list stat1.pgid $pgid1 + + set filters_available [expr $filters_available - 1] + } + src_ip { + #Ensure src_ip1 was passed + if {![info exists src_ip1]} { + error "\nYou need to pass src_ip1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for src ip + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_src_offset + filterPallette config -pattern1 [host2addr $src_ip1] + filterPallette config -patternMask1 {00 00 00 00} + filterPallette set $chassis $card $port + + keylset return_list stat1.type src_ip + keylset return_list stat1.src_ip $src_ip1 + + set filters_available [expr $filters_available - 1] + } + + dst_ip { + #Ensure dst_ip1 was passed + if {![info exists dst_ip1]} { + error "\nYou need to pass dst_ip1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for dst ip + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_dst_offset + filterPallette config -pattern1 [host2addr $dst_ip1] + filterPallette config -patternMask1 {00 00 00 00} + filterPallette set $chassis $card $port + + keylset return_list stat1.type dst_ip + keylset return_list stat1.dst_ip $dst_ip1 + + set filters_available [expr $filters_available - 1] + } + + src_dst_ip { + #Ensure src_ip1 & dst_ip1 were passed + if {!([info exists src_ip1]) || !([info exists dst_ip1])} { + error "\nYou need to pass src_ip1 and dst_ip1 to\ + ixia_add_rx_filter\n\n" + } + #Configure UDF1 for src & dst ip + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_src_offset + filterPallette config -pattern1\ + [host2addr $src_ip1][host2addr $dst_ip1] + filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + filterPallette set $chassis $card $port + + keylset return_list stat1.type src_dst_ip + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.dst_ip $dst_ip1 + + set filters_available [expr $filters_available - 1] + } + + prec { + #Ensure prec was passed + if {![info exists prec1]} { + error "\nYou need to pass prec1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for prec + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_tos_offset + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [dectohex $shiftedPrec] + filterPallette config -pattern1 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + filterPallette config -patternMask1 {1f} + filterPallette set $chassis $card $port + + keylset return_list stat1.type prec + keylset return_list stat1.prec $prec1 + + set filters_available [expr $filters_available - 1] + } + + dscp { + #Ensure dscp1 was passed + if {![info exists dscp1]} { + error "\nYou need to pass dscp1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for dscp + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_tos_offset + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [dectohex $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[dectohex $shiftedDscp] + } + filterPallette config -pattern1 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + filterPallette config -patternMask1 {03} + filterPallette set $chassis $card $port + + keylset return_list stat1.type dscp + keylset return_list stat1.dscp $dscp1 + + set filters_available [expr $filters_available - 1] + } + tos { + #Ensure tos1 was passed + if {![info exists tos1]} { + error "\nYou need to pass tos1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for tos + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_tos_offset + + if {$tos1 > 15} { + set hexTos1 [dectohex $tos1] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexTos1 0[dectohex $tos1] + } + + filterPallette config -pattern1 $hexTos1 + + + #look at all bits of TOS byte + filterPallette config -patternMask1 {00} + filterPallette set $chassis $card $port + + keylset return_list stat1.type tos + keylset return_list stat1.tos $tos1 + + set filters_available [expr $filters_available - 1] + } + ecn { + #Ensure tos1 was passed + if {![info exists ecn1]} { + error "\nYou need to pass ecn1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for ecn + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $ip_tos_offset + + #Prepend 0 as ecn will only ever produce a nibble + set hex_ecn1 0[dectohex $ecn1] + + filterPallette config -pattern1 $hex_ecn1 + + #only look at ecn bits of TOS byte + filterPallette config -patternMask1 {F8} + filterPallette set $chassis $card $port + + keylset return_list stat1.type ecn + keylset return_list stat1.tos $ecn1 + + set filters_available [expr $filters_available - 1] + } + cos { + #Ensure tos1 was passed + if {![info exists cos1]} { + error "\nYou need to pass cos1 to ixia_add_rx_filter\n\n" + } + + if {![string match $rx_port_encaps "dot1q"]} { + error "\ncos filtering is only supported with dot1q encaps\n\n" + } + #Configure UDF1 for cos + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $cos_offset + set shifted_cos1 [expr $cos1 << 1] + set hex_cos1 [dectohex $shifted_cos1] + + filterPallette config -pattern1 $hex_cos1 + + #look at only first 3 bits of nibble - 4th is CFI bit + #Since ixia programs a byte mask out second nibble + filterPallette config -patternMask1 {1F} + + filterPallette set $chassis $card $port + + keylset return_list stat1.type cos + keylset return_list stat1.cos $cos1 + + set filters_available [expr $filters_available - 1] + } + src_ip_prec { + #Ensure src_ip1 & prec1 were passed + if {!([info exists src_ip1]) || !([info exists prec1])} { + error "\nYou need to pass src_ip1 and prec1 to \ + ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1AndPattern2 + filter set $chassis $card $port + + filterPallette setDefault + #pattern 1 = src ip - UDF1 + filterPallette config -patternOffset1 $ip_src_offset + filterPallette config -pattern1 [host2addr $src_ip1] + filterPallette config -patternMask1 {00 00 00 00} + #pattern 2 = prec - UDF2 + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [dectohex $shiftedPrec] + filterPallette config -pattern2 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + filterPallette config -patternMask2 {1f} + filterPallette set $chassis $card $port + + keylset return_list stat1.type src_ip_prec + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.prec $prec1 + + set filters_available [expr $filters_available - 2] + } + + dst_ip_prec { + #Ensure dst_ip1 & prec1 were passed + if {!([info exists dst_ip1]) || !([info exists prec1])} { + error "\nYou need to pass dst_ip1 and prec1\ + to ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "\nYou can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'\n\n" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1AndPattern2 + filter set $chassis $card $port + + filterPallette setDefault + #pattern 1 = dst ip - UDF1 + filterPallette config -patternOffset1 $ip_dst_offset + filterPallette config -pattern1 [host2addr $dst_ip1] + filterPallette config -patternMask1 {00 00 00 00} + #pattern 2 = prec - UDF2 + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [dectohex $shiftedPrec] + filterPallette config -pattern2 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + filterPallette config -patternMask2 {1f} + filterPallette set $chassis $card $port + + keylset return_list stat1.type dst_ip_prec + keylset return_list stat1.dst_ip $dst_ip + keylset return_list stat1.prec $prec + + set filters_available [expr $filters_available - 2] + } + + src_dst_ip_prec { + #Ensure src_ip1 & dst_ip1 and prec1 were passed + if {!([info exists src_ip1]) || !([info exists dst_ip1]) \ + || !([info exists prec1])} { + error "\nYou need to pass src_ip1, dst_ip1 and prec1\ + \nto ixia_add_rx_filter\n\n" + } + + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1AndPattern2 + filter set $chassis $card $port + + filterPallette setDefault + #pattern1 = src ip and dst ip - UDF1 + filterPallette config -patternOffset1 $ip_src_offset + filterPallette config -pattern1 \ + [host2addr $src_ip1][host2addr $dst_ip1] + filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + #pattern 2 = prec + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [dectohex $shiftedPrec] + filterPallette config -pattern2 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + filterPallette config -patternMask2 {1f} + filterPallette set $chassis $card $port + + keylset return_list stat1.type src_dst_ip_prec + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.dst_ip $dst_ip1 + keylset return_list stat1.prec $prec1 + + set filters_available [expr $filters_available - 2] + } + + src_ip_dscp { + #Ensure src_ip & dscp were passed + if {!([info exists src_ip1]) || !([info exists dscp1])} { + error "You need to pass src_ip1 and dscp1 to ixia_add_rx_filter" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1AndPattern2 + filter set $chassis $card $port + + filterPallette setDefault + #pattern 1 = src ip - UDF1 + filterPallette config -patternOffset1 $ip_src_offset + filterPallette config -pattern1 [host2addr $src_ip1] + filterPallette config -patternMask1 {00 00 00 00} + #pattern 2 = dscp - UDF2 + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [dectohex $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[dectohex $shiftedDscp] + } + filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + filterPallette config -patternMask2 {03} + filterPallette set $chassis $card $port + + keylset return_list stat1.type src_ip_dscp + keylset return_list stat1.src_ip $src_ip + keylset return_list stat1.dscp $dscp + + set filters_available [expr $filters_available - 2] + } + + dst_ip_dscp { + #Ensure src_ip1 & dscp1 were passed + if {!([info exists dst_ip1]) || !([info exists dscp1])} { + error "\nYou need to pass dst_ip1 and dscp1\ + to ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "\nYou can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'\n\n" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1AndPattern2 + filter set $chassis $card $port + + filterPallette setDefault + #pattern 1 = dst ip - UDF1 + filterPallette config -patternOffset1 $ip_dst_offset + filterPallette config -pattern1 [host2addr $dst_ip1] + filterPallette config -patternMask1 {00 00 00 00} + #pattern 2 = dscp + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [dectohex $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[dectohex $shiftedDscp] + } + filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + filterPallette config -patternMask2 {03} + filterPallette set $chassis $card $port + + keylset return_list stat1.type dst_ip_dscp + keylset return_list stat1.dst_ip $dst_ip1 + keylset return_list stat1.dscp $dscp1 + + set filters_available [expr $filters_available - 2] + } + + src_dst_ip_dscp { + #Ensure src_ip1, dst_ip1 and dscp1 were passed + if {!([info exists src_ip1]) || !([info exists dst_ip1]) \ + || !([info exists dscp1])} { + error "\nYou need to pass src_ip1, dst_ip1 and dscp1\ + \nto ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1AndPattern2 + filter set $chassis $card $port + + filterPallette setDefault + #pattern1 = src ip and dst ip - UDF1 + filterPallette config -patternOffset1 $ip_src_offset + filterPallette config -pattern1 \ + [host2addr $src_ip1][host2addr $dst_ip1] + filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + #pattern 2 = dscp - UDF2 + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [dectohex $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[dectohex $shiftedDscp] + } + filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + filterPallette config -patternMask2 {03} + filterPallette set $chassis $card $port + + keylset return_list stat1.type src_dst_ip_dscp + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.dst_ip $dst_ip1 + keylset return_list stat1.dscp $dscp1 + + set filters_available [expr $filters_available - 2] + } + + fr_de { + #Ensure fr_de1 was passed + if {![info exists fr_de1]} { + error "\nYou need to pass fr_de1 to ixia_add_rx_filter\n\n" + } + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $fr_de_offset + set shiftedFrDe [expr $fr_de1 << 1] + set hexShiftedFrDe [dectohex $shiftedFrDe] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + filterPallette config -pattern1 "00 0$hexShiftedFrDe" + #Only look at significant 1 bit of 3 fr bytes + filterPallette config -patternMask1 {ff fd} + filterPallette set $chassis $card $port + + keylset return_list stat1.type fr_de + keylset return_list stat1.fr_de $fr_de1 + + set filters_available [expr $filters_available - 1] + } + + mpls_exp { + #Ensure mpls_exp1 was passed + if {![info exists mpls_exp1]} { + error "\nYou need to pass mpls_exp1 to ixia_add_rx_filter\n\n" + } + + #Configure UDS1 + filter setDefault + filter config -userDefinedStat1Enable true + filter config -userDefinedStat1Pattern pattern1 + filter set $chassis $card $port + + filterPallette setDefault + filterPallette config -patternOffset1 $mpls_offset + + #First Label + set shiftedMplsExp [expr $mpls_exp1 << 1] + set hexShiftedMplsExp [dectohex $shiftedMplsExp] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + set exp1_pattern "00 00 0$hexShiftedMplsExp 00" + + #Add second label to pattern if required + if {[info exists mpls_exp1_label2]} { + set shifted_mpls_exp1_label2 [expr $mpls_exp1_label2 << 1] + set hex_shifted_mpls_exp1_label2 \ + [dectohex $shifted_mpls_exp1_label2] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + set exp1_label2_pattern \ + " 00 00 0$hex_shifted_mpls_exp1_label2 00" + + append exp1_pattern $exp1_label2_pattern + } + + filterPallette config -pattern1 $exp1_pattern + + #Only look at significant 3 bits of mpls exp byte + set mask_to_program "ff ff f1 ff" + + #Add mask for second label if necessary + if {[info exists mpls_exp1_label2]} { + append mask_to_program " ff ff f1 ff" + } + + filterPallette config -patternMask1 $mask_to_program + filterPallette set $chassis $card $port + + keylset return_list stat1.type mpls_exp + keylset return_list stat1.mpls_exp $mpls_exp1 + if {[info exists mpls_exp1_label2]} { + keylset return_list stat1.mpls_exp_label2 $mpls_exp1_label2 + } + + set filters_available [expr $filters_available - 1] + } + + default { + error "\nstat_key1 \'$stat_key1\' passed to\ + ixia_add_rx_filter is not supported\n\n" + } + } ;# end switch $stat_key1 + + + + #Configure the second stat only if requested + if {[info exists stat_key2]} { + switch $stat_key2 { + src_ip { + #Ensure src_ip2 was passed + if {![info exists src_ip2]} { + error "\nYou need to pass src_ip2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for src ip + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_src_offset + filterPallette config -pattern2 [host2addr $src_ip2] + filterPallette config -patternMask2 {00 00 00 00} + filterPallette set $chassis $card $port + + keylset return_list stat2.type src_ip + keylset return_list stat2.src_ip $src_ip2 + } + + dst_ip { + #Ensure dst_ip2 was passed + if {![info exists dst_ip2]} { + error "\nYou need to pass dst_ip2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for dst ip + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_dst_offset + filterPallette config -pattern2 [host2addr $dst_ip2] + filterPallette config -patternMask2 {00 00 00 00} + filterPallette set $chassis $card $port + + keylset return_list stat2.type dst_ip + keylset return_list stat2.dst_ip $dst_ip2 + } + + src_dst_ip { + #Ensure src_ip2 & dst_ip2 were passed + if {!([info exists src_ip2]) || !([info exists dst_ip2])} { + error "\nYou need to pass src_ip2 and dst_ip2 to\ + ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for src & dst ip + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_src_offset + filterPallette config -pattern2\ + [host2addr $src_ip2][host2addr $dst_ip2] + filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + filterPallette set $chassis $card $port + + keylset return_list stat2.type src_dst_ip + keylset return_list stat2.src_ip $src_ip2 + keylset return_list stat2.dst_ip $dst_ip2 + } + + prec { + #Ensure prec2 was passed + if {![info exists prec2]} { + error "\nYou need to pass prec2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for prec + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedPrec [expr $prec2 << 5] + set hexShiftedPrec [dectohex $shiftedPrec] + filterPallette config -pattern2 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + filterPallette config -patternMask2 {1f} + filterPallette set $chassis $card $port + + keylset return_list stat2.type prec + keylset return_list stat2.prec $prec2 + } + + dscp { + #Ensure dscp2 was passed + if {![info exists dscp2]} { + error "\nYou need to pass dscp2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for dscp + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_tos_offset + set shiftedDscp [expr $dscp2 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [dectohex $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[dectohex $shiftedDscp] + } + filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + filterPallette config -patternMask2 {03} + filterPallette set $chassis $card $port + + keylset return_list stat2.type dscp + keylset return_list stat2.dscp $dscp2 + } + tos { + #Ensure tos2 was passed + if {![info exists tos2]} { + error "\nYou need to pass tos2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for tos + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_tos_offset + + if {$tos2 > 15} { + set hexTos2 [dectohex $tos2] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexTos2 0[dectohex $tos2] + } + + filterPallette config -pattern2 $hexTos2 + + #Only look at all 8 bits of TOS byte + filterPallette config -patternMask2 {00} + filterPallette set $chassis $card $port + + keylset return_list stat2.type tos + keylset return_list stat2.tos $tos2 + } + ecn { + #Ensure tos2 was passed + if {![info exists ecn2]} { + error "\nYou need to pass ecn2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for tos + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $ip_tos_offset + set hex_ecn2 0[dectohex $ecn2] + filterPallette config -pattern2 $hex_ecn2 + + #Only look at ecn bits of TOS byte + filterPallette config -patternMask2 {F8} + filterPallette set $chassis $card $port + + keylset return_list stat2.type ecn + keylset return_list stat2.tos $ecn2 + } + cos { + #Ensure tos1 was passed + if {![info exists cos2]} { + error "\nYou need to pass cos2 to ixia_add_rx_filter\n\n" + } + + if {![string match $rx_port_encaps "dot1q"]} { + error "\ncos filtering is only supported with dot1q\ + encaps\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDF2 for cos + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $cos_offset + set shifted_cos2 [expr $cos2 << 1] + set hex_cos2 [dectohex $shifted_cos2] + + filterPallette config -pattern1 $hex_cos2 + + #look at only first 3 bits of nibble - 4th is CFI bit + #Since ixia programs a byte mask out second nibble + filterPallette config -patternMask2 {1F} + + filterPallette set $chassis $card $port + + keylset return_list stat2.type cos + keylset return_list stat2.cos $cos2 + } + + fr_de { + #Ensure fr_de2 was passed + if {![info exists fr_de2]} { + error "\nYou need to pass fr_de2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $fr_de_offset + set shiftedFrDe [expr $fr_de2 << 1] + set hexShiftedFrDe [dectohex $shiftedFrDe] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + filterPallette config -pattern2 "00 0$hexShiftedFrDe" + #Only look at significant 1 bit of 3 fr bytes + filterPallette config -patternMask2 {ff fd} + filterPallette set $chassis $card $port + + keylset return_list stat2.type fr_de + keylset return_list stat2.fr_de $fr_de2 + } + + mpls_exp { + #Ensure mpls_exp2 was passed + if {![info exists mpls_exp2]} { + error "\nYou need to pass mpls_exp2 to\ + ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + + #Configure UDS2 + filter config -userDefinedStat2Enable true + filter config -userDefinedStat2Pattern pattern2 + filter set $chassis $card $port + + filterPallette config -patternOffset2 $mpls_offset + + set shiftedMplsExp [expr $mpls_exp2 << 1] + set hexShiftedMplsExp [dectohex $shiftedMplsExp] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + set exp2_pattern "00 00 0$hexShiftedMplsExp 00" + + + #Add second label to pattern if required + if {[info exists mpls_exp2_label2]} { + set shifted_mpls_exp2_label2 [expr $mpls_exp2_label2 << 1] + set hex_shifted_mpls_exp2_label2 \ + [dectohex $shifted_mpls_exp2_label2] + #dectohex only returns a nibble if value < 15 - which it + #always will be hence add 0 before this value to create byte + set exp2_label2_pattern \ + " 00 00 0$hex_shifted_mpls_exp2_label2 00" + + append exp2_pattern $exp2_label2_pattern + } + + + filterPallette config -pattern2 $exp2_pattern + + #Only look at significant 3 bits of mpls exp byte + set mask_to_program "ff ff f1 ff" + + #Add mask for second label if necessary + if {[info exists mpls_exp2_label2]} { + append mask_to_program " ff ff f1 ff" + } + + + filterPallette config -patternMask2 $mask_to_program + filterPallette set $chassis $card $port + + keylset return_list stat2.type mpls_exp + keylset return_list stat2.mpls_exp $mpls_exp2 + if {[info exists mpls_exp2_label2]} { + keylset return_list stat2.mpls_exp_label2 $mpls_exp2_label2 + } + } + + default { + error "\nstat_key2 \'$stat_key2\' passed to\ + ixia_add_rx_filter is not supported\n\n" + } + + };# End switch $stat_key2 + } ;#end if info exists stat_key2 + + port set $chassis $card $port + port write $chassis $card $port + + return $return_list + } + if {$tgen_app == "IxNetwork"} { + #debug 1 + #Read current port info to ensure we don't accidently change anything + #Note - don't think this is really necessary but it's the kind of thing + #ixia may change version to version.. + #port get $chassis $card $port + #port config -receiveMode portCapture + if {![regexp {(\d+) +(\d+) +(\d+)} $rx_port - chassis card port]} { + error "rx_port format should be like {1 5 1} - was passed $rx_port" + } + set vports [interp eval $::ixia::TclInterp " ixNet getList [ixNet getRoot] vport "] + foreach vportHdl $vports { + set vportObj [interp eval $::ixia::TclInterp " ixNet getA $vportHdl -connectedTo "] + if {[regexp -nocase ".*card:$card\/port:$port" $vportObj match]} { + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHdl/capture -hardwareEnabled true " + set vportHandle $vportHdl + set receivemode [interp eval $::ixia::TclInterp " ixNet getA $vportHdl/capture -sliceSize"] + } + } + #Receive mode '1' = capture mode => 2 filters available + #[port cget -receiveMode] + if {$receivemode == 1} { + set filters_available 2 + } else { + set filters_available 1 + } + + #Error out straight away if 2 stat_keys are passed but only one + #user defined filter is available + if {[info exists stat_key1] && [info exists stat_key2] && + ($filters_available == 1)} { + error "\nYou requested ixia_add_rx_filter to configure 2 statistic\ + \nfilters but since the port is not in capture mode only one\ + \nuser defined filter is available\n\n" + } + + #following will be used to track number of filters consumed by first stat + set filters_used 0 + + #Figure out the L2 header length from the encaps / number of flags + #Will need this when calculating offsets + switch $rx_port_encaps { + arpa { + set rx_port_l2_header_len 14 + } + dot1q { + set rx_port_l2_header_len 18 + } + hdlc { + set rx_port_l2_header_len 4 + } + ppp { + set rx_port_l2_header_len 4 + } + fr { + set rx_port_l2_header_len 4 + } + default { + error "rx_port encaps \'$rx_port_encaps\' passed to\ + ixia_add_rx_filter is not supported" + } + } ;# end switch rx_port_encaps + + #Remember This offset as it will be the outer label offset + set mpls_offset $rx_port_l2_header_len + + #fr de offset will always be zero - point at fr header + set fr_de_offset 0 + + #For dot1q COS always look in the dot1q header at offset 14 + # +------+------+------+-----+-----+------+-------+-------------+-----+ + # | DMAC | SMAC | 8100 | QOS | CFI | VLID | 0x800 | IP Datagram | CRC | + # +------+------+------+-----+-----+------+-------+-------------+-----+ + # 6byte 6byte 2byte 3bit 1bit 12bit 2byte + set cos_offset 14 + + #Allow for any label expected on the rx port + if {[info exists rx_port_labels]} { + set rx_port_l2_header_len [expr $rx_port_l2_header_len \ + + ($rx_port_labels * 4) ] + } + + #Define Offsets for Other fields we're interested in + set ip_src_offset [expr $rx_port_l2_header_len + 12] + set ip_dst_offset [expr $rx_port_l2_header_len + 16] + set ip_tos_offset [expr $rx_port_l2_header_len + 1] + set ip_tcp_src_port_offset [expr $rx_port_l2_header_len + 20] + set ip_tcp_dst_port_offset [expr $rx_port_l2_header_len + 22] + set ip_udp_src_port_offset [expr $rx_port_l2_header_len + 20] + set ip_udp_dst_port_offset [expr $rx_port_l2_header_len + 22] + + #vlan tag is right after src mac + set vlan_tag_offset 12 + + + + + #Configure the first stat requested + switch $stat_key1 { + pgid { + #Ensure pgid1 was passed + if {![info exists pgid1]} { + error "\nYou need to pass pgid1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for pgid + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $pgid_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $pgid_offset " + #Pad hex value with zeros as needed + if {$pgid1 < 16 } { + #convert pgid1 decimal to hex + set inhex_pgid 000[format %x $pgid1] + } elseif {$pgid1 < 256 } { + #convert pgid1 decimal to hex + set inhex_pgid 00[format %x $pgid1] + } elseif {$pgid1 < 4096} { + #convert pgid1 decimal to hex + set inhex_pgid 0[format %x $pgid1] + } else { + #convert pgid1 decimal to hex + set inhex_pgid [format %x $pgid1] + } + #putting in a work around for a bug with ixia low level calls + #output is now expected to have a space between each 2 number set + if {![regexp {(\w\w)(\w\w)} $inhex_pgid - num_group_a num_group_b]} { + error "Did not match PGID hex value in regular expression\n\n" + } else { + set inhex_pgid "$num_group_a $num_group_b" + } + + #filterPallette config -patternMask1 {00 00} + #filterPallette config -pattern1 $inhex_pgid + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00} " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $inhex_pgid " + keylset return_list stat1.type pgid + keylset return_list stat1.pgid $pgid1 + + set filters_available [expr $filters_available - 1] + } + src_ip { + #Ensure src_ip1 was passed + if {![info exists src_ip1]} { + error "\nYou need to pass src_ip1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for src ip + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_src_offset + #filterPallette config -pattern1 [host2addr $src_ip1] + #filterPallette config -patternMask1 {00 00 00 00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $src_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00} " + + keylset return_list stat1.type src_ip + keylset return_list stat1.src_ip $src_ip1 + + set filters_available [expr $filters_available - 1] + } + + dst_ip { + #Ensure dst_ip1 was passed + if {![info exists dst_ip1]} { + error "\nYou need to pass dst_ip1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for dst ip + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_dst_offset + #filterPallette config -pattern1 [host2addr $dst_ip1] + #filterPallette config -patternMask1 {00 00 00 00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_dst_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $dst_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00} " + + keylset return_list stat1.type dst_ip + keylset return_list stat1.dst_ip $dst_ip1 + + set filters_available [expr $filters_available - 1] + } + + src_dst_ip { + #Ensure src_ip1 & dst_ip1 were passed + if {!([info exists src_ip1]) || !([info exists dst_ip1])} { + error "\nYou need to pass src_ip1 and dst_ip1 to\ + ixia_add_rx_filter\n\n" + } + #Configure UDF1 for src & dst ip + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_src_offset + #filterPallette config -pattern1\ + # [host2addr $src_ip1][host2addr $dst_ip1] + #filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $src_ip1][host2addr $dst_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00 00 00 00 00} " + + keylset return_list stat1.type src_dst_ip + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.dst_ip $dst_ip1 + + set filters_available [expr $filters_available - 1] + } + + prec { + #Ensure prec was passed + if {![info exists prec1]} { + error "\nYou need to pass prec1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for prec + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_tos_offset " + + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [format %x $shiftedPrec] + #filterPallette config -pattern1 $hexShiftedPrec + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $hexShiftedPrec " + #Only look at upper 3 bits of TOS byte + #filterPallette config -patternMask1 {1f} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {1f} " + keylset return_list stat1.type prec + keylset return_list stat1.prec $prec1 + + set filters_available [expr $filters_available - 1] + } + + dscp { + #Ensure dscp1 was passed + if {![info exists dscp1]} { + error "\nYou need to pass dscp1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for dscp + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_tos_offset " + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [format %x $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[format %x $shiftedDscp] + } + #filterPallette config -pattern1 $hexShiftedDscp + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $hexShiftedDscp " + #Only look at upper 6 bits of TOS byte + #filterPallette config -patternMask1 {03} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {03} " + + keylset return_list stat1.type dscp + keylset return_list stat1.dscp $dscp1 + + set filters_available [expr $filters_available - 1] + } + tos { + #Ensure tos1 was passed + if {![info exists tos1]} { + error "\nYou need to pass tos1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for tos + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_tos_offset " + if {$tos1 > 15} { + #set hexTos1 [dectohex $tos1] + set hexTos1 [format %x $tos1] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + #set hexTos1 0[dectohex $tos1] + set hexTos1 0[format %x $tos1] + } + + #filterPallette config -pattern1 $hexTos1 + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $hexTos1 " + + #look at all bits of TOS byte + #filterPallette config -patternMask1 {00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00} " + + keylset return_list stat1.type tos + keylset return_list stat1.tos $tos1 + + set filters_available [expr $filters_available - 1] + } + ecn { + #Ensure tos1 was passed + if {![info exists ecn1]} { + error "\nYou need to pass ecn1 to ixia_add_rx_filter\n\n" + } + #Configure UDF1 for ecn + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_tos_offset " + + #Prepend 0 as ecn will only ever produce a nibble + set hex_ecn1 0[format %x $ecn1] + + #filterPallette config -pattern1 $hex_ecn1 + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $hex_ecn1 " + + #only look at ecn bits of TOS byte + #filterPallette config -patternMask1 {F8} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {F8} " + + keylset return_list stat1.type ecn + keylset return_list stat1.tos $ecn1 + + set filters_available [expr $filters_available - 1] + } + cos { + #Ensure tos1 was passed + if {![info exists cos1]} { + error "\nYou need to pass cos1 to ixia_add_rx_filter\n\n" + } + + if {![string match $rx_port_encaps "dot1q"]} { + error "\ncos filtering is only supported with dot1q encaps\n\n" + } + #Configure UDF1 for cos + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $cos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $cos_offset " + set shifted_cos1 [expr $cos1 << 1] + set hex_cos1 [format %x $shifted_cos1] + + #filterPallette config -pattern1 $hex_cos1 + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $hex_cos1 " + + #look at only first 3 bits of nibble - 4th is CFI bit + #Since ixia programs a byte mask out second nibble + #filterPallette config -patternMask1 {1F} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {1F} " + #filterPallette set $chassis $card $port + + keylset return_list stat1.type cos + keylset return_list stat1.cos $cos1 + + set filters_available [expr $filters_available - 1] + } + src_ip_prec { + #Ensure src_ip1 & prec1 were passed + if {!([info exists src_ip1]) || !([info exists prec1])} { + error "\nYou need to pass src_ip1 and prec1 to \ + ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1AndPattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1AndPattern2 " + + #filterPallette setDefault + #pattern 1 = src ip - UDF1 + #filterPallette config -patternOffset1 $ip_src_offset + #filterPallette config -pattern1 [host2addr $src_ip1] + #filterPallette config -patternMask1 {00 00 00 00} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $src_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00} " + + #pattern 2 = prec - UDF2 + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [format %x $shiftedPrec] + filterPallette config -pattern2 $hexShiftedPrec + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedPrec " + #Only look at upper 3 bits of TOS byte + #filterPallette config -patternMask2 {1f} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {1f} " + + keylset return_list stat1.type src_ip_prec + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.prec $prec1 + + set filters_available [expr $filters_available - 2] + } + + dst_ip_prec { + #Ensure dst_ip1 & prec1 were passed + if {!([info exists dst_ip1]) || !([info exists prec1])} { + error "\nYou need to pass dst_ip1 and prec1\ + to ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "\nYou can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'\n\n" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1AndPattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1AndPattern2 " + + #filterPallette setDefault + #pattern 1 = dst ip - UDF1 + #filterPallette config -patternOffset1 $ip_dst_offset + #filterPallette config -pattern1 [host2addr $dst_ip1] + #filterPallette config -patternMask1 {00 00 00 00} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_dst_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $dst_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00} " + + #pattern 2 = prec - UDF2 + #filterPallette config -patternOffset2 $ip_tos_offset + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [format %x $shiftedPrec] + #filterPallette config -pattern2 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + #filterPallette config -patternMask2 {1f} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedPrec " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {1f} " + + keylset return_list stat1.type dst_ip_prec + keylset return_list stat1.dst_ip $dst_ip + keylset return_list stat1.prec $prec + + set filters_available [expr $filters_available - 2] + } + + src_dst_ip_prec { + #Ensure src_ip1 & dst_ip1 and prec1 were passed + if {!([info exists src_ip1]) || !([info exists dst_ip1]) \ + || !([info exists prec1])} { + error "\nYou need to pass src_ip1, dst_ip1 and prec1\ + \nto ixia_add_rx_filter\n\n" + } + + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1AndPattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1AndPattern2 " + + #filterPallette setDefault + #pattern1 = src ip and dst ip - UDF1 + #filterPallette config -patternOffset1 $ip_src_offset + #filterPallette config -pattern1 \ + # [host2addr $src_ip1][host2addr $dst_ip1] + #filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $src_ip1][host2addr $dst_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00 00 00 00 00} " + #pattern 2 = prec + #filterPallette config -patternOffset2 $ip_tos_offset + set shiftedPrec [expr $prec1 << 5] + set hexShiftedPrec [format %x $shiftedPrec] + #filterPallette config -pattern2 $hexShiftedPrec + #Only look at upper 3 bits of TOS byte + #filterPallette config -patternMask2 {1f} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedPrec " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {1f} " + + keylset return_list stat1.type src_dst_ip_prec + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.dst_ip $dst_ip1 + keylset return_list stat1.prec $prec1 + + set filters_available [expr $filters_available - 2] + } + + src_ip_dscp { + #Ensure src_ip & dscp were passed + if {!([info exists src_ip1]) || !([info exists dscp1])} { + error "You need to pass src_ip1 and dscp1 to ixia_add_rx_filter" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1AndPattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1AndPattern2 " + + #filterPallette setDefault + #pattern 1 = src ip - UDF1 + #filterPallette config -patternOffset1 $ip_src_offset + #filterPallette config -pattern1 [host2addr $src_ip1] + #filterPallette config -patternMask1 {00 00 00 00} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $src_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00} " + #pattern 2 = dscp - UDF2 + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [format %x $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[format %x $shiftedDscp] + } + #filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + #filterPallette config -patternMask2 {03} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedDscp " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {03} " + + keylset return_list stat1.type src_ip_dscp + keylset return_list stat1.src_ip $src_ip + keylset return_list stat1.dscp $dscp + + set filters_available [expr $filters_available - 2] + } + + dst_ip_dscp { + #Ensure src_ip1 & dscp1 were passed + if {!([info exists dst_ip1]) || !([info exists dscp1])} { + error "\nYou need to pass dst_ip1 and dscp1\ + to ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "\nYou can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'\n\n" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1AndPattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1AndPattern2 " + + #filterPallette setDefault + #pattern 1 = dst ip - UDF1 + #filterPallette config -patternOffset1 $ip_dst_offset + #filterPallette config -pattern1 [host2addr $dst_ip1] + #filterPallette config -patternMask1 {00 00 00 00} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_dst_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $dst_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00} " + + #pattern 2 = dscp + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [format %x $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[format %x $shiftedDscp] + } + #filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + #filterPallette config -patternMask2 {03} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedDscp " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {03} " + keylset return_list stat1.type dst_ip_dscp + keylset return_list stat1.dst_ip $dst_ip1 + keylset return_list stat1.dscp $dscp1 + + set filters_available [expr $filters_available - 2] + } + + src_dst_ip_dscp { + #Ensure src_ip1, dst_ip1 and dscp1 were passed + if {!([info exists src_ip1]) || !([info exists dst_ip1]) \ + || !([info exists dscp1])} { + error "\nYou need to pass src_ip1, dst_ip1 and dscp1\ + \nto ixia_add_rx_filter\n\n" + } + #Check receive mode is 'capture' - otherwise only 1 user + #defined stat available + if {$filters_available != 2} { + error "You can only define one pattern when IXIA receive mode \ + \nis anything other than \'Capture\'" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1AndPattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1AndPattern2 " + + #filterPallette setDefault + #pattern1 = src ip and dst ip - UDF1 + #filterPallette config -patternOffset1 $ip_src_offset + #filterPallette config -pattern1 \ + # [host2addr $src_ip1][host2addr $dst_ip1] + #filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 [host2addr $src_ip1][host2addr $dst_ip1] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {00 00 00 00 00 00 00 00} " + + #pattern 2 = dscp - UDF2 + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set shiftedDscp [expr $dscp1 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [format %x $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[format %x $shiftedDscp] + } + #filterPallette config -pattern2 $hexShiftedDscp + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedDscp " + #Only look at upper 6 bits of TOS byte + #filterPallette config -patternMask2 {03} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {03} " + + keylset return_list stat1.type src_dst_ip_dscp + keylset return_list stat1.src_ip $src_ip1 + keylset return_list stat1.dst_ip $dst_ip1 + keylset return_list stat1.dscp $dscp1 + + set filters_available [expr $filters_available - 2] + } + + fr_de { + #Ensure fr_de1 was passed + if {![info exists fr_de1]} { + error "\nYou need to pass fr_de1 to ixia_add_rx_filter\n\n" + } + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $fr_de_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $fr_de_offset " + set shiftedFrDe [expr $fr_de1 << 1] + set hexShiftedFrDe [format %x $shiftedFrDe] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + #filterPallette config -pattern1 "00 0$hexShiftedFrDe" + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 '00 0$hexShiftedFrDe' " + #Only look at significant 1 bit of 3 fr bytes + #filterPallette config -patternMask1 {ff fd} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 {ff fd} " + + keylset return_list stat1.type fr_de + keylset return_list stat1.fr_de $fr_de1 + + set filters_available [expr $filters_available - 1] + } + + mpls_exp { + #Ensure mpls_exp1 was passed + if {![info exists mpls_exp1]} { + error "\nYou need to pass mpls_exp1 to ixia_add_rx_filter\n\n" + } + + #Configure UDS1 + #filter setDefault + #filter config -userDefinedStat1Enable true + #filter config -userDefinedStat1Pattern pattern1 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern1 " + + #filterPallette setDefault + #filterPallette config -patternOffset1 $mpls_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset1 $mpls_offset " + + #First Label + set shiftedMplsExp [expr $mpls_exp1 << 1] + set hexShiftedMplsExp [format %x $shiftedMplsExp] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + set exp1_pattern "00 00 0$hexShiftedMplsExp 00" + + #Add second label to pattern if required + if {[info exists mpls_exp1_label2]} { + set shifted_mpls_exp1_label2 [expr $mpls_exp1_label2 << 1] + set hex_shifted_mpls_exp1_label2 \ + [dectohex $shifted_mpls_exp1_label2] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + set exp1_label2_pattern \ + " 00 00 0$hex_shifted_mpls_exp1_label2 00" + + append exp1_pattern $exp1_label2_pattern + } + + #filterPallette config -pattern1 $exp1_pattern + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $exp1_pattern " + + #Only look at significant 3 bits of mpls exp byte + set mask_to_program "ff ff f1 ff" + + #Add mask for second label if necessary + if {[info exists mpls_exp1_label2]} { + append mask_to_program " ff ff f1 ff" + } + + #filterPallette config -patternMask1 $mask_to_program + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask1 $mask_to_program " + + keylset return_list stat1.type mpls_exp + keylset return_list stat1.mpls_exp $mpls_exp1 + if {[info exists mpls_exp1_label2]} { + keylset return_list stat1.mpls_exp_label2 $mpls_exp1_label2 + } + + set filters_available [expr $filters_available - 1] + } + + default { + error "\nstat_key1 \'$stat_key1\' passed to\ + ixia_add_rx_filter is not supported\n\n" + } + } ;# end switch $stat_key1 + + + + #Configure the second stat only if requested + if {[info exists stat_key2]} { + switch $stat_key2 { + src_ip { + #Ensure src_ip2 was passed + if {![info exists src_ip2]} { + error "\nYou need to pass src_ip2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for src ip + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_src_offset + #filterPallette config -pattern2 [host2addr $src_ip2] + #filterPallette config -patternMask2 {00 00 00 00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 [host2addr $src_ip2] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {00 00 00 00} " + + keylset return_list stat2.type src_ip + keylset return_list stat2.src_ip $src_ip2 + } + + dst_ip { + #Ensure dst_ip2 was passed + if {![info exists dst_ip2]} { + error "\nYou need to pass dst_ip2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for dst ip + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_dst_offset + #filterPallette config -pattern2 [host2addr $dst_ip2] + #filterPallette config -patternMask2 {00 00 00 00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_dst_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 [host2addr $dst_ip2] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {00 00 00 00} " + + keylset return_list stat2.type dst_ip + keylset return_list stat2.dst_ip $dst_ip2 + } + + src_dst_ip { + #Ensure src_ip2 & dst_ip2 were passed + if {!([info exists src_ip2]) || !([info exists dst_ip2])} { + error "\nYou need to pass src_ip2 and dst_ip2 to\ + ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for src & dst ip + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_src_offset + #filterPallette config -pattern2\ + # [host2addr $src_ip2][host2addr $dst_ip2] + #filterPallette config -patternMask1 {00 00 00 00 00 00 00 00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_src_offset " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 [host2addr $src_ip2][host2addr $dst_ip2] " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {00 00 00 00 00 00 00 00} " + + keylset return_list stat2.type src_dst_ip + keylset return_list stat2.src_ip $src_ip2 + keylset return_list stat2.dst_ip $dst_ip2 + } + + prec { + #Ensure prec2 was passed + if {![info exists prec2]} { + error "\nYou need to pass prec2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for prec + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set shiftedPrec [expr $prec2 << 5] + set hexShiftedPrec [format %x $shiftedPrec] + #filterPallette config -pattern2 $hexShiftedPrec + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedPrec " + #Only look at upper 3 bits of TOS byte + #filterPallette config -patternMask2 {1f} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {1f} " + + keylset return_list stat2.type prec + keylset return_list stat2.prec $prec2 + } + + dscp { + #Ensure dscp2 was passed + if {![info exists dscp2]} { + error "\nYou need to pass dscp2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for dscp + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set shiftedDscp [expr $dscp2 << 2] + if {$shiftedDscp > 15} { + set hexShiftedDscp [format %x $shiftedDscp] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + set hexShiftedDscp 0[format %x $shiftedDscp] + } + #filterPallette config -pattern2 $hexShiftedDscp + #Only look at upper 6 bits of TOS byte + #filterPallette config -patternMask2 {03} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexShiftedDscp " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {03} " + + keylset return_list stat2.type dscp + keylset return_list stat2.dscp $dscp2 + } + tos { + #Ensure tos2 was passed + if {![info exists tos2]} { + error "\nYou need to pass tos2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for tos + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + if {$tos2 > 15} { + #set hexTos2 [dectohex $tos2] + set hexTos2 [format %x $tos2] + } else { + #dectohex will only produce a nibble if $dec < 15 + #need to add the leading 0 to create a byte + #set hexTos2 0[dectohex $tos2] + set hexTos2 0[format %x $tos2] + } + + #filterPallette config -pattern2 $hexTos2 + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hexTos2 " + + #Only look at all 8 bits of TOS byte + #filterPallette config -patternMask2 {00} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {00} " + + keylset return_list stat2.type tos + keylset return_list stat2.tos $tos2 + } + ecn { + #Ensure tos2 was passed + if {![info exists ecn2]} { + error "\nYou need to pass ecn2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 for tos + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $ip_tos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $ip_tos_offset " + set hex_ecn2 0[format %x $ecn2] + #filterPallette config -pattern2 $hex_ecn2 + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $hex_ecn2 " + + #Only look at ecn bits of TOS byte + #filterPallette config -patternMask2 {F8} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {F8} " + + keylset return_list stat2.type ecn + keylset return_list stat2.tos $ecn2 + } + cos { + #Ensure tos1 was passed + if {![info exists cos2]} { + error "\nYou need to pass cos2 to ixia_add_rx_filter\n\n" + } + + if {![string match $rx_port_encaps "dot1q"]} { + error "\ncos filtering is only supported with dot1q\ + encaps\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDF2 for cos + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $cos_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $cos_offset " + set shifted_cos2 [expr $cos2 << 1] + set hex_cos2 [format %x $shifted_cos2] + + #filterPallette config -pattern1 $hex_cos2 + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern1 $hex_cos2 " + #look at only first 3 bits of nibble - 4th is CFI bit + #Since ixia programs a byte mask out second nibble + #filterPallette config -patternMask2 {1F} + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {1F} " + #filterPallette set $chassis $card $port + + keylset return_list stat2.type cos + keylset return_list stat2.cos $cos2 + } + + fr_de { + #Ensure fr_de2 was passed + if {![info exists fr_de2]} { + error "\nYou need to pass fr_de2 to ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + #Configure UDS2 + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $fr_de_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $fr_de_offset " + set shiftedFrDe [expr $fr_de2 << 1] + set hexShiftedFrDe [format %x $shiftedFrDe] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + #filterPallette config -pattern2 "00 0$hexShiftedFrDe" + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 '00 0$hexShiftedFrDe' " + #Only look at significant 1 bit of 3 fr bytes + #filterPallette config -patternMask2 {ff fd} + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 {ff fd} " + + keylset return_list stat2.type fr_de + keylset return_list stat2.fr_de $fr_de2 + } + + mpls_exp { + #Ensure mpls_exp2 was passed + if {![info exists mpls_exp2]} { + error "\nYou need to pass mpls_exp2 to\ + ixia_add_rx_filter\n\n" + } + #Check there is still a filter available + if {!($filters_available)} { + error "\nThere is no filter available to configure the\ + second statistic filter in ixia_add_rx_filter.\ + \nCheck the port is in 'capture mode' and that the\ + first statistic only requires one filter.\n\n" + } + + #Configure UDS2 + #filter config -userDefinedStat2Enable true + #filter config -userDefinedStat2Pattern pattern2 + #filter set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterFrameSizeEnable true " + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filter -captureFilterPattern pattern2 " + + #filterPallette config -patternOffset2 $mpls_offset + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternOffset2 $mpls_offset " + set shiftedMplsExp [expr $mpls_exp2 << 1] + set hexShiftedMplsExp [format %x $shiftedMplsExp] + #dectohex only returns a nibble if value < 15 - which it always + #will be hence add 0 before this value to create byte + set exp2_pattern "00 00 0$hexShiftedMplsExp 00" + + + #Add second label to pattern if required + if {[info exists mpls_exp2_label2]} { + set shifted_mpls_exp2_label2 [expr $mpls_exp2_label2 << 1] + set hex_shifted_mpls_exp2_label2 \ + [dectohex $shifted_mpls_exp2_label2] + #dectohex only returns a nibble if value < 15 - which it + #always will be hence add 0 before this value to create byte + set exp2_label2_pattern \ + " 00 00 0$hex_shifted_mpls_exp2_label2 00" + + append exp2_pattern $exp2_label2_pattern + } + + + #filterPallette config -pattern2 $exp2_pattern + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -pattern2 $exp2_pattern " + + #Only look at significant 3 bits of mpls exp byte + set mask_to_program "ff ff f1 ff" + + #Add mask for second label if necessary + if {[info exists mpls_exp2_label2]} { + append mask_to_program " ff ff f1 ff" + } + + + #filterPallette config -patternMask2 $mask_to_program + #filterPallette set $chassis $card $port + interp eval $::ixia::TclInterp " ixNet setMultiAttribute $vportHandle/capture/filterPallette -patternMask2 $mask_to_program " + keylset return_list stat2.type mpls_exp + keylset return_list stat2.mpls_exp $mpls_exp2 + if {[info exists mpls_exp2_label2]} { + keylset return_list stat2.mpls_exp_label2 $mpls_exp2_label2 + } + } + + default { + error "\nstat_key2 \'$stat_key2\' passed to\ + ixia_add_rx_filter is not supported\n\n" + } + + };# End switch $stat_key2 + } ;#end if info exists stat_key2 + + #port set $chassis $card $port + #port write $chassis $card $port + + return $return_list + } +} + + + +########################################################################## + + +procDescr vtmsIxiaUtils::pps2bps { + + Author: Michael Fingleton + Date: Jun 2005 + + Description: + Procedure to take a receive rate in Packets Per Second (PPS) and + translate this to Bits Per Second (BPS). + This procedure is only useful when all packets being received are of + a fixed and known packet length. + + The calculated bps is returned in a number of formats: + l2_datagram_bps :includes only datagram + l2_header_bps :includes L2 header bytes, including MPLS labels + l2_frame_bps :includes L2 header and CRC bytes + l2_all_bps :includes all mandatroy per packet inter packet + overhead. + + For further clarrification see the procDescr for ixia_measure_rates above. + + Usage: + pps2bps -pps \ + -encaps \ + -datagram_length \ + [-num_labels ] + Returns: + A keyed list with a key for each of the rates. + + Example: + set ret [pps2bps -pps 10 -encaps arpa -datagram_length 20] + + returns: + l2_datagram_bps = 1600 + l2_header_bps = 2720 + l2_frame_bps = 3040 + l2_all_bps = 4640 +} + + +proc vtmsIxiaUtils::pps2bps {args} { + + #mandatory args + set man_args { + -pps NUMERIC + -encaps CHOICES arpa dot1q hdlc ppp fr + -datagram_length NUMERIC + } + + # optional_args + set opt_args { + -num_labels RANGE 0-4 + DEFAULT 0 + -crc_len RANGE 2-4 + } + + parse_dashed_args -args $args -mandatory_args $man_args \ + -optional_args $opt_args + + set return_list {} + + switch $encaps { + arpa { + set l2_header_len 14 + if {![info exists crc_len]} { + set crc_len 4 + } + set inter_frame_overhead 20 + } + dot1q { + set l2_header_len 18 + if {![info exists crc_len]} { + set crc_len 4 + } + set inter_frame_overhead 20 + } + hdlc { + set l2_header_len 4 + if {![info exists crc_len]} { + set crc_len 2 + } + set inter_frame_overhead 1 + } + ppp { + set l2_header_len 4 + if {![info exists crc_len]} { + set crc_len 2 + } + set inter_frame_overhead 1 + } + fr { + set l2_header_len 4 + if {![info exists crc_len]} { + set crc_len 2 + } + set inter_frame_overhead 1 + } + default { + error "\nencaps passed to pps2bps is not supported\n\n" + } + } ;# end switch encaps + + set l2_datagram_bps [expr $pps * $datagram_length * 8] + + set l2_header_bps [expr ($pps * 8 *(($num_labels * 4) + $l2_header_len)) \ + + $l2_datagram_bps] + + set l2_frame_bps [expr ($pps * 8 * $crc_len) + $l2_header_bps] + + set l2_all_bps [expr ($pps * 8 * $inter_frame_overhead) + $l2_frame_bps] + + keylset return_list l2_datagram_bps $l2_datagram_bps + keylset return_list l2_header_bps $l2_header_bps + keylset return_list l2_frame_bps $l2_frame_bps + keylset return_list l2_all_bps $l2_all_bps + + return $return_list +} + +########################################################################## + + +procDescr vtmsIxiaUtils::ixia_read_stats { + + Author: Michael Fingleton + Date: Jun 2005 + + Description: + This proc is to read a subset of the statistics from an Ixia port + and put them into a keyed list. + This proc only reads aggregate values and not rates - if you want rates + use ixia_measure_rates + + Usage: + ixia_read_stats + + Example: + ixia_read_stats {1 1 1} + + Returns: + A keyed list with keys as follows: + rx_bytes + rx_frames + tx_bytes + tx_frames + user_stat1_frames + user_stat2_frames +} + +proc vtmsIxiaUtils::ixia_read_stats {args} { + + #mandatory args + set man_args { + -port SHIFT + LIST_SIZE 1 + } + + # optional_args + set opt_args { + -tgen_app CHOICES IxExplorer IxNetwork + DEFAULT IxNetwork + } + + parse_dashed_args -args $args -mandatory_args $man_args -optional_args $opt_args + + set return_list {} + if {$tgen_app == "IxExplorer"} { + #Grep port info + if {![regexp {(\d+) +(\d+) +(\d+)} $port - chassis card port]} { + error "port format should be like {1 5 1} - was passed $port" + } + + stat get allStats $chassis $card $port + + #Read IXIA Results + set rx_bytes [stat cget -bytesReceived] + set rx_frames [stat cget -framesReceived] + set tx_bytes [stat cget -bytesSent] + set tx_frames [stat cget -framesSent] + set user_stat1_frames [stat cget -userDefinedStat1] + set user_stat2_frames [stat cget -userDefinedStat2] + + + keylset return_list rx_bytes $rx_bytes + keylset return_list rx_frames $rx_frames + keylset return_list tx_bytes $tx_bytes + keylset return_list tx_frames $tx_frames + keylset return_list user_stat1_frames $user_stat1_frames + keylset return_list user_stat2_frames $user_stat2_frames + + return $return_list + } + if {$tgen_app == "IxNetwork"} { + #debug 1 + regexp -nocase {(\d+) (\d+) (\d+)} $port match chassis card port0 + set port1 $chassis/$card/$port0 + set rxStats [::ixia::traffic_stats -port_handle $port1] + keylset return_list rx_bytes [keylget rxStats $port1.aggregate.rx.pkt_byte_count] + keylset return_list rx_frames [keylget rxStats $port1.aggregate.rx.raw_pkt_count] + keylset return_list tx_bytes [keylget rxStats $port1.aggregate.tx.pkt_byte_count] + keylset return_list tx_frames [keylget rxStats $port1.aggregate.tx.tx_aal5_scheduled_frames_count] + keylset return_list user_stat1_frames [keylget rxStats $port1.aggregate.rx.uds1_frame_count] + keylset return_list user_stat2_frames [keylget rxStats $port1.aggregate.rx.uds2_frame_count] + return $return_list + } + +} + +procDescr vtmsIxiaUtils::underbar_ixia_port { + Usage: + underbar_ixia_port + + Description: + Will take an ixia port in the format {1 15 1} and return 1_15_1 + This is useful when accessing keyekd lists where one of the keys + is the ixia port in underbar format + + Returns: port with underbars - eg 1_15_1 +} + +proc vtmsIxiaUtils::underbar_ixia_port {port} { + set ix_chassis [lindex $port 0] + set ix_card [lindex $port 1] + set ix_port [lindex $port 2] + + return $ix_chassis\_$ix_card\_$ix_port +} + +################################################################################ +#Calculate per packet cell tax # +################################################################################ +##Procedure Header +# +# Name: _calc_per_pkt_cell_tax +# +# Author: Michael Fingleton +# +# Support Alias: +# mrr-scripting@cisco.com +# +# Usage: +# _calc_per_pkt_cell_tax -datagram_len +# -aal_header_len +# -aal_trailer_len +# +# +# Purpose / Description : +# When calculating a tx rate including cell tax we need to know how many extra +# bytes will be sent per packet + + +proc _calc_per_pkt_cell_tax {args} { + + set man_args { + -datagram_len ANY + -aal_header_len CHOICES 2 8 2.0 8.0 + -aal_trailer_len CHOICES 8 8.0 + } + + + parse_dashed_args -args $args -mandatory_args $man_args + + if {$datagram_len == "imix"} { + set avg_imix_datagram_len 335.83 + + set 46_atm_pdu_length [expr 46 + $aal_header_len + $aal_trailer_len] + set 552_atm_pdu_length [expr 552 + $aal_header_len + $aal_trailer_len] + set 1500_atm_pdu_length [expr 1500 + $aal_header_len + $aal_trailer_len] + + set 46_atm_pdu_length [expr round($46_atm_pdu_length)] + set 552_atm_pdu_length [expr round($552_atm_pdu_length)] + set 1500_atm_pdu_length [expr round($1500_atm_pdu_length)] + + if { [ expr ($46_atm_pdu_length % 48) ] } { + set cell_per_46_pkt [ expr ($46_atm_pdu_length / 48) + 1 ] + } else { + set cell_per_46_pkt [ expr ($46_atm_pdu_length / 48) ] + } + + if { [ expr ($552_atm_pdu_length % 48) ] } { + set cells_per_552_pkt [ expr ($552_atm_pdu_length / 48) + 1 ] + } else { + set cells_per_552_pkt [ expr ($552_atm_pdu_length / 48) ] + } + + if { [ expr ($1500_atm_pdu_length % 48) ] } { + set cells_per_1500_pkt [ expr ($1500_atm_pdu_length / 48) + 1 ] + } else { + set cells_per_1500_pkt [ expr ($1500_atm_pdu_length / 48) ] + } + + #Calculate The Total Number of Cells for one IMIX Block (12 packets) + set total_imix_cell_count [expr (7 * $cell_per_46_pkt) \ + + (4 * $cells_per_552_pkt) \ + + (1 * $cells_per_1500_pkt)] + + set total_imix_byte_count [expr $total_imix_cell_count * 53.0] + set avg_bytes_per_imix_pkt [expr $total_imix_byte_count / 12.0] + set avg_imix_overhead [expr $avg_bytes_per_imix_pkt \ + - $avg_imix_datagram_len] + return $avg_imix_overhead + } else { + #This section for single length datagram + set atm_pdu_len [expr $datagram_len + $aal_header_len \ + + $aal_trailer_len] + + #Ensure datagram length is integer (shouyld be) + set atm_pdu_len [expr round($atm_pdu_len)] + + if { [ expr ($atm_pdu_len % 48) ] } { + set cells_per_pkt [ expr ($atm_pdu_len / 48) + 1 ] + } else { + set cells_per_pkt [ expr ($atm_pdu_len / 48) ] + } + + set bytes_inc_cell_tax [expr $cells_per_pkt * 53.0] + set cell_tax_overhead [expr $bytes_inc_cell_tax - $datagram_len] + return $cell_tax_overhead + } +} + +################################################################################ +#Calculate average IMIX length including cell tax # +################################################################################ +procDescr _calc_avg_imix_bytes_with_cell_tax { + + Author: Michael Fingleton + Date: October 2008 + + Usage: + _calc_avg_imix_bytes_with_cell_tax \ + -aal_header_len \ + -aal_trailer_len + + Description: + Internal procedure to claculate what's the average length of an IMIX + packet when all cell tax is included. + Note - proc assumes proper Cisco imix - 12 packet distribution + with 7:4:1 46, 552 and 1500 byte datagrams + + Returns: + Average length in bytes +} + + +proc _calc_avg_imix_bytes_with_cell_tax {args} { + + set man_args { + -aal_header_len CHOICES 2 8 2.0 8.0 + -aal_trailer_len CHOICES 8 8.0 + } + + + parse_dashed_args -args $args -mandatory_args $man_args + + + set 46_atm_pdu_length [expr 46 + $aal_header_len + $aal_trailer_len] + set 552_atm_pdu_length [expr 552 + $aal_header_len + $aal_trailer_len] + set 1500_atm_pdu_length [expr 1500 + $aal_header_len + $aal_trailer_len] + + set 46_atm_pdu_length [expr round($46_atm_pdu_length)] + set 552_atm_pdu_length [expr round($552_atm_pdu_length)] + set 1500_atm_pdu_length [expr round($1500_atm_pdu_length)] + + if { [ expr ($46_atm_pdu_length % 48) ] } { + set cell_per_46_pkt [ expr ($46_atm_pdu_length / 48) + 1 ] + } else { + set cell_per_46_pkt [ expr ($46_atm_pdu_length / 48) ] + } + + if { [ expr ($552_atm_pdu_length % 48) ] } { + set cells_per_552_pkt [ expr ($552_atm_pdu_length / 48) + 1 ] + } else { + set cells_per_552_pkt [ expr ($552_atm_pdu_length / 48) ] + } + + if { [ expr ($1500_atm_pdu_length % 48) ] } { + set cells_per_1500_pkt [ expr ($1500_atm_pdu_length / 48) + 1 ] + } else { + set cells_per_1500_pkt [ expr ($1500_atm_pdu_length / 48) ] + } + + #Calculate The Total Number of Cells for one IMIX Block (12 packets) + set total_imix_cell_count [expr (7 * $cell_per_46_pkt) \ + + (4 * $cells_per_552_pkt) \ + + (1 * $cells_per_1500_pkt)] + + set total_imix_byte_count [expr $total_imix_cell_count * 53.0] + set avg_bytes_per_imix_pkt [expr $total_imix_byte_count / 12.0] + return $avg_bytes_per_imix_pkt +} + + +###################################################################### + +procDescr vtmsIxiaUtils::ixia_measure_vc_rates { + + Author: Michael Fingleton + Date: October 2008 + + Usage: + ixia_measure_vc_rates \ + [-tx_port_list ] \ + [-rx_port_list ] \ + [-measure_interval ] + + + Example: + set traffic_stats [ixia_measure_vc_rates \ + -tx_port_list 1/1/1 \ + -rx_port_list 1/1/2 \ + -measure_interval 300 ] + + + Description / Arguments: + + -tx_ports : List of ports on which we will measure / calculate tx rates + + -rx_ports : List of ports on which we will measure / calculate rx rates + + -measure_interval : Number of seconds over which rates are calculated. + It seems the ixia per VC stats are not updated very + regularly so this interval needs to be long (~300 sec) + to achieve a reasonable accurate result + + Notes:- + + -Proc requires Ixia HLTAPI + + - Proc assumes VCs of interest have already being registered on the tx + and rx ports + + - rx_ports & tx_ports are both optional but one or the other must + be passed + + + Returns a keyed list with structure as folows: + tx_port + + vp + + vc + + initial_tx_cells + final_tx_cells + tx_cells + tx_cells_per_sec + tx_bps_cell + tx_bps_cell_no_hec + aggregate + tx_cells + tx_cells_per_sec + tx_bps_cell + tx_bps_cell_no_hec + rx_port + + vp + + vc + + initial_rx_cells + final_rx_cells + rx_cells + rx_cells_per_sec + rx_bps_cell + rx_bps_cell_no_hec + aggregate + rx_cells + rx_cells_per_sec + rx_bps_cell + rx_bps_cell_no_hec + + + + Notes on returned values: + + With cell based QOS there are really two rates that are of interest. + + 1. When looking at physical link utilization or when testing accuracy of SAR + shaping we need to include entire cell (53 bytes) in all calculations. + The rate counting 53 bytes per cell is returned in the key rate_bps_cell + + 2. For some obscure reason IOS only counts 52 bytes per cell in any + policing / scheduling calculations. I assume this is because HEC byte is + added by SAR so the cell is actually just 52 bytes before it is sent to SPA. + The key rx_bps_cell_no_hec returns a rate which only includes 52 bytes per + cell. This rate should be used when testing policer/scheduling accuracy. + + For an example of how to configure ixia ATM ports and register VCs look + at the atom_vp_qos script in functionality/MCP/qos directory +} + + +proc vtmsIxiaUtils::ixia_measure_vc_rates {args} { + + set opt_args { + -tx_port_list REGEXP ^[0-9]+/[0-9]+/[0-9]+$ + -rx_port_list REGEXP ^[0-9]+/[0-9]+/[0-9]+$ + -measure_interval RANGE 10-600 + DEFAULT 300 + } + parse_dashed_args -args $args -optional_args $opt_args + + + #Verify user passed us at least one of tx_port_list or rx_port_list + if {(![info exists tx_port_list]) && (![info exists rx_port_list])} { + error "tx_port_list and/or rx_port_list must be passed" + } + + + #Create one list with tx and rx ports + if {([info exists tx_port_list]) && ([info exists rx_port_list])} { + set all_port_list [concat $tx_port_list $rx_port_list] + } elseif {[info exists tx_port_list]} { + set all_port_list $tx_port_list + } else { + set all_port_list $rx_port_list + } + + #Read packet throughput stats + set initial_stats_list [ixia::traffic_stats -port_handle $all_port_list] + + #Sleep for the specified measure_interval + sleep $measure_interval + + #Read the final stats + set final_stats_list [ixia::traffic_stats -port_handle $all_port_list] + + + if {[info exists tx_port_list]} { + #Initial tx_cell counts + foreach tx_port $tx_port_list { + + set possible_vp_list [keylkeys initial_stats_list \ + $tx_port.aggregate.tx] + + set actual_vp_list "" + foreach key $possible_vp_list { + if {[regexp {^([0-9]+)$} $key - found_vp]} { + lappend actual_vp_list $found_vp + } + } + foreach vp $actual_vp_list { + set vc_list [keylkeys initial_stats_list \ + $tx_port.aggregate.tx.$vp] + + foreach vc $vc_list { + set trimmed_vc [string trimleft $vc 0] + set tx_cells [keylget initial_stats_list \ + $tx_port.aggregate.tx.$vp.$vc.tx_atm_cells_count] + + keylset ret_list \ + tx_port.$tx_port.vp.$vp.vc.$trimmed_vc.initial_tx_cells \ + $tx_cells + } + } + } + } + + + if {[info exists rx_port_list]} { + #Initial rx_cell counts + foreach rx_port $rx_port_list { + + set possible_vp_list [keylkeys initial_stats_list \ + $rx_port.aggregate.rx] + + set actual_vp_list "" + foreach key $possible_vp_list { + if {[regexp {^([0-9]+)$} $key - found_vp]} { + lappend actual_vp_list $found_vp + } + } + foreach vp $actual_vp_list { + + set vc_list [keylkeys initial_stats_list \ + $rx_port.aggregate.rx.$vp] + + foreach vc $vc_list { + set trimmed_vc [string trimleft $vc 0] + set rx_cells [keylget initial_stats_list \ + $rx_port.aggregate.rx.$vp.$vc.rx_atm_cells_count] + + keylset ret_list \ + rx_port.$rx_port.vp.$vp.vc.$trimmed_vc.initial_rx_cells \ + $rx_cells + } + } + } + } + + if {[info exists tx_port_list]} { + #Final tx_cell counts + foreach tx_port $tx_port_list { + + set possible_vp_list [keylkeys final_stats_list \ + $tx_port.aggregate.tx] + + set actual_vp_list "" + foreach key $possible_vp_list { + if {[regexp {^([0-9]+)$} $key - found_vp]} { + lappend actual_vp_list $found_vp + } + } + foreach vp $actual_vp_list { + + set vc_list [keylkeys final_stats_list \ + $tx_port.aggregate.tx.$vp] + + foreach vc $vc_list { + set trimmed_vc [string trimleft $vc 0] + set tx_cells [keylget final_stats_list \ + $tx_port.aggregate.tx.$vp.$vc.tx_atm_cells_count] + + keylset ret_list \ + tx_port.$tx_port.vp.$vp.vc.$trimmed_vc.final_tx_cells \ + $tx_cells + } + } + } + } + + + #Final rx_cell counts + if {[info exists rx_port_list]} { + + foreach rx_port $rx_port_list { + + set possible_vp_list [keylkeys final_stats_list \ + $rx_port.aggregate.rx] + + set actual_vp_list "" + foreach key $possible_vp_list { + if {[regexp {^([0-9]+)$} $key - found_vp]} { + lappend actual_vp_list $found_vp + } + } + + foreach vp $actual_vp_list { + + set vc_list [keylkeys final_stats_list \ + $rx_port.aggregate.rx.$vp] + + foreach vc $vc_list { + set trimmed_vc [string trimleft $vc 0] + set rx_cells [keylget final_stats_list \ + $rx_port.aggregate.rx.$vp.$vc.rx_atm_cells_count] + + keylset ret_list \ + rx_port.$rx_port.vp.$vp.vc.$trimmed_vc.final_rx_cells \ + $rx_cells + } + } + } + } + + + #Now step through the keylist we plan to return and calculate rates + if {[info exists tx_port_list]} { + #Tx Rates + foreach tx_port [keylkeys ret_list tx_port] { + + #Initialize aggregate counters for the port + set aggregate_tx_cells 0 + set aggregate_tx_cells_per_sec 0 + set aggregate_tx_bps_cell 0 + set aggregate_tx_bps_cell_no_hec 0 + + foreach vp [keylkeys ret_list tx_port.$tx_port.vp] { + foreach vc [keylkeys ret_list tx_port.$tx_port.vp.$vp.vc] { + + set initial_tx_cells [keylget ret_list \ + tx_port.$tx_port.vp.$vp.vc.$vc.initial_tx_cells] + + set final_tx_cells [keylget ret_list \ + tx_port.$tx_port.vp.$vp.vc.$vc.final_tx_cells] + + set tx_cells [expr {($final_tx_cells * 1.0) \ + - ($initial_tx_cells * 1.0)}] + + set tx_cells_per_sec [mpexpr {$tx_cells \ + / ($measure_interval * 1.0)}] + + set tx_bps_cell [mpexpr {$tx_cells_per_sec * 53.0 * 8.0}] + + set tx_bps_cell_no_hec \ + [mpexpr {$tx_cells_per_sec * 52.0 * 8.0}] + + keylset ret_list \ + tx_port.$tx_port.vp.$vp.vc.$vc.tx_cells $tx_cells + + keylset ret_list \ + tx_port.$tx_port.vp.$vp.vc.$vc.tx_cells_per_sec \ + $tx_cells_per_sec + + keylset ret_list \ + tx_port.$tx_port.vp.$vp.vc.$vc.tx_bps_cell $tx_bps_cell + + keylset ret_list \ + tx_port.$tx_port.vp.$vp.vc.$vc.tx_bps_cell_no_hec \ + $tx_bps_cell_no_hec + + #Update aggregate numbers with values from current vc + set aggregate_tx_cells [expr \ + {$aggregate_tx_cells + $tx_cells}] + + set aggregate_tx_cells_per_sec [mpexpr \ + {$aggregate_tx_cells_per_sec + $tx_cells_per_sec}] + + set aggregate_tx_bps_cell [mpexpr \ + {$aggregate_tx_bps_cell + $tx_bps_cell}] + + set aggregate_tx_bps_cell_no_hec [mpexpr \ + {$aggregate_tx_bps_cell_no_hec + $tx_bps_cell_no_hec}] + + } + } + + + keylset ret_list tx_port.$tx_port.aggregate.tx_cells \ + $aggregate_tx_cells + + keylset ret_list tx_port.$tx_port.aggregate.tx_cells_per_sec \ + $aggregate_tx_cells_per_sec + + keylset ret_list tx_port.$tx_port.aggregate.tx_bps_cell \ + $aggregate_tx_bps_cell + + keylset ret_list tx_port.$tx_port.aggregate.tx_bps_cell_no_hec \ + $aggregate_tx_bps_cell_no_hec + } ;#end foreach tx_port + } ;# end if info exists tx_port_list + + + if {[info exists rx_port_list]} { + #Rx Rates + foreach rx_port [keylkeys ret_list rx_port] { + + #Initialize aggregate counters for the port + set aggregate_rx_cells 0 + set aggregate_rx_cells_per_sec 0 + set aggregate_rx_bps_cell 0 + set aggregate_rx_bps_cell_no_hec 0 + + foreach vp [keylkeys ret_list rx_port.$rx_port.vp] { + foreach vc [keylkeys ret_list rx_port.$rx_port.vp.$vp.vc] { + + set initial_rx_cells [keylget ret_list \ + rx_port.$rx_port.vp.$vp.vc.$vc.initial_rx_cells] + + set final_rx_cells [keylget ret_list \ + rx_port.$rx_port.vp.$vp.vc.$vc.final_rx_cells] + + set rx_cells [expr {($final_rx_cells * 1.0) \ + - ($initial_rx_cells * 1.0)}] + + set rx_cells_per_sec [mpexpr {$rx_cells \ + / ($measure_interval * 1.0)}] + + set rx_bps_cell [mpexpr {$rx_cells_per_sec * 53.0 * 8.0}] + + set rx_bps_cell_no_hec [mpexpr {$rx_cells_per_sec \ + * 52.0 * 8.0}] + + keylset ret_list \ + rx_port.$rx_port.vp.$vp.vc.$vc.rx_cells $rx_cells + + keylset ret_list \ + rx_port.$rx_port.vp.$vp.vc.$vc.rx_cells_per_sec \ + $rx_cells_per_sec + + keylset ret_list \ + rx_port.$rx_port.vp.$vp.vc.$vc.rx_bps_cell $rx_bps_cell + + keylset ret_list \ + rx_port.$rx_port.vp.$vp.vc.$vc.rx_bps_cell_no_hec \ + $rx_bps_cell_no_hec + + #Update aggregate numbers with values from current vc + set aggregate_rx_cells [expr \ + {$aggregate_rx_cells + $rx_cells}] + + set aggregate_rx_cells_per_sec [mpexpr \ + {$aggregate_rx_cells_per_sec + $rx_cells_per_sec}] + + set aggregate_rx_bps_cell [mpexpr \ + {$aggregate_rx_bps_cell + $rx_bps_cell}] + + set aggregate_rx_bps_cell_no_hec [mpexpr \ + {$aggregate_rx_bps_cell_no_hec + $rx_bps_cell_no_hec}] + } + } + + keylset ret_list rx_port.$rx_port.aggregate.rx_cells \ + $aggregate_rx_cells + + keylset ret_list rx_port.$rx_port.aggregate.rx_cells_per_sec \ + $aggregate_rx_cells_per_sec + + keylset ret_list rx_port.$rx_port.aggregate.rx_bps_cell \ + $aggregate_rx_bps_cell + + keylset ret_list rx_port.$rx_port.aggregate.rx_bps_cell_no_hec \ + $aggregate_rx_bps_cell_no_hec + } ;#end foreach rx_port + };# End if info exists rx_port_list + + return $ret_list +} + + + + +# $Log: vtmsIxiaUtils.lib,v $ +# Revision 1.9 2010/07/21 22:39:40 kvieira +# Added a work around to an issue introduced in IxOS 5.X where it expects the value for PGID filters to be passed with a space between two sets of hex numbers. +# +# example of old output: PGID value of "0003" +# example of new output: PGID value of "00 03" +# +# reviewed by: prafulla +# +# Revision 1.8 2010/01/16 00:38:04 kvieira +# Added PGID as an option to the add-filter proc +# Reviewed by mfinglet +# +# Revision 1.7 2008/10/20 21:34:43 mfinglet +# Fix a bug introduce in adding atm +# Reviewed by yvenkate +# +# Revision 1.6 2008/10/16 22:57:32 mfinglet +# Add atm support to ixia rate measuring procs +# Reviewed in MCP QOS devtest meeting +# +# Revision 1.5 2007/09/03 19:51:51 mfinglet +# Add ecn support to add_rx_filter plus fix type on burtsy proc +# +# Revision 1.4 2007/02/15 20:26:04 mfinglet +# Added support for cos and exp values in two labels to ixia_add_rx_filter +# +# Revision 1.3 2007/01/25 18:40:04 mfinglet +# Fix cut & paste error - return key for tos +# +# Revision 1.2 2007/01/24 22:14:47 mfinglet +# Added support for filtering entire TOS byte in ixia_add_rx_filter +# +# Revision 1.1 2005/06/15 23:37:02 mfinglet +# Initial commit of ixiaVtmsUtils. +# This library contains Ixia utilities used in 7304 VTMS scripts. +# + +# Used for emacs +# Local Variables: +# mode:tcl +# indent-tabs-mode:nil +# End: \ No newline at end of file