open-traffic-generator / models

Open Traffic Generator Core Models
https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/open-traffic-generator/models/master/artifacts/openapi.yaml&nocors
MIT License
63 stars 16 forks source link

L4-L7 traffic and emulation support #238

Open waseembaig opened 2 years ago

waseembaig commented 2 years ago

We need to extend existing model to support vendor-agnostic L4-L7 traffic and emulation testing testing.

Model structure for L4-L7 protocol support is as follows:

  1. The L4-7 session configuration shall be part of root config, sitting next to device and flows.
  2. The interface properties (ethernet and IP) shall be configured as part of device..
  3. The L4-7 session configuration, aka app shall be used to configure protocols such as:
    • L4 protocols : TCP and UDP
    • L7 protocols : HTTP
  4. flows shall be used to configure end points of data traffic configurations and parameters as test objectives, test durations, etc.
    • Each flow will have end points(tx,rx) in traffic.
    • For example if we have 2 flows then 2 tx and rx will be configured.
  5. Sample of the script using the above model will be represented like below: image

Please refer to updated proposal and code snippet in : https://github.com/open-traffic-generator/models/issues/238#issuecomment-1176097943

Sample script for HTTP config

import snappi
api = snappi.api(host="10.22.40.53", version="8.50.0.465")
confObj = api.config()
port_1 = confObj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
port_2 = confObj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

rx_device, tx_device  = confObj.devices.device(name="client").device(name="server")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = tx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.name = "eth_r1"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

rx_tcp = rx_ipv4.tcp
rx_tcp.keep_alive_time = 700
rx_tcp.receive_buffer_size = 4096
rx_tcp.transmit_buffer_size = 4096
rx_tcp.fin_timeout = 60
rx_tcp.syn_retries = 5 
rx_tcp.source_port_range.min = 1024
rx_tcp.source_port_range.max = 65535

http_client = rx_tcp.http[-1]
http_client.role = "Client"
http_client.name = "HTTP Client1"
http_client.enable_ssl = "True"

#server configurations

tx_eth = tx_device.ethernet
tx_eth.name = "tx_eth"
tx_eth.mac = "00:00:00:00:70:01"
tx_eth.name = "eth_S1"
tx_eth.mtu = 1500

tx_ipv4 = tx_eth.ipv4
tx_ipv4.name = "tx_ipv4"
tx_ipv4.address = "21.1.1.2"
tx_ipv4.prefix = "24"
tx_ipv4.gateway = "21.1.1.1"

tx_tcp = tx_ipv4.tcp
tx_tcp.keep_alive_time = 700
tx_tcp.dest_port_range.min = 1024
tx_tcp.dest_port_range.max = 65535

http_server = tx_tcp.http()[-1]
http_server[0].role = "Server"
http_server[0].name = "HTTP Server"
http_server[0].enable_ssl = "True"
http_server[0].method.get(name="get", response=200, url="/b.html").post(name="post", response=201, url="/128k.html")

http_client.method.get(name="get").post(name="post")

#Flow Configurations
flow = confObj.flows.flow()
flow.tx_rx.tx(name=rx_device.name)
flow.tx_rx.rx(name=tx_device.name)

#Objective and Traffic configurations
flow.test_type = "ConnectionPerSecond"
flow.test_value = 100
flow.duration.ramp_up = 10
flow.duration.sustain_time = 180
flow.duration.ramp_down = 180
api.set_config(confObj)
api.control(state= start)

Sample script for TCP:-

import snappi
api = snappi.api(host="10.22.40.53", version="8.50.0.465")
confObj = api.config()
port_1 = confObj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
port_2 = confObj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

rx_device, tx_device  = confObj.devices.device(name="client").device(name="server")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = tx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.name = "eth_r1"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

rx_tcp = rx_ipv4.tcp
rx_tcp.keep_alive_time = 700
rx_tcp.receive_buffer_size = 4096
rx_tcp.transmit_buffer_size = 4096
rx_tcp.fin_timeout = 60
rx_tcp.syn_retries = 5 
rx_tcp.src_port.increment.start = 5000
rx_tcp.src_port.increment.step = 2
rx_tcp.src_port.increment.count = 10

