From 72c4f12cb3938886f98965063e1acc82df96ce22 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Fri, 29 Jan 2021 13:21:47 -0300 Subject: [PATCH 01/19] In this PR, the FLiRT test case is added to verify the port shaping rate. Also, the chassis_config is added to support port shapign rate. --- .../chassis_config.pb_with_PortShaping.txt | 79 +++++++++++++++++++ trex-scripts/tests/port_shaping_rate.py | 71 +++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 stratum/chassis_config.pb_with_PortShaping.txt create mode 100644 trex-scripts/tests/port_shaping_rate.py diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_PortShaping.txt new file mode 100644 index 0000000..06a1ff9 --- /dev/null +++ b/stratum/chassis_config.pb_with_PortShaping.txt @@ -0,0 +1,79 @@ +channel: 1 + 23,13 Top +description: "Chassis Config for Menlo PDP 32QS" +chassis { +platform: PLT_GENERIC_BAREFOOT_TOFINO +name: "Edgecore Wedge100BF-32qs" +} +nodes { +id: 1 +slot: 1 +index: 1 +} + +vendor_config { +tofino_config { + node_id_to_port_shaping_config { + key: 1 + value { + per_port_shaping_configs { + key:30 + value { + byte_shaping { + max_rate_bps: 1000000000 # 1G + max_burst_bytes: 2000 # 2x jumbo frame + } + } + } + } + } + } +} +singleton_ports { + id: 29 + name: "29/0" + slot: 1 + port: 29 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} +singleton_ports { + id: 30 + name: "30/0" + slot: 1 + port: 30 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} +singleton_ports { + id: 31 + name: "31/0" + slot: 1 + port: 31 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} +singleton_ports { + id: 32 + name: "32/1" + slot: 1 + port: 32 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} diff --git a/trex-scripts/tests/port_shaping_rate.py b/trex-scripts/tests/port_shaping_rate.py new file mode 100644 index 0000000..782947f --- /dev/null +++ b/trex-scripts/tests/port_shaping_rate.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. +# SPDX-License-Identifier: Apache-2.0 + +import logging +import os +import json +from argparse import ArgumentParser +from datetime import datetime +from scapy.layers.all import IP, TCP, UDP, Ether + +from lib.base_test import StatelessTest +from lib.utils import list_port_status,get_readable_port_stats +from lib.xnt import analysis_report_pcap +from trex_stl_lib.api import STLPktBuilder, STLStream, STLTXCont, STLTXSingleBurst + +SOURCE_MAC = "00:00:00:00:00:01" +DEST_MAC = "00:00:00:00:00:02" + + +SENDER_PORT = [0] +RECEIVER_PORT = [1] + + +class PortShapingSTL(StatelessTest): + + # setup_subparser is an optional class method + # You can implement this method if you want to add additional command line + # parameters for your test. + # Those parameters will be parsed and be passed to the "start" method below as + # "args" argument. + @classmethod + def setup_subparser(cls, parser: ArgumentParser) -> None: + parser.add_argument( + "--mult", type=str, help="The speed multiplier", default="1pps" + ) + parser.add_argument("--duration", type=float, help="Test duration", default=-1) + + + # The entrypoint of a test + def start(self, args: dict) -> None: + + pkt = Ether(dst=DEST_MAC) / IP() / TCP() / ("*" * 1500) + # Create a traffic stream + stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXCont()) + #stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXSingleBurst(total_pkts=5)) + self.client.add_streams(stream, ports=[0]) + + + logging.info( + "Starting traffic, TX rate: %s, duration: %d sec", args.mult, args.duration, + ) + + # Start sending traffic + self.client.start(SENDER_PORT, mult=args.mult, duration=args.duration) + + logging.info("Waiting until all traffic stop") + self.client.wait_on_traffic(ports=SENDER_PORT) + + # Get statistics for TX and RX ports + stats = self.client.get_stats() + readable_stats_0 = get_readable_port_stats(stats[0]) + readable_stats_1 = get_readable_port_stats(stats[1]) + + print ("\n Statistics for TX port: \n") + print (readable_stats_0) + + print ("\n Statistics for RX port: \n") + print (readable_stats_1) + + #print (json.dumps(stats[0], indent = 4, separators=(',', ': '), sort_keys = True)) + #print (json.dumps(stats[1], indent = 4, separators=(',', ': '), sort_keys = True)) From 48474c8ea9811dc0f8743f20e3692512e19730de Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Fri, 29 Jan 2021 13:21:47 -0300 Subject: [PATCH 02/19] In this PR, the FLiRT test case is added to verify the port shaping rate. Also, the chassis_config is added to support port shapign rate. --- .../chassis_config.pb_with_PortShaping.txt | 79 +++++++++++++++++++ trex-scripts/tests/port_shaping_rate.py | 71 +++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 stratum/chassis_config.pb_with_PortShaping.txt create mode 100644 trex-scripts/tests/port_shaping_rate.py diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_PortShaping.txt new file mode 100644 index 0000000..06a1ff9 --- /dev/null +++ b/stratum/chassis_config.pb_with_PortShaping.txt @@ -0,0 +1,79 @@ +channel: 1 + 23,13 Top +description: "Chassis Config for Menlo PDP 32QS" +chassis { +platform: PLT_GENERIC_BAREFOOT_TOFINO +name: "Edgecore Wedge100BF-32qs" +} +nodes { +id: 1 +slot: 1 +index: 1 +} + +vendor_config { +tofino_config { + node_id_to_port_shaping_config { + key: 1 + value { + per_port_shaping_configs { + key:30 + value { + byte_shaping { + max_rate_bps: 1000000000 # 1G + max_burst_bytes: 2000 # 2x jumbo frame + } + } + } + } + } + } +} +singleton_ports { + id: 29 + name: "29/0" + slot: 1 + port: 29 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} +singleton_ports { + id: 30 + name: "30/0" + slot: 1 + port: 30 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} +singleton_ports { + id: 31 + name: "31/0" + slot: 1 + port: 31 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} +singleton_ports { + id: 32 + name: "32/1" + slot: 1 + port: 32 + channel: 1 + speed_bps: 40000000000 + config_params { + admin_state: ADMIN_STATE_ENABLED + } + node: 1 +} diff --git a/trex-scripts/tests/port_shaping_rate.py b/trex-scripts/tests/port_shaping_rate.py new file mode 100644 index 0000000..782947f --- /dev/null +++ b/trex-scripts/tests/port_shaping_rate.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. +# SPDX-License-Identifier: Apache-2.0 + +import logging +import os +import json +from argparse import ArgumentParser +from datetime import datetime +from scapy.layers.all import IP, TCP, UDP, Ether + +from lib.base_test import StatelessTest +from lib.utils import list_port_status,get_readable_port_stats +from lib.xnt import analysis_report_pcap +from trex_stl_lib.api import STLPktBuilder, STLStream, STLTXCont, STLTXSingleBurst + +SOURCE_MAC = "00:00:00:00:00:01" +DEST_MAC = "00:00:00:00:00:02" + + +SENDER_PORT = [0] +RECEIVER_PORT = [1] + + +class PortShapingSTL(StatelessTest): + + # setup_subparser is an optional class method + # You can implement this method if you want to add additional command line + # parameters for your test. + # Those parameters will be parsed and be passed to the "start" method below as + # "args" argument. + @classmethod + def setup_subparser(cls, parser: ArgumentParser) -> None: + parser.add_argument( + "--mult", type=str, help="The speed multiplier", default="1pps" + ) + parser.add_argument("--duration", type=float, help="Test duration", default=-1) + + + # The entrypoint of a test + def start(self, args: dict) -> None: + + pkt = Ether(dst=DEST_MAC) / IP() / TCP() / ("*" * 1500) + # Create a traffic stream + stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXCont()) + #stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXSingleBurst(total_pkts=5)) + self.client.add_streams(stream, ports=[0]) + + + logging.info( + "Starting traffic, TX rate: %s, duration: %d sec", args.mult, args.duration, + ) + + # Start sending traffic + self.client.start(SENDER_PORT, mult=args.mult, duration=args.duration) + + logging.info("Waiting until all traffic stop") + self.client.wait_on_traffic(ports=SENDER_PORT) + + # Get statistics for TX and RX ports + stats = self.client.get_stats() + readable_stats_0 = get_readable_port_stats(stats[0]) + readable_stats_1 = get_readable_port_stats(stats[1]) + + print ("\n Statistics for TX port: \n") + print (readable_stats_0) + + print ("\n Statistics for RX port: \n") + print (readable_stats_1) + + #print (json.dumps(stats[0], indent = 4, separators=(',', ': '), sort_keys = True)) + #print (json.dumps(stats[1], indent = 4, separators=(',', ': '), sort_keys = True)) From 3935bb7eb365ee7a2b6046059a5532387a026de4 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Mon, 1 Feb 2021 18:03:43 -0300 Subject: [PATCH 03/19] In this PR, the FLiRT test case is added to verify priority scheduling. --- trex-scripts/tests/priority_scheduling.py | 113 ++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 trex-scripts/tests/priority_scheduling.py diff --git a/trex-scripts/tests/priority_scheduling.py b/trex-scripts/tests/priority_scheduling.py new file mode 100644 index 0000000..ee3d097 --- /dev/null +++ b/trex-scripts/tests/priority_scheduling.py @@ -0,0 +1,113 @@ +# SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. +# SPDX-License-Identifier: Apache-2.0 + +import logging +import os +import json +from argparse import ArgumentParser +from datetime import datetime +from scapy.layers.all import IP, TCP, UDP, Ether + +from lib.base_test import StatelessTest +from lib.utils import list_port_status,get_readable_port_stats +from lib.xnt import analysis_report_pcap +from trex_stl_lib.api import STLPktBuilder, STLStream, STLTXCont, STLTXSingleBurst, STLFlowLatencyStats + + +SOURCE_MAC = "00:00:00:00:00:01" +DEST_MAC = "00:00:00:00:00:02" + +SENDER_PORT = [0] +RECEIVER_PORT = [1] + + +class PortShapingSTL(StatelessTest): + + # setup_subparser is an optional class method + # You can implement this method if you want to add additional command line + # parameters for your test. + # Those parameters will be parsed and be passed to the "start" method below as + # "args" argument. + @classmethod + def setup_subparser(cls, parser: ArgumentParser) -> None: + parser.add_argument("--duration", type=float, help="Test duration", default=10) + + + # The entrypoint of a test + def start(self, args: dict) -> None: + + # create packets + pkt1 = Ether(dst=DEST_MAC) / IP(src="16.0.0.1",dst="48.0.0.1") / UDP(dport=12,sport=1025) / ("*" * 1500) + pkt2 = Ether(dst=DEST_MAC) / IP(src="16.0.0.2",dst="48.0.0.2") / UDP(dport=12,sport=1025) / ("*" * 1500) + + #stream list + streams = [] + + # Create a traffic stream + # assume s1 is a delay critical stream + s1 = STLStream( packet=STLPktBuilder(pkt=pkt1), mode=STLTXCont(bps_L2 = 200000), flow_stats = STLFlowLatencyStats(pg_id = 5)) + # assume s2 is a lower priority stream + s2 = STLStream( packet=STLPktBuilder(pkt=pkt2), mode=STLTXCont(bps_L2 = 35000000000), flow_stats = STLFlowLatencyStats(pg_id = 10)) + + + # prepare ports + self.client.reset(ports=[0,1]) + + # add sterams + streams.append(s1) + streams.append(s2) + self.client.add_streams(streams, ports=[0]) + + + logging.info( + "Starting traffic, duration: %d sec", args.duration, + ) + + # Start sending traffic + self.client.start(SENDER_PORT, mult="100%", duration=args.duration) + pgids = self.client.get_active_pgids() + + + logging.info("Waiting until all traffic stop") + self.client.wait_on_traffic(ports=SENDER_PORT) + + # stats for pg_id 5 + stats = self.client.get_pgid_stats(pgids['latency']) + flow_stats = stats['flow_stats'].get(5) + global_lat_stats = stats['latency'] + lat_stats = global_lat_stats.get(5) + + tx_pkts = flow_stats['tx_pkts'].get(0, 0) + tx_bytes = flow_stats['tx_bytes'].get(0, 0) + tx_pps = flow_stats['tx_pps'].get(0, 0) + rx_pkts = flow_stats['rx_pkts'].get(1, 0) + drops = lat_stats['err_cntrs']['dropped'] + + print(" \n TX and RX flow stats and packet dopped for pg id 5 (i.e., delay critical): ") + print(" tx packets: {0}".format(tx_pkts)) + print(" tx bytes : {0}".format(tx_pps)) + print(" rx packets : {0}".format(rx_pkts)) + print(" drops: {0}".format(drops)) + + + # latency info for pg_id 5 + lat = lat_stats['latency'] + jitter = lat['jitter'] + avg = lat['average'] + tot_max = lat['total_max'] + tot_min = lat['total_min'] + print('\n Latency info for pg id 5 (ie., delay critical):') + print(" Maximum latency(usec): {0}".format(tot_max)) + print(" Minimum latency(usec): {0}".format(tot_min)) + print(" Average latency(usec): {0}".format(avg)) + + + # Get statistics for TX and RX ports + stats = self.client.get_stats() + readable_stats_0 = get_readable_port_stats(stats[0]) + readable_stats_1 = get_readable_port_stats(stats[1]) + + print ("\n Overall Statistics for TX port: \n") + print (readable_stats_0) + print ("\n Overall Statistics for RX port: \n") + print (readable_stats_1) From af29617f0b5aad054dc0a2c598347c68aa5e0f2e Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Tue, 2 Feb 2021 14:09:06 -0300 Subject: [PATCH 04/19] add license --- stratum/chassis_config.pb_with_PortShaping.txt.license | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 stratum/chassis_config.pb_with_PortShaping.txt.license diff --git a/stratum/chassis_config.pb_with_PortShaping.txt.license b/stratum/chassis_config.pb_with_PortShaping.txt.license new file mode 100644 index 0000000..dd38bc6 --- /dev/null +++ b/stratum/chassis_config.pb_with_PortShaping.txt.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. +SPDX-License-Identifier: Apache-2.0 From a5e2a11672e91659753553a7d232ac37c18f8fbd Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Tue, 2 Feb 2021 15:03:02 -0300 Subject: [PATCH 05/19] add assert statement and clean --- trex-scripts/tests/port_shaping_rate.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/trex-scripts/tests/port_shaping_rate.py b/trex-scripts/tests/port_shaping_rate.py index 782947f..85f391b 100644 --- a/trex-scripts/tests/port_shaping_rate.py +++ b/trex-scripts/tests/port_shaping_rate.py @@ -19,6 +19,7 @@ SENDER_PORT = [0] RECEIVER_PORT = [1] +Shaping_rate = 1000 # in Mbps class PortShapingSTL(StatelessTest): @@ -30,10 +31,7 @@ class PortShapingSTL(StatelessTest): # "args" argument. @classmethod def setup_subparser(cls, parser: ArgumentParser) -> None: - parser.add_argument( - "--mult", type=str, help="The speed multiplier", default="1pps" - ) - parser.add_argument("--duration", type=float, help="Test duration", default=-1) + parser.add_argument("--duration", type=float, help="Test duration", default=10) # The entrypoint of a test @@ -47,7 +45,7 @@ def start(self, args: dict) -> None: logging.info( - "Starting traffic, TX rate: %s, duration: %d sec", args.mult, args.duration, + "Starting traffic, duration: %d sec", args.duration, ) # Start sending traffic @@ -58,6 +56,11 @@ def start(self, args: dict) -> None: # Get statistics for TX and RX ports stats = self.client.get_stats() + rx_rate = stats[1]['rx_bps'] / (10**6) + assert (Shaping_rate*0.95 < rx_rate < Shaping_rate), \ + "The measured RX rate is not close to the port shaping rate" + + readable_stats_0 = get_readable_port_stats(stats[0]) readable_stats_1 = get_readable_port_stats(stats[1]) @@ -66,6 +69,3 @@ def start(self, args: dict) -> None: print ("\n Statistics for RX port: \n") print (readable_stats_1) - - #print (json.dumps(stats[0], indent = 4, separators=(',', ': '), sort_keys = True)) - #print (json.dumps(stats[1], indent = 4, separators=(',', ': '), sort_keys = True)) From 71015801911097f5ed4a1c6e6a5865e722aa16db Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Tue, 2 Feb 2021 15:06:02 -0300 Subject: [PATCH 06/19] fix the class name --- trex-scripts/tests/priority_scheduling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trex-scripts/tests/priority_scheduling.py b/trex-scripts/tests/priority_scheduling.py index ee3d097..4ac2347 100644 --- a/trex-scripts/tests/priority_scheduling.py +++ b/trex-scripts/tests/priority_scheduling.py @@ -21,7 +21,7 @@ RECEIVER_PORT = [1] -class PortShapingSTL(StatelessTest): +class PriorityScheduling(StatelessTest): # setup_subparser is an optional class method # You can implement this method if you want to add additional command line From 5d65ffd3c856a9dc1a08a4b2c709735f13ee8589 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Tue, 2 Feb 2021 15:10:56 -0300 Subject: [PATCH 07/19] fix mult --- trex-scripts/tests/port_shaping_rate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trex-scripts/tests/port_shaping_rate.py b/trex-scripts/tests/port_shaping_rate.py index 85f391b..920cf69 100644 --- a/trex-scripts/tests/port_shaping_rate.py +++ b/trex-scripts/tests/port_shaping_rate.py @@ -49,7 +49,7 @@ def start(self, args: dict) -> None: ) # Start sending traffic - self.client.start(SENDER_PORT, mult=args.mult, duration=args.duration) + self.client.start(SENDER_PORT, mult="100%", duration=args.duration) logging.info("Waiting until all traffic stop") self.client.wait_on_traffic(ports=SENDER_PORT) From d4997b13bdb305e2d9de34ce73d8d343ce4b0290 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Wed, 3 Feb 2021 00:42:19 -0300 Subject: [PATCH 08/19] fix constants and vaiables representation --- trex-scripts/tests/port_shaping_rate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trex-scripts/tests/port_shaping_rate.py b/trex-scripts/tests/port_shaping_rate.py index 920cf69..27caf1e 100644 --- a/trex-scripts/tests/port_shaping_rate.py +++ b/trex-scripts/tests/port_shaping_rate.py @@ -19,7 +19,7 @@ SENDER_PORT = [0] RECEIVER_PORT = [1] -Shaping_rate = 1000 # in Mbps +SHAPING_RATE_MBPS = 1000 # in Mbps class PortShapingSTL(StatelessTest): @@ -56,8 +56,8 @@ def start(self, args: dict) -> None: # Get statistics for TX and RX ports stats = self.client.get_stats() - rx_rate = stats[1]['rx_bps'] / (10**6) - assert (Shaping_rate*0.95 < rx_rate < Shaping_rate), \ + rx_rate_mbps = stats[1]['rx_bps'] / (10**6) + assert (SHAPING_RATE_MBPS*0.95 < rx_rate_mbps < SHAPING_RATE_MBPS), \ "The measured RX rate is not close to the port shaping rate" From 7d43cb8236551995bff497be21eefbdbc04dbfbf Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Wed, 3 Feb 2021 00:44:06 -0300 Subject: [PATCH 09/19] add assert statement --- trex-scripts/tests/priority_scheduling.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/trex-scripts/tests/priority_scheduling.py b/trex-scripts/tests/priority_scheduling.py index 4ac2347..18728af 100644 --- a/trex-scripts/tests/priority_scheduling.py +++ b/trex-scripts/tests/priority_scheduling.py @@ -20,6 +20,9 @@ SENDER_PORT = [0] RECEIVER_PORT = [1] +# assume maximum latency for delay critical flows +LATENCY_DC_MAX_uSEC = 100 # in mircoseconds + class PriorityScheduling(StatelessTest): @@ -102,6 +105,10 @@ def start(self, args: dict) -> None: print(" Average latency(usec): {0}".format(avg)) + assert (avg <= LATENCY_DC_MAX_uSEC), \ + "The avg latency is greater than the max latency for delay critcial flow" + + # Get statistics for TX and RX ports stats = self.client.get_stats() readable_stats_0 = get_readable_port_stats(stats[0]) From 02255130634d387f262bd70178d24e4a0de3d2ef Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Wed, 3 Feb 2021 00:48:17 -0300 Subject: [PATCH 10/19] fix the indent and max burst bytes --- stratum/chassis_config.pb_with_PortShaping.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_PortShaping.txt index 06a1ff9..a123778 100644 --- a/stratum/chassis_config.pb_with_PortShaping.txt +++ b/stratum/chassis_config.pb_with_PortShaping.txt @@ -12,7 +12,7 @@ index: 1 } vendor_config { -tofino_config { + tofino_config { node_id_to_port_shaping_config { key: 1 value { @@ -20,8 +20,8 @@ tofino_config { key:30 value { byte_shaping { - max_rate_bps: 1000000000 # 1G - max_burst_bytes: 2000 # 2x jumbo frame + max_rate_bps: 1000000000 # 1Gbps + max_burst_bytes: 160000 # 2x jumbo frame } } } From 222da981ebaa0f14442cc67333346117dbe1b941 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Sun, 7 Feb 2021 00:26:42 -0300 Subject: [PATCH 11/19] assure flow priortization by adding one more delay critical flow without prioritization. --- trex-scripts/tests/priority_scheduling.py | 92 +++++++++++++++-------- 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/trex-scripts/tests/priority_scheduling.py b/trex-scripts/tests/priority_scheduling.py index 18728af..326127e 100644 --- a/trex-scripts/tests/priority_scheduling.py +++ b/trex-scripts/tests/priority_scheduling.py @@ -21,7 +21,11 @@ RECEIVER_PORT = [1] # assume maximum latency for delay critical flows -LATENCY_DC_MAX_uSEC = 100 # in mircoseconds +LATENCY_DC_MAX_uSEC = 1000 # in mircoseconds +# assume maximum latency for low priority flows during congestion +LATENCY_LP_MAX_uSEC = 25500 # in mircoseconds +# assume average latency for low priority flows during congestion +LATENCY_LP_AVG_uSEC = 15000 # in mircoseconds class PriorityScheduling(StatelessTest): @@ -42,15 +46,18 @@ def start(self, args: dict) -> None: # create packets pkt1 = Ether(dst=DEST_MAC) / IP(src="16.0.0.1",dst="48.0.0.1") / UDP(dport=12,sport=1025) / ("*" * 1500) pkt2 = Ether(dst=DEST_MAC) / IP(src="16.0.0.2",dst="48.0.0.2") / UDP(dport=12,sport=1025) / ("*" * 1500) + pkt3 = Ether(dst=DEST_MAC) / IP(src="16.0.0.3",dst="48.0.0.3") / UDP(dport=12,sport=1025) / ("*" * 1500) #stream list streams = [] # Create a traffic stream - # assume s1 is a delay critical stream - s1 = STLStream( packet=STLPktBuilder(pkt=pkt1), mode=STLTXCont(bps_L2 = 200000), flow_stats = STLFlowLatencyStats(pg_id = 5)) - # assume s2 is a lower priority stream - s2 = STLStream( packet=STLPktBuilder(pkt=pkt2), mode=STLTXCont(bps_L2 = 35000000000), flow_stats = STLFlowLatencyStats(pg_id = 10)) + # assume s1 is a delay critical stream with QoS + s1 = STLStream( packet=STLPktBuilder(pkt=pkt1), mode=STLTXCont(percentage = 1), flow_stats = STLFlowLatencyStats(pg_id = 5)) + # assume s2 is a delay critical stream without QoS + s2 = STLStream( packet=STLPktBuilder(pkt=pkt2), mode=STLTXCont(percentage = 1), flow_stats = STLFlowLatencyStats(pg_id = 10)) + # assume s3 is a lower priority stream + s3 = STLStream( packet=STLPktBuilder(pkt=pkt3), mode=STLTXCont(percentage = 98), flow_stats = STLFlowLatencyStats(pg_id = 15)) # prepare ports @@ -59,6 +66,7 @@ def start(self, args: dict) -> None: # add sterams streams.append(s1) streams.append(s2) + streams.append(s3) self.client.add_streams(streams, ports=[0]) @@ -74,39 +82,62 @@ def start(self, args: dict) -> None: logging.info("Waiting until all traffic stop") self.client.wait_on_traffic(ports=SENDER_PORT) - # stats for pg_id 5 - stats = self.client.get_pgid_stats(pgids['latency']) - flow_stats = stats['flow_stats'].get(5) - global_lat_stats = stats['latency'] - lat_stats = global_lat_stats.get(5) - tx_pkts = flow_stats['tx_pkts'].get(0, 0) - tx_bytes = flow_stats['tx_bytes'].get(0, 0) - tx_pps = flow_stats['tx_pps'].get(0, 0) - rx_pkts = flow_stats['rx_pkts'].get(1, 0) - drops = lat_stats['err_cntrs']['dropped'] + # stats for pg_id 5 and 15 + stats = self.client.get_pgid_stats(pgids['latency']) + flow_stats_5 = stats['flow_stats'].get(5) + flow_stats_10 = stats['flow_stats'].get(10) + global_lat_stats = stats['latency'] + lat_stats_5 = global_lat_stats.get(5) + lat_stats_10 = global_lat_stats.get(10) + + tx_pkts_5 = flow_stats_5['tx_pkts'].get(0, 0) + rx_pkts_5 = flow_stats_5['rx_pkts'].get(1, 0) + drops_5 = lat_stats_5['err_cntrs']['dropped'] + + tx_pkts_10 = flow_stats_10['tx_pkts'].get(0, 0) + rx_pkts_10 = flow_stats_10['rx_pkts'].get(1, 0) + drops_10 = lat_stats_10['err_cntrs']['dropped'] print(" \n TX and RX flow stats and packet dopped for pg id 5 (i.e., delay critical): ") - print(" tx packets: {0}".format(tx_pkts)) - print(" tx bytes : {0}".format(tx_pps)) - print(" rx packets : {0}".format(rx_pkts)) - print(" drops: {0}".format(drops)) + print(" tx packets: {0}".format(tx_pkts_5)) + print(" tx bytes : {0}".format(tx_pps_5)) + print(" rx packets : {0}".format(rx_pkts_5)) + print(" drops: {0}".format(drops_5)) + print(" \n TX and RX flow stats and packet dopped for pg id 10 (i.e., delay critical): ") + print(" tx packets: {0}".format(tx_pkts_10)) + print(" tx bytes : {0}".format(tx_pps_10)) + print(" rx packets : {0}".format(rx_pkts_10)) + print(" drops: {0}".format(drops_10)) # latency info for pg_id 5 - lat = lat_stats['latency'] - jitter = lat['jitter'] - avg = lat['average'] - tot_max = lat['total_max'] - tot_min = lat['total_min'] - print('\n Latency info for pg id 5 (ie., delay critical):') - print(" Maximum latency(usec): {0}".format(tot_max)) - print(" Minimum latency(usec): {0}".format(tot_min)) - print(" Average latency(usec): {0}".format(avg)) + lat_5 = lat_stats_5['latency'] + avg_5 = lat_5['average'] + tot_max_5 = lat_5['total_max'] + tot_min_5 = lat_5['total_min'] + + # latency info for pg_id 10 + lat_10 = lat_stats_10['latency'] + avg_10 = lat_10['average'] + tot_max_10 = lat_10['total_max'] + tot_min_10 = lat_10['total_min'] + + print('\n Latency info for pg id 5 (ie., delay critical with QoS):') + print(" Maximum latency(usec): {0}".format(tot_max_5)) + print(" Minimum latency(usec): {0}".format(tot_min_5)) + print(" Average latency(usec): {0}".format(avg_5)) + + print('\n Latency info for pg id 10 (ie., delay critical without QoS):') + print(" Maximum latency(usec): {0}".format(tot_max_10)) + print(" Minimum latency(usec): {0}".format(tot_min_10)) + print(" Average latency(usec): {0}".format(avg_10)) + # max latency difference between delay critcal flows with gp id 5 and 15 + dc_max_lat_diff = tot_max_10 - tot_max_5 - assert (avg <= LATENCY_DC_MAX_uSEC), \ - "The avg latency is greater than the max latency for delay critcial flow" + assert ((LATENCY_LP_AVG_uSEC <= dc_max_lat_diff <= LATENCY_LP_MAX_uSEC) & (tot_max_5 <= LATENCY_DC_MAX_uSEC)), \ + "Priority scheduling test failed." # Get statistics for TX and RX ports @@ -114,6 +145,7 @@ def start(self, args: dict) -> None: readable_stats_0 = get_readable_port_stats(stats[0]) readable_stats_1 = get_readable_port_stats(stats[1]) + logging.info("Priority scheduling test successfully executed.") print ("\n Overall Statistics for TX port: \n") print (readable_stats_0) print ("\n Overall Statistics for RX port: \n") From b2873f6cf9da8163f58d2be7a3d655083406c38e Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Sun, 7 Feb 2021 14:42:53 -0300 Subject: [PATCH 12/19] fix the representation and comments, and clean --- trex-scripts/tests/port_shaping_rate.py | 1 - trex-scripts/tests/priority_scheduling.py | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/trex-scripts/tests/port_shaping_rate.py b/trex-scripts/tests/port_shaping_rate.py index 27caf1e..2a258bb 100644 --- a/trex-scripts/tests/port_shaping_rate.py +++ b/trex-scripts/tests/port_shaping_rate.py @@ -40,7 +40,6 @@ def start(self, args: dict) -> None: pkt = Ether(dst=DEST_MAC) / IP() / TCP() / ("*" * 1500) # Create a traffic stream stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXCont()) - #stream = STLStream(packet=STLPktBuilder(pkt=pkt, vm=[]), mode=STLTXSingleBurst(total_pkts=5)) self.client.add_streams(stream, ports=[0]) diff --git a/trex-scripts/tests/priority_scheduling.py b/trex-scripts/tests/priority_scheduling.py index 326127e..7ec77a2 100644 --- a/trex-scripts/tests/priority_scheduling.py +++ b/trex-scripts/tests/priority_scheduling.py @@ -20,12 +20,13 @@ SENDER_PORT = [0] RECEIVER_PORT = [1] -# assume maximum latency for delay critical flows +# In this test case, we consider two types of flows: 1) delay critical, and 2) best effort +# assume max. latency for delay critical flows LATENCY_DC_MAX_uSEC = 1000 # in mircoseconds -# assume maximum latency for low priority flows during congestion -LATENCY_LP_MAX_uSEC = 25500 # in mircoseconds -# assume average latency for low priority flows during congestion -LATENCY_LP_AVG_uSEC = 15000 # in mircoseconds +# assume max. latency for best effort (i.e., low priority flows) traffic during congestion +# with the priortization of delay critical flows +LATENCY_LP_MAX_uSEC = 24000 # in mircoseconds + class PriorityScheduling(StatelessTest): @@ -83,7 +84,7 @@ def start(self, args: dict) -> None: self.client.wait_on_traffic(ports=SENDER_PORT) - # stats for pg_id 5 and 15 + # stats for pg_id 5 and 10 stats = self.client.get_pgid_stats(pgids['latency']) flow_stats_5 = stats['flow_stats'].get(5) flow_stats_10 = stats['flow_stats'].get(10) @@ -133,13 +134,12 @@ def start(self, args: dict) -> None: print(" Minimum latency(usec): {0}".format(tot_min_10)) print(" Average latency(usec): {0}".format(avg_10)) - # max latency difference between delay critcal flows with gp id 5 and 15 + # max latency difference between delay critcal flows of gp id 5 and 10 dc_max_lat_diff = tot_max_10 - tot_max_5 - assert ((LATENCY_LP_AVG_uSEC <= dc_max_lat_diff <= LATENCY_LP_MAX_uSEC) & (tot_max_5 <= LATENCY_DC_MAX_uSEC)), \ + assert ((LATENCY_LP_MAX_uSEC - LATENCY_DC_MAX_uSEC) <= dc_max_lat_diff), \ "Priority scheduling test failed." - # Get statistics for TX and RX ports stats = self.client.get_stats() readable_stats_0 = get_readable_port_stats(stats[0]) From b54a66ca1e870528431d2b3a9e2be33171a1bcb5 Mon Sep 17 00:00:00 2001 From: Suneet Kumar Singh <38260494+ersuneetsingh@users.noreply.github.com> Date: Sun, 7 Feb 2021 14:45:23 -0300 Subject: [PATCH 13/19] Update stratum/chassis_config.pb_with_PortShaping.txt Co-authored-by: Yi Tseng --- .../chassis_config.pb_with_PortShaping.txt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_PortShaping.txt index a123778..9b8952e 100644 --- a/stratum/chassis_config.pb_with_PortShaping.txt +++ b/stratum/chassis_config.pb_with_PortShaping.txt @@ -12,22 +12,22 @@ index: 1 } vendor_config { - tofino_config { - node_id_to_port_shaping_config { - key: 1 - value { - per_port_shaping_configs { - key:30 - value { - byte_shaping { - max_rate_bps: 1000000000 # 1Gbps - max_burst_bytes: 160000 # 2x jumbo frame + tofino_config { + node_id_to_port_shaping_config { + key: 1 + value { + per_port_shaping_configs { + key:30 + value { + byte_shaping { + max_rate_bps: 1000000000 # 1Gbps + max_burst_bytes: 160000 # 2x jumbo frame + } } } } } } - } } singleton_ports { id: 29 From b649b2835f01d6ab7aac17834b5a5f813b5a81bb Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Wed, 10 Feb 2021 18:21:24 -0300 Subject: [PATCH 14/19] fix some minor representations and notations --- trex-scripts/tests/priority_scheduling.py | 114 +++++++++++----------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/trex-scripts/tests/priority_scheduling.py b/trex-scripts/tests/priority_scheduling.py index 7ec77a2..af7d41a 100644 --- a/trex-scripts/tests/priority_scheduling.py +++ b/trex-scripts/tests/priority_scheduling.py @@ -22,10 +22,10 @@ # In this test case, we consider two types of flows: 1) delay critical, and 2) best effort # assume max. latency for delay critical flows -LATENCY_DC_MAX_uSEC = 1000 # in mircoseconds +LATENCY_DC_MAX_USEC = 1000 # in mircoseconds # assume max. latency for best effort (i.e., low priority flows) traffic during congestion # with the priortization of delay critical flows -LATENCY_LP_MAX_uSEC = 24000 # in mircoseconds +LATENCY_LP_MAX_USEC = 24000 # in mircoseconds @@ -54,11 +54,11 @@ def start(self, args: dict) -> None: # Create a traffic stream # assume s1 is a delay critical stream with QoS - s1 = STLStream( packet=STLPktBuilder(pkt=pkt1), mode=STLTXCont(percentage = 1), flow_stats = STLFlowLatencyStats(pg_id = 5)) + s1 = STLStream( packet=STLPktBuilder(pkt=pkt1), mode=STLTXCont(percentage = 1), flow_stats = STLFlowLatencyStats(pg_id = 1)) # assume s2 is a delay critical stream without QoS - s2 = STLStream( packet=STLPktBuilder(pkt=pkt2), mode=STLTXCont(percentage = 1), flow_stats = STLFlowLatencyStats(pg_id = 10)) + s2 = STLStream( packet=STLPktBuilder(pkt=pkt2), mode=STLTXCont(percentage = 1), flow_stats = STLFlowLatencyStats(pg_id = 2)) # assume s3 is a lower priority stream - s3 = STLStream( packet=STLPktBuilder(pkt=pkt3), mode=STLTXCont(percentage = 98), flow_stats = STLFlowLatencyStats(pg_id = 15)) + s3 = STLStream( packet=STLPktBuilder(pkt=pkt3), mode=STLTXCont(percentage = 98), flow_stats = STLFlowLatencyStats(pg_id = 3)) # prepare ports @@ -84,60 +84,60 @@ def start(self, args: dict) -> None: self.client.wait_on_traffic(ports=SENDER_PORT) - # stats for pg_id 5 and 10 + # stats for pg_id 1 and 2 stats = self.client.get_pgid_stats(pgids['latency']) - flow_stats_5 = stats['flow_stats'].get(5) - flow_stats_10 = stats['flow_stats'].get(10) + flow_stats_1 = stats['flow_stats'].get(1) + flow_stats_2 = stats['flow_stats'].get(2) global_lat_stats = stats['latency'] - lat_stats_5 = global_lat_stats.get(5) - lat_stats_10 = global_lat_stats.get(10) - - tx_pkts_5 = flow_stats_5['tx_pkts'].get(0, 0) - rx_pkts_5 = flow_stats_5['rx_pkts'].get(1, 0) - drops_5 = lat_stats_5['err_cntrs']['dropped'] - - tx_pkts_10 = flow_stats_10['tx_pkts'].get(0, 0) - rx_pkts_10 = flow_stats_10['rx_pkts'].get(1, 0) - drops_10 = lat_stats_10['err_cntrs']['dropped'] - - print(" \n TX and RX flow stats and packet dopped for pg id 5 (i.e., delay critical): ") - print(" tx packets: {0}".format(tx_pkts_5)) - print(" tx bytes : {0}".format(tx_pps_5)) - print(" rx packets : {0}".format(rx_pkts_5)) - print(" drops: {0}".format(drops_5)) - - print(" \n TX and RX flow stats and packet dopped for pg id 10 (i.e., delay critical): ") - print(" tx packets: {0}".format(tx_pkts_10)) - print(" tx bytes : {0}".format(tx_pps_10)) - print(" rx packets : {0}".format(rx_pkts_10)) - print(" drops: {0}".format(drops_10)) - - # latency info for pg_id 5 - lat_5 = lat_stats_5['latency'] - avg_5 = lat_5['average'] - tot_max_5 = lat_5['total_max'] - tot_min_5 = lat_5['total_min'] - - # latency info for pg_id 10 - lat_10 = lat_stats_10['latency'] - avg_10 = lat_10['average'] - tot_max_10 = lat_10['total_max'] - tot_min_10 = lat_10['total_min'] - - print('\n Latency info for pg id 5 (ie., delay critical with QoS):') - print(" Maximum latency(usec): {0}".format(tot_max_5)) - print(" Minimum latency(usec): {0}".format(tot_min_5)) - print(" Average latency(usec): {0}".format(avg_5)) - - print('\n Latency info for pg id 10 (ie., delay critical without QoS):') - print(" Maximum latency(usec): {0}".format(tot_max_10)) - print(" Minimum latency(usec): {0}".format(tot_min_10)) - print(" Average latency(usec): {0}".format(avg_10)) - - # max latency difference between delay critcal flows of gp id 5 and 10 - dc_max_lat_diff = tot_max_10 - tot_max_5 - - assert ((LATENCY_LP_MAX_uSEC - LATENCY_DC_MAX_uSEC) <= dc_max_lat_diff), \ + lat_stats_1 = global_lat_stats.get(1) + lat_stats_2 = global_lat_stats.get(2) + + tx_pkts_1 = flow_stats_1['tx_pkts'].get(0, 0) + rx_pkts_1 = flow_stats_1['rx_pkts'].get(1, 0) + drops_1 = lat_stats_1['err_cntrs']['dropped'] + + tx_pkts_2 = flow_stats_2['tx_pkts'].get(0, 0) + rx_pkts_2 = flow_stats_2['rx_pkts'].get(1, 0) + drops_2 = lat_stats_2['err_cntrs']['dropped'] + + print(" \n TX and RX flow stats and packets dropped for s1 (i.e., delay critical): ") + print(" tx packets: {0}".format(tx_pkts_1)) + print(" tx bytes : {0}".format(tx_pps_1)) + print(" rx packets : {0}".format(rx_pkts_1)) + print(" drops: {0}".format(drops_1)) + + print(" \n TX and RX flow stats and packets dropped for s2 (i.e., delay critical): ") + print(" tx packets: {0}".format(tx_pkts_2)) + print(" tx bytes : {0}".format(tx_pps_2)) + print(" rx packets : {0}".format(rx_pkts_2)) + print(" drops: {0}".format(drops_2)) + + # latency info for s1 + lat_1 = lat_stats_1['latency'] + avg_1 = lat_1['average'] + tot_max_1 = lat_1['total_max'] + tot_min_1 = lat_1['total_min'] + + # latency info for s2 + lat_2 = lat_stats_2['latency'] + avg_2 = lat_2['average'] + tot_max_2 = lat_2['total_max'] + tot_min_2 = lat_2['total_min'] + + print('\n Latency info for s1 (ie., delay critical with QoS):') + print(" Maximum latency(usec): {0}".format(tot_max_1)) + print(" Minimum latency(usec): {0}".format(tot_min_1)) + print(" Average latency(usec): {0}".format(avg_1)) + + print('\n Latency info for s2 (ie., delay critical without QoS):') + print(" Maximum latency(usec): {0}".format(tot_max_2)) + print(" Minimum latency(usec): {0}".format(tot_min_2)) + print(" Average latency(usec): {0}".format(avg_2)) + + # max latency difference between delay critcal streams s1 and s2 + dc_max_lat_diff = tot_max_2 - tot_max_1 + + assert ((LATENCY_LP_MAX_USEC - LATENCY_DC_MAX_USEC) <= dc_max_lat_diff), \ "Priority scheduling test failed." # Get statistics for TX and RX ports From aa41cd1743f77b8e6ec110ac676cb021c6e8c315 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Thu, 11 Feb 2021 20:36:17 -0300 Subject: [PATCH 15/19] fix error --- stratum/chassis_config.pb_with_PortShaping.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_PortShaping.txt index 9b8952e..8766a79 100644 --- a/stratum/chassis_config.pb_with_PortShaping.txt +++ b/stratum/chassis_config.pb_with_PortShaping.txt @@ -1,5 +1,3 @@ -channel: 1 - 23,13 Top description: "Chassis Config for Menlo PDP 32QS" chassis { platform: PLT_GENERIC_BAREFOOT_TOFINO @@ -10,7 +8,6 @@ id: 1 slot: 1 index: 1 } - vendor_config { tofino_config { node_id_to_port_shaping_config { From d41999bdbb6d269f2c4a1409a9fd1a28bcf7fd54 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Fri, 12 Feb 2021 08:43:56 -0300 Subject: [PATCH 16/19] fix and place license text inline at the top of the chassis config; remove the extra file --- stratum/chassis_config.pb_with_PortShaping.txt | 3 +++ stratum/chassis_config.pb_with_PortShaping.txt.license | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 stratum/chassis_config.pb_with_PortShaping.txt.license diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_PortShaping.txt index 8766a79..f5f4f87 100644 --- a/stratum/chassis_config.pb_with_PortShaping.txt +++ b/stratum/chassis_config.pb_with_PortShaping.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. +# SPDX-License-Identifier: Apache-2.0 + description: "Chassis Config for Menlo PDP 32QS" chassis { platform: PLT_GENERIC_BAREFOOT_TOFINO diff --git a/stratum/chassis_config.pb_with_PortShaping.txt.license b/stratum/chassis_config.pb_with_PortShaping.txt.license deleted file mode 100644 index dd38bc6..0000000 --- a/stratum/chassis_config.pb_with_PortShaping.txt.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. -SPDX-License-Identifier: Apache-2.0 From aad6dc75f67fdb03fe22b6522d96f57fa9680e67 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Fri, 12 Feb 2021 16:34:22 -0300 Subject: [PATCH 17/19] fix the file name. --- ...PortShaping.txt => chassis_config.pb_with_port_shaping.pb.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename stratum/{chassis_config.pb_with_PortShaping.txt => chassis_config.pb_with_port_shaping.pb.txt} (100%) diff --git a/stratum/chassis_config.pb_with_PortShaping.txt b/stratum/chassis_config.pb_with_port_shaping.pb.txt similarity index 100% rename from stratum/chassis_config.pb_with_PortShaping.txt rename to stratum/chassis_config.pb_with_port_shaping.pb.txt From b630bbd4473764a182cf77e53e7c06f849044d51 Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Fri, 12 Feb 2021 16:48:08 -0300 Subject: [PATCH 18/19] fix the file name. --- ...ort_shaping.pb.txt => chassis_config_with_port_shaping.pb.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename stratum/{chassis_config.pb_with_port_shaping.pb.txt => chassis_config_with_port_shaping.pb.txt} (100%) diff --git a/stratum/chassis_config.pb_with_port_shaping.pb.txt b/stratum/chassis_config_with_port_shaping.pb.txt similarity index 100% rename from stratum/chassis_config.pb_with_port_shaping.pb.txt rename to stratum/chassis_config_with_port_shaping.pb.txt From 3e47d25f5e0adbaf0e85c331684579740e585cef Mon Sep 17 00:00:00 2001 From: ersuneetsingh Date: Mon, 15 Feb 2021 17:51:29 -0300 Subject: [PATCH 19/19] Test case to verify metering --- trex-scripts/tests/metering.py | 165 +++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 trex-scripts/tests/metering.py diff --git a/trex-scripts/tests/metering.py b/trex-scripts/tests/metering.py new file mode 100644 index 0000000..218af49 --- /dev/null +++ b/trex-scripts/tests/metering.py @@ -0,0 +1,165 @@ +# SPDX-FileCopyrightText: Copyright 2020-present Open Networking Foundation. +# SPDX-License-Identifier: Apache-2.0 + +import logging +import os +import json +from argparse import ArgumentParser +from datetime import datetime +from scapy.layers.all import IP, TCP, UDP, Ether + +from lib.base_test import StatelessTest +from lib.utils import list_port_status,get_readable_port_stats +from lib.xnt import analysis_report_pcap +from trex_stl_lib.api import STLPktBuilder, STLStream, STLTXCont, STLTXSingleBurst, STLFlowLatencyStats, STLFlowStats + + +SOURCE_MAC = "00:00:00:00:00:01" +DEST_MAC = "00:00:00:00:00:02" + +SENDER_PORT = [0] +RECEIVER_PORT = [1] + +class Metering(StatelessTest): + + # setup_subparser is an optional class method + # You can implement this method if you want to add additional command line + # parameters for your test. + # Those parameters will be parsed and be passed to the "start" method below as + # "args" argument. + @classmethod + def setup_subparser(cls, parser: ArgumentParser) -> None: + parser.add_argument("--duration", type=float, help="Test duration", default=2) + + + # The entrypoint of a test + def start(self, args: dict) -> None: + + # create packets + pkt1 = Ether(dst=DEST_MAC) / IP(src="16.0.0.1",dst="48.0.0.1") / UDP(dport=12,sport=1025) + pkt2 = Ether(dst=DEST_MAC) / IP(src="16.0.0.2",dst="48.0.0.2") / UDP(dport=12,sport=1025) + + pad1 = max(0, 1500 - len(pkt1)) * 'x' + pad2 = max(0, 1500 - len(pkt2)) * 'x' + + # two different burst sizes + burst_size_b1 = 83333 # 1 Gb + burst_size_b2 = 416666 # 5 Gb + + + # In this test case, we consider two delay critical streams: 1) s1 with metering, and 2) s2 without metering + # This test verifies both peak information rate (pir) and peak burst size (pbs) + # For this test case, meter parameters for stream s1 are set as follows: + # pir (in kbps) = 2000000 (i.e., 2Gbps) + # pbs (in kbits) = 1000000 (i.e., 1Gb) + # cir (in kbps) = 100 + # cbs (in kbits) = 1000 + + # stream s1 is a delay critical, contains two bursts s1_b1 and s1_b2 with burst size 'burst_size_b1' and 'burst_size_b2' + # rate (in pps) for each burst is set as same as burst size + s1_b1 = STLStream( name = 's1_b1', packet=STLPktBuilder(pkt=pkt1 / pad1), \ + mode=STLTXSingleBurst(pps=burst_size_b1, total_pkts = burst_size_b1), \ + next ='s1_b2',flow_stats = STLFlowStats(pg_id = 1)) + s1_b2 = STLStream( name = 's1_b2', self_start = False, packet=STLPktBuilder(pkt=pkt1 / pad1), \ + mode=STLTXSingleBurst(pps=burst_size_b2, total_pkts = burst_size_b2),\ + flow_stats = STLFlowStats(pg_id = 2)) + + # stream s2 is a delay critcial, contains two bursts s2_b1 and s2_b2 with burt size burst_size_b1 and burst_size_b2 + # rate (in pps) for each burst is set as same as burst size + s2_b1 = STLStream( name = 's2_b1', packet=STLPktBuilder(pkt=pkt2 / pad2), \ + mode=STLTXSingleBurst(pps = burst_size_b1, total_pkts = burst_size_b1), \ + next ='s2_b2', flow_stats = STLFlowStats(pg_id = 3)) + s2_b2 = STLStream( name = 's2_b2', self_start = False, packet=STLPktBuilder(pkt=pkt2 / pad2), \ + mode=STLTXSingleBurst(pps = burst_size_b2, total_pkts = burst_size_b2), \ + flow_stats = STLFlowStats(pg_id = 4)) + + # prepare ports + self.client.reset(ports=[0,1]) + + # add sterams + self.client.add_streams(streams=[s1_b1, s1_b2], ports=[0]) + self.client.add_streams(streams=[s2_b1, s2_b2], ports=[0]) + + + logging.info( + "Starting traffic, duration: %d sec", args.duration, + ) + + # Start sending traffic + self.client.start(SENDER_PORT, duration=args.duration) + pgids = self.client.get_active_pgids() + + + logging.info("Waiting until all traffic stop") + self.client.wait_on_traffic(ports=SENDER_PORT) + + # stats for s1 and s2 + stats = self.client.get_pgid_stats()['flow_stats'] + flow_stats_s1_b1 = stats.get(1) + flow_stats_s1_b2 = stats.get(2) + flow_stats_s2_b1 = stats.get(3) + flow_stats_s2_b2 = stats.get(4) + + tx_pkts_s1_b1 = flow_stats_s1_b1['tx_pkts'].get(0, 0) + rx_pkts_s1_b1 = flow_stats_s1_b1['rx_pkts'].get(1, 0) + pkt_drop_s1_b1 = tx_pkts_s1_b1 - rx_pkts_s1_b1 + tx_gbps_s1_b1 = (tx_pkts_s1_b1 * 1500 * 8)/10**9 + rx_gbps_s1_b1 = (rx_pkts_s1_b1 * 1500 * 8)/10**9 + + tx_pkts_s1_b2 = flow_stats_s1_b2['tx_pkts'].get(0, 0) + rx_pkts_s1_b2 = flow_stats_s1_b2['rx_pkts'].get(1, 0) + pkt_drop_s1_b2 = tx_pkts_s1_b2 - rx_pkts_s1_b2 + tx_gbps_s1_b2 = (tx_pkts_s1_b2 * 1500 * 8)/10**9 + rx_gbps_s1_b2 = (rx_pkts_s1_b2 * 1500 * 8)/10**9 + + tx_pkts_s2_b1 = flow_stats_s2_b1['tx_pkts'].get(0, 0) + rx_pkts_s2_b1 = flow_stats_s2_b1['rx_pkts'].get(1, 0) + pkt_drop_s2_b1 = tx_pkts_s2_b1 - rx_pkts_s2_b1 + tx_gbps_s2_b1 = (tx_pkts_s2_b1 * 1500 * 8)/10**9 + rx_gbps_s2_b1 = (rx_pkts_s2_b1 * 1500 * 8)/10**9 + + tx_pkts_s2_b2 = flow_stats_s2_b2['tx_pkts'].get(0, 0) + rx_pkts_s2_b2 = flow_stats_s2_b2['rx_pkts'].get(1, 0) + pkt_drop_s2_b2 = tx_pkts_s2_b2 - rx_pkts_s2_b2 + tx_gbps_s2_b2 = (tx_pkts_s2_b2 * 1500 * 8)/10**9 + rx_gbps_s2_b2 = (rx_pkts_s2_b2 * 1500 * 8)/10**9 + + print(" \n TX and RX flow stats and packet dopped for s1 with metering (i.e., delay critical): ") + print(" \n for s1 burst 1 : ") + print(" tx packets : {0}".format(tx_pkts_s1_b1)) + print(" rx packets : {0}".format(rx_pkts_s1_b1)) + print(" dropped pkts : {0}".format(pkt_drop_s1_b1)) + print(" tx gbps : {0}".format(tx_gbps_s1_b1)) + print(" rx gbps : {0}".format(rx_gbps_s1_b1)) + + print(" \n for s1 burst 2 : ") + print(" tx packets : {0}".format(tx_pkts_s1_b2)) + print(" rx packets : {0}".format(rx_pkts_s1_b2)) + print(" dropped pkts : {0}".format(pkt_drop_s1_b2)) + print(" tx gbps : {0}".format(tx_gbps_s1_b2)) + print(" rx gbps : {0}".format(rx_gbps_s1_b2)) + + print(" \n TX and RX flow stats and packet dopped for s2 without metering (i.e., delay critical): ") + print(" \n for s2 burst 1 : ") + print(" tx packets : {0}".format(tx_pkts_s2_b1)) + print(" rx packets : {0}".format(rx_pkts_s2_b1)) + print(" dropped pkts : {0}".format(pkt_drop_s2_b1)) + print(" tx gbps : {0}".format(tx_gbps_s2_b1)) + print(" rx gbps : {0}".format(rx_gbps_s2_b1)) + + print(" \n for s2 burst 2 : ") + print(" tx packets : {0}".format(tx_pkts_s2_b2)) + print(" rx packets : {0}".format(rx_pkts_s2_b2)) + print(" dropped pkts : {0}".format(pkt_drop_s2_b2)) + print(" tx gbps : {0}".format(tx_gbps_s2_b2)) + print(" rx gbps : {0}".format(rx_gbps_s2_b2)) + + + total_pkt_drops_s2 = pkt_drop_s2_b1 + pkt_drop_s2_b2 + + # since pir is set to 2 Gbps and pbs is 1 Gb, the total allowable bytes will be around 3Gb for each burst of s1 + # Note: initally tocken bucket is filled with 1 Gb. If the first burst of s1 contians 3Gb, then for the second burst, + # the allowable bytes will be only 1 Gb in case of tx burst rate > pir + # Since s2 is without metering, there should be 0 packets drop + assert (total_pkt_drops_s2 == 0 and pkt_drop_s1_b1 == 0 and 3*0.99 < rx_gbps_s1_b2 <= 3.0), \ + "meter test failed."