blob: 9a52313def286d2acba6ee1f5ff2be3056fe216e [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):
10 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 # Load traffic config for the current test case
20 cfgFile = "%s/tests/CASE_%d.json" % (main.configPath, test_idx)
21 with open(cfgFile) as cfg:
22 testCfg = json.load(cfg)
23
24 trex = Trex()
25 trex.setup(main.TRexClient)
26
27 original_flows_number = onos_cli.checkFlowCount()
28
29 main.step("Add and verify Slices and Traffic Classes")
30 added_slices = True
31 new_flows = 0 # one for every new TC in SLICE and 1 for every Flow Classifier
32 for slice_name in main.params["SLICING"]["slices"]:
33 slice = main.params["SLICING"]["slices"][slice_name]
34 if "slice_id" not in slice:
35 continue
36 slice_id = int(slice["slice_id"])
37 onos_rest.addSlice(slice_id=slice_id, debug=True)
38 slices_onos = onos_rest.getSlices(debug=True)
39 # Verify the slice has been added
40 added_slices = added_slices and \
41 {"SliceId": slice_id} in json.loads(slices_onos)
42
43 tcs = []
44 for tc in slice.get("traffic_classes", "").split(","):
45 onos_rest.addTrafficClassToSlice(slice_id=slice_id,
46 traffic_class=tc,
47 debug=True)
48 tcs.append({"TrafficClass": tc})
49 new_flows += 1
50 tcs_onos = onos_rest.getTrafficClasses(slice_id=slice_id,
51 debug=True)
52 # Verify the TC has been added to the slice
53 added_slices = added_slices and \
54 sorted(json.loads(tcs_onos)) == sorted(tcs)
55 utilities.assert_equal(
56 expect=True,
57 actual=added_slices,
58 onpass="Slices and Traffic Classes installed in slicing service",
59 onfail="Error in installing Slices and Traffic Classes in slicing service"
60 )
61
62 main.step("Add and verify slicing traffic classifier")
63 flows_in_slicing = True
64 for slicing_cfg_name in main.params["SLICING"]["traffic_classification"]:
65 new_flows += 1
66 slicing_config = main.params["SLICING"]["traffic_classification"][
67 slicing_cfg_name]
68
69 traffic_selector = self.__cleanupTrafficSelector(slicing_config.get("traffic_selector", []))
70 onos_rest.addSlicingClassifierFlow(
71 slice_id=int(slicing_config.get("slice_id", "0")),
72 traffic_class=slicing_config.get("traffic_class",
73 "BEST_EFFORT"),
74 traffic_selector=traffic_selector,
75 debug=True
76 )
77 # Verify classifier flows
78 onos_flows = json.loads(onos_rest.getSlicingClassifierFlow(
79 slice_id=int(slicing_config.get("slice_id", "0")),
80 traffic_class=slicing_config.get("traffic_class",
81 "BEST_EFFORT"),
82 debug=True
83 ))
84 flows_in_slicing = flows_in_slicing and traffic_selector in onos_flows
85
86 utilities.assert_equal(
87 expect=True,
88 actual=flows_in_slicing,
89 onpass="Traffic Classifier Flows installed in slicing service",
90 onfail="Error in installing Classifier Flows in slicing service"
91 )
92
93 run.checkFlows(
94 main,
95 minFlowCount=original_flows_number + (new_flows * n_switches)
96 )
97
98 main.step("Send traffic with TRex")
99 for flow in testCfg["flows"]:
100 trex.createFlow(flow)
101 trex.sendAndReceiveTraffic(testCfg["duration"])
102
103 trex.logPortStats()
104 for flow in testCfg["flows"]:
105 trex.logFlowStats(flow)
106
107 # Assert Flow Stats
108 for flow in testCfg["flows"]:
109 if trex.isFlowStats(flow):
110 main.step("{}: Assert RX Packets".format(flow))
111 trex.assertRxPackets(flow)
112 main.step("{}: Assert Dropped Packets".format(flow))
113 trex.assertDroppedPacket(flow)
114 main.step("{}: Assert 99.9 Percentile Latency".format(flow))
115 trex.assert99_9PercentileLatency(flow)
116
117 main.step("Remove and verify slicing traffic classifier")
118 no_flows_in_slicing = True
119 for slicing_cfg_name in main.params["SLICING"]["traffic_classification"]:
120 slicing_config = main.params["SLICING"]["traffic_classification"][
121 slicing_cfg_name]
122
123 traffic_selector = self.__cleanupTrafficSelector(slicing_config.get("traffic_selector", []))
124 onos_rest.removeSlicingClassifierFlow(
125 slice_id=int(slicing_config.get("slice_id", "0")),
126 traffic_class=slicing_config.get("traffic_class",
127 "BEST_EFFORT"),
128 traffic_selector=traffic_selector,
129 debug=True
130 )
131 flow = onos_rest.getSlicingClassifierFlow(
132 slice_id=int(slicing_config.get("slice_id", "0")),
133 traffic_class=slicing_config.get("traffic_class",
134 "BEST_EFFORT"),
135 debug=True
136 )
137 no_flows_in_slicing = no_flows_in_slicing and flow == "[]"
138
139 utilities.assert_equal(
140 expect=True,
141 actual=no_flows_in_slicing,
142 onpass="Traffic Classifier Flows removed in slicing service",
143 onfail="Error in removing Classifier Flows in slicing service"
144 )
145
146 main.step("Remove and verify Slices and Traffic Classes")
147 removed_slices = []
148 for slice_name in main.params["SLICING"]["slices"]:
149 slice = main.params["SLICING"]["slices"][slice_name]
150 if "slice_id" not in slice:
151 continue
152 slice_id = int(slice["slice_id"])
153 for tc in slice.get("traffic_classes", "").split(","):
154 # BEST_EFFORT must be removed as last, or we can leave it,
155 # it will be removed when removing the slice
156 if tc != "BEST_EFFORT":
157 onos_rest.removeTrafficClassToSlice(slice_id=slice_id,
158 traffic_class=tc,
159 debug=True)
160 # Do not try to remove the Default Slice!
161 if slice_id != 0:
162 onos_rest.removeSlice(slice_id=slice_id, debug=True)
163 removed_slices.append(slice_id)
164
165 slices_onos = json.loads(onos_rest.getSlices(debug=True))
166 utilities.assert_equal(
167 expect=True,
168 actual=not any([{"SliceId": slice_id} in slices_onos for slice_id in
169 removed_slices]),
170 onpass="Slices and Traffic Classes removed from slicing service",
171 onfail="Error in removing Slices and Traffic Classes from slicing service"
172 )
173
174 run.checkFlows(main, minFlowCount=original_flows_number)
175
176 main.step("Teardown")
177 trex.teardown()
178 run.cleanup(main)
179
180 def __cleanupTrafficSelector(self, traffic_selector):
181 ts = {
182 "criteria": [traffic_selector[criteria] for criteria in
183 traffic_selector]}
184 # Cleanup the traffic selector, by converting into integer the
185 # required fields, conversion is required for checking the result
186 # from ONOS
187 for criteria in ts["criteria"]:
188 if "udpPort" in criteria:
189 criteria["udpPort"] = int(criteria["udpPort"])
190 return ts