#server configurations

tx_eth = tx_device.ethernet
tx_eth.name = "tx_eth"
tx_eth.mac = "00:00:00:00:70:01"
tx_eth.name = "eth_S1"
tx_eth.mtu = 1500

tx_ipv4 = tx_eth.ipv4
tx_ipv4.name = "tx_ipv4"
tx_ipv4.address = "21.1.1.2"
tx_ipv4.prefix = "24"
tx_ipv4.gateway = "21.1.1.1"

tx_tcp = tx_ipv4.tcp
tx_tcp.keep_alive_time = 700
tx_tcp.fin_timeout = 60
tx_tcp.syn_retries = 5 
tx_tcp.dst_port.decrement.start = 6000
tx_tcp.dst_port.decrement.step = 2
tx_tcp.dst_port.decrement.count = 10

#Flow Configurations
flow = confObj.flows.flow()
flow.tx_rx.tx(name=rx_device.name)
flow.tx_rx.rx(name=tx_device.name)

#Objective and Traffic configurations
flow.test_type = "TcpThroupgut"
flow.test_value = 1000
flow.duration.ramp_up = 10
flow.duration.sustain_time = 180
flow.duration.ramp_down = 180
api.set_config(confObj)
api.control(state= start)

Sample script for UDP:-

import snappi
api = snappi.api(host="10.22.40.53", version="8.50.0.465")
confObj = api.config()
port_1 = confObj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
port_2 = confObj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

rx_device, tx_device  = confObj.devices.device(name="client").device(name="server")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = tx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.name = "eth_r1"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

udp_rx = rx_ipv4.udp
udp_rx.src_port.increment.start = 5000
udp_rx.src_port.increment.step = 2
udp_rx.src_port.increment.count = 10

#server configurations

tx_eth = tx_device.ethernet
tx_eth.name = "tx_eth"
tx_eth.mac = "00:00:00:00:70:01"
tx_eth.name = "eth_S1"
tx_eth.mtu = 1500

tx_ipv4 = tx_eth.ipv4
tx_ipv4.name = "tx_ipv4"
tx_ipv4.address = "21.1.1.2"
tx_ipv4.prefix = "24"
tx_ipv4.gateway = "21.1.1.1"

udp_tx = tx_ipv4.udp
udp_tx.dst_port.decrement.start = 6000
udp_tx.dst_port.decrement.step = 2
udp_tx.dst_port.decrement.count = 10

#Flow Configurations
flow = confObj.flows.flow()
flow.tx_rx.tx(name=rx_device.name)
flow.tx_rx.rx(name=tx_device.name)

#Objective and Traffic configurations
flow.test_type = "UdpThroupgut"
flow.test_value = 1000
flow.duration.ramp_up = 10
flow.duration.sustain_time = 180
flow.duration.ramp_down = 180
api.set_config(confObj)
api.control(state= start)
ajbalogh commented 2 years ago

The app object should be used for test_type, test_value etc instead of the flow node. The flow object should be reserved for L2L3 stateless traffic while the app object can be used for L4L7 stateful traffic properties.

# L4L7 stateful flow configurations
app = confObj.apps.add(name="Application Flow 1")
app.tx_device(name=rx_device.name)
app.rx_device(name=tx_device.name)

# objective and traffic configuration that are specific to L4L7
app.test_type = app.TEST_TYPE_UDP_THROUGHPUT
app.test_value = 1000
app.duration.ramp_up = 10
app.duration.sustain_time = 180
app.duration.ramp_down = 180
lemoncrust commented 2 years ago

Lets explicitly outline the big picture first, as it heavily affects what meaning an 'application' may have. For some products, application means everything - starting from dns resolution, to having a a combination of interdependent flows. If we talk about HTTP, versions beyond 1.1 make it not as trivial to describe application behavior.

