blob: f0d7fa5656972ebd91ac8532eaa61a8534c54cec [file] [log] [blame]
Daniele Moro790cc102021-08-30 18:27:30 +02001class UP4:
2
3 def __init__(self):
4 self.default = ''
5
Daniele Moro790cc102021-08-30 18:27:30 +02006 def CASE1(self, main):
Daniele Morobf53dec2021-09-13 18:11:56 +02007 main.case("Fabric UPF traffic terminated in the fabric")
Daniele Moro790cc102021-08-30 18:27:30 +02008 """
Daniele Moro49a843c2022-01-05 14:36:32 +01009 Program UPF entities for UEs
10 Verify UPF entities
Daniele Moro790cc102021-08-30 18:27:30 +020011 Generate traffic from UE to PDN
12 Verify traffic received from PDN
13 Generate traffic from PDN to UE
14 Verify traffic received from UE
Daniele Moro49a843c2022-01-05 14:36:32 +010015 Remove UPF entities for UEs
16 Verify removed UPF entities
Daniele Moro790cc102021-08-30 18:27:30 +020017 """
Daniele Moro790cc102021-08-30 18:27:30 +020018 try:
Daniele Moroc6811a82021-10-12 11:29:41 +020019 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
20 N_FLOWS_PER_UE
Daniele Moro790cc102021-08-30 18:27:30 +020021 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
22 Testcaselib as run
Daniele Moro790cc102021-08-30 18:27:30 +020023 except ImportError as e:
24 main.log.error("Import not found. Exiting the test")
25 main.log.error(e)
26 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +020027 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro790cc102021-08-30 18:27:30 +020028
Daniele Moro790cc102021-08-30 18:27:30 +020029 run.initTest(main)
30 main.log.info(main.Cluster.numCtrls)
31 main.Cluster.setRunningNode(3)
32 run.installOnos(main, skipPackage=True, cliSleep=5)
33
Daniele Moro790cc102021-08-30 18:27:30 +020034 main.step("Start scapy and p4rt client")
Daniele Morobf53dec2021-09-13 18:11:56 +020035 # Use the first available ONOS instance CLI
36 onos_cli = main.Cluster.active(0).CLI
Daniele Moro9ba5cf02021-10-08 18:00:56 +020037 initial_flow_count = onos_cli.checkFlowCount()
Daniele Moro80889562021-09-08 10:09:26 +020038 up4 = UP4()
39 # Get the P4RT client connected to UP4 in the first available ONOS instance
40 up4.setup(main.Cluster.active(0).p4rtUp4)
Daniele Moro790cc102021-08-30 18:27:30 +020041
Daniele Moro49a843c2022-01-05 14:36:32 +010042 main.step("Program and Verify UPF entities via UP4")
Daniele Moro80889562021-09-08 10:09:26 +020043 up4.attachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +020044 up4.verifyUp4Flow(onos_cli)
45
Daniele Moro9ba5cf02021-10-08 18:00:56 +020046 run.checkFlows(
47 main,
Daniele Moroc6811a82021-10-12 11:29:41 +020048 minFlowCount=initial_flow_count + (
49 len(up4.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +020050 )
51
Daniele Moro80889562021-09-08 10:09:26 +020052 # ------- Test Upstream traffic (enb->pdn)
Daniele Morobef0c7e2022-02-16 17:47:13 -080053 for app_filter_name in up4.app_filters:
54 main.step("Test upstream traffic %s" % app_filter_name)
55 up4.testUpstreamTraffic(app_filter_name=app_filter_name)
Daniele Moro790cc102021-08-30 18:27:30 +020056
Daniele Moro80889562021-09-08 10:09:26 +020057 # ------- Test Downstream traffic (pdn->enb)
Daniele Morobef0c7e2022-02-16 17:47:13 -080058 for app_filter_name in up4.app_filters:
59 main.step("Test downstream traffic %s" % app_filter_name)
60 up4.testDownstreamTraffic(app_filter_name=app_filter_name)
Daniele Moro790cc102021-08-30 18:27:30 +020061
Daniele Moro49a843c2022-01-05 14:36:32 +010062 main.step("Remove and Verify UPF entities via UP4")
Daniele Moro80889562021-09-08 10:09:26 +020063 up4.detachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +020064 up4.verifyNoUesFlow(onos_cli)
65
Daniele Moro9ba5cf02021-10-08 18:00:56 +020066 run.checkFlows(main, minFlowCount=initial_flow_count)
67
Daniele Moro790cc102021-08-30 18:27:30 +020068 main.step("Stop scapy and p4rt client")
Daniele Moro80889562021-09-08 10:09:26 +020069 up4.teardown()
Daniele Moroc99bf822021-10-11 23:21:15 +020070
Daniele Moro790cc102021-08-30 18:27:30 +020071 run.cleanup(main)
Daniele Morobf53dec2021-09-13 18:11:56 +020072
Daniele Moro9ba5cf02021-10-08 18:00:56 +020073 def CASE2(self, main):
Daniele Morobf53dec2021-09-13 18:11:56 +020074 main.case("BESS traffic routed")
75 """
Daniele Moro49a843c2022-01-05 14:36:32 +010076 Program UPF entities for UEs managed via UP4
77 Verify UPF entities
Daniele Morobf53dec2021-09-13 18:11:56 +020078 Verify Upstream Traffic: eNB -> Fabric -> BESS (encapped)
79 Verify Upstream Traffic: BESS -> Fabric -> PDN (not encapped)
80 Verify Downstream Traffic: PDN -> Fabric -> BESS (not encapped)
81 Verify Downstream Traffic: BESS -> Fabric -> eNB (encapped)
Daniele Moro49a843c2022-01-05 14:36:32 +010082 Remove UPF entities for UEs managed via UP4
83 Verify removed UPF entities
Daniele Morobf53dec2021-09-13 18:11:56 +020084 """
85 BESS_TEID = 300
Daniele Morobf53dec2021-09-13 18:11:56 +020086 GPDU_PORT = 2152
87 UE_PORT = 400
88 PDN_PORT = 800
89 try:
Daniele Moroc6811a82021-10-12 11:29:41 +020090 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
91 N_FLOWS_PER_UE
Daniele Morobf53dec2021-09-13 18:11:56 +020092 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
93 Testcaselib as run
94 except ImportError as e:
95 main.log.error("Import not found. Exiting the test")
96 main.log.error(e)
97 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +020098 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Morobf53dec2021-09-13 18:11:56 +020099
100 run.initTest(main)
101 main.log.info(main.Cluster.numCtrls)
102 main.Cluster.setRunningNode(3)
103 run.installOnos(main, skipPackage=True, cliSleep=5)
104
105 main.step("Start scapy and p4rt client + Scapy on BESS Host")
106 # Use the first available ONOS instance CLI
107 onos_cli = main.Cluster.active(0).CLI
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200108 initial_flow_count = onos_cli.checkFlowCount()
Daniele Morobf53dec2021-09-13 18:11:56 +0200109 up4 = UP4()
110 # Get the P4RT client connected to UP4 in the first available ONOS instance
111 up4.setup(main.Cluster.active(0).p4rtUp4)
112
113 # Setup the emulated BESS host and required parameters
Daniele Moro522023c2021-10-15 17:30:33 +0200114 bess_host = getattr(main, main.params["BESS_UPF"]["bess_host"])
Daniele Morobf53dec2021-09-13 18:11:56 +0200115 bess_interface = bess_host.interfaces[0]
116 bess_s1u_address = bess_interface["ips"][0]
117 bess_host.startScapy(ifaceName=bess_interface["name"], enableGtp=True)
Daniele Moro522023c2021-10-15 17:30:33 +0200118 bess_ue_address = main.params["BESS_UPF"]["ue_address"]
119 enodeb_host = getattr(main, main.params["BESS_UPF"]["enodeb_host"])
120 enodeb_address = main.params["BESS_UPF"]["enb_address"]
121 enodeb_interface = enodeb_host.interfaces[0]["name"]
Daniele Morobf53dec2021-09-13 18:11:56 +0200122 pdn_host = up4.pdn_host
123 pdn_interface = up4.pdn_interface
124
Daniele Moro49a843c2022-01-05 14:36:32 +0100125 main.step("Program and Verify UPF entities for UEs via UP4")
Daniele Morobf53dec2021-09-13 18:11:56 +0200126 up4.attachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +0200127 up4.verifyUp4Flow(onos_cli)
128
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200129 run.checkFlows(
130 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200131 minFlowCount=initial_flow_count + (
132 len(up4.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200133 )
134
Daniele Morobf53dec2021-09-13 18:11:56 +0200135 # ------------------- UPSTREAM -------------------
136 # ------- eNB -> fabric -> BESS (encapped)
137 main.step("Test upstream eNB -> fabric -> BESS")
138 # Start filter before sending packets, BESS should receive GTP encapped
139 # packets
140 pkt_filter_upstream = "ip and udp src port %d and udp dst port %d and src host %s and dst host %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200141 GPDU_PORT, GPDU_PORT, enodeb_address, bess_s1u_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200142 main.log.info("Start listening on %s intf %s" % (
143 bess_host.name, bess_interface["name"]))
144 main.log.debug("BPF Filter BESS Upstream: \n %s" % pkt_filter_upstream)
145 bess_host.startFilter(ifaceName=bess_interface["name"],
146 sniffCount=1,
147 pktFilter=pkt_filter_upstream)
148 # Send GTP Packet
149 UP4.buildGtpPacket(enodeb_host,
Daniele Moro522023c2021-10-15 17:30:33 +0200150 src_ip_outer=enodeb_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200151 dst_ip_outer=bess_s1u_address,
Daniele Moro522023c2021-10-15 17:30:33 +0200152 src_ip_inner=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200153 dst_ip_inner=pdn_interface["ips"][0],
154 src_udp_inner=UE_PORT,
155 dst_udp_inner=PDN_PORT,
156 teid=BESS_TEID)
157 enodeb_host.sendPacket()
158
159 packets = UP4.checkFilterAndGetPackets(bess_host)
160 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
161 n_packets = packets.count("TEID=" + hex(BESS_TEID) + "L ")
162 tot_packets = packets.count('Ether')
163 utilities.assert_equal(expect=True,
164 actual=n_packets == 1 and tot_packets == 1,
165 onpass="BESS correctly received 1 GTP encapped packet",
166 onfail="ERROR: BESS received %d GTP encapped packets and filter captured %d packets" % (
167 n_packets, tot_packets))
168
169 # ------- BESS -> fabric -> PDN (not-encapped)
170 main.step("Test upstream BESS -> fabric -> PDN")
171 # Start filter before sending packets, PDN should receive non-GTP packet
172 pkt_filter_upstream = "ip and udp src port %d and udp dst port %d and src host %s and dst host %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200173 UE_PORT, PDN_PORT, bess_ue_address, pdn_interface["ips"][0])
Daniele Morobf53dec2021-09-13 18:11:56 +0200174 main.log.info("Start listening on %s intf %s" % (
175 pdn_host.name, pdn_interface["name"]))
176 main.log.debug("BPF Filter PDN Upstream: \n %s" % pkt_filter_upstream)
177 pdn_host.startFilter(ifaceName=pdn_interface["name"],
178 sniffCount=1,
179 pktFilter=pkt_filter_upstream)
180 # Send UDP Packet
181 UP4.buildUdpPacket(bess_host,
Daniele Moro522023c2021-10-15 17:30:33 +0200182 src_ip=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200183 dst_ip=pdn_interface["ips"][0],
184 src_udp=UE_PORT,
185 dst_udp=PDN_PORT)
186 bess_host.sendPacket()
187
188 packets = UP4.checkFilterAndGetPackets(pdn_host)
189 tot_packets = packets.count('Ether')
190 utilities.assert_equal(expect=True,
191 actual=tot_packets == 1,
192 onpass="PDN correctly received 1 packet",
193 onfail="ERROR: PDN received %d packets" % (
194 tot_packets))
195 # ------------------------------------------------
196
197 # ------------------ DOWNSTREAM ------------------
198 # ------- PDN -> fabric -> BESS (not-encapped)
199 main.step("Test downstream PDN -> fabric -> BESS")
200 pkt_filter_downstream = "ip and udp src port %d and udp dst port %d and src host %s and dst host %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200201 PDN_PORT, UE_PORT, pdn_interface["ips"][0], bess_ue_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200202 main.log.info("Start listening on %s intf %s" % (
203 bess_host.name, bess_interface["name"]))
204 main.log.debug(
205 "BPF Filter BESS Downstream: \n %s" % pkt_filter_downstream)
206 bess_host.startFilter(ifaceName=bess_interface["name"],
207 sniffCount=1,
208 pktFilter=pkt_filter_downstream)
209 UP4.buildUdpPacket(pdn_host,
210 dst_eth=up4.router_mac,
211 src_ip=pdn_interface["ips"][0],
Daniele Moro522023c2021-10-15 17:30:33 +0200212 dst_ip=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200213 src_udp=PDN_PORT,
214 dst_udp=UE_PORT)
215 pdn_host.sendPacket()
216
217 packets = UP4.checkFilterAndGetPackets(bess_host)
218
219 tot_packets = packets.count('Ether')
220 utilities.assert_equal(expect=True,
221 actual=tot_packets == 1,
222 onpass="BESS correctly received 1 packet",
223 onfail="ERROR: BESS received %d packets" % (
224 tot_packets))
225
226 # ------- BESS -> fabric -> eNB (encapped)
227 main.step("Test downstream BESS -> fabric -> eNB")
228 pkt_filter_downstream = "ip and udp src port %d and udp dst port %d and src host %s and dst host %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200229 GPDU_PORT, GPDU_PORT, bess_s1u_address, enodeb_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200230 main.log.info("Start listening on %s intf %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200231 enodeb_host.name, enodeb_interface))
Daniele Morobf53dec2021-09-13 18:11:56 +0200232 main.log.debug(
233 "BPF Filter BESS Downstream: \n %s" % pkt_filter_downstream)
Daniele Moro522023c2021-10-15 17:30:33 +0200234 enodeb_host.startFilter(ifaceName=enodeb_interface,
Daniele Morobf53dec2021-09-13 18:11:56 +0200235 sniffCount=1,
236 pktFilter=pkt_filter_downstream)
237 # Build GTP packet from BESS host
238 UP4.buildGtpPacket(bess_host,
239 src_ip_outer=bess_s1u_address,
Daniele Moro522023c2021-10-15 17:30:33 +0200240 dst_ip_outer=enodeb_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200241 src_ip_inner=pdn_interface["ips"][0],
Daniele Moro522023c2021-10-15 17:30:33 +0200242 dst_ip_inner=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200243 src_udp_inner=PDN_PORT,
244 dst_udp_inner=UE_PORT,
245 teid=BESS_TEID)
246 bess_host.sendPacket()
247
248 packets = UP4.checkFilterAndGetPackets(enodeb_host)
249
250 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
251 n_packets = packets.count("TEID=" + hex(BESS_TEID) + "L ")
252 tot_packets = packets.count('Ether')
253 utilities.assert_equal(expect=True,
254 actual=n_packets == 1 and tot_packets == 1,
255 onpass="eNodeB correctly received 1 GTP encapped packet",
256 onfail="ERROR: eNodeb received %d GTP encapped packets and filter captured %d packets" % (
257 n_packets, tot_packets))
258 # ------------------------------------------------
259
Daniele Moro49a843c2022-01-05 14:36:32 +0100260 main.step("Remove and Verify UPF entities for UEs via UP4")
Daniele Morobf53dec2021-09-13 18:11:56 +0200261 up4.detachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +0200262 up4.verifyNoUesFlow(onos_cli)
263
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200264 run.checkFlows(main, minFlowCount=initial_flow_count)
265
Daniele Morobf53dec2021-09-13 18:11:56 +0200266 main.step("Stop scapy and p4rt client")
267 up4.teardown()
268 bess_host.stopScapy()
Daniele Moroc99bf822021-10-11 23:21:15 +0200269
Daniele Morobf53dec2021-09-13 18:11:56 +0200270 run.cleanup(main)
Daniele Moro954e2282021-09-22 17:32:03 +0200271
272 def CASE3(self, main):
273 main.case("Verify UP4 from different ONOS instances")
274 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100275 Program UPF entitiesvia UP4 on first ONOS instance
Daniele Moro954e2282021-09-22 17:32:03 +0200276 Repeat for all ONOS Instances:
Daniele Moro49a843c2022-01-05 14:36:32 +0100277 Verify UPF entities via P4RT
Daniele Moro954e2282021-09-22 17:32:03 +0200278 Disconnect P4RT client
Daniele Moro49a843c2022-01-05 14:36:32 +0100279 Verify and delete UPF entities via UP4 on the third ONOS instance
Daniele Moro954e2282021-09-22 17:32:03 +0200280 Repeat for all ONOS Instance:
Daniele Moro49a843c2022-01-05 14:36:32 +0100281 Verify removed UPF entities via P4RT
Daniele Moro954e2282021-09-22 17:32:03 +0200282 Disconnect P4RT client
283 """
284 try:
Daniele Morofbfdfbd2021-10-18 22:47:51 +0200285 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
286 N_FLOWS_PER_UE
Daniele Moro954e2282021-09-22 17:32:03 +0200287 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
288 Testcaselib as run
289 except ImportError as e:
290 main.log.error("Import not found. Exiting the test")
291 main.log.error(e)
292 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +0200293 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro954e2282021-09-22 17:32:03 +0200294
295 run.initTest(main)
296 main.log.info(main.Cluster.numCtrls)
297 main.Cluster.setRunningNode(3)
298 run.installOnos(main, skipPackage=True, cliSleep=5)
299
300 onos_cli_0 = main.Cluster.active(0).CLI
301 onos_cli_1 = main.Cluster.active(1).CLI
302 onos_cli_2 = main.Cluster.active(2).CLI
303 up4_0 = UP4()
304 up4_1 = UP4()
305 up4_2 = UP4()
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200306 initial_flow_count = onos_cli_0.checkFlowCount()
Daniele Moro954e2282021-09-22 17:32:03 +0200307
Daniele Moro49a843c2022-01-05 14:36:32 +0100308 main.step("Program and Verify UPF entities via UP4 on ONOS 0")
Daniele Moro954e2282021-09-22 17:32:03 +0200309 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
310 up4_0.attachUes()
311 up4_0.verifyUp4Flow(onos_cli_0)
312 up4_0.teardown()
313
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200314 run.checkFlows(
315 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200316 minFlowCount=initial_flow_count + (
317 len(up4_0.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200318 )
319
Daniele Moro49a843c2022-01-05 14:36:32 +0100320 main.step("Verify UPF entities number via UP4 P4RT on ONOS 1")
Daniele Moro954e2282021-09-22 17:32:03 +0200321 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
322 utilities.assert_equal(
323 expect=True,
324 actual=up4_1.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100325 onpass="Correct number of UPF entities",
326 onfail="Wrong number of UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200327 )
328 up4_1.teardown()
329
Daniele Moro49a843c2022-01-05 14:36:32 +0100330 main.step("Verify UPF entities number via UP4 P4RT on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200331 up4_2.setup(main.Cluster.active(2).p4rtUp4, no_host=True)
332 utilities.assert_equal(
333 expect=True,
334 actual=up4_2.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100335 onpass="Correct number of UPF entities",
336 onfail="Wrong number of UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200337 )
338
339 main.step("Verify all ONOS instances have the same number of flows")
340 onos_0_flow_count = onos_cli_0.checkFlowCount()
341 onos_1_flow_count = onos_cli_1.checkFlowCount()
342 onos_2_flow_count = onos_cli_2.checkFlowCount()
343 utilities.assert_equal(
344 expect=True,
345 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
346 onpass="All ONOS instances have the same number of flows",
347 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
348 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
349 )
350
Daniele Moro49a843c2022-01-05 14:36:32 +0100351 main.step("Remove and Verify UPF entities via UP4 on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200352 up4_2.detachUes()
353 up4_2.verifyNoUesFlow(onos_cli_2)
354
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200355 run.checkFlows(main, minFlowCount=initial_flow_count)
356
Daniele Moro49a843c2022-01-05 14:36:32 +0100357 main.step("Verify no UPF entities via UP4 P4RT on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200358 utilities.assert_equal(
359 expect=True,
360 actual=up4_2.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100361 onpass="No UPF entities",
362 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200363 )
364 up4_2.teardown()
365
Daniele Moro49a843c2022-01-05 14:36:32 +0100366 main.step("Verify no UPF entities via UP4 P4RT on ONOS 1")
Daniele Moro954e2282021-09-22 17:32:03 +0200367 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
368 utilities.assert_equal(
369 expect=True,
370 actual=up4_1.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100371 onpass="No UPF entities",
372 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200373 )
374 up4_1.teardown()
375
Daniele Moro49a843c2022-01-05 14:36:32 +0100376 main.step("Verify no UPF entities via UP4 P4RT on ONOS 0")
Daniele Moro954e2282021-09-22 17:32:03 +0200377 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
378 utilities.assert_equal(
379 expect=True,
380 actual=up4_0.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100381 onpass="No UPF entities",
382 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200383 )
384 up4_0.teardown()
385
386 main.step("Verify all ONOS instances have the same number of flows")
387 onos_0_flow_count = onos_cli_0.checkFlowCount()
388 onos_1_flow_count = onos_cli_1.checkFlowCount()
389 onos_2_flow_count = onos_cli_2.checkFlowCount()
390 utilities.assert_equal(
391 expect=True,
392 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
393 onpass="All ONOS instances have the same number of flows",
394 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200395 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
Daniele Moro954e2282021-09-22 17:32:03 +0200396 )
Daniele Moroc99bf822021-10-11 23:21:15 +0200397
Daniele Moro954e2282021-09-22 17:32:03 +0200398 run.cleanup(main)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200399
400 def CASE4(self, main):
401 main.case("Verify UP4 wipe-out after ONOS reboot")
402 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100403 Program UPF entities
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200404 Kill ONOS POD
Daniele Moro49a843c2022-01-05 14:36:32 +0100405 Verify UPF entities from other ONOS instances
406 Remove UPF entities
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200407 Wait/Verify ONOS is back
Daniele Moro49a843c2022-01-05 14:36:32 +0100408 Verify no UPF entities from rebooted instance
409 Re-program UPF entities from rebooted instance
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200410 Verify all instances have same number of flows
Daniele Moro49a843c2022-01-05 14:36:32 +0100411 Remove UPF entities (cleanup)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200412 """
413 try:
Daniele Moroc6811a82021-10-12 11:29:41 +0200414 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
415 N_FLOWS_PER_UE
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200416 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
417 Testcaselib as run
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100418 from tests.USECASE.SegmentRouting.SRStaging.dependencies.SRStagingTest import \
419 SRStagingTest
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200420 except ImportError as e:
421 main.log.error("Import not found. Exiting the test")
422 main.log.error(e)
423 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +0200424 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200425
426 run.initTest(main)
427 main.log.info(main.Cluster.numCtrls)
428 main.Cluster.setRunningNode(3)
429 run.installOnos(main, skipPackage=True, cliSleep=5)
430
431 onos_cli_0 = main.Cluster.active(0).CLI
432 onos_cli_1 = main.Cluster.active(1).CLI
433 onos_cli_2 = main.Cluster.active(2).CLI
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100434 ctrl_0 = main.Cluster.active(0)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200435
436 up4_0 = UP4()
437 up4_1 = UP4()
438 up4_2 = UP4()
439
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200440 initial_flow_count = onos_cli_0.checkFlowCount()
441
Daniele Moro49a843c2022-01-05 14:36:32 +0100442 main.step("Program and Verify UPF entities via UP4 on ONOS 0")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200443 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
444 up4_0.attachUes()
445 up4_0.verifyUp4Flow(onos_cli_0)
446 up4_0.teardown()
447
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200448 run.checkFlows(
449 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200450 minFlowCount=initial_flow_count + (
451 len(up4_0.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200452 )
453
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200454 onosPod = main.params["UP4_delete_pod"]
Daniele Moroc99bf822021-10-11 23:21:15 +0200455
456 # Save ONOS diags of the POD we are killing otherwise we lose ONOS logs
457 main.ONOSbench.onosDiagnosticsK8s(
458 [onosPod],
459 main.logdir,
460 "-CASE%d-%s_BeforeKill" % (main.CurrentTestCaseNumber, onosPod)
461 )
462
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100463 onosK8sNode = SRStagingTest.onosDown(main, ctrl_0, preventRestart=True)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200464
Daniele Moro49a843c2022-01-05 14:36:32 +0100465 main.step("Verify UPF entities number via UP4 P4RT on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200466 up4_2.setup(main.Cluster.active(2).p4rtUp4, no_host=True)
467 utilities.assert_equal(
468 expect=True,
469 actual=up4_2.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100470 onpass="Correct number of UPF entities",
471 onfail="Wrong number of UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200472 )
473
Daniele Moro49a843c2022-01-05 14:36:32 +0100474 main.step("Remove and Verify UPF entities via UP4 on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200475 up4_2.detachUes()
476 up4_2.verifyNoUesFlow(onos_cli_2)
477
Daniele Moro49a843c2022-01-05 14:36:32 +0100478 main.step("Verify no UPF entities via UP4 P4RT on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200479 utilities.assert_equal(
480 expect=True,
481 actual=up4_2.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100482 onpass="No UPF entities",
483 onfail="Stale UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200484 )
485 up4_2.teardown()
486
Daniele Moroc6811a82021-10-12 11:29:41 +0200487 main.step(
488 "Verify all active ONOS instances have the same number of flows")
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200489 onos_1_flow_count = onos_cli_1.checkFlowCount()
490 onos_2_flow_count = onos_cli_2.checkFlowCount()
491 utilities.assert_equal(
492 expect=True,
493 actual=onos_1_flow_count == onos_2_flow_count,
494 onpass="All ONOS instances have the same number of flows",
495 onfail="ONOS instances have different number of flows: (%d, %d)" % (
496 onos_1_flow_count, onos_2_flow_count)
497 )
498
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100499 SRStagingTest.onosUp(main, onosK8sNode, ctrl_0)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200500
501 main.step("Verify ONOS cluster is in good shape")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200502 onosNodesStatus = utilities.retry(
503 f=main.Cluster.nodesCheck,
504 retValue=False,
505 sleep=5,
506 attempts=10
507 )
508 utilities.assert_equal(
509 expect=True,
510 actual=onosNodesStatus,
511 onpass="ONOS nodes status correct",
512 onfail="Wrong ONOS nodes status"
513 )
514
Daniele Moro49a843c2022-01-05 14:36:32 +0100515 main.step("Verify no UPF entities via UP4 P4RT on ONOS 0")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200516 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
517 utilities.assert_equal(
518 expect=True,
519 actual=up4_0.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100520 onpass="No UPF entities",
521 onfail="Stale UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200522 )
523
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200524 run.checkFlows(main, minFlowCount=initial_flow_count)
525
Daniele Moro49a843c2022-01-05 14:36:32 +0100526 main.step("Re-program UPF entities via UP4 on ONOS 0 after restart")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200527 up4_0.attachUes()
528 up4_0.verifyUp4Flow(onos_cli_0)
529 up4_0.teardown()
530
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200531 run.checkFlows(
532 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200533 minFlowCount=initial_flow_count + (
534 len(up4_0.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200535 )
536
Daniele Moro49a843c2022-01-05 14:36:32 +0100537 main.step("Verify UPF entities via UP4 on ONOS 1")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200538 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
539 up4_1.verifyUp4Flow(onos_cli_1)
540
541 main.step("Verify all ONOS instances have the same number of flows")
542 onos_0_flow_count = onos_cli_0.checkFlowCount()
543 onos_1_flow_count = onos_cli_1.checkFlowCount()
544 onos_2_flow_count = onos_cli_2.checkFlowCount()
545 utilities.assert_equal(
546 expect=True,
547 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
548 onpass="All ONOS instances have the same number of flows",
549 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
550 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
551 )
552
Daniele Moro49a843c2022-01-05 14:36:32 +0100553 main.step("Cleanup UPF entities via UP4 on ONOS 1")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200554 up4_1.detachUes()
Daniele Moro6dfbfef2021-09-28 22:44:19 +0200555 up4_1.verifyNoUesFlow(onos_cli_1)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200556 up4_1.teardown()
557
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200558 run.checkFlows(main, minFlowCount=initial_flow_count)
559
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200560 run.cleanup(main)
Daniele Moro522023c2021-10-15 17:30:33 +0200561
562 def CASE5(self, main):
563 main.case("UP4 Data Plane Failure Test")
564 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100565 Program UPF entities
Daniele Moro522023c2021-10-15 17:30:33 +0200566 Kill one switch
Daniele Moro80271cb2021-11-11 20:08:51 +0100567 Set label on switch K8S node to prevent K8S to redeploy stratum
Daniele Moro522023c2021-10-15 17:30:33 +0200568 Verify that traffic from eNodebs that are connected to that switch fails
569 Verify that traffic from other eNodeBs is being forwarded
570 Wait for the switch to be up again
571 Check flows
Daniele Moro49a843c2022-01-05 14:36:32 +0100572 Remove UPF entities (cleanup)
Daniele Moro522023c2021-10-15 17:30:33 +0200573 """
574 try:
575 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
576 N_FLOWS_PER_UE
577 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
578 Testcaselib as run
579 from tests.USECASE.SegmentRouting.SRStaging.dependencies.SRStagingTest import \
580 SRStagingTest
581 import time
582 import itertools
583 except ImportError as e:
584 main.log.error("Import not found. Exiting the test")
585 main.log.error(e)
586 main.cleanAndExit()
587 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro80271cb2021-11-11 20:08:51 +0100588 switch_to_kill = main.params["UP4"]["UP4_dataplane_fail"]["switch_to_kill"]
589 k8s_switch_node = main.params["UP4"]["UP4_dataplane_fail"]["k8s_switch_node"]
590 k8s_label = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label"]
591 k8s_label_value_test = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label_value_test"]
592 k8s_label_value_normal = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label_value_normal"]
Daniele Moro522023c2021-10-15 17:30:33 +0200593
594 run.initTest(main)
595 main.log.info(main.Cluster.numCtrls)
596 main.Cluster.setRunningNode(3)
597 run.installOnos(main, skipPackage=True, cliSleep=5)
598
599 onos_cli = main.Cluster.active(0).CLI
Daniele Moro80271cb2021-11-11 20:08:51 +0100600 kubectl = main.Cluster.active(0).Bench
601 kubeconfig = main.Cluster.active(0).k8s.kubeConfig
602 namespace = main.params['kubernetes']['namespace']
Daniele Moro522023c2021-10-15 17:30:33 +0200603
604 up4 = UP4()
605
606 initial_flow_count = onos_cli.checkFlowCount()
607
Daniele Moro49a843c2022-01-05 14:36:32 +0100608 main.step("Program and Verify UPF entities via UP4")
Daniele Moro522023c2021-10-15 17:30:33 +0200609 up4.setup(main.Cluster.active(0).p4rtUp4)
610 up4.attachUes()
611 up4.verifyUp4Flow(onos_cli)
612
613 run.checkFlows(
614 main,
615 minFlowCount=initial_flow_count+(len(up4.emulated_ues)*4*n_switches)
616 )
617
Daniele Moro80271cb2021-11-11 20:08:51 +0100618 main.step("Set label to switch k8s node and kill switch")
619 # K8s node name correspond to the switch name in lowercase
Daniele Moro522023c2021-10-15 17:30:33 +0200620 utilities.assert_equal(
Daniele Moro80271cb2021-11-11 20:08:51 +0100621 expect=main.TRUE,
622 actual=kubectl.kubectlSetLabel(
623 nodeName=k8s_switch_node,
624 label=k8s_label,
625 value=k8s_label_value_test,
626 kubeconfig=kubeconfig,
627 namespace=namespace,
628 ),
629 onpass="Label has been set correctly on node %s" % k8s_switch_node,
630 onfail="Label has not been set on node %s" % k8s_switch_node
Daniele Moro522023c2021-10-15 17:30:33 +0200631 )
Daniele Moro80271cb2021-11-11 20:08:51 +0100632 try:
633 def checkNumberStratumPods(n_value):
634 pods = kubectl.kubectlGetPodNames(
635 kubeconfig=kubeconfig,
636 namespace=namespace,
637 name="stratum"
638 )
639 main.log.info("PODS: " + str(pods))
640 return n_value == len(pods) if pods is not main.FALSE else False
641 # Execute the following in try/except/finally to be sure to restore the
642 # k8s label even in case of unhandled exception.
Daniele Moro522023c2021-10-15 17:30:33 +0200643
Daniele Moro80271cb2021-11-11 20:08:51 +0100644 # Wait for stratum pod to be removed from the switch
645 removed = utilities.retry(checkNumberStratumPods,
646 False,
647 args=[n_switches-1],
648 attempts=50
649 )
650 main.log.info("Stratum has been removed from the switch? %s" % removed)
Daniele Moro522023c2021-10-15 17:30:33 +0200651
Daniele Moro80271cb2021-11-11 20:08:51 +0100652 switch_component = getattr(main, switch_to_kill)
653 switch_component.handle.sendline("sudo reboot")
Daniele Moro522023c2021-10-15 17:30:33 +0200654
Daniele Moro80271cb2021-11-11 20:08:51 +0100655 sleepTime = 20
656 main.log.info("Sleeping %s seconds for Fabric to react" % sleepTime)
657 time.sleep(sleepTime)
Daniele Moro522023c2021-10-15 17:30:33 +0200658
Daniele Moro80271cb2021-11-11 20:08:51 +0100659 available = utilities.retry(SRStagingTest.switchIsConnected,
660 True,
661 args=[switch_component],
662 attempts=300,
663 getRetryingTime=True)
664 main.log.info("Switch %s is available in ONOS? %s" % (
665 switch_to_kill, available))
666 utilities.assert_equal(
667 expect=True,
668 actual=not available and removed,
669 onpass="Switch was rebooted (ONL reboot) successfully and stratum" +
670 " removed from switch k8s node",
671 onfail="Switch was not rebooted (ONL reboot) successfully or stratum " +
672 "not removed from switch k8s node"
673 )
674
675 enodebs_fail = main.params["UP4"]["UP4_dataplane_fail"]["enodebs_fail"].split(",")
676 enodebs_no_fail = list(set(up4.enodebs.keys()) - set(enodebs_fail))
677
Daniele Moro80271cb2021-11-11 20:08:51 +0100678
Daniele Morobef0c7e2022-02-16 17:47:13 -0800679 for app_filter_name in up4.app_filters:
680 # Failure only when we forward traffic, when dropping we should
681 # still see traffic being dropped.
682 if up4.app_filters["action"] == "allow":
683 main.step("Test upstream traffic FAIL %s" % app_filter_name)
684 up4.testUpstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name, shouldFail=True)
685 main.step("Test downstream traffic FAIL %s" % app_filter_name)
686 up4.testDownstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name, shouldFail=True)
687 else:
688 main.step("Test upstream traffic FAIL %s" % app_filter_name)
689 up4.testUpstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name)
690 main.step("Test downstream traffic FAIL %s" % app_filter_name)
691 up4.testDownstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name)
692
693 main.step("Test upstream traffic NO FAIL %s" % app_filter_name)
694 up4.testUpstreamTraffic(enb_names=enodebs_no_fail, app_filter_name=app_filter_name)
695 main.step("Test downstream traffic NO FAIL %s" % app_filter_name)
696 up4.testDownstreamTraffic(enb_names=enodebs_no_fail, app_filter_name=app_filter_name)
697
Daniele Moro80271cb2021-11-11 20:08:51 +0100698 except Exception as e:
699 main.log.error("Unhandled exception!")
700 main.log.error(e)
701 finally:
702 utilities.assert_equal(
703 expect=main.TRUE,
704 actual=kubectl.kubectlSetLabel(
705 nodeName=k8s_switch_node,
706 label=k8s_label,
707 value=k8s_label_value_normal,
708 kubeconfig=kubeconfig,
709 namespace=namespace,
710 ),
711 onpass="Label has been set correctly on node %s" % k8s_switch_node,
712 onfail="Label has not been set on node %s" % k8s_switch_node
713 )
714 # Reconnect to the switch
715 connect = utilities.retry(switch_component.connect,
716 main.FALSE,
717 attempts=30,
718 getRetryingTime=True)
719 main.log.info("Connected to the switch %s? %s" % (
720 switch_to_kill, connect))
721
722 # Wait for stratum pod to be re-deployed on the switch
723 deployed = utilities.retry(checkNumberStratumPods,
724 False,
725 args=[n_switches],
726 attempts=50
727 )
728 main.log.info("Stratum has been redeployed on the switch? %s" % deployed)
729
730 # Wait switch to be back in ONOS
731 available = utilities.retry(SRStagingTest.switchIsConnected,
732 False,
733 args=[switch_component],
734 attempts=300,
735 getRetryingTime=True)
736 main.log.info("Switch %s is available in ONOS? %s" % (
737 switch_to_kill, available))
738 utilities.assert_equal(
739 expect=True,
740 actual=available and connect == main.TRUE and deployed,
741 onpass="Switch is back available in ONOS and stratum has been redeployed",
742 onfail="Switch is not available in ONOS, may influence subsequent tests!"
743 )
Daniele Moro522023c2021-10-15 17:30:33 +0200744
Daniele Morobef0c7e2022-02-16 17:47:13 -0800745 for app_filter_name in up4.app_filters:
746 main.step("Test upstream traffic AFTER switch reboot %s" % app_filter_name)
747 up4.testUpstreamTraffic(app_filter_name=app_filter_name)
Daniele Moro522023c2021-10-15 17:30:33 +0200748
Daniele Moro49a843c2022-01-05 14:36:32 +0100749 main.step("Cleanup UPF entities via UP4")
Daniele Moro522023c2021-10-15 17:30:33 +0200750 up4.detachUes()
751 up4.verifyNoUesFlow(onos_cli)
752 up4.teardown()
753
754 run.checkFlows(main, minFlowCount=initial_flow_count)
755
756 # Teardown
757 run.cleanup(main)
Daniele Moro80271cb2021-11-11 20:08:51 +0100758