blob: f599c5d3d289a3f944294b08876916d43ecd8e4e [file] [log] [blame]
Daniele Moro04a62d12021-10-06 17:37:36 +02001from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
2 Testcaselib as run
3from tests.USECASE.SegmentRouting.dependencies.trex import Trex
4import json
5
6
7class QOSNonMobileTest:
8
9 def runTest(self, main, test_idx, n_switches):
Jon Halldd05bbc2022-01-27 12:14:50 -080010 try:
11 run.initTest(main)
12 main.log.info(main.Cluster.numCtrls)
13 main.Cluster.setRunningNode(3)
14 run.installOnos(main, skipPackage=True, cliSleep=5)
Daniele Moro04a62d12021-10-06 17:37:36 +020015
Jon Halldd05bbc2022-01-27 12:14:50 -080016 # Use the first available ONOS instance CLI
17 onos_rest = main.Cluster.active(0).REST
18 onos_cli = main.Cluster.active(0).CLI
Daniele Moro04a62d12021-10-06 17:37:36 +020019
Jon Halldd05bbc2022-01-27 12:14:50 -080020 # Load traffic config for the current test case
21 cfgFile = "%s/tests/CASE_%d.json" % (main.configPath, test_idx)
22 with open(cfgFile) as cfg:
23 testCfg = json.load(cfg)
Daniele Moro04a62d12021-10-06 17:37:36 +020024
Jon Halldd05bbc2022-01-27 12:14:50 -080025 trex = Trex()
26 trex.setup(main.TRexClient)
Daniele Moro04a62d12021-10-06 17:37:36 +020027
Jon Halldd05bbc2022-01-27 12:14:50 -080028 original_flows_number = onos_cli.checkFlowCount()
Daniele Moro04a62d12021-10-06 17:37:36 +020029
Jon Halldd05bbc2022-01-27 12:14:50 -080030 main.step("Add and verify Slices and Traffic Classes")
31 added_slices = True
32 new_flows = 0 # one for every new TC in SLICE and 1 for every Flow Classifier
33 for slice_name in main.params["SLICING"]["slices"]:
34 slice = main.params["SLICING"]["slices"][slice_name]
35 if "slice_id" not in slice:
36 continue
37 slice_id = int(slice["slice_id"])
38 onos_rest.addSlice(slice_id=slice_id, debug=True)
39 slices_onos = onos_rest.getSlices(debug=True)
40 # Verify the slice has been added
41 added_slices = added_slices and \
42 {"SliceId": slice_id} in json.loads(slices_onos)
Daniele Moro04a62d12021-10-06 17:37:36 +020043
Jon Halldd05bbc2022-01-27 12:14:50 -080044 tcs = []
45 for tc in slice.get("traffic_classes", "").split(","):
46 onos_rest.addTrafficClassToSlice(slice_id=slice_id,
47 traffic_class=tc,
48 debug=True)
49 tcs.append({"TrafficClass": tc})
50 new_flows += 1
51 tcs_onos = onos_rest.getTrafficClasses(slice_id=slice_id,
52 debug=True)
53 # Verify the TC has been added to the slice
54 added_slices = added_slices and \
55 sorted(json.loads(tcs_onos)) == sorted(tcs)
56 utilities.assert_equal(
57 expect=True,
58 actual=added_slices,
59 onpass="Slices and Traffic Classes installed in slicing service",
60 onfail="Error in installing Slices and Traffic Classes in slicing service"
61 )
62
63 main.step("Add and verify slicing traffic classifier")
64 flows_in_slicing = True
65 for slicing_cfg_name in main.params["SLICING"]["traffic_classification"]:
Daniele Moro04a62d12021-10-06 17:37:36 +020066 new_flows += 1
Jon Halldd05bbc2022-01-27 12:14:50 -080067 slicing_config = main.params["SLICING"]["traffic_classification"][
68 slicing_cfg_name]
Daniele Moro04a62d12021-10-06 17:37:36 +020069
Jon Halldd05bbc2022-01-27 12:14:50 -080070 traffic_selector = self.__cleanupTrafficSelector(slicing_config.get("traffic_selector", []))
71 onos_rest.addSlicingClassifierFlow(
72 slice_id=int(slicing_config.get("slice_id", "0")),
73 traffic_class=slicing_config.get("traffic_class",
74 "BEST_EFFORT"),
75 traffic_selector=traffic_selector,
76 debug=True
77 )
78 # Verify classifier flows
79 onos_flows = json.loads(onos_rest.getSlicingClassifierFlow(
80 slice_id=int(slicing_config.get("slice_id", "0")),
81 traffic_class=slicing_config.get("traffic_class",
82 "BEST_EFFORT"),
83 debug=True
84 ))
85 flows_in_slicing = flows_in_slicing and traffic_selector in onos_flows
Daniele Moro04a62d12021-10-06 17:37:36 +020086
Jon Halldd05bbc2022-01-27 12:14:50 -080087 utilities.assert_equal(
88 expect=True,
89 actual=flows_in_slicing,
90 onpass="Traffic Classifier Flows installed in slicing service",
91 onfail="Error in installing Classifier Flows in slicing service"
Daniele Moro04a62d12021-10-06 17:37:36 +020092 )
Daniele Moro04a62d12021-10-06 17:37:36 +020093
Jon Halldd05bbc2022-01-27 12:14:50 -080094 run.checkFlows(
95 main,
96 minFlowCount=original_flows_number + (new_flows * n_switches)
Daniele Moro04a62d12021-10-06 17:37:36 +020097 )
Jon Halldd05bbc2022-01-27 12:14:50 -080098
99 main.step("Send traffic with TRex")
100 for flow in testCfg["flows"]:
101 trex.createFlow(flow)
102 results = trex.sendAndReceiveTraffic(testCfg["duration"])
103 trex.verifyCongestion(results)
104
105 trex.logPortStats()
106 for flow in testCfg["flows"]:
107 trex.logFlowStats(flow)
108
109 # Assert Flow Stats
110 for flow in testCfg["flows"]:
111 if trex.isFlowStats(flow):
112 main.step("{}: Assert RX Packets".format(flow))
113 trex.assertRxPackets(flow)
114 main.step("{}: Assert Dropped Packets".format(flow))
115 trex.assertDroppedPacket(flow)
116 main.step("{}: Assert 99.9 Percentile Latency".format(flow))
117 trex.assert99_9PercentileLatency(flow)
118
119 main.step("Remove and verify slicing traffic classifier")
120 no_flows_in_slicing = True
121 for slicing_cfg_name in main.params["SLICING"]["traffic_classification"]:
122 slicing_config = main.params["SLICING"]["traffic_classification"][
123 slicing_cfg_name]
124
125 traffic_selector = self.__cleanupTrafficSelector(slicing_config.get("traffic_selector", []))
126 onos_rest.removeSlicingClassifierFlow(
127 slice_id=int(slicing_config.get("slice_id", "0")),
128 traffic_class=slicing_config.get("traffic_class",
129 "BEST_EFFORT"),
130 traffic_selector=traffic_selector,
131 debug=True
132 )
133 flow = onos_rest.getSlicingClassifierFlow(
134 slice_id=int(slicing_config.get("slice_id", "0")),
135 traffic_class=slicing_config.get("traffic_class",
136 "BEST_EFFORT"),
137 debug=True
138 )
139 no_flows_in_slicing = no_flows_in_slicing and flow == "[]"
140
141 utilities.assert_equal(
142 expect=True,
143 actual=no_flows_in_slicing,
144 onpass="Traffic Classifier Flows removed in slicing service",
145 onfail="Error in removing Classifier Flows in slicing service"
Daniele Moro04a62d12021-10-06 17:37:36 +0200146 )
Daniele Moro04a62d12021-10-06 17:37:36 +0200147
Jon Halldd05bbc2022-01-27 12:14:50 -0800148 main.step("Remove and verify Slices and Traffic Classes")
149 removed_slices = []
150 for slice_name in main.params["SLICING"]["slices"]:
151 slice = main.params["SLICING"]["slices"][slice_name]
152 if "slice_id" not in slice:
153 continue
154 slice_id = int(slice["slice_id"])
155 for tc in slice.get("traffic_classes", "").split(","):
156 # BEST_EFFORT must be removed as last, or we can leave it,
157 # it will be removed when removing the slice
158 if tc != "BEST_EFFORT":
159 onos_rest.removeTrafficClassToSlice(slice_id=slice_id,
160 traffic_class=tc,
161 debug=True)
162 # Do not try to remove the Default Slice!
163 if slice_id != 0:
164 onos_rest.removeSlice(slice_id=slice_id, debug=True)
165 removed_slices.append(slice_id)
Daniele Moro04a62d12021-10-06 17:37:36 +0200166
Jon Halldd05bbc2022-01-27 12:14:50 -0800167 slices_onos = json.loads(onos_rest.getSlices(debug=True))
168 utilities.assert_equal(
169 expect=True,
170 actual=not any([{"SliceId": slice_id} in slices_onos for slice_id in
171 removed_slices]),
172 onpass="Slices and Traffic Classes removed from slicing service",
173 onfail="Error in removing Slices and Traffic Classes from slicing service"
174 )
Daniele Moro04a62d12021-10-06 17:37:36 +0200175
Jon Halldd05bbc2022-01-27 12:14:50 -0800176 run.checkFlows(main, minFlowCount=original_flows_number)
177 finally:
178 main.step("Teardown")
179 trex.teardown()
180 run.cleanup(main)
Daniele Moro04a62d12021-10-06 17:37:36 +0200181
182 def __cleanupTrafficSelector(self, traffic_selector):
183 ts = {
184 "criteria": [traffic_selector[criteria] for criteria in
185 traffic_selector]}
186 # Cleanup the traffic selector, by converting into integer the
187 # required fields, conversion is required for checking the result
188 # from ONOS
189 for criteria in ts["criteria"]:
190 if "udpPort" in criteria:
191 criteria["udpPort"] = int(criteria["udpPort"])
192 return ts