waseembaig commented 2 years ago

Updated script and design based on Andy, Razvan and Lyle. image


import snappi
api = snappi.api(host="10.22.40.53", version="8.50.0.465")
conf_obj = api.config()
port_1 = conf_obj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
port_2 = conf_obj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

#rx and tx varible naming is to differentiate between client and server configs.
rx_device, tx_device  = conf_obj.devices.device(name="client").device(name="server")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = rx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

rx_tcp = rx_ipv4.tcp
rx_tcp.keep_alive_time = 700
rx_tcp.receive_buffer_size = 4096
rx_tcp.transmit_buffer_size = 4096
rx_tcp.fin_timeout = 60
rx_tcp.syn_retries = 5 
rx_tcp.source_port_range.min = 1024
rx_tcp.source_port_range.max = 65535
#Modified tcp.http[-1] to tcp.http_client 
http_client = rx_tcp.http_client
http_client.name = "HTTP Client1"
http_client.enable_ssl = "True"

#server configurations

tx_eth = tx_device.ethernet
tx_eth.name = "tx_eth"
tx_eth.mac = "00:00:00:00:70:01"
tx_eth.mtu = "1500"

tx_ipv4 = tx_eth.ipv4
tx_ipv4.name = "tx_ipv4"
tx_ipv4.address = "21.1.1.2"
tx_ipv4.prefix = "24"
tx_ipv4.gateway = "21.1.1.1"

tx_tcp = tx_ipv4.tcp
tx_tcp.keep_alive_time = 700
tx_tcp.dest_port_range.min = 1024
tx_tcp.dest_port_range.max = 65535
#Modified tcp.http[-1] to tcp.http_server 
http_server = tx_tcp.http_server
http_server.name = "HTTP_Server"
http_server.enable_ssl = True
#changing from http_server.method.get() to http_server.traffic.get() 
http_client.traffic.get(page_name="/b.html", destination=http_server.name)

#IxLoad traffic configurations
app = conf_obj.apps.add(name="Application Flow 1")
app.tx_device(name=rx_device.name)
app.rx_device(name=tx_device.name)

# objective and traffic configuration that are specific to L4L7
#test_type-> test_objective_type
app.test_objective_type = app.concurrent_connections
app.test_objective_value  = 1000
app.duration.ramp_up_time = 10  #in seconds
app.duration.sustain_time = 180 #in seconds
app.duration.ramp_down_time = 10 #in seconds
api.set_config(conf_obj)
api.control(state= "start")
waseembaig commented 2 years ago

Sample script for TCP test with review comment changes


import snappi
api = snappi.api(host="10.22.40.53", version="8.50.0.465")
confObj = api.config()
port_1 = confObj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
port_2 = confObj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

rx_device, tx_device  = confObj.devices.device(name="client").device(name="server")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = tx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.name = "eth_r1"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

rx_tcp = rx_ipv4.tcp
rx_tcp.keep_alive_time = 700
rx_tcp.receive_buffer_size = 4096
rx_tcp.transmit_buffer_size = 4096
rx_tcp.fin_timeout = 60
rx_tcp.syn_retries = 5 
rx_tcp.src_port.increment.start = 5000
rx_tcp.src_port.increment.step = 2
rx_tcp.src_port.increment.count = 10

#server configurations

tx_eth = tx_device.ethernet
tx_eth.name = "tx_eth"
tx_eth.mac = "00:00:00:00:70:01"
tx_eth.name = "eth_S1"
tx_eth.mtu = 1500

tx_ipv4 = tx_eth.ipv4
tx_ipv4.name = "tx_ipv4"
tx_ipv4.address = "21.1.1.2"
tx_ipv4.prefix = "24"
tx_ipv4.gateway = "21.1.1.1"

tx_tcp = tx_ipv4.tcp
tx_tcp.keep_alive_time = 700
tx_tcp.fin_timeout = 60
tx_tcp.syn_retries = 5 
tx_tcp.dst_port.decrement.start = 6000
tx_tcp.dst_port.decrement.step = 2
tx_tcp.dst_port.decrement.count = 10

