blob: f60d353c416c9161175b56c9bf001535daac249b [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 Moro790cc102021-08-30 18:27:30 +020053 main.step("Test upstream traffic")
Daniele Moro80889562021-09-08 10:09:26 +020054 up4.testUpstreamTraffic()
Daniele Moro790cc102021-08-30 18:27:30 +020055
Daniele Moro80889562021-09-08 10:09:26 +020056 # ------- Test Downstream traffic (pdn->enb)
Daniele Moro790cc102021-08-30 18:27:30 +020057 main.step("Test downstream traffic")
Daniele Moro80889562021-09-08 10:09:26 +020058 up4.testDownstreamTraffic()
Daniele Moro790cc102021-08-30 18:27:30 +020059
Daniele Moro49a843c2022-01-05 14:36:32 +010060 main.step("Remove and Verify UPF entities via UP4")
Daniele Moro80889562021-09-08 10:09:26 +020061 up4.detachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +020062 up4.verifyNoUesFlow(onos_cli)
63
Daniele Moro9ba5cf02021-10-08 18:00:56 +020064 run.checkFlows(main, minFlowCount=initial_flow_count)
65
Daniele Moro790cc102021-08-30 18:27:30 +020066 main.step("Stop scapy and p4rt client")
Daniele Moro80889562021-09-08 10:09:26 +020067 up4.teardown()
Daniele Moroc99bf822021-10-11 23:21:15 +020068
Daniele Moro790cc102021-08-30 18:27:30 +020069 run.cleanup(main)
Daniele Morobf53dec2021-09-13 18:11:56 +020070
Daniele Moro9ba5cf02021-10-08 18:00:56 +020071 def CASE2(self, main):
Daniele Morobf53dec2021-09-13 18:11:56 +020072 main.case("BESS traffic routed")
73 """
Daniele Moro49a843c2022-01-05 14:36:32 +010074 Program UPF entities for UEs managed via UP4
75 Verify UPF entities
Daniele Morobf53dec2021-09-13 18:11:56 +020076 Verify Upstream Traffic: eNB -> Fabric -> BESS (encapped)
77 Verify Upstream Traffic: BESS -> Fabric -> PDN (not encapped)
78 Verify Downstream Traffic: PDN -> Fabric -> BESS (not encapped)
79 Verify Downstream Traffic: BESS -> Fabric -> eNB (encapped)
Daniele Moro49a843c2022-01-05 14:36:32 +010080 Remove UPF entities for UEs managed via UP4
81 Verify removed UPF entities
Daniele Morobf53dec2021-09-13 18:11:56 +020082 """
83 BESS_TEID = 300
Daniele Morobf53dec2021-09-13 18:11:56 +020084 GPDU_PORT = 2152
85 UE_PORT = 400
86 PDN_PORT = 800
87 try:
Daniele Moroc6811a82021-10-12 11:29:41 +020088 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
89 N_FLOWS_PER_UE
Daniele Morobf53dec2021-09-13 18:11:56 +020090 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
91 Testcaselib as run
92 except ImportError as e:
93 main.log.error("Import not found. Exiting the test")
94 main.log.error(e)
95 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +020096 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Morobf53dec2021-09-13 18:11:56 +020097
98 run.initTest(main)
99 main.log.info(main.Cluster.numCtrls)
100 main.Cluster.setRunningNode(3)
101 run.installOnos(main, skipPackage=True, cliSleep=5)
102
103 main.step("Start scapy and p4rt client + Scapy on BESS Host")
104 # Use the first available ONOS instance CLI
105 onos_cli = main.Cluster.active(0).CLI
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200106 initial_flow_count = onos_cli.checkFlowCount()
Daniele Morobf53dec2021-09-13 18:11:56 +0200107 up4 = UP4()
108 # Get the P4RT client connected to UP4 in the first available ONOS instance
109 up4.setup(main.Cluster.active(0).p4rtUp4)
110
111 # Setup the emulated BESS host and required parameters
Daniele Moro522023c2021-10-15 17:30:33 +0200112 bess_host = getattr(main, main.params["BESS_UPF"]["bess_host"])
Daniele Morobf53dec2021-09-13 18:11:56 +0200113 bess_interface = bess_host.interfaces[0]
114 bess_s1u_address = bess_interface["ips"][0]
115 bess_host.startScapy(ifaceName=bess_interface["name"], enableGtp=True)
Daniele Moro522023c2021-10-15 17:30:33 +0200116 bess_ue_address = main.params["BESS_UPF"]["ue_address"]
117 enodeb_host = getattr(main, main.params["BESS_UPF"]["enodeb_host"])
118 enodeb_address = main.params["BESS_UPF"]["enb_address"]
119 enodeb_interface = enodeb_host.interfaces[0]["name"]
Daniele Morobf53dec2021-09-13 18:11:56 +0200120 pdn_host = up4.pdn_host
121 pdn_interface = up4.pdn_interface
122
Daniele Moro49a843c2022-01-05 14:36:32 +0100123 main.step("Program and Verify UPF entities for UEs via UP4")
Daniele Morobf53dec2021-09-13 18:11:56 +0200124 up4.attachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +0200125 up4.verifyUp4Flow(onos_cli)
126
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200127 run.checkFlows(
128 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200129 minFlowCount=initial_flow_count + (
130 len(up4.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200131 )
132
Daniele Morobf53dec2021-09-13 18:11:56 +0200133 # ------------------- UPSTREAM -------------------
134 # ------- eNB -> fabric -> BESS (encapped)
135 main.step("Test upstream eNB -> fabric -> BESS")
136 # Start filter before sending packets, BESS should receive GTP encapped
137 # packets
138 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 +0200139 GPDU_PORT, GPDU_PORT, enodeb_address, bess_s1u_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200140 main.log.info("Start listening on %s intf %s" % (
141 bess_host.name, bess_interface["name"]))
142 main.log.debug("BPF Filter BESS Upstream: \n %s" % pkt_filter_upstream)
143 bess_host.startFilter(ifaceName=bess_interface["name"],
144 sniffCount=1,
145 pktFilter=pkt_filter_upstream)
146 # Send GTP Packet
147 UP4.buildGtpPacket(enodeb_host,
Daniele Moro522023c2021-10-15 17:30:33 +0200148 src_ip_outer=enodeb_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200149 dst_ip_outer=bess_s1u_address,
Daniele Moro522023c2021-10-15 17:30:33 +0200150 src_ip_inner=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200151 dst_ip_inner=pdn_interface["ips"][0],
152 src_udp_inner=UE_PORT,
153 dst_udp_inner=PDN_PORT,
154 teid=BESS_TEID)
155 enodeb_host.sendPacket()
156
157 packets = UP4.checkFilterAndGetPackets(bess_host)
158 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
159 n_packets = packets.count("TEID=" + hex(BESS_TEID) + "L ")
160 tot_packets = packets.count('Ether')
161 utilities.assert_equal(expect=True,
162 actual=n_packets == 1 and tot_packets == 1,
163 onpass="BESS correctly received 1 GTP encapped packet",
164 onfail="ERROR: BESS received %d GTP encapped packets and filter captured %d packets" % (
165 n_packets, tot_packets))
166
167 # ------- BESS -> fabric -> PDN (not-encapped)
168 main.step("Test upstream BESS -> fabric -> PDN")
169 # Start filter before sending packets, PDN should receive non-GTP packet
170 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 +0200171 UE_PORT, PDN_PORT, bess_ue_address, pdn_interface["ips"][0])
Daniele Morobf53dec2021-09-13 18:11:56 +0200172 main.log.info("Start listening on %s intf %s" % (
173 pdn_host.name, pdn_interface["name"]))
174 main.log.debug("BPF Filter PDN Upstream: \n %s" % pkt_filter_upstream)
175 pdn_host.startFilter(ifaceName=pdn_interface["name"],
176 sniffCount=1,
177 pktFilter=pkt_filter_upstream)
178 # Send UDP Packet
179 UP4.buildUdpPacket(bess_host,
Daniele Moro522023c2021-10-15 17:30:33 +0200180 src_ip=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200181 dst_ip=pdn_interface["ips"][0],
182 src_udp=UE_PORT,
183 dst_udp=PDN_PORT)
184 bess_host.sendPacket()
185
186 packets = UP4.checkFilterAndGetPackets(pdn_host)
187 tot_packets = packets.count('Ether')
188 utilities.assert_equal(expect=True,
189 actual=tot_packets == 1,
190 onpass="PDN correctly received 1 packet",
191 onfail="ERROR: PDN received %d packets" % (
192 tot_packets))
193 # ------------------------------------------------
194
195 # ------------------ DOWNSTREAM ------------------
196 # ------- PDN -> fabric -> BESS (not-encapped)
197 main.step("Test downstream PDN -> fabric -> BESS")
198 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 +0200199 PDN_PORT, UE_PORT, pdn_interface["ips"][0], bess_ue_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200200 main.log.info("Start listening on %s intf %s" % (
201 bess_host.name, bess_interface["name"]))
202 main.log.debug(
203 "BPF Filter BESS Downstream: \n %s" % pkt_filter_downstream)
204 bess_host.startFilter(ifaceName=bess_interface["name"],
205 sniffCount=1,
206 pktFilter=pkt_filter_downstream)
207 UP4.buildUdpPacket(pdn_host,
208 dst_eth=up4.router_mac,
209 src_ip=pdn_interface["ips"][0],
Daniele Moro522023c2021-10-15 17:30:33 +0200210 dst_ip=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200211 src_udp=PDN_PORT,
212 dst_udp=UE_PORT)
213 pdn_host.sendPacket()
214
215 packets = UP4.checkFilterAndGetPackets(bess_host)
216
217 tot_packets = packets.count('Ether')
218 utilities.assert_equal(expect=True,
219 actual=tot_packets == 1,
220 onpass="BESS correctly received 1 packet",
221 onfail="ERROR: BESS received %d packets" % (
222 tot_packets))
223
224 # ------- BESS -> fabric -> eNB (encapped)
225 main.step("Test downstream BESS -> fabric -> eNB")
226 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 +0200227 GPDU_PORT, GPDU_PORT, bess_s1u_address, enodeb_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200228 main.log.info("Start listening on %s intf %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200229 enodeb_host.name, enodeb_interface))
Daniele Morobf53dec2021-09-13 18:11:56 +0200230 main.log.debug(
231 "BPF Filter BESS Downstream: \n %s" % pkt_filter_downstream)
Daniele Moro522023c2021-10-15 17:30:33 +0200232 enodeb_host.startFilter(ifaceName=enodeb_interface,
Daniele Morobf53dec2021-09-13 18:11:56 +0200233 sniffCount=1,
234 pktFilter=pkt_filter_downstream)
235 # Build GTP packet from BESS host
236 UP4.buildGtpPacket(bess_host,
237 src_ip_outer=bess_s1u_address,
Daniele Moro522023c2021-10-15 17:30:33 +0200238 dst_ip_outer=enodeb_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200239 src_ip_inner=pdn_interface["ips"][0],
Daniele Moro522023c2021-10-15 17:30:33 +0200240 dst_ip_inner=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200241 src_udp_inner=PDN_PORT,
242 dst_udp_inner=UE_PORT,
243 teid=BESS_TEID)
244 bess_host.sendPacket()
245
246 packets = UP4.checkFilterAndGetPackets(enodeb_host)
247
248 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
249 n_packets = packets.count("TEID=" + hex(BESS_TEID) + "L ")
250 tot_packets = packets.count('Ether')
251 utilities.assert_equal(expect=True,
252 actual=n_packets == 1 and tot_packets == 1,
253 onpass="eNodeB correctly received 1 GTP encapped packet",
254 onfail="ERROR: eNodeb received %d GTP encapped packets and filter captured %d packets" % (
255 n_packets, tot_packets))
256 # ------------------------------------------------
257
Daniele Moro49a843c2022-01-05 14:36:32 +0100258 main.step("Remove and Verify UPF entities for UEs via UP4")
Daniele Morobf53dec2021-09-13 18:11:56 +0200259 up4.detachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +0200260 up4.verifyNoUesFlow(onos_cli)
261
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200262 run.checkFlows(main, minFlowCount=initial_flow_count)
263
Daniele Morobf53dec2021-09-13 18:11:56 +0200264 main.step("Stop scapy and p4rt client")
265 up4.teardown()
266 bess_host.stopScapy()
Daniele Moroc99bf822021-10-11 23:21:15 +0200267
Daniele Morobf53dec2021-09-13 18:11:56 +0200268 run.cleanup(main)
Daniele Moro954e2282021-09-22 17:32:03 +0200269
270 def CASE3(self, main):
271 main.case("Verify UP4 from different ONOS instances")
272 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100273 Program UPF entitiesvia UP4 on first ONOS instance
Daniele Moro954e2282021-09-22 17:32:03 +0200274 Repeat for all ONOS Instances:
Daniele Moro49a843c2022-01-05 14:36:32 +0100275 Verify UPF entities via P4RT
Daniele Moro954e2282021-09-22 17:32:03 +0200276 Disconnect P4RT client
Daniele Moro49a843c2022-01-05 14:36:32 +0100277 Verify and delete UPF entities via UP4 on the third ONOS instance
Daniele Moro954e2282021-09-22 17:32:03 +0200278 Repeat for all ONOS Instance:
Daniele Moro49a843c2022-01-05 14:36:32 +0100279 Verify removed UPF entities via P4RT
Daniele Moro954e2282021-09-22 17:32:03 +0200280 Disconnect P4RT client
281 """
282 try:
Daniele Morofbfdfbd2021-10-18 22:47:51 +0200283 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
284 N_FLOWS_PER_UE
Daniele Moro954e2282021-09-22 17:32:03 +0200285 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
286 Testcaselib as run
287 except ImportError as e:
288 main.log.error("Import not found. Exiting the test")
289 main.log.error(e)
290 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +0200291 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro954e2282021-09-22 17:32:03 +0200292
293 run.initTest(main)
294 main.log.info(main.Cluster.numCtrls)
295 main.Cluster.setRunningNode(3)
296 run.installOnos(main, skipPackage=True, cliSleep=5)
297
298 onos_cli_0 = main.Cluster.active(0).CLI
299 onos_cli_1 = main.Cluster.active(1).CLI
300 onos_cli_2 = main.Cluster.active(2).CLI
301 up4_0 = UP4()
302 up4_1 = UP4()
303 up4_2 = UP4()
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200304 initial_flow_count = onos_cli_0.checkFlowCount()
Daniele Moro954e2282021-09-22 17:32:03 +0200305
Daniele Moro49a843c2022-01-05 14:36:32 +0100306 main.step("Program and Verify UPF entities via UP4 on ONOS 0")
Daniele Moro954e2282021-09-22 17:32:03 +0200307 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
308 up4_0.attachUes()
309 up4_0.verifyUp4Flow(onos_cli_0)
310 up4_0.teardown()
311
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200312 run.checkFlows(
313 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200314 minFlowCount=initial_flow_count + (
315 len(up4_0.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200316 )
317
Daniele Moro49a843c2022-01-05 14:36:32 +0100318 main.step("Verify UPF entities number via UP4 P4RT on ONOS 1")
Daniele Moro954e2282021-09-22 17:32:03 +0200319 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
320 utilities.assert_equal(
321 expect=True,
322 actual=up4_1.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100323 onpass="Correct number of UPF entities",
324 onfail="Wrong number of UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200325 )
326 up4_1.teardown()
327
Daniele Moro49a843c2022-01-05 14:36:32 +0100328 main.step("Verify UPF entities number via UP4 P4RT on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200329 up4_2.setup(main.Cluster.active(2).p4rtUp4, no_host=True)
330 utilities.assert_equal(
331 expect=True,
332 actual=up4_2.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100333 onpass="Correct number of UPF entities",
334 onfail="Wrong number of UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200335 )
336
337 main.step("Verify all ONOS instances have the same number of flows")
338 onos_0_flow_count = onos_cli_0.checkFlowCount()
339 onos_1_flow_count = onos_cli_1.checkFlowCount()
340 onos_2_flow_count = onos_cli_2.checkFlowCount()
341 utilities.assert_equal(
342 expect=True,
343 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
344 onpass="All ONOS instances have the same number of flows",
345 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
346 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
347 )
348
Daniele Moro49a843c2022-01-05 14:36:32 +0100349 main.step("Remove and Verify UPF entities via UP4 on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200350 up4_2.detachUes()
351 up4_2.verifyNoUesFlow(onos_cli_2)
352
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200353 run.checkFlows(main, minFlowCount=initial_flow_count)
354
Daniele Moro49a843c2022-01-05 14:36:32 +0100355 main.step("Verify no UPF entities via UP4 P4RT on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200356 utilities.assert_equal(
357 expect=True,
358 actual=up4_2.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100359 onpass="No UPF entities",
360 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200361 )
362 up4_2.teardown()
363
Daniele Moro49a843c2022-01-05 14:36:32 +0100364 main.step("Verify no UPF entities via UP4 P4RT on ONOS 1")
Daniele Moro954e2282021-09-22 17:32:03 +0200365 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
366 utilities.assert_equal(
367 expect=True,
368 actual=up4_1.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100369 onpass="No UPF entities",
370 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200371 )
372 up4_1.teardown()
373
Daniele Moro49a843c2022-01-05 14:36:32 +0100374 main.step("Verify no UPF entities via UP4 P4RT on ONOS 0")
Daniele Moro954e2282021-09-22 17:32:03 +0200375 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
376 utilities.assert_equal(
377 expect=True,
378 actual=up4_0.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100379 onpass="No UPF entities",
380 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200381 )
382 up4_0.teardown()
383
384 main.step("Verify all ONOS instances have the same number of flows")
385 onos_0_flow_count = onos_cli_0.checkFlowCount()
386 onos_1_flow_count = onos_cli_1.checkFlowCount()
387 onos_2_flow_count = onos_cli_2.checkFlowCount()
388 utilities.assert_equal(
389 expect=True,
390 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
391 onpass="All ONOS instances have the same number of flows",
392 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200393 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
Daniele Moro954e2282021-09-22 17:32:03 +0200394 )
Daniele Moroc99bf822021-10-11 23:21:15 +0200395
Daniele Moro954e2282021-09-22 17:32:03 +0200396 run.cleanup(main)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200397
398 def CASE4(self, main):
399 main.case("Verify UP4 wipe-out after ONOS reboot")
400 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100401 Program UPF entities
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200402 Kill ONOS POD
Daniele Moro49a843c2022-01-05 14:36:32 +0100403 Verify UPF entities from other ONOS instances
404 Remove UPF entities
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200405 Wait/Verify ONOS is back
Daniele Moro49a843c2022-01-05 14:36:32 +0100406 Verify no UPF entities from rebooted instance
407 Re-program UPF entities from rebooted instance
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200408 Verify all instances have same number of flows
Daniele Moro49a843c2022-01-05 14:36:32 +0100409 Remove UPF entities (cleanup)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200410 """
411 try:
Daniele Moroc6811a82021-10-12 11:29:41 +0200412 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
413 N_FLOWS_PER_UE
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200414 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
415 Testcaselib as run
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100416 from tests.USECASE.SegmentRouting.SRStaging.dependencies.SRStagingTest import \
417 SRStagingTest
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200418 except ImportError as e:
419 main.log.error("Import not found. Exiting the test")
420 main.log.error(e)
421 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +0200422 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200423
424 run.initTest(main)
425 main.log.info(main.Cluster.numCtrls)
426 main.Cluster.setRunningNode(3)
427 run.installOnos(main, skipPackage=True, cliSleep=5)
428
429 onos_cli_0 = main.Cluster.active(0).CLI
430 onos_cli_1 = main.Cluster.active(1).CLI
431 onos_cli_2 = main.Cluster.active(2).CLI
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100432 ctrl_0 = main.Cluster.active(0)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200433
434 up4_0 = UP4()
435 up4_1 = UP4()
436 up4_2 = UP4()
437
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200438 initial_flow_count = onos_cli_0.checkFlowCount()
439
Daniele Moro49a843c2022-01-05 14:36:32 +0100440 main.step("Program and Verify UPF entities via UP4 on ONOS 0")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200441 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
442 up4_0.attachUes()
443 up4_0.verifyUp4Flow(onos_cli_0)
444 up4_0.teardown()
445
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200446 run.checkFlows(
447 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200448 minFlowCount=initial_flow_count + (
449 len(up4_0.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200450 )
451
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200452 onosPod = main.params["UP4_delete_pod"]
Daniele Moroc99bf822021-10-11 23:21:15 +0200453
454 # Save ONOS diags of the POD we are killing otherwise we lose ONOS logs
455 main.ONOSbench.onosDiagnosticsK8s(
456 [onosPod],
457 main.logdir,
458 "-CASE%d-%s_BeforeKill" % (main.CurrentTestCaseNumber, onosPod)
459 )
460
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100461 onosK8sNode = SRStagingTest.onosDown(main, ctrl_0, preventRestart=True)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200462
Daniele Moro49a843c2022-01-05 14:36:32 +0100463 main.step("Verify UPF entities number via UP4 P4RT on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200464 up4_2.setup(main.Cluster.active(2).p4rtUp4, no_host=True)
465 utilities.assert_equal(
466 expect=True,
467 actual=up4_2.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100468 onpass="Correct number of UPF entities",
469 onfail="Wrong number of UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200470 )
471
Daniele Moro49a843c2022-01-05 14:36:32 +0100472 main.step("Remove and Verify UPF entities via UP4 on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200473 up4_2.detachUes()
474 up4_2.verifyNoUesFlow(onos_cli_2)
475
Daniele Moro49a843c2022-01-05 14:36:32 +0100476 main.step("Verify no UPF entities via UP4 P4RT on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200477 utilities.assert_equal(
478 expect=True,
479 actual=up4_2.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100480 onpass="No UPF entities",
481 onfail="Stale UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200482 )
483 up4_2.teardown()
484
Daniele Moroc6811a82021-10-12 11:29:41 +0200485 main.step(
486 "Verify all active ONOS instances have the same number of flows")
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200487 onos_1_flow_count = onos_cli_1.checkFlowCount()
488 onos_2_flow_count = onos_cli_2.checkFlowCount()
489 utilities.assert_equal(
490 expect=True,
491 actual=onos_1_flow_count == onos_2_flow_count,
492 onpass="All ONOS instances have the same number of flows",
493 onfail="ONOS instances have different number of flows: (%d, %d)" % (
494 onos_1_flow_count, onos_2_flow_count)
495 )
496
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100497 SRStagingTest.onosUp(main, onosK8sNode, ctrl_0)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200498
499 main.step("Verify ONOS cluster is in good shape")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200500 onosNodesStatus = utilities.retry(
501 f=main.Cluster.nodesCheck,
502 retValue=False,
503 sleep=5,
504 attempts=10
505 )
506 utilities.assert_equal(
507 expect=True,
508 actual=onosNodesStatus,
509 onpass="ONOS nodes status correct",
510 onfail="Wrong ONOS nodes status"
511 )
512
Daniele Moro49a843c2022-01-05 14:36:32 +0100513 main.step("Verify no UPF entities via UP4 P4RT on ONOS 0")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200514 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
515 utilities.assert_equal(
516 expect=True,
517 actual=up4_0.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100518 onpass="No UPF entities",
519 onfail="Stale UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200520 )
521
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200522 run.checkFlows(main, minFlowCount=initial_flow_count)
523
Daniele Moro49a843c2022-01-05 14:36:32 +0100524 main.step("Re-program UPF entities via UP4 on ONOS 0 after restart")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200525 up4_0.attachUes()
526 up4_0.verifyUp4Flow(onos_cli_0)
527 up4_0.teardown()
528
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200529 run.checkFlows(
530 main,
Daniele Moroc6811a82021-10-12 11:29:41 +0200531 minFlowCount=initial_flow_count + (
532 len(up4_0.emulated_ues) * N_FLOWS_PER_UE * n_switches)
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200533 )
534
Daniele Moro49a843c2022-01-05 14:36:32 +0100535 main.step("Verify UPF entities via UP4 on ONOS 1")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200536 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
537 up4_1.verifyUp4Flow(onos_cli_1)
538
539 main.step("Verify all ONOS instances have the same number of flows")
540 onos_0_flow_count = onos_cli_0.checkFlowCount()
541 onos_1_flow_count = onos_cli_1.checkFlowCount()
542 onos_2_flow_count = onos_cli_2.checkFlowCount()
543 utilities.assert_equal(
544 expect=True,
545 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
546 onpass="All ONOS instances have the same number of flows",
547 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
548 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
549 )
550
Daniele Moro49a843c2022-01-05 14:36:32 +0100551 main.step("Cleanup UPF entities via UP4 on ONOS 1")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200552 up4_1.detachUes()
Daniele Moro6dfbfef2021-09-28 22:44:19 +0200553 up4_1.verifyNoUesFlow(onos_cli_1)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200554 up4_1.teardown()
555
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200556 run.checkFlows(main, minFlowCount=initial_flow_count)
557
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200558 run.cleanup(main)
Daniele Moro522023c2021-10-15 17:30:33 +0200559
560 def CASE5(self, main):
561 main.case("UP4 Data Plane Failure Test")
562 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100563 Program UPF entities
Daniele Moro522023c2021-10-15 17:30:33 +0200564 Kill one switch
Daniele Moro80271cb2021-11-11 20:08:51 +0100565 Set label on switch K8S node to prevent K8S to redeploy stratum
Daniele Moro522023c2021-10-15 17:30:33 +0200566 Verify that traffic from eNodebs that are connected to that switch fails
567 Verify that traffic from other eNodeBs is being forwarded
568 Wait for the switch to be up again
569 Check flows
Daniele Moro49a843c2022-01-05 14:36:32 +0100570 Remove UPF entities (cleanup)
Daniele Moro522023c2021-10-15 17:30:33 +0200571 """
572 try:
573 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4, \
574 N_FLOWS_PER_UE
575 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
576 Testcaselib as run
577 from tests.USECASE.SegmentRouting.SRStaging.dependencies.SRStagingTest import \
578 SRStagingTest
579 import time
580 import itertools
581 except ImportError as e:
582 main.log.error("Import not found. Exiting the test")
583 main.log.error(e)
584 main.cleanAndExit()
585 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro80271cb2021-11-11 20:08:51 +0100586 switch_to_kill = main.params["UP4"]["UP4_dataplane_fail"]["switch_to_kill"]
587 k8s_switch_node = main.params["UP4"]["UP4_dataplane_fail"]["k8s_switch_node"]
588 k8s_label = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label"]
589 k8s_label_value_test = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label_value_test"]
590 k8s_label_value_normal = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label_value_normal"]
Daniele Moro522023c2021-10-15 17:30:33 +0200591
592 run.initTest(main)
593 main.log.info(main.Cluster.numCtrls)
594 main.Cluster.setRunningNode(3)
595 run.installOnos(main, skipPackage=True, cliSleep=5)
596
597 onos_cli = main.Cluster.active(0).CLI
Daniele Moro80271cb2021-11-11 20:08:51 +0100598 kubectl = main.Cluster.active(0).Bench
599 kubeconfig = main.Cluster.active(0).k8s.kubeConfig
600 namespace = main.params['kubernetes']['namespace']
Daniele Moro522023c2021-10-15 17:30:33 +0200601
602 up4 = UP4()
603
604 initial_flow_count = onos_cli.checkFlowCount()
605
Daniele Moro49a843c2022-01-05 14:36:32 +0100606 main.step("Program and Verify UPF entities via UP4")
Daniele Moro522023c2021-10-15 17:30:33 +0200607 up4.setup(main.Cluster.active(0).p4rtUp4)
608 up4.attachUes()
609 up4.verifyUp4Flow(onos_cli)
610
611 run.checkFlows(
612 main,
613 minFlowCount=initial_flow_count+(len(up4.emulated_ues)*4*n_switches)
614 )
615
Daniele Moro80271cb2021-11-11 20:08:51 +0100616 main.step("Set label to switch k8s node and kill switch")
617 # K8s node name correspond to the switch name in lowercase
Daniele Moro522023c2021-10-15 17:30:33 +0200618 utilities.assert_equal(
Daniele Moro80271cb2021-11-11 20:08:51 +0100619 expect=main.TRUE,
620 actual=kubectl.kubectlSetLabel(
621 nodeName=k8s_switch_node,
622 label=k8s_label,
623 value=k8s_label_value_test,
624 kubeconfig=kubeconfig,
625 namespace=namespace,
626 ),
627 onpass="Label has been set correctly on node %s" % k8s_switch_node,
628 onfail="Label has not been set on node %s" % k8s_switch_node
Daniele Moro522023c2021-10-15 17:30:33 +0200629 )
Daniele Moro80271cb2021-11-11 20:08:51 +0100630 try:
631 def checkNumberStratumPods(n_value):
632 pods = kubectl.kubectlGetPodNames(
633 kubeconfig=kubeconfig,
634 namespace=namespace,
635 name="stratum"
636 )
637 main.log.info("PODS: " + str(pods))
638 return n_value == len(pods) if pods is not main.FALSE else False
639 # Execute the following in try/except/finally to be sure to restore the
640 # k8s label even in case of unhandled exception.
Daniele Moro522023c2021-10-15 17:30:33 +0200641
Daniele Moro80271cb2021-11-11 20:08:51 +0100642 # Wait for stratum pod to be removed from the switch
643 removed = utilities.retry(checkNumberStratumPods,
644 False,
645 args=[n_switches-1],
646 attempts=50
647 )
648 main.log.info("Stratum has been removed from the switch? %s" % removed)
Daniele Moro522023c2021-10-15 17:30:33 +0200649
Daniele Moro80271cb2021-11-11 20:08:51 +0100650 switch_component = getattr(main, switch_to_kill)
651 switch_component.handle.sendline("sudo reboot")
Daniele Moro522023c2021-10-15 17:30:33 +0200652
Daniele Moro80271cb2021-11-11 20:08:51 +0100653 sleepTime = 20
654 main.log.info("Sleeping %s seconds for Fabric to react" % sleepTime)
655 time.sleep(sleepTime)
Daniele Moro522023c2021-10-15 17:30:33 +0200656
Daniele Moro80271cb2021-11-11 20:08:51 +0100657 available = utilities.retry(SRStagingTest.switchIsConnected,
658 True,
659 args=[switch_component],
660 attempts=300,
661 getRetryingTime=True)
662 main.log.info("Switch %s is available in ONOS? %s" % (
663 switch_to_kill, available))
664 utilities.assert_equal(
665 expect=True,
666 actual=not available and removed,
667 onpass="Switch was rebooted (ONL reboot) successfully and stratum" +
668 " removed from switch k8s node",
669 onfail="Switch was not rebooted (ONL reboot) successfully or stratum " +
670 "not removed from switch k8s node"
671 )
672
673 enodebs_fail = main.params["UP4"]["UP4_dataplane_fail"]["enodebs_fail"].split(",")
674 enodebs_no_fail = list(set(up4.enodebs.keys()) - set(enodebs_fail))
675
676 # ------- Test Upstream traffic (enbs->pdn)
677 main.step("Test upstream traffic FAIL")
678 up4.testUpstreamTraffic(enb_names=enodebs_fail, shouldFail=True)
679 main.step("Test upstream traffic NO FAIL")
680 up4.testUpstreamTraffic(enb_names=enodebs_no_fail, shouldFail=False)
681
682 # ------- Test Downstream traffic (pdn->enbs)
683 main.step("Test downstream traffic FAIL")
684 up4.testDownstreamTraffic(enb_names=enodebs_fail, shouldFail=True)
685 main.step("Test downstream traffic NO FAIL")
686 up4.testDownstreamTraffic(enb_names=enodebs_no_fail, shouldFail=False)
687 except Exception as e:
688 main.log.error("Unhandled exception!")
689 main.log.error(e)
690 finally:
691 utilities.assert_equal(
692 expect=main.TRUE,
693 actual=kubectl.kubectlSetLabel(
694 nodeName=k8s_switch_node,
695 label=k8s_label,
696 value=k8s_label_value_normal,
697 kubeconfig=kubeconfig,
698 namespace=namespace,
699 ),
700 onpass="Label has been set correctly on node %s" % k8s_switch_node,
701 onfail="Label has not been set on node %s" % k8s_switch_node
702 )
703 # Reconnect to the switch
704 connect = utilities.retry(switch_component.connect,
705 main.FALSE,
706 attempts=30,
707 getRetryingTime=True)
708 main.log.info("Connected to the switch %s? %s" % (
709 switch_to_kill, connect))
710
711 # Wait for stratum pod to be re-deployed on the switch
712 deployed = utilities.retry(checkNumberStratumPods,
713 False,
714 args=[n_switches],
715 attempts=50
716 )
717 main.log.info("Stratum has been redeployed on the switch? %s" % deployed)
718
719 # Wait switch to be back in ONOS
720 available = utilities.retry(SRStagingTest.switchIsConnected,
721 False,
722 args=[switch_component],
723 attempts=300,
724 getRetryingTime=True)
725 main.log.info("Switch %s is available in ONOS? %s" % (
726 switch_to_kill, available))
727 utilities.assert_equal(
728 expect=True,
729 actual=available and connect == main.TRUE and deployed,
730 onpass="Switch is back available in ONOS and stratum has been redeployed",
731 onfail="Switch is not available in ONOS, may influence subsequent tests!"
732 )
Daniele Moro522023c2021-10-15 17:30:33 +0200733
734 main.step("Test upstream traffic AFTER switch reboot")
735 up4.testUpstreamTraffic()
736
Daniele Moro49a843c2022-01-05 14:36:32 +0100737 main.step("Cleanup UPF entities via UP4")
Daniele Moro522023c2021-10-15 17:30:33 +0200738 up4.detachUes()
739 up4.verifyNoUesFlow(onos_cli)
740 up4.teardown()
741
742 run.checkFlows(main, minFlowCount=initial_flow_count)
743
744 # Teardown
745 run.cleanup(main)
Daniele Moro80271cb2021-11-11 20:08:51 +0100746