blob: a7f9804dc06fbeadbf023dedf50b5d010cdc3de6 [file] [log] [blame]
Daniele Moro790cc102021-08-30 18:27:30 +02001class UP4:
2
3 def __init__(self):
4 self.default = ''
5
6 # TODO: add test case that checks entries are being inserted and deleted from ONOS correclty
7 def CASE1(self, main):
8 """
9 Attach UE
10 Generate traffic from UE to PDN
11 Verify traffic received from PDN
12 Generate traffic from PDN to UE
13 Verify traffic received from UE
14 Detach UE
15 """
16 UE_PORT = 400
17 PDN_PORT = 800
18 GPDU_PORT = 2152
19 try:
20 from tests.USECASE.SegmentRouting.dependencies.up4libcli import \
21 Up4LibCli
22 from tests.USECASE.SegmentRouting.dependencies.Testcaselib import \
23 Testcaselib as run
24 from distutils.util import strtobool
25 except ImportError as e:
26 main.log.error("Import not found. Exiting the test")
27 main.log.error(e)
28 main.cleanAndExit()
29
30 # TODO: Move to a setup script
31 run.initTest(main)
32 main.log.info(main.Cluster.numCtrls)
33 main.Cluster.setRunningNode(3)
34 run.installOnos(main, skipPackage=True, cliSleep=5)
35
36 # Get the P4RT client connected to UP4 in the first available ONOS instance
37 up4Client = main.Cluster.active(0).p4rtUp4
38
39 s1u_address = main.params["UP4"]["s1u_address"]
40 enb_address = main.params["UP4"]["enb_address"]
41 router_mac = main.params["UP4"]["router_mac"]
42
43 pdn_host = getattr(main, main.params["UP4"]["pdn_host"])
44 pdn_interface = pdn_host.interfaces[0]
45
46 enodeb_host = getattr(main, main.params["UP4"]["enodeb_host"])
47 enodeb_interface = enodeb_host.interfaces[0]
48
49 emulated_ues = main.params["UP4"]['ues']
50 n_ues = len(emulated_ues)
51
52 main.step("Start scapy and p4rt client")
53 pdn_host.startScapy(ifaceName=pdn_interface["name"])
54 enodeb_host.startScapy(ifaceName=enodeb_interface["name"],
55 enableGtp=True)
56 up4Client.startP4RtClient()
57
58 # TODO: move to library in dependencies
59 main.step("Attach UEs")
60 for ue in emulated_ues.values():
61 # Sanitize values coming from the params file
62 if "five_g" in ue:
63 ue["five_g"] = bool(strtobool(ue["five_g"]))
64 if "qfi" in ue and ue["qfi"] == "":
65 ue["qfi"] = None
66 Up4LibCli.attachUe(up4Client, s1u_address=s1u_address,
67 enb_address=enb_address,
68 **ue)
69
70 # ----------------- Test Upstream traffic (enb->pdn)
71 main.step("Test upstream traffic")
72 # Scapy filter needs to start before sending traffic
73 pkt_filter_upstream = ""
74 for ue in emulated_ues.values():
75 if "ue_address" in ue:
76 if len(pkt_filter_upstream) != 0:
77 pkt_filter_upstream += " or "
78 pkt_filter_upstream += "src host " + ue["ue_address"]
79 pkt_filter_upstream = "ip and udp dst port %s and (%s) and dst host %s" % \
80 (PDN_PORT, pkt_filter_upstream,
81 pdn_interface["ips"][0])
82 main.log.info("Start listening on %s intf %s" %
83 (main.params["UP4"]["pdn_host"], pdn_interface["name"]))
84 main.log.debug("BPF Filter Upstream: \n %s" % pkt_filter_upstream)
85 pdn_host.startFilter(ifaceName=pdn_interface["name"],
86 sniffCount=n_ues,
87 pktFilter=pkt_filter_upstream)
88
89 main.log.info("Sending %d packets from eNodeB host" % len(emulated_ues))
90 for ue in emulated_ues.values():
91 enodeb_host.buildEther()
92 enodeb_host.buildIP(src=enb_address, dst=s1u_address)
93 enodeb_host.buildUDP(ipVersion=4, dport=GPDU_PORT)
94 # FIXME: With newer scapy TEID becomes teid (required for Scapy 2.4.5)
95 enodeb_host.buildGTP(gtp_type=0xFF, TEID=int(ue["teid"]))
96 enodeb_host.buildIP(overGtp=True, src=ue["ue_address"],
97 dst=pdn_interface["ips"][0])
98 enodeb_host.buildUDP(ipVersion=4, overGtp=True, sport=UE_PORT,
99 dport=PDN_PORT)
100
101 enodeb_host.sendPacket(iface=enodeb_interface["name"])
102
103 finished = pdn_host.checkFilter()
104 packets = ""
105 if finished:
106 packets = pdn_host.readPackets(detailed=True)
107 for p in packets.splitlines():
108 main.log.debug(p)
109 # We care only of the last line from readPackets
110 packets = packets.splitlines()[-1]
111 else:
112 kill = pdn_host.killFilter()
113 main.log.debug(kill)
114
115 fail = False
116 if len(emulated_ues) != packets.count('Ether'):
117 fail = True
118 msg = "Failed to capture packets in PDN. "
119 else:
120 msg = "Correctly captured packet in PDN. "
121 # We expect exactly 1 packet per UE
122 pktsFiltered = [packets.count("src=" + ue["ue_address"])
123 for ue in emulated_ues.values()]
124 if pktsFiltered.count(1) != len(pktsFiltered):
125 fail = True
126 msg += "More than one packet per UE in downstream. "
127 else:
128 msg += "One packet per UE in upstream. "
129
130 utilities.assert_equal(
131 expect=False, actual=fail, onpass=msg, onfail=msg)
132
133 # --------------- Test Downstream traffic (pdn->enb)
134 main.step("Test downstream traffic")
135 pkt_filter_downstream = "ip and udp src port %d and udp dst port %d and dst host %s and src host %s" % (
136 GPDU_PORT, GPDU_PORT, enb_address, s1u_address)
137 main.log.info("Start listening on %s intf %s" % (
138 main.params["UP4"]["enodeb_host"], enodeb_interface["name"]))
139 main.log.debug("BPF Filter Downstream: \n %s" % pkt_filter_downstream)
140 enodeb_host.startFilter(ifaceName=enodeb_interface["name"],
141 sniffCount=len(emulated_ues),
142 pktFilter=pkt_filter_downstream)
143
144 main.log.info("Sending %d packets from PDN host" % len(emulated_ues))
145 for ue in emulated_ues.values():
146 # From PDN we have to set dest MAC, otherwise scapy will do ARP
147 # request for the UE IP address.
148 pdn_host.buildEther(dst=router_mac)
149 pdn_host.buildIP(src=pdn_interface["ips"][0],
150 dst=ue["ue_address"])
151 pdn_host.buildUDP(ipVersion=4, sport=PDN_PORT, dport=UE_PORT)
152 pdn_host.sendPacket(iface=pdn_interface["name"])
153
154 finished = enodeb_host.checkFilter()
155 packets = ""
156 if finished:
157 packets = enodeb_host.readPackets(detailed=True)
158 for p in packets.splitlines():
159 main.log.debug(p)
160 # We care only of the last line from readPackets
161 packets = packets.splitlines()[-1]
162 else:
163 kill = enodeb_host.killFilter()
164 main.log.debug(kill)
165
166 # The BPF filter might capture non-GTP packets because we can't filter
167 # GTP header in BPF. For this reason, check that the captured packets
168 # are from the expected tunnels.
169 # TODO: check inner UDP and IP fields as well
170 # FIXME: with newer scapy TEID becomes teid (required for Scapy 2.4.5)
171 pktsFiltered = [packets.count("TEID=" + hex(int(ue["teid"])) + "L ")
172 for ue in emulated_ues.values()]
173
174 fail = False
175 if len(emulated_ues) != sum(pktsFiltered):
176 fail = True
177 msg = "Failed to capture packets in eNodeB. "
178 else:
179 msg = "Correctly captured packets in eNodeB. "
180 # We expect exactly 1 packet per UE
181 if pktsFiltered.count(1) != len(pktsFiltered):
182 fail = True
183 msg += "More than one packet per GTP TEID in downstream. "
184 else:
185 msg += "One packet per GTP TEID in downstream. "
186
187 utilities.assert_equal(
188 expect=False, actual=fail, onpass=msg, onfail=msg)
189
190 # Detach UEs
191 main.step("Detach UEs")
192 for ue in emulated_ues.values():
193 # No need to sanitize values, already sanitized during attachment
194 Up4LibCli.detachUe(up4Client, s1u_address=s1u_address,
195 enb_address=enb_address,
196 **ue)
197
198 # Teardown
199 main.step("Stop scapy and p4rt client")
200 enodeb_host.stopScapy()
201 pdn_host.stopScapy()
202 up4Client.stopP4RtClient()
203 run.cleanup(main)