#Traffic  Configurations
app = conf_obj.apps.add(name="Application Flow 1")
app.tx_device(name=rx_device.name)
app.rx_device(name=tx_device.name)

app.test_objective_type = app.tcpthroughput
app.test_objective_value  = 1000
app.duration.ramp_up_time = 10  #in seconds
app.duration.sustain_time = 180 #in seconds
app.duration.ramp_down_time = 180 #in seconds
api.set_config(conf_obj)
api.control(state= start)

Sample script for 1 ARM test

import snappi
api = snappi.api(host="10.22.40.53", version="8.50.0.465")
conf_obj = api.config()
port_1 = conf_obj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]

#rx and tx varible naming is to differentiate between client and server configs.
rx_device = conf_obj.devices.device(name="client")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = rx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

rx_tcp = rx_ipv4.tcp
rx_tcp.keep_alive_time = 700
rx_tcp.receive_buffer_size = 4096
rx_tcp.transmit_buffer_size = 4096
rx_tcp.fin_timeout = 60
rx_tcp.syn_retries = 5 
rx_tcp.source_port_range.min = 1024
rx_tcp.source_port_range.max = 65535

http_client = rx_tcp.http_client
http_client.role = "Client"
http_client.name = "HTTP Client1"
http_client.enable_ssl = "True"

#DUT Server config
server_ip = "10.10.0.1"

http_client.traffic.get(destination= server_ip, name="/b.html")

app = conf_obj.apps.add(name="Application Flow 1")
app.tx_device(name=rx_device.name)
app.rx_device(name=server_ip)

# objective and traffic configuration that are specific to L4L7
#test_type-> test_objective_type
app.test_objective_type = app.concurrent_connections
app.test_objective_value  = 100
app.duration.ramp_up_time = 10  #in seconds
app.duration.sustain_time = 180 #in seconds
app.duration.ramp_down_time = 180 #in seconds
api.set_config(conf_obj)
api.control(state= start)
ajbalogh commented 2 years ago

The definition of the http object under tcp should not be a dual purpose object that is governed by the .role property. There should be specific models for tcp.http_client and tcp.http_server that have explicit properties as opposed to runtime, dynamic, dependent properties.

ajbalogh commented 2 years ago

Specifying a filename and file location for dynamic content must be avoided and the content must be provided by a user as a byte stream. If there is static content then it should be explicitly modeled.

ankur-sheth commented 2 years ago

@waseembaig thanks for the script. Few questions/comments (looking at the most recent script) :

  1. Typo?

    rx_eth = tx_device.ethernet

Should this be rx_device.ethernet?

  1. Inadvertently setting rx_eth.name and tx_eth.name twice?

rx_eth.name = "rx_eth" rx_eth.mac = "00:00:00:00:65:01" rx_eth.name = "eth_r1"

tx_eth.name = "tx_eth" tx_eth.mac = "00:00:00:00:70:01" tx_eth.name = "eth_S1"

  1. Which is the one script that incorporates all the traffic (UDP from IxNetwork, TCP/HTTP from IxLoad and additional background traffic from IxNetwork) for the DASH HERO test? Do we have such a script? If so, could you please point me to it?
waseembaig commented 2 years ago

Hi @ankur-sheth and @ajbalogh ,

I have updated the script based on review comments.

@ankur-sheth, Which is the one script that incorporates all the traffic (UDP from IxNetwork, TCP/HTTP from IxLoad and additional background traffic from IxNetwork) -- TCP/UDP of IXNetwork falls under flows where as TCP of IxLoad falls under deviceand traffic of IxNetwork is configurable under flow and traffic of IxLoad is configurable under app, following is the scripts.

import snappi
#IxLoad Snippet of TCP and HTTTP  configs under device object.
ixload_api = snappi.api(host="10.22.40.53", version="8.50.0.465")
conf_obj = ixload_api.config()
port_1 = conf_obj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
port_2 = conf_obj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

