blob: 88035d7f77c30f1ef4ee62224033fe133e4c2280 [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 Moro54581242022-02-25 19:56:02 +010019 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4
Daniele Moro790cc102021-08-30 18:27:30 +020020 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
21 Testcaselib as run
Daniele Moro790cc102021-08-30 18:27:30 +020022 except ImportError as e:
23 main.log.error("Import not found. Exiting the test")
24 main.log.error(e)
25 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +020026 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro790cc102021-08-30 18:27:30 +020027
Daniele Moro790cc102021-08-30 18:27:30 +020028 run.initTest(main)
29 main.log.info(main.Cluster.numCtrls)
30 main.Cluster.setRunningNode(3)
31 run.installOnos(main, skipPackage=True, cliSleep=5)
32
Daniele Moro790cc102021-08-30 18:27:30 +020033 main.step("Start scapy and p4rt client")
Daniele Morobf53dec2021-09-13 18:11:56 +020034 # Use the first available ONOS instance CLI
Jon Halla4a79312022-01-25 17:16:53 -080035 node = main.Cluster.active(0)
36 onos_cli = node.CLI
37 kubeconfig = node.k8s.kubeConfig
38 namespace = main.params['kubernetes']['namespace']
Daniele Moro80889562021-09-08 10:09:26 +020039 up4 = UP4()
Jon Halla4a79312022-01-25 17:16:53 -080040 nodeIP = node.Bench.kubectlCmd("get node %s --output=jsonpath='{.metadata.annotations.rke\.cattle\.io/external-ip}{\"\\n\"}'" % node.Bench.kubectlGetPodNode("pfcp-agent-0", kubeconfig, namespace))
41 # Connect P4RT and the mock smf if configured
42 up4.setup(node.p4rtUp4, mock_smf=node.mock_smf,
43 pfcpAddress=nodeIP,
44 pfcpPort=node.Bench.kubectlGetNodePort("pfcp-agent", kubeconfig, namespace))
Daniele Moro790cc102021-08-30 18:27:30 +020045
Daniele Moro49a843c2022-01-05 14:36:32 +010046 main.step("Program and Verify UPF entities via UP4")
Daniele Moro80889562021-09-08 10:09:26 +020047 up4.attachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +020048 up4.verifyUp4Flow(onos_cli)
49
Daniele Moro80889562021-09-08 10:09:26 +020050 # ------- Test Upstream traffic (enb->pdn)
Daniele Morobef0c7e2022-02-16 17:47:13 -080051 for app_filter_name in up4.app_filters:
52 main.step("Test upstream traffic %s" % app_filter_name)
53 up4.testUpstreamTraffic(app_filter_name=app_filter_name)
Daniele Moro790cc102021-08-30 18:27:30 +020054
Daniele Moro80889562021-09-08 10:09:26 +020055 # ------- Test Downstream traffic (pdn->enb)
Daniele Morobef0c7e2022-02-16 17:47:13 -080056 for app_filter_name in up4.app_filters:
57 main.step("Test downstream traffic %s" % app_filter_name)
58 up4.testDownstreamTraffic(app_filter_name=app_filter_name)
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 Moro790cc102021-08-30 18:27:30 +020064 main.step("Stop scapy and p4rt client")
Daniele Moro80889562021-09-08 10:09:26 +020065 up4.teardown()
Daniele Moroc99bf822021-10-11 23:21:15 +020066
Daniele Moro790cc102021-08-30 18:27:30 +020067 run.cleanup(main)
Daniele Morobf53dec2021-09-13 18:11:56 +020068
Daniele Moro9ba5cf02021-10-08 18:00:56 +020069 def CASE2(self, main):
Daniele Morobf53dec2021-09-13 18:11:56 +020070 main.case("BESS traffic routed")
71 """
Daniele Moro49a843c2022-01-05 14:36:32 +010072 Program UPF entities for UEs managed via UP4
73 Verify UPF entities
Daniele Morobf53dec2021-09-13 18:11:56 +020074 Verify Upstream Traffic: eNB -> Fabric -> BESS (encapped)
75 Verify Upstream Traffic: BESS -> Fabric -> PDN (not encapped)
76 Verify Downstream Traffic: PDN -> Fabric -> BESS (not encapped)
77 Verify Downstream Traffic: BESS -> Fabric -> eNB (encapped)
Daniele Moro49a843c2022-01-05 14:36:32 +010078 Remove UPF entities for UEs managed via UP4
79 Verify removed UPF entities
Daniele Morobf53dec2021-09-13 18:11:56 +020080 """
81 BESS_TEID = 300
Daniele Morobf53dec2021-09-13 18:11:56 +020082 GPDU_PORT = 2152
83 UE_PORT = 400
84 PDN_PORT = 800
85 try:
Daniele Moro54581242022-02-25 19:56:02 +010086 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4
Daniele Morobf53dec2021-09-13 18:11:56 +020087 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
88 Testcaselib as run
89 except ImportError as e:
90 main.log.error("Import not found. Exiting the test")
91 main.log.error(e)
92 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +020093 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Morobf53dec2021-09-13 18:11:56 +020094
95 run.initTest(main)
96 main.log.info(main.Cluster.numCtrls)
97 main.Cluster.setRunningNode(3)
98 run.installOnos(main, skipPackage=True, cliSleep=5)
99
100 main.step("Start scapy and p4rt client + Scapy on BESS Host")
101 # Use the first available ONOS instance CLI
102 onos_cli = main.Cluster.active(0).CLI
103 up4 = UP4()
104 # Get the P4RT client connected to UP4 in the first available ONOS instance
105 up4.setup(main.Cluster.active(0).p4rtUp4)
106
107 # Setup the emulated BESS host and required parameters
Daniele Moro522023c2021-10-15 17:30:33 +0200108 bess_host = getattr(main, main.params["BESS_UPF"]["bess_host"])
Daniele Morobf53dec2021-09-13 18:11:56 +0200109 bess_interface = bess_host.interfaces[0]
110 bess_s1u_address = bess_interface["ips"][0]
111 bess_host.startScapy(ifaceName=bess_interface["name"], enableGtp=True)
Daniele Moro522023c2021-10-15 17:30:33 +0200112 bess_ue_address = main.params["BESS_UPF"]["ue_address"]
113 enodeb_host = getattr(main, main.params["BESS_UPF"]["enodeb_host"])
114 enodeb_address = main.params["BESS_UPF"]["enb_address"]
115 enodeb_interface = enodeb_host.interfaces[0]["name"]
Daniele Morobf53dec2021-09-13 18:11:56 +0200116 pdn_host = up4.pdn_host
117 pdn_interface = up4.pdn_interface
118
Daniele Moro49a843c2022-01-05 14:36:32 +0100119 main.step("Program and Verify UPF entities for UEs via UP4")
Daniele Morobf53dec2021-09-13 18:11:56 +0200120 up4.attachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +0200121 up4.verifyUp4Flow(onos_cli)
122
123 # ------------------- UPSTREAM -------------------
124 # ------- eNB -> fabric -> BESS (encapped)
125 main.step("Test upstream eNB -> fabric -> BESS")
126 # Start filter before sending packets, BESS should receive GTP encapped
127 # packets
128 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 +0200129 GPDU_PORT, GPDU_PORT, enodeb_address, bess_s1u_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200130 main.log.info("Start listening on %s intf %s" % (
131 bess_host.name, bess_interface["name"]))
132 main.log.debug("BPF Filter BESS Upstream: \n %s" % pkt_filter_upstream)
133 bess_host.startFilter(ifaceName=bess_interface["name"],
134 sniffCount=1,
135 pktFilter=pkt_filter_upstream)
136 # Send GTP Packet
137 UP4.buildGtpPacket(enodeb_host,
Daniele Moro522023c2021-10-15 17:30:33 +0200138 src_ip_outer=enodeb_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200139 dst_ip_outer=bess_s1u_address,
Daniele Moro522023c2021-10-15 17:30:33 +0200140 src_ip_inner=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200141 dst_ip_inner=pdn_interface["ips"][0],
142 src_udp_inner=UE_PORT,
143 dst_udp_inner=PDN_PORT,
144 teid=BESS_TEID)
145 enodeb_host.sendPacket()
146
147 packets = UP4.checkFilterAndGetPackets(bess_host)
148 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
149 n_packets = packets.count("TEID=" + hex(BESS_TEID) + "L ")
150 tot_packets = packets.count('Ether')
151 utilities.assert_equal(expect=True,
152 actual=n_packets == 1 and tot_packets == 1,
153 onpass="BESS correctly received 1 GTP encapped packet",
154 onfail="ERROR: BESS received %d GTP encapped packets and filter captured %d packets" % (
155 n_packets, tot_packets))
156
157 # ------- BESS -> fabric -> PDN (not-encapped)
158 main.step("Test upstream BESS -> fabric -> PDN")
159 # Start filter before sending packets, PDN should receive non-GTP packet
160 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 +0200161 UE_PORT, PDN_PORT, bess_ue_address, pdn_interface["ips"][0])
Daniele Morobf53dec2021-09-13 18:11:56 +0200162 main.log.info("Start listening on %s intf %s" % (
163 pdn_host.name, pdn_interface["name"]))
164 main.log.debug("BPF Filter PDN Upstream: \n %s" % pkt_filter_upstream)
165 pdn_host.startFilter(ifaceName=pdn_interface["name"],
166 sniffCount=1,
167 pktFilter=pkt_filter_upstream)
168 # Send UDP Packet
169 UP4.buildUdpPacket(bess_host,
Daniele Moro522023c2021-10-15 17:30:33 +0200170 src_ip=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200171 dst_ip=pdn_interface["ips"][0],
172 src_udp=UE_PORT,
173 dst_udp=PDN_PORT)
174 bess_host.sendPacket()
175
176 packets = UP4.checkFilterAndGetPackets(pdn_host)
177 tot_packets = packets.count('Ether')
178 utilities.assert_equal(expect=True,
179 actual=tot_packets == 1,
180 onpass="PDN correctly received 1 packet",
181 onfail="ERROR: PDN received %d packets" % (
182 tot_packets))
183 # ------------------------------------------------
184
185 # ------------------ DOWNSTREAM ------------------
186 # ------- PDN -> fabric -> BESS (not-encapped)
187 main.step("Test downstream PDN -> fabric -> BESS")
188 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 +0200189 PDN_PORT, UE_PORT, pdn_interface["ips"][0], bess_ue_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200190 main.log.info("Start listening on %s intf %s" % (
191 bess_host.name, bess_interface["name"]))
192 main.log.debug(
193 "BPF Filter BESS Downstream: \n %s" % pkt_filter_downstream)
194 bess_host.startFilter(ifaceName=bess_interface["name"],
195 sniffCount=1,
196 pktFilter=pkt_filter_downstream)
197 UP4.buildUdpPacket(pdn_host,
198 dst_eth=up4.router_mac,
199 src_ip=pdn_interface["ips"][0],
Daniele Moro522023c2021-10-15 17:30:33 +0200200 dst_ip=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200201 src_udp=PDN_PORT,
202 dst_udp=UE_PORT)
203 pdn_host.sendPacket()
204
205 packets = UP4.checkFilterAndGetPackets(bess_host)
206
207 tot_packets = packets.count('Ether')
208 utilities.assert_equal(expect=True,
209 actual=tot_packets == 1,
210 onpass="BESS correctly received 1 packet",
211 onfail="ERROR: BESS received %d packets" % (
212 tot_packets))
213
214 # ------- BESS -> fabric -> eNB (encapped)
215 main.step("Test downstream BESS -> fabric -> eNB")
216 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 +0200217 GPDU_PORT, GPDU_PORT, bess_s1u_address, enodeb_address)
Daniele Morobf53dec2021-09-13 18:11:56 +0200218 main.log.info("Start listening on %s intf %s" % (
Daniele Moro522023c2021-10-15 17:30:33 +0200219 enodeb_host.name, enodeb_interface))
Daniele Morobf53dec2021-09-13 18:11:56 +0200220 main.log.debug(
221 "BPF Filter BESS Downstream: \n %s" % pkt_filter_downstream)
Daniele Moro522023c2021-10-15 17:30:33 +0200222 enodeb_host.startFilter(ifaceName=enodeb_interface,
Daniele Morobf53dec2021-09-13 18:11:56 +0200223 sniffCount=1,
224 pktFilter=pkt_filter_downstream)
225 # Build GTP packet from BESS host
226 UP4.buildGtpPacket(bess_host,
227 src_ip_outer=bess_s1u_address,
Daniele Moro522023c2021-10-15 17:30:33 +0200228 dst_ip_outer=enodeb_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200229 src_ip_inner=pdn_interface["ips"][0],
Daniele Moro522023c2021-10-15 17:30:33 +0200230 dst_ip_inner=bess_ue_address,
Daniele Morobf53dec2021-09-13 18:11:56 +0200231 src_udp_inner=PDN_PORT,
232 dst_udp_inner=UE_PORT,
233 teid=BESS_TEID)
234 bess_host.sendPacket()
235
236 packets = UP4.checkFilterAndGetPackets(enodeb_host)
237
238 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
239 n_packets = packets.count("TEID=" + hex(BESS_TEID) + "L ")
240 tot_packets = packets.count('Ether')
241 utilities.assert_equal(expect=True,
242 actual=n_packets == 1 and tot_packets == 1,
243 onpass="eNodeB correctly received 1 GTP encapped packet",
244 onfail="ERROR: eNodeb received %d GTP encapped packets and filter captured %d packets" % (
245 n_packets, tot_packets))
246 # ------------------------------------------------
247
Daniele Moro49a843c2022-01-05 14:36:32 +0100248 main.step("Remove and Verify UPF entities for UEs via UP4")
Daniele Morobf53dec2021-09-13 18:11:56 +0200249 up4.detachUes()
Daniele Morobf53dec2021-09-13 18:11:56 +0200250 up4.verifyNoUesFlow(onos_cli)
251
252 main.step("Stop scapy and p4rt client")
253 up4.teardown()
254 bess_host.stopScapy()
Daniele Moroc99bf822021-10-11 23:21:15 +0200255
Daniele Morobf53dec2021-09-13 18:11:56 +0200256 run.cleanup(main)
Daniele Moro954e2282021-09-22 17:32:03 +0200257
258 def CASE3(self, main):
259 main.case("Verify UP4 from different ONOS instances")
260 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100261 Program UPF entitiesvia UP4 on first ONOS instance
Daniele Moro954e2282021-09-22 17:32:03 +0200262 Repeat for all ONOS Instances:
Daniele Moro49a843c2022-01-05 14:36:32 +0100263 Verify UPF entities via P4RT
Daniele Moro954e2282021-09-22 17:32:03 +0200264 Disconnect P4RT client
Daniele Moro49a843c2022-01-05 14:36:32 +0100265 Verify and delete UPF entities via UP4 on the third ONOS instance
Daniele Moro954e2282021-09-22 17:32:03 +0200266 Repeat for all ONOS Instance:
Daniele Moro49a843c2022-01-05 14:36:32 +0100267 Verify removed UPF entities via P4RT
Daniele Moro954e2282021-09-22 17:32:03 +0200268 Disconnect P4RT client
269 """
270 try:
Daniele Moro54581242022-02-25 19:56:02 +0100271 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4
Daniele Moro954e2282021-09-22 17:32:03 +0200272 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
273 Testcaselib as run
274 except ImportError as e:
275 main.log.error("Import not found. Exiting the test")
276 main.log.error(e)
277 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +0200278 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro954e2282021-09-22 17:32:03 +0200279
280 run.initTest(main)
281 main.log.info(main.Cluster.numCtrls)
282 main.Cluster.setRunningNode(3)
283 run.installOnos(main, skipPackage=True, cliSleep=5)
284
285 onos_cli_0 = main.Cluster.active(0).CLI
286 onos_cli_1 = main.Cluster.active(1).CLI
287 onos_cli_2 = main.Cluster.active(2).CLI
288 up4_0 = UP4()
289 up4_1 = UP4()
290 up4_2 = UP4()
291
Daniele Moro49a843c2022-01-05 14:36:32 +0100292 main.step("Program and Verify UPF entities via UP4 on ONOS 0")
Daniele Moro954e2282021-09-22 17:32:03 +0200293 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
294 up4_0.attachUes()
295 up4_0.verifyUp4Flow(onos_cli_0)
296 up4_0.teardown()
297
Daniele Moro49a843c2022-01-05 14:36:32 +0100298 main.step("Verify UPF entities number via UP4 P4RT on ONOS 1")
Daniele Moro954e2282021-09-22 17:32:03 +0200299 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
300 utilities.assert_equal(
301 expect=True,
302 actual=up4_1.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100303 onpass="Correct number of UPF entities",
304 onfail="Wrong number of UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200305 )
306 up4_1.teardown()
307
Daniele Moro49a843c2022-01-05 14:36:32 +0100308 main.step("Verify UPF entities number via UP4 P4RT on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200309 up4_2.setup(main.Cluster.active(2).p4rtUp4, no_host=True)
310 utilities.assert_equal(
311 expect=True,
312 actual=up4_2.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100313 onpass="Correct number of UPF entities",
314 onfail="Wrong number of UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200315 )
316
317 main.step("Verify all ONOS instances have the same number of flows")
318 onos_0_flow_count = onos_cli_0.checkFlowCount()
319 onos_1_flow_count = onos_cli_1.checkFlowCount()
320 onos_2_flow_count = onos_cli_2.checkFlowCount()
321 utilities.assert_equal(
322 expect=True,
323 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
324 onpass="All ONOS instances have the same number of flows",
325 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
326 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
327 )
328
Daniele Moro49a843c2022-01-05 14:36:32 +0100329 main.step("Remove and Verify UPF entities via UP4 on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200330 up4_2.detachUes()
331 up4_2.verifyNoUesFlow(onos_cli_2)
332
Daniele Moro49a843c2022-01-05 14:36:32 +0100333 main.step("Verify no UPF entities via UP4 P4RT on ONOS 2")
Daniele Moro954e2282021-09-22 17:32:03 +0200334 utilities.assert_equal(
335 expect=True,
336 actual=up4_2.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100337 onpass="No UPF entities",
338 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200339 )
340 up4_2.teardown()
341
Daniele Moro49a843c2022-01-05 14:36:32 +0100342 main.step("Verify no UPF entities via UP4 P4RT on ONOS 1")
Daniele Moro954e2282021-09-22 17:32:03 +0200343 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
344 utilities.assert_equal(
345 expect=True,
346 actual=up4_1.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100347 onpass="No UPF entities",
348 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200349 )
350 up4_1.teardown()
351
Daniele Moro49a843c2022-01-05 14:36:32 +0100352 main.step("Verify no UPF entities via UP4 P4RT on ONOS 0")
Daniele Moro954e2282021-09-22 17:32:03 +0200353 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
354 utilities.assert_equal(
355 expect=True,
356 actual=up4_0.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100357 onpass="No UPF entities",
358 onfail="Stale UPF entities"
Daniele Moro954e2282021-09-22 17:32:03 +0200359 )
360 up4_0.teardown()
361
362 main.step("Verify all ONOS instances have the same number of flows")
363 onos_0_flow_count = onos_cli_0.checkFlowCount()
364 onos_1_flow_count = onos_cli_1.checkFlowCount()
365 onos_2_flow_count = onos_cli_2.checkFlowCount()
366 utilities.assert_equal(
367 expect=True,
368 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
369 onpass="All ONOS instances have the same number of flows",
370 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200371 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
Daniele Moro954e2282021-09-22 17:32:03 +0200372 )
Daniele Moroc99bf822021-10-11 23:21:15 +0200373
Daniele Moro954e2282021-09-22 17:32:03 +0200374 run.cleanup(main)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200375
376 def CASE4(self, main):
377 main.case("Verify UP4 wipe-out after ONOS reboot")
378 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100379 Program UPF entities
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200380 Kill ONOS POD
Daniele Moro49a843c2022-01-05 14:36:32 +0100381 Verify UPF entities from other ONOS instances
382 Remove UPF entities
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200383 Wait/Verify ONOS is back
Daniele Moro49a843c2022-01-05 14:36:32 +0100384 Verify no UPF entities from rebooted instance
385 Re-program UPF entities from rebooted instance
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200386 Verify all instances have same number of flows
Daniele Moro49a843c2022-01-05 14:36:32 +0100387 Remove UPF entities (cleanup)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200388 """
389 try:
Daniele Moro54581242022-02-25 19:56:02 +0100390 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200391 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
392 Testcaselib as run
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100393 from tests.USECASE.SegmentRouting.SRStaging.dependencies.SRStagingTest import \
394 SRStagingTest
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200395 except ImportError as e:
396 main.log.error("Import not found. Exiting the test")
397 main.log.error(e)
398 main.cleanAndExit()
Daniele Moroc6811a82021-10-12 11:29:41 +0200399 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200400
401 run.initTest(main)
402 main.log.info(main.Cluster.numCtrls)
403 main.Cluster.setRunningNode(3)
404 run.installOnos(main, skipPackage=True, cliSleep=5)
405
406 onos_cli_0 = main.Cluster.active(0).CLI
407 onos_cli_1 = main.Cluster.active(1).CLI
408 onos_cli_2 = main.Cluster.active(2).CLI
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100409 ctrl_0 = main.Cluster.active(0)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200410
411 up4_0 = UP4()
412 up4_1 = UP4()
413 up4_2 = UP4()
414
Daniele Moro49a843c2022-01-05 14:36:32 +0100415 main.step("Program and Verify UPF entities via UP4 on ONOS 0")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200416 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
417 up4_0.attachUes()
418 up4_0.verifyUp4Flow(onos_cli_0)
419 up4_0.teardown()
420
421 onosPod = main.params["UP4_delete_pod"]
Daniele Moroc99bf822021-10-11 23:21:15 +0200422
423 # Save ONOS diags of the POD we are killing otherwise we lose ONOS logs
424 main.ONOSbench.onosDiagnosticsK8s(
425 [onosPod],
426 main.logdir,
427 "-CASE%d-%s_BeforeKill" % (main.CurrentTestCaseNumber, onosPod)
428 )
429
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100430 onosK8sNode = SRStagingTest.onosDown(main, ctrl_0, preventRestart=True)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200431
Daniele Moro49a843c2022-01-05 14:36:32 +0100432 main.step("Verify UPF entities number via UP4 P4RT on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200433 up4_2.setup(main.Cluster.active(2).p4rtUp4, no_host=True)
434 utilities.assert_equal(
435 expect=True,
436 actual=up4_2.verifyUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100437 onpass="Correct number of UPF entities",
438 onfail="Wrong number of UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200439 )
440
Daniele Moro49a843c2022-01-05 14:36:32 +0100441 main.step("Remove and Verify UPF entities via UP4 on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200442 up4_2.detachUes()
443 up4_2.verifyNoUesFlow(onos_cli_2)
444
Daniele Moro49a843c2022-01-05 14:36:32 +0100445 main.step("Verify no UPF entities via UP4 P4RT on ONOS 2")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200446 utilities.assert_equal(
447 expect=True,
448 actual=up4_2.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100449 onpass="No UPF entities",
450 onfail="Stale UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200451 )
452 up4_2.teardown()
453
Daniele Moroc6811a82021-10-12 11:29:41 +0200454 main.step(
455 "Verify all active ONOS instances have the same number of flows")
Daniele Moro9ba5cf02021-10-08 18:00:56 +0200456 onos_1_flow_count = onos_cli_1.checkFlowCount()
457 onos_2_flow_count = onos_cli_2.checkFlowCount()
458 utilities.assert_equal(
459 expect=True,
460 actual=onos_1_flow_count == onos_2_flow_count,
461 onpass="All ONOS instances have the same number of flows",
462 onfail="ONOS instances have different number of flows: (%d, %d)" % (
463 onos_1_flow_count, onos_2_flow_count)
464 )
465
Daniele Moro5d88e2a2021-11-12 17:47:55 +0100466 SRStagingTest.onosUp(main, onosK8sNode, ctrl_0)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200467
468 main.step("Verify ONOS cluster is in good shape")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200469 onosNodesStatus = utilities.retry(
470 f=main.Cluster.nodesCheck,
471 retValue=False,
472 sleep=5,
473 attempts=10
474 )
475 utilities.assert_equal(
476 expect=True,
477 actual=onosNodesStatus,
478 onpass="ONOS nodes status correct",
479 onfail="Wrong ONOS nodes status"
480 )
481
Daniele Moro49a843c2022-01-05 14:36:32 +0100482 main.step("Verify no UPF entities via UP4 P4RT on ONOS 0")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200483 up4_0.setup(main.Cluster.active(0).p4rtUp4, no_host=True)
484 utilities.assert_equal(
485 expect=True,
486 actual=up4_0.verifyNoUesFlowNumberP4rt(),
Daniele Moro49a843c2022-01-05 14:36:32 +0100487 onpass="No UPF entities",
488 onfail="Stale UPF entities"
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200489 )
490
Daniele Moro49a843c2022-01-05 14:36:32 +0100491 main.step("Re-program UPF entities via UP4 on ONOS 0 after restart")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200492 up4_0.attachUes()
493 up4_0.verifyUp4Flow(onos_cli_0)
494 up4_0.teardown()
495
Daniele Moro49a843c2022-01-05 14:36:32 +0100496 main.step("Verify UPF entities via UP4 on ONOS 1")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200497 up4_1.setup(main.Cluster.active(1).p4rtUp4, no_host=True)
498 up4_1.verifyUp4Flow(onos_cli_1)
499
500 main.step("Verify all ONOS instances have the same number of flows")
501 onos_0_flow_count = onos_cli_0.checkFlowCount()
502 onos_1_flow_count = onos_cli_1.checkFlowCount()
503 onos_2_flow_count = onos_cli_2.checkFlowCount()
504 utilities.assert_equal(
505 expect=True,
506 actual=onos_0_flow_count == onos_1_flow_count == onos_2_flow_count,
507 onpass="All ONOS instances have the same number of flows",
508 onfail="ONOS instances have different number of flows: (%d, %d, %d)" % (
509 onos_0_flow_count, onos_1_flow_count, onos_2_flow_count)
510 )
511
Daniele Moro49a843c2022-01-05 14:36:32 +0100512 main.step("Cleanup UPF entities via UP4 on ONOS 1")
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200513 up4_1.detachUes()
Daniele Moro6dfbfef2021-09-28 22:44:19 +0200514 up4_1.verifyNoUesFlow(onos_cli_1)
Daniele Moroe1d05eb2021-09-23 19:52:30 +0200515 up4_1.teardown()
516
517 run.cleanup(main)
Daniele Moro522023c2021-10-15 17:30:33 +0200518
519 def CASE5(self, main):
520 main.case("UP4 Data Plane Failure Test")
521 """
Daniele Moro49a843c2022-01-05 14:36:32 +0100522 Program UPF entities
Daniele Moro522023c2021-10-15 17:30:33 +0200523 Kill one switch
Daniele Moro80271cb2021-11-11 20:08:51 +0100524 Set label on switch K8S node to prevent K8S to redeploy stratum
Daniele Moro522023c2021-10-15 17:30:33 +0200525 Verify that traffic from eNodebs that are connected to that switch fails
526 Verify that traffic from other eNodeBs is being forwarded
527 Wait for the switch to be up again
528 Check flows
Daniele Moro49a843c2022-01-05 14:36:32 +0100529 Remove UPF entities (cleanup)
Daniele Moro522023c2021-10-15 17:30:33 +0200530 """
531 try:
Daniele Moro54581242022-02-25 19:56:02 +0100532 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4
Daniele Moro522023c2021-10-15 17:30:33 +0200533 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
534 Testcaselib as run
535 from tests.USECASE.SegmentRouting.SRStaging.dependencies.SRStagingTest import \
536 SRStagingTest
537 import time
538 import itertools
539 except ImportError as e:
540 main.log.error("Import not found. Exiting the test")
541 main.log.error(e)
542 main.cleanAndExit()
543 n_switches = int(main.params["TOPO"]["switchNum"])
Daniele Moro80271cb2021-11-11 20:08:51 +0100544 switch_to_kill = main.params["UP4"]["UP4_dataplane_fail"]["switch_to_kill"]
545 k8s_switch_node = main.params["UP4"]["UP4_dataplane_fail"]["k8s_switch_node"]
546 k8s_label = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label"]
547 k8s_label_value_test = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label_value_test"]
548 k8s_label_value_normal = main.params["UP4"]["UP4_dataplane_fail"]["k8s_label_value_normal"]
Daniele Moro522023c2021-10-15 17:30:33 +0200549
550 run.initTest(main)
551 main.log.info(main.Cluster.numCtrls)
552 main.Cluster.setRunningNode(3)
553 run.installOnos(main, skipPackage=True, cliSleep=5)
554
555 onos_cli = main.Cluster.active(0).CLI
Daniele Moro80271cb2021-11-11 20:08:51 +0100556 kubectl = main.Cluster.active(0).Bench
557 kubeconfig = main.Cluster.active(0).k8s.kubeConfig
558 namespace = main.params['kubernetes']['namespace']
Daniele Moro522023c2021-10-15 17:30:33 +0200559
560 up4 = UP4()
561
Daniele Moro49a843c2022-01-05 14:36:32 +0100562 main.step("Program and Verify UPF entities via UP4")
Daniele Moro522023c2021-10-15 17:30:33 +0200563 up4.setup(main.Cluster.active(0).p4rtUp4)
564 up4.attachUes()
565 up4.verifyUp4Flow(onos_cli)
566
Daniele Moro80271cb2021-11-11 20:08:51 +0100567 main.step("Set label to switch k8s node and kill switch")
568 # K8s node name correspond to the switch name in lowercase
Daniele Moro522023c2021-10-15 17:30:33 +0200569 utilities.assert_equal(
Daniele Moro80271cb2021-11-11 20:08:51 +0100570 expect=main.TRUE,
571 actual=kubectl.kubectlSetLabel(
572 nodeName=k8s_switch_node,
573 label=k8s_label,
574 value=k8s_label_value_test,
575 kubeconfig=kubeconfig,
576 namespace=namespace,
577 ),
578 onpass="Label has been set correctly on node %s" % k8s_switch_node,
579 onfail="Label has not been set on node %s" % k8s_switch_node
Daniele Moro522023c2021-10-15 17:30:33 +0200580 )
Daniele Moro80271cb2021-11-11 20:08:51 +0100581 try:
582 def checkNumberStratumPods(n_value):
583 pods = kubectl.kubectlGetPodNames(
584 kubeconfig=kubeconfig,
585 namespace=namespace,
586 name="stratum"
587 )
588 main.log.info("PODS: " + str(pods))
589 return n_value == len(pods) if pods is not main.FALSE else False
590 # Execute the following in try/except/finally to be sure to restore the
591 # k8s label even in case of unhandled exception.
Daniele Moro522023c2021-10-15 17:30:33 +0200592
Daniele Moro80271cb2021-11-11 20:08:51 +0100593 # Wait for stratum pod to be removed from the switch
594 removed = utilities.retry(checkNumberStratumPods,
595 False,
596 args=[n_switches-1],
597 attempts=50
598 )
599 main.log.info("Stratum has been removed from the switch? %s" % removed)
Daniele Moro522023c2021-10-15 17:30:33 +0200600
Daniele Moro80271cb2021-11-11 20:08:51 +0100601 switch_component = getattr(main, switch_to_kill)
602 switch_component.handle.sendline("sudo reboot")
Daniele Moro522023c2021-10-15 17:30:33 +0200603
Daniele Moro80271cb2021-11-11 20:08:51 +0100604 sleepTime = 20
605 main.log.info("Sleeping %s seconds for Fabric to react" % sleepTime)
606 time.sleep(sleepTime)
Daniele Moro522023c2021-10-15 17:30:33 +0200607
Daniele Moro80271cb2021-11-11 20:08:51 +0100608 available = utilities.retry(SRStagingTest.switchIsConnected,
609 True,
610 args=[switch_component],
611 attempts=300,
612 getRetryingTime=True)
613 main.log.info("Switch %s is available in ONOS? %s" % (
614 switch_to_kill, available))
615 utilities.assert_equal(
616 expect=True,
617 actual=not available and removed,
618 onpass="Switch was rebooted (ONL reboot) successfully and stratum" +
619 " removed from switch k8s node",
620 onfail="Switch was not rebooted (ONL reboot) successfully or stratum " +
621 "not removed from switch k8s node"
622 )
623
624 enodebs_fail = main.params["UP4"]["UP4_dataplane_fail"]["enodebs_fail"].split(",")
625 enodebs_no_fail = list(set(up4.enodebs.keys()) - set(enodebs_fail))
626
Daniele Moro80271cb2021-11-11 20:08:51 +0100627
Daniele Morobef0c7e2022-02-16 17:47:13 -0800628 for app_filter_name in up4.app_filters:
629 # Failure only when we forward traffic, when dropping we should
630 # still see traffic being dropped.
631 if up4.app_filters["action"] == "allow":
632 main.step("Test upstream traffic FAIL %s" % app_filter_name)
633 up4.testUpstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name, shouldFail=True)
634 main.step("Test downstream traffic FAIL %s" % app_filter_name)
635 up4.testDownstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name, shouldFail=True)
636 else:
637 main.step("Test upstream traffic FAIL %s" % app_filter_name)
638 up4.testUpstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name)
639 main.step("Test downstream traffic FAIL %s" % app_filter_name)
640 up4.testDownstreamTraffic(enb_names=enodebs_fail, app_filter_name=app_filter_name)
641
642 main.step("Test upstream traffic NO FAIL %s" % app_filter_name)
643 up4.testUpstreamTraffic(enb_names=enodebs_no_fail, app_filter_name=app_filter_name)
644 main.step("Test downstream traffic NO FAIL %s" % app_filter_name)
645 up4.testDownstreamTraffic(enb_names=enodebs_no_fail, app_filter_name=app_filter_name)
646
Daniele Moro80271cb2021-11-11 20:08:51 +0100647 except Exception as e:
648 main.log.error("Unhandled exception!")
649 main.log.error(e)
650 finally:
651 utilities.assert_equal(
652 expect=main.TRUE,
653 actual=kubectl.kubectlSetLabel(
654 nodeName=k8s_switch_node,
655 label=k8s_label,
656 value=k8s_label_value_normal,
657 kubeconfig=kubeconfig,
658 namespace=namespace,
659 ),
660 onpass="Label has been set correctly on node %s" % k8s_switch_node,
661 onfail="Label has not been set on node %s" % k8s_switch_node
662 )
663 # Reconnect to the switch
664 connect = utilities.retry(switch_component.connect,
665 main.FALSE,
666 attempts=30,
667 getRetryingTime=True)
668 main.log.info("Connected to the switch %s? %s" % (
669 switch_to_kill, connect))
670
671 # Wait for stratum pod to be re-deployed on the switch
672 deployed = utilities.retry(checkNumberStratumPods,
673 False,
674 args=[n_switches],
675 attempts=50
676 )
677 main.log.info("Stratum has been redeployed on the switch? %s" % deployed)
678
679 # Wait switch to be back in ONOS
680 available = utilities.retry(SRStagingTest.switchIsConnected,
681 False,
682 args=[switch_component],
683 attempts=300,
684 getRetryingTime=True)
685 main.log.info("Switch %s is available in ONOS? %s" % (
686 switch_to_kill, available))
687 utilities.assert_equal(
688 expect=True,
689 actual=available and connect == main.TRUE and deployed,
690 onpass="Switch is back available in ONOS and stratum has been redeployed",
691 onfail="Switch is not available in ONOS, may influence subsequent tests!"
692 )
Daniele Moro522023c2021-10-15 17:30:33 +0200693
Daniele Morobef0c7e2022-02-16 17:47:13 -0800694 for app_filter_name in up4.app_filters:
695 main.step("Test upstream traffic AFTER switch reboot %s" % app_filter_name)
696 up4.testUpstreamTraffic(app_filter_name=app_filter_name)
Daniele Moro522023c2021-10-15 17:30:33 +0200697
Daniele Moro49a843c2022-01-05 14:36:32 +0100698 main.step("Cleanup UPF entities via UP4")
Daniele Moro522023c2021-10-15 17:30:33 +0200699 up4.detachUes()
700 up4.verifyNoUesFlow(onos_cli)
701 up4.teardown()
702
Daniele Moro522023c2021-10-15 17:30:33 +0200703 # Teardown
704 run.cleanup(main)
Daniele Moro80271cb2021-11-11 20:08:51 +0100705
Jon Halla4a79312022-01-25 17:16:53 -0800706 def CASE11(self, main):
707 main.case("Fabric UPF traffic terminated in the fabric using pfcpsim to generate UE sessions")
708 """
709 Program UPF entities for UEs
710 Verify UPF entities
711 Generate traffic from UE to PDN
712 Verify traffic received from PDN
713 Generate traffic from PDN to UE
714 Verify traffic received from UE
715 Remove UPF entities for UEs
716 Verify removed UPF entities
717 """
718 try:
719 from tests.USECASE.SegmentRouting.dependencies.up4 import UP4
720 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
721 Testcaselib as run
722 except ImportError as e:
723 main.log.error("Import not found. Exiting the test")
724 main.log.error(e)
725 main.cleanAndExit()
726 n_switches = int(main.params["TOPO"]["switchNum"])
727
728 run.initTest(main)
729 main.log.info(main.Cluster.numCtrls)
730 main.Cluster.setRunningNode(3)
731 run.installOnos(main, skipPackage=True, cliSleep=5)
732
733 main.step("Start scapy and p4rt client")
734 # Use the first available ONOS instance CLI
735 node = main.Cluster.active(0)
736 onos_cli = node.CLI
737 kubeconfig = node.k8s.kubeConfig
738 namespace = main.params['kubernetes']['namespace']
739
740 # Use pfcpctl instead of pr4untime to add ue sessions
741 smf = main.ONOScell.createMockSMFComponent( "pfcpsim", node.ip_address )
742 main.ONOScell.mock_smf = True
743 node.mock_smf = smf
744
745 up4 = UP4()
746 nodeIP = node.Bench.kubectlCmd("get node %s --output=jsonpath='{.metadata.annotations.rke\.cattle\.io/external-ip}{\"\\n\"}'" % node.Bench.kubectlGetPodNode("pfcp-agent-0", kubeconfig, namespace))
747
748 # Connect P4RT and the mock smf if configured
749 up4.setup(node.p4rtUp4, mock_smf=node.mock_smf,
750 pfcpAddress=nodeIP,
751 pfcpPort=node.Bench.kubectlGetNodePort("pfcp-agent", kubeconfig, namespace))
752 app_filters = up4.app_filters
753 app_filters.update( up4.DEFAULT_APP)
754 for name, app in app_filters.iteritems():
755 up4.app_filters = { name: app }
756 main.step("Program and Verify UPF entities via pfcp for app: %s" % name)
757 up4.attachUes()
758 up4.verifyUp4Flow(onos_cli)
759
760 # ------- Test Upstream traffic (enb->pdn)
761 for app_filter_name in up4.app_filters:
762 main.step("Test upstream traffic %s" % app_filter_name)
763 up4.testUpstreamTraffic(app_filter_name=app_filter_name)
764
765 # ------- Test Downstream traffic (pdn->enb)
766 for app_filter_name in up4.app_filters:
767 main.step("Test downstream traffic %s" % app_filter_name)
768 up4.testDownstreamTraffic(app_filter_name=app_filter_name)
769
770 main.step("Remove and Verify UPF entities via pfcp for app: %s" % name)
771 up4.detachUes()
772 up4.verifyNoUesFlow(onos_cli)
773
774 # hack to make sure next iteration uses different seids
775 for ue_name in up4.emulated_ues:
776 up4.emulated_ues[ue_name]["seid"] = None
777 main.step("Stop scapy and p4rt client")
778 up4.teardown()
779
780 run.cleanup(main)
781
782