blob: 456699e9af982b96a230166bbad2e32f2b1f3b59 [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):
Daniele Morob8404e82022-02-25 00:17:28 +010010 run.initTest(main)
11 main.log.info(main.Cluster.numCtrls)
12 main.Cluster.setRunningNode(3)
13 run.installOnos(main, skipPackage=True, cliSleep=5)
14
15 # Use the first available ONOS instance CLI
16 onos_rest = main.Cluster.active(0).REST
17 onos_cli = main.Cluster.active(0).CLI
18
19 trex = Trex()
20 trex.setup(main.TRexClient)
Jon Halldd05bbc2022-01-27 12:14:50 -080021 try:
Jon Halldd05bbc2022-01-27 12:14:50 -080022 # Load traffic config for the current test case
23 cfgFile = "%s/tests/CASE_%d.json" % (main.configPath, test_idx)
24 with open(cfgFile) as cfg:
25 testCfg = json.load(cfg)
Daniele Moro04a62d12021-10-06 17:37:36 +020026
Jon Halldd05bbc2022-01-27 12:14:50 -080027 original_flows_number = onos_cli.checkFlowCount()
Daniele Moro04a62d12021-10-06 17:37:36 +020028
Carmelo Cascone848d1f52022-01-27 18:15:58 -080029 main.step("Verify slices and traffic Classes")
Carmelo Cascone848d1f52022-01-27 18:15:58 -080030 slices_onos = onos_rest.getSlices(debug=True)
31
32 # Sanity check for the API, at least the default slice should be there.
33 utilities.assert_equal(
34 expect=True,
35 actual={"SliceId": 0} in json.loads(slices_onos),
36 onpass="Default slice verified in slicing service",
37 onfail="Error in verifying default slice in slicing service"
38 )
39
Jon Halldd05bbc2022-01-27 12:14:50 -080040 for slice_name in main.params["SLICING"]["slices"]:
41 slice = main.params["SLICING"]["slices"][slice_name]
42 if "slice_id" not in slice:
43 continue
44 slice_id = int(slice["slice_id"])
Carmelo Cascone848d1f52022-01-27 18:15:58 -080045 utilities.assert_equal(
46 expect=True,
47 actual={"SliceId": slice_id} in json.loads(slices_onos),
48 onpass="Verified presence of slice %s in slicing service" % slice_id,
49 onfail="Slice %s not found in slicing service" % slice_id
50 )
Daniele Moro04a62d12021-10-06 17:37:36 +020051
Carmelo Cascone848d1f52022-01-27 18:15:58 -080052 tcs = slice.get("traffic_classes", "").split(",")
53
Jon Halldd05bbc2022-01-27 12:14:50 -080054 tcs_onos = onos_rest.getTrafficClasses(slice_id=slice_id,
55 debug=True)
Carmelo Cascone848d1f52022-01-27 18:15:58 -080056 for tc in tcs:
57 utilities.assert_equal(
58 expect=True,
59 actual={"TrafficClass": tc} in json.loads(tcs_onos),
60 onpass="Verified presence of TC %s for slice %s in slicing service" % (tc, slice_id),
61 onfail="TC %s not found for slice %s in slicing service" % (tc, slice_id)
62 )
Jon Halldd05bbc2022-01-27 12:14:50 -080063
Carmelo Cascone848d1f52022-01-27 18:15:58 -080064 main.step("Add and verify traffic classifier flows")
65 new_flows = 0
66 for flow_name in main.params["SLICING"]["traffic_classification"]:
Daniele Moro04a62d12021-10-06 17:37:36 +020067 new_flows += 1
Carmelo Cascone848d1f52022-01-27 18:15:58 -080068 flow_config = main.params["SLICING"]["traffic_classification"][
69 flow_name]
Daniele Moro04a62d12021-10-06 17:37:36 +020070
Carmelo Cascone11bd4422022-02-07 18:22:24 -080071 traffic_selector = self.__normalizeTrafficSelector(flow_config.get("traffic_selector"))
Jon Halldd05bbc2022-01-27 12:14:50 -080072 onos_rest.addSlicingClassifierFlow(
Carmelo Cascone848d1f52022-01-27 18:15:58 -080073 slice_id=int(flow_config.get("slice_id")),
74 traffic_class=flow_config.get("traffic_class"),
Jon Halldd05bbc2022-01-27 12:14:50 -080075 traffic_selector=traffic_selector,
76 debug=True
77 )
Carmelo Cascone848d1f52022-01-27 18:15:58 -080078
Carmelo Cascone11bd4422022-02-07 18:22:24 -080079 actual_selectors = json.loads(onos_rest.getSlicingClassifierFlows(
Carmelo Cascone848d1f52022-01-27 18:15:58 -080080 slice_id=int(flow_config.get("slice_id")),
81 traffic_class=flow_config.get("traffic_class"),
Jon Halldd05bbc2022-01-27 12:14:50 -080082 debug=True
83 ))
Carmelo Cascone848d1f52022-01-27 18:15:58 -080084 utilities.assert_equal(
85 expect=True,
Carmelo Cascone11bd4422022-02-07 18:22:24 -080086 actual=self.__containsTrafficSelector(actual_selectors, traffic_selector),
Carmelo Cascone848d1f52022-01-27 18:15:58 -080087 onpass="Classifier flow %s installed" % flow_name,
88 onfail="Classifier flow %s not found after insert" % flow_name
89 )
Daniele Moro04a62d12021-10-06 17:37:36 +020090
Jon Halldd05bbc2022-01-27 12:14:50 -080091 run.checkFlows(
92 main,
93 minFlowCount=original_flows_number + (new_flows * n_switches)
Daniele Moro04a62d12021-10-06 17:37:36 +020094 )
Jon Halldd05bbc2022-01-27 12:14:50 -080095
Jon Halldd05bbc2022-01-27 12:14:50 -080096 for flow in testCfg["flows"]:
97 trex.createFlow(flow)
98 results = trex.sendAndReceiveTraffic(testCfg["duration"])
Daniele Morob8404e82022-02-25 00:17:28 +010099 main.step("Verify congestion")
Jon Halldd05bbc2022-01-27 12:14:50 -0800100 trex.verifyCongestion(results)
101
102 trex.logPortStats()
103 for flow in testCfg["flows"]:
104 trex.logFlowStats(flow)
105
106 # Assert Flow Stats
107 for flow in testCfg["flows"]:
108 if trex.isFlowStats(flow):
109 main.step("{}: Assert RX Packets".format(flow))
110 trex.assertRxPackets(flow)
111 main.step("{}: Assert Dropped Packets".format(flow))
112 trex.assertDroppedPacket(flow)
113 main.step("{}: Assert 99.9 Percentile Latency".format(flow))
114 trex.assert99_9PercentileLatency(flow)
115
Carmelo Cascone848d1f52022-01-27 18:15:58 -0800116 main.step("Remove and verify traffic classifier flows")
117 for flow_name in main.params["SLICING"]["traffic_classification"]:
118 flow_config = main.params["SLICING"]["traffic_classification"][
119 flow_name]
Jon Halldd05bbc2022-01-27 12:14:50 -0800120
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800121 traffic_selector = self.__normalizeTrafficSelector(flow_config.get("traffic_selector"))
Jon Halldd05bbc2022-01-27 12:14:50 -0800122 onos_rest.removeSlicingClassifierFlow(
Carmelo Cascone848d1f52022-01-27 18:15:58 -0800123 slice_id=int(flow_config.get("slice_id")),
124 traffic_class=flow_config.get("traffic_class"),
Jon Halldd05bbc2022-01-27 12:14:50 -0800125 traffic_selector=traffic_selector,
126 debug=True
127 )
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800128 actual_selectors = json.loads(onos_rest.getSlicingClassifierFlows(
Carmelo Cascone848d1f52022-01-27 18:15:58 -0800129 slice_id=int(flow_config.get("slice_id")),
130 traffic_class=flow_config.get("traffic_class"),
Jon Halldd05bbc2022-01-27 12:14:50 -0800131 debug=True
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800132 ))
Carmelo Cascone848d1f52022-01-27 18:15:58 -0800133 utilities.assert_equal(
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800134 expect=False,
135 actual=self.__containsTrafficSelector(actual_selectors, traffic_selector),
Carmelo Cascone848d1f52022-01-27 18:15:58 -0800136 onpass="Classifier flow %s removed from slicing service" % flow_name,
137 onfail="Unable to remove classifier flow %s from slicing service" % flow_name
138 )
Daniele Moro04a62d12021-10-06 17:37:36 +0200139
Jon Halldd05bbc2022-01-27 12:14:50 -0800140 run.checkFlows(main, minFlowCount=original_flows_number)
141 finally:
142 main.step("Teardown")
143 trex.teardown()
144 run.cleanup(main)
Daniele Moro04a62d12021-10-06 17:37:36 +0200145
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800146 def __normalizeTrafficSelector(self, traffic_selector):
Daniele Moro04a62d12021-10-06 17:37:36 +0200147 ts = {
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800148 "criteria": [traffic_selector[criterion] for criterion in
Daniele Moro04a62d12021-10-06 17:37:36 +0200149 traffic_selector]}
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800150 # Converts the required fields into integer, required to compare them
151 # with the API result from ONOS.
152 for criterion in ts["criteria"]:
153 if "udpPort" in criterion:
154 criterion["udpPort"] = int(criterion["udpPort"])
155 elif "protocol" in criterion:
156 criterion["protocol"] = int(criterion["protocol"])
Daniele Moro04a62d12021-10-06 17:37:36 +0200157 return ts
Carmelo Cascone11bd4422022-02-07 18:22:24 -0800158
159 def __containsTrafficSelector(self, actual_selectors, expected_selector):
160 # actual_selectors = [{"criteria":[{"type":"IP_PROTO","protocol":17},{"type":"UDP_DST","udpPort":200}]}]
161 expected_criteria = expected_selector["criteria"]
162 for actual_selector in actual_selectors:
163 actual_criteria = actual_selector["criteria"]
164 if len(actual_criteria) != len(expected_criteria):
165 continue
166 for actual_criterion in actual_criteria:
167 # actual_criterion = {"type":"IP_PROTO","protocol":17}
168 if actual_criterion not in expected_criteria:
169 # Next selector
170 break
171 else:
172 # We found all criteria in this selector.
173 return True
174 return False