#rx and tx varible naming is to differentiate between client and server configs.
rx_device, tx_device  = conf_obj.devices.device(name="client").device(name="server")

rx_device.port_name = port_1.name
tx_device.port_name = port_2.name
#Client Configuration
rx_eth = rx_device.ethernet
rx_eth.name = "rx_eth"
rx_eth.mac = "00:00:00:00:65:01"
rx_eth.mtu = 1500

rx_ipv4 = rx_eth.ipv4
rx_ipv4.name = "rx_ipv4"
rx_ipv4.address = "21.1.1.2"
rx_ipv4.prefix = "24"
rx_ipv4.gateway = "21.1.1.1"

rx_tcp = rx_ipv4.tcp
rx_tcp.keep_alive_time = 700
rx_tcp.receive_buffer_size = 4096
rx_tcp.transmit_buffer_size = 4096
rx_tcp.fin_timeout = 60
rx_tcp.syn_retries = 5 
rx_tcp.source_port_range.min = 1024
rx_tcp.source_port_range.max = 65535
#Modified tcp.http[-1] to tcp.http_client 
http_client = rx_tcp.http_client
http_client.role = "Client"
http_client.name = "HTTP Client1"
http_client.enable_ssl = "True"

#server configurations

tx_eth = tx_device.ethernet
tx_eth.name = "tx_eth"
tx_eth.mac = "00:00:00:00:70:01"
tx_eth.mtu = 1500

tx_ipv4 = tx_eth.ipv4
tx_ipv4.name = "tx_ipv4"
tx_ipv4.address = "21.1.1.2"
tx_ipv4.prefix = "24"
tx_ipv4.gateway = "21.1.1.1"

tx_tcp = tx_ipv4.tcp
tx_tcp.keep_alive_time = 700
tx_tcp.dest_port_range.min = 1024
tx_tcp.dest_port_range.max = 65535
#Modified tcp.http[-1] to tcp.http_server 
http_server = tx_tcp.http_server
http_server.role = "Server"
http_server.name = "HTTP Server"
http_server.enable_ssl = "True"
#changing from http_server.method.get() to http_server.content.add() 
#adding support of file payload
http_server.content.add(name="/b.html", response=200, payload_type="file", file_name=file_path).add(name="/1024.html", response=200, payload_type="range", fixed_size="1048576")
#changing from http_server.method.get() to http_server.traffic.get() 
http_client.traffic.get(name="/b.html").post(name="/1024.html")
#IxLoad traffic configurations
app = conf_obj.apps.add(name="Application Flow 1")
app.tx_device(name=rx_device.name)
app.rx_device(name=tx_device.name)

# objective and traffic configuration that are specific to L4L7
#test_type-> test_objective_type
app.test_objective_type = app.concurrent_connections
app.test_objective_value  = 100
app.duration.ramp_up_time = 10  #in seconds
app.duration.sustain_time = 180 #in seconds
app.duration.ramp_down_time = 180 #in seconds
api.set_config(conf_obj)
api.control(state= start)

IxNetwork code snippet of TCP config under flow object.

ixnet_api = snappi.api(host="10.22.40.53", version="8.50.0.465")
ixn_conf_obj = ixnet_api.config()
f = ixn_conf_obj.flows[0]
size = 1518
packets = 100
f.packet.ethernet().ipv4().tcp()
eth, ip, tcp = f.packet[0], f.packet[1], f.packet[2]
eth.src.value = "00:CD:DC:CD:DC:CD"
eth.dst.value = "00:AB:BC:AB:BC:AB"
ip.src.value = "1.1.1.2"
ip.dst.value = "1.1.1.1"
tcp.src_port.increment.start = 5000
tcp.src_port.increment.step = 2
tcp.src_port.increment.count = 10
tcp.dst_port.decrement.start = 6000
tcp.dst_port.decrement.step = 2
tcp.dst_port.decrement.count = 10

IxNetwork code snippet of UDP config under flow object.

ixn_conf_obj = ixnet_api.config()
f = ixn_conf_obj.flows[0]
packets = 1
size = 74
f.packet.ethernet().ipv4().udp()
eth, ip, udp = f.packet[0], f.packet[1], f.packet[2]
eth.src.value = "00:0c:29:1d:10:67"
eth.dst.value = "00:0c:29:1d:10:71"
ip.src.value = "10.10.10.1"
ip.dst.value = "10.10.10.2"
udp.src_port.value = 3000
udp.dst_port.value = 4000
waseembaig commented 2 years ago

Dash-Hero Script

import snappi

def configure_ixnetwork(api):
    conf_obj = api.config()
    port_1 = conf_obj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
    d1 = conf_obj.devices.device(name="d1")

    eth1 = d1.ethernets.add()
    eth1.name = "eth1"
    eth1.port_name = port_1.name
    eth1.mac = "00:ad:aa:13:11:01"

    ip1 = eth1.ipv4_addresses.add()
    ip1.name = "ipv41"
    ip1.address = "10.1.1.1"
    ip1.gateway = "10.1.1.2"

    rx1_bgpv4 = ip1.bgpv4
    rx1_bgpv4.name = "rx1_bgpv4"
    rx1_bgpv4.as_type = "ebgp"
    rx1_bgpv4.dut_address = "22.1.1.1"
    rx1_bgpv4.as_number = "65200"
    rx1_rr = rx1_bgpv4.bgpv4_routes.bgpv4route()[-1]
    rx1_rr.name = "rx1_rr"

    flow = conf_obj.flows.flow(name="flow1")[-1]
    flow.tx_rx.device.rx_names = [rx1_rr.name]

    eth1, ip1, udp1 = flow.packet.ethernet().ipv4().udp()

    # set source and destination MAC addresses
    eth1.src.value, eth1.dst.value = "00:AA:00:00:04:00", "00:AA:00:00:00:AA"

    # set source and destination IPv4 addresses
    ip1.src.value, ip1.dst.value = "10.0.0.1", "10.0.0.2"

    # set incrementing port numbers as source UDP ports
    udp1.src_port.increment.start = 5000
    udp1.src_port.increment.step = 2
    udp1.src_port.increment.count = 10
    # assign list of port numbers as destination UDP ports
    udp1.dst_port.values = [4000, 4044, 4060, 4074]

    print("Pushing traffic configuration ...")
    api.set_config(conf_obj)

def configure_ixload(api):
    conf_obj = api.config()
    port_1 = conf_obj.ports.port(name="p1", location='10.22.40.53/1/1')[-1]
    port_2 = conf_obj.ports.port(name="p2", location='10.22.40.53/1/2')[-1]

    #rx and tx varible naming is to differentiate between client and server configs.
    rx_device, tx_device  = conf_obj.devices.device(name="client").device(name="server")

    rx_device.port_name = port_1.name
    tx_device.port_name = port_2.name
    #Client Configuration
    rx_eth = rx_device.ethernet
    rx_eth.name = "rx_eth"
    rx_eth.mac = "00:00:00:00:65:01"
    rx_eth.mtu = 1500

    rx_ipv4 = rx_eth.ipv4
    rx_ipv4.name = "rx_ipv4"
    rx_ipv4.address = "21.1.1.2"
    rx_ipv4.prefix = "24"
    rx_ipv4.gateway = "21.1.1.1"

    rx_tcp = rx_ipv4.tcp
    rx_tcp.keep_alive_time = 700
    rx_tcp.receive_buffer_size = 4096
    rx_tcp.transmit_buffer_size = 4096
    rx_tcp.fin_timeout = 60
    rx_tcp.syn_retries = 5 
    rx_tcp.source_port_range.min = 1024
    rx_tcp.source_port_range.max = 65535
    #Modified tcp.http[-1] to tcp.http_client 
    http_client = rx_tcp.http_client
    http_client.name = "HTTP Client1"
    http_client.enable_ssl = "True"

    #server configurations

    tx_eth = tx_device.ethernet
    tx_eth.name = "tx_eth"
    tx_eth.mac = "00:00:00:00:70:01"
    tx_eth.mtu = "1500"

    tx_ipv4 = tx_eth.ipv4
    tx_ipv4.name = "tx_ipv4"
    tx_ipv4.address = "21.1.1.2"
    tx_ipv4.prefix = "24"
    tx_ipv4.gateway = "21.1.1.1"

    tx_tcp = tx_ipv4.tcp
    tx_tcp.keep_alive_time = 700
    tx_tcp.dest_port_range.min = 1024
    tx_tcp.dest_port_range.max = 65535
    #Modified tcp.http[-1] to tcp.http_server 
    http_server = tx_tcp.http_server
    http_server.name = "HTTP_Server"
    http_server.enable_ssl = True
    #changing from http_server.method.get() to http_server.traffic.get() 
    http_client.traffic.get(page_name="/b.html", destination=http_server.name)

    #IxLoad traffic configurations
    app = conf_obj.apps.add(name="Application Flow 1")
    app.tx_device(name=rx_device.name)
    app.rx_device(name=tx_device.name)

    # objective and traffic configuration that are specific to L4L7
    #test_type-> test_objective_type
    app.test_objective_type = app.concurrent_connections
    app.test_objective_value  = 1000
    app.duration.ramp_up_time = 10  #in seconds
    app.duration.sustain_time = 180 #in seconds
    app.duration.ramp_down_time = 10 #in seconds
    api.set_config(conf_obj)
    api.control(state= "start")

if  __name__=="__main__":
    L_23_api = snappi.api(host="10.22.40.53", version="9.20.2199.45")
    L_47_api = snappi.api(host="10.22.40.53", version="9.10.0.279", ext="ixload")
    configure_ixnetwork(L_23_api )
    configure_ixload(L_47_api )
ajbalogh commented 2 years ago

minor nits http_client.role = "Client" - is this needed as an http_client object us being created (same goes for "Server")? http_client.enable_ssl = "True" - True should not be in quotes app.tx_device(name=rx_device.name) - should this be more explicit like app.tx_name and should it take the http_client.name?

waseembaig commented 2 years ago

http_client.role = "Client" - is this needed as an http_client object us being created (same goes for "Server")? --> Updated the script http_client.enable_ssl = "True" - True should not be in quotes --> Updated the script app.tx_device(name=rx_device.name) - should this be more explicit like app.tx_name and should it take the http_client.name? --> In the earlier discussion, we decided to link device to app instead of http or tcp (for tcp testcase).
Following are reference diagram.

image

winstonliu1111 commented 2 years ago

@ajbalogh @ankur-sheth @waseembaig initial thoughts:

1) does http or other things above L4 really belong in the device stack config? we should probably work on an alternate view of including apps/protocols beyond the transport be properties of the app config node?

2) test_objective and test_type sounded very vendor/domain specific. is there a better and more neutral way to describe it?

3) consider rename variables like ixnet, ixload to something more neutral.

waseembaig commented 2 years ago

@winstonliu1111

1) does http or other things above L4 really belong in the device stack config? we should probably work on an alternate view of including apps/protocols beyond the transport be properties of the app config node? -> We had discussions on that in early review discussions. Following are the old proposed models.

image

New proposed models.

image

2) test_objective and test_type sounded very vendor/domain specific. is there a better and more neutral way to describe it? -> Will work on it****

3) consider rename variables like ixnet, ixload to something more neutral. --> Updated the script with L_23_api and L_47_api.

winstonliu1111 commented 2 years ago

@winstonliu1111

  1. does http or other things above L4 really belong in the device stack config? we should probably work on an alternate view of including apps/protocols beyond the transport be properties of the app config node? -> We had discussions on that in early review discussions. Following are the old proposed models.

image

New proposed models.

image

  1. test_objective and test_type sounded very vendor/domain specific. is there a better and more neutral way to describe it? -> Will work on it****
  2. consider rename variables like ixnet, ixload to something more neutral. --> Updated the script with L_23_api and L_47_api.

have we thought about

Device -> Ethernet -> IP -> UDP/TCP Apps -> HTTP/grpc/quic -> Traffic config

waseembaig commented 2 years ago

@winstonliu1111

  1. does http or other things above L4 really belong in the device stack config? we should probably work on an alternate view of including apps/protocols beyond the transport be properties of the app config node? -> We had discussions on that in early review discussions. Following are the old proposed models.

image New proposed models. image

  1. test_objective and test_type sounded very vendor/domain specific. is there a better and more neutral way to describe it? -> Will work on it****
  2. consider rename variables like ixnet, ixload to something more neutral. --> Updated the script with L_23_api and L_47_api.

have we thought about

Device -> Ethernet -> IP -> UDP/TCP Apps -> HTTP/grpc/quic -> Traffic config

Yes Winston, we had discussions on those modelling as well, following are the proposed model.

image

winstonliu1111 commented 2 years ago

@winstonliu1111

  1. does http or other things above L4 really belong in the device stack config? we should probably work on an alternate view of including apps/protocols beyond the transport be properties of the app config node? -> We had discussions on that in early review discussions. Following are the old proposed models.

image New proposed models. image

  1. test_objective and test_type sounded very vendor/domain specific. is there a better and more neutral way to describe it? -> Will work on it****
  2. consider rename variables like ixnet, ixload to something more neutral. --> Updated the script with L_23_api and L_47_api.

have we thought about Device -> Ethernet -> IP -> UDP/TCP Apps -> HTTP/grpc/quic -> Traffic config

Yes Winston, we had discussions on those modelling as well, following are the proposed model.

image

@ankur-sheth @ajbalogh @waseembaig @ashutshkumr can we have the pros/cons? aside from the DASH use case, can we think of the more complicated what if use cases to see how it will look overall? think in terms of environments such as KNE or containerlab...

application/attack clients -> [some network] -> border router of an AS (say an emulator) -> border router of another AS (say a router running a real NOS) -> [some network] -> middle box -> application server/services

should look at how L23/L47 concepts will be configured in the most natural/understandable way.

waseembaig commented 2 years ago

@winstonliu1111

  1. does http or other things above L4 really belong in the device stack config? we should probably work on an alternate view of including apps/protocols beyond the transport be properties of the app config node? -> We had discussions on that in early review discussions. Following are the old proposed models.

image New proposed models. image

  1. test_objective and test_type sounded very vendor/domain specific. is there a better and more neutral way to describe it? -> Will work on it****
  2. consider rename variables like ixnet, ixload to something more neutral. --> Updated the script with L_23_api and L_47_api.

have we thought about Device -> Ethernet -> IP -> UDP/TCP Apps -> HTTP/grpc/quic -> Traffic config

Yes Winston, we had discussions on those modelling as well, following are the proposed model. image

@ankur-sheth @ajbalogh @waseembaig @ashutshkumr can we have the pros/cons? aside from the DASH use case, can we think of the more complicated what if use cases to see how it will look overall? think in terms of environments such as KNE or containerlab...

application/attack clients -> [some network] -> border router of an AS (say an emulator) -> border router of another AS (say a router running a real NOS) -> [some network] -> middle box -> application server/services

should look at how L23/L47 concepts will be configured in the most natural/understandable way.

@winstonliu1111 from the complex use case front, are you looking for below configs.

"application(Ixload) -> IxNetwork -> border router of another AS (say a router running a real NOS) -> IxNetwork -> DUT -> application server/services (IxLoad)"

if Yes. We can achieve the above config with existing L23 and proposed L47 models.

Please let me know if you are looking for other configs.

winstonliu1111 commented 2 years ago

Waseem, i'm looking for pro vs. con of the different approaches, and need to see UX of the above use case i mentioned by actually showing how it is configured in the different approaches.