blob: 7a96e84e34f41b334565ddf818152a978a057df6 [file] [log] [blame]
Dave Wallace54a77802020-11-30 16:56:43 -05001#!/usr/bin/env python3
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -08002
3from framework import VppTestCase
4from ipaddress import IPv4Address
5from ipaddress import IPv6Address
Takeru Hayasaka68ac2442022-10-28 04:26:05 +09006from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto, VppIpTable
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00007from config import config
Takeru Hayasaka68ac2442022-10-28 04:26:05 +09008
9from vpp_srv6_mobile import (
10 SRv6MobileNhtype,
11 VppSRv6MobilePolicy,
12 VppSRv6MobileLocalSID,
13)
14
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080015from scapy.contrib.gtp import *
16from scapy.all import *
17
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000018import unittest
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080019
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000020
21@unittest.skipIf(
22 "srv6-mobile" in config.excluded_plugins, "Exclude srv6-mobile plugin tests"
23)
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080024class TestSRv6EndMGTP4E(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020025 """SRv6 End.M.GTP4.E (SRv6 -> GTP-U)"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080026
27 @classmethod
28 def setUpClass(cls):
29 super(TestSRv6EndMGTP4E, cls).setUpClass()
30 try:
31 cls.create_pg_interfaces(range(2))
32 cls.pg_if_i = cls.pg_interfaces[0]
33 cls.pg_if_o = cls.pg_interfaces[1]
34
35 cls.pg_if_i.config_ip6()
36 cls.pg_if_o.config_ip4()
37
38 cls.ip4_dst = cls.pg_if_o.remote_ip4
39 # cls.ip4_src = cls.pg_if_o.local_ip4
40 cls.ip4_src = "192.168.192.10"
41
42 for pg_if in cls.pg_interfaces:
43 pg_if.admin_up()
44 pg_if.resolve_arp()
45
46 except Exception:
47 super(TestSRv6EndMGTP4E, cls).tearDownClass()
48 raise
49
50 def create_packets(self, inner):
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080051 ip4_dst = IPv4Address(str(self.ip4_dst))
52 # 32bit prefix + 32bit IPv4 DA + 8bit + 32bit TEID + 24bit
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020053 dst = b"\xaa" * 4 + ip4_dst.packed + b"\x11" + b"\xbb" * 4 + b"\x11" * 3
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080054 ip6_dst = IPv6Address(dst)
55
56 ip4_src = IPv4Address(str(self.ip4_src))
57 # 64bit prefix + 32bit IPv4 SA + 16 bit port + 16bit
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020058 src = b"\xcc" * 8 + ip4_src.packed + b"\xdd" * 2 + b"\x11" * 2
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080059 ip6_src = IPv6Address(src)
60
61 self.logger.info("ip4 dst: {}".format(ip4_dst))
62 self.logger.info("ip4 src: {}".format(ip4_src))
63 self.logger.info("ip6 dst (remote srgw): {}".format(ip6_dst))
64 self.logger.info("ip6 src (local srgw): {}".format(ip6_src))
65
66 pkts = list()
67 for d, s in inner:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020068 pkt = (
Steven Luonge4238aa2024-04-19 09:49:20 -070069 Ether(dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020070 / IPv6(dst=str(ip6_dst), src=str(ip6_src))
71 / IPv6ExtHdrSegmentRouting()
72 / IPv6(dst=d, src=s)
73 / UDP(sport=1000, dport=23)
74 )
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080075 self.logger.info(pkt.show2(dump=True))
76 pkts.append(pkt)
77
78 return pkts
79
80 def test_srv6_mobile(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020081 """test_srv6_mobile"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080082 pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")])
83
Takeru Hayasaka68ac2442022-10-28 04:26:05 +090084 # "sr localsid address {} behavior end.m.gtp4.e v4src_position 64 fib-table 0"
85 # ".format(pkts[0]["IPv6"].dst)
86 localsid = VppSRv6MobileLocalSID(
87 self,
88 # address params case is length 0
89 localsid_prefix="{}/{}".format(pkts[0]["IPv6"].dst, 0),
90 behavior="end.m.gtp4.e",
91 v4src_position=64,
92 fib_table=0,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020093 )
Takeru Hayasaka68ac2442022-10-28 04:26:05 +090094 localsid.add_vpp_config()
95
96 # log the localsids
Tetsuya Murakamibe872a82021-12-10 08:11:07 -080097 self.logger.info(self.vapi.cli("show sr localsid"))
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -080098
99 self.vapi.cli("clear errors")
100
101 self.pg0.add_stream(pkts)
102 self.pg_enable_capture(self.pg_interfaces)
103 self.pg_start()
104
105 self.logger.info(self.vapi.cli("show errors"))
106 self.logger.info(self.vapi.cli("show int address"))
107
108 capture = self.pg1.get_capture(len(pkts))
109
110 for pkt in capture:
111 self.logger.info(pkt.show2(dump=True))
112 self.assertEqual(pkt[IP].dst, self.ip4_dst)
113 self.assertEqual(pkt[IP].src, self.ip4_src)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200114 self.assertEqual(pkt[GTP_U_Header].teid, 0xBBBBBBBB)
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800115
116
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000117@unittest.skipIf(
118 "srv6-mobile" in config.excluded_plugins, "Exclude srv6-mobile plugin tests"
119)
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800120class TestSRv6TMGTP4D(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200121 """SRv6 T.M.GTP4.D (GTP-U -> SRv6)"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800122
123 @classmethod
124 def setUpClass(cls):
125 super(TestSRv6TMGTP4D, cls).setUpClass()
126 try:
127 cls.create_pg_interfaces(range(2))
128 cls.pg_if_i = cls.pg_interfaces[0]
129 cls.pg_if_o = cls.pg_interfaces[1]
130
131 cls.pg_if_i.config_ip4()
132 cls.pg_if_i.config_ip6()
133 cls.pg_if_o.config_ip4()
134 cls.pg_if_o.config_ip6()
135
136 cls.ip4_dst = "1.1.1.1"
137 cls.ip4_src = "2.2.2.2"
138
139 cls.ip6_dst = cls.pg_if_o.remote_ip6
140
141 for pg_if in cls.pg_interfaces:
142 pg_if.admin_up()
143 pg_if.resolve_arp()
144 pg_if.resolve_ndp(timeout=5)
145
146 except Exception:
147 super(TestSRv6TMGTP4D, cls).tearDownClass()
148 raise
149
150 def create_packets(self, inner):
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800151 ip4_dst = IPv4Address(str(self.ip4_dst))
152
153 ip4_src = IPv4Address(str(self.ip4_src))
154
155 self.logger.info("ip4 dst: {}".format(ip4_dst))
156 self.logger.info("ip4 src: {}".format(ip4_src))
157
158 pkts = list()
159 for d, s in inner:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200160 pkt = (
Steven Luonge4238aa2024-04-19 09:49:20 -0700161 Ether(dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200162 / IP(dst=str(ip4_dst), src=str(ip4_src))
163 / UDP(sport=2152, dport=2152)
164 / GTP_U_Header(gtp_type="g_pdu", teid=200)
165 / IPv6(dst=d, src=s)
166 / UDP(sport=1000, dport=23)
167 )
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800168 self.logger.info(pkt.show2(dump=True))
169 pkts.append(pkt)
170
171 return pkts
172
173 def test_srv6_mobile(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200174 """test_srv6_mobile"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800175 pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")])
176
177 self.vapi.cli("set sr encaps source addr A1::1")
178 self.vapi.cli("sr policy add bsid D4:: next D2:: next D3::")
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800179
Takeru Hayasaka68ac2442022-10-28 04:26:05 +0900180 # sr policy add bsid D5:: behavior t.m.gtp4.d D4::/32 v6src_prefix C1::/64 nhtype ipv6 fib-table 0 drop-in
181 policy = VppSRv6MobilePolicy(
182 self,
183 bsid_addr="D5::",
184 behavior="t.m.gtp4.d",
185 sr_prefix="{}/{}".format("D4::", 32),
186 v6src_prefix="{}/{}".format("C1::", 64),
187 nhtype=SRv6MobileNhtype.SRV6_NHTYPE_API_IPV6,
188 fib_table=0,
189 drop_in=1,
190 )
191 policy.add_vpp_config()
192
193 self.vapi.cli("sr steer l3 {}/32 via bsid D5::".format(self.ip4_dst))
194
195 # "ip route add D2::/32 via {}".format(self.ip6_dst)
196 route = VppIpRoute(
197 self, "D2::", 32, [VppRoutePath(self.ip6_dst, self.pg1.sw_if_index)]
198 )
199 route.add_vpp_config()
200 self.logger.info(self.vapi.cli("show ip6 fib"))
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800201 self.logger.info(self.vapi.cli("show sr steer"))
202 self.logger.info(self.vapi.cli("show sr policies"))
203
204 self.vapi.cli("clear errors")
205
206 self.pg0.add_stream(pkts)
207 self.pg_enable_capture(self.pg_interfaces)
208 self.pg_start()
209
210 self.logger.info(self.vapi.cli("show errors"))
211 self.logger.info(self.vapi.cli("show int address"))
212
213 capture = self.pg1.get_capture(len(pkts))
214
215 for pkt in capture:
216 self.logger.info(pkt.show2(dump=True))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200217 self.logger.info(
218 "GTP4.D Address={}".format(
219 str(pkt[IPv6ExtHdrSegmentRouting].addresses[0])
220 )
221 )
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800222 self.assertEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200223 str(pkt[IPv6ExtHdrSegmentRouting].addresses[0]), "d4:0:101:101::c800:0"
224 )
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800225
226
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000227@unittest.skipIf(
228 "srv6-mobile" in config.excluded_plugins, "Exclude srv6-mobile plugin tests"
229)
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800230class TestSRv6EndMGTP6E(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200231 """SRv6 End.M.GTP6.E"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800232
233 @classmethod
234 def setUpClass(cls):
235 super(TestSRv6EndMGTP6E, cls).setUpClass()
236 try:
237 cls.create_pg_interfaces(range(2))
238 cls.pg_if_i = cls.pg_interfaces[0]
239 cls.pg_if_o = cls.pg_interfaces[1]
240
241 cls.pg_if_i.config_ip6()
242 cls.pg_if_o.config_ip6()
243
244 cls.ip6_nhop = cls.pg_if_o.remote_ip6
245
246 for pg_if in cls.pg_interfaces:
247 pg_if.admin_up()
248 pg_if.resolve_ndp(timeout=5)
249
250 except Exception:
251 super(TestSRv6EndMGTP6E, cls).tearDownClass()
252 raise
253
254 def create_packets(self, inner):
Tetsuya Murakamiddba6702020-12-01 19:19:13 -0800255 # 64bit prefix + 8bit QFI + 32bit TEID + 24bit
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 dst = b"\xaa" * 8 + b"\x00" + b"\xbb" * 4 + b"\x00" * 3
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800257 ip6_dst = IPv6Address(dst)
258
259 self.ip6_dst = ip6_dst
260
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200261 src = b"\xcc" * 8 + b"\xdd" * 4 + b"\x11" * 4
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800262 ip6_src = IPv6Address(src)
263
264 self.ip6_src = ip6_src
265
266 pkts = list()
267 for d, s in inner:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200268 pkt = (
Steven Luonge4238aa2024-04-19 09:49:20 -0700269 Ether(dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200270 / IPv6(dst=str(ip6_dst), src=str(ip6_src))
271 / IPv6ExtHdrSegmentRouting(
272 segleft=1, lastentry=0, tag=0, addresses=["a1::1"]
273 )
274 / IPv6(dst=d, src=s)
275 / UDP(sport=1000, dport=23)
276 )
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800277 self.logger.info(pkt.show2(dump=True))
278 pkts.append(pkt)
279
280 return pkts
281
282 def test_srv6_mobile(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200283 """test_srv6_mobile"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800284 pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")])
285
Takeru Hayasaka68ac2442022-10-28 04:26:05 +0900286 # "sr localsid prefix {}/64 behavior end.m.gtp6.e fib-table 0"
287 # .format(pkts[0]["IPv6"].dst)
288 localsid = VppSRv6MobileLocalSID(
289 self,
290 localsid_prefix="{}/{}".format(pkts[0]["IPv6"].dst, 64),
291 behavior="end.m.gtp6.e",
292 fib_table=0,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 )
Takeru Hayasaka68ac2442022-10-28 04:26:05 +0900294 localsid.add_vpp_config()
295
296 # "ip route add a1::/64 via {}".format(self.ip6_nhop)
297 route = VppIpRoute(
298 self, "a1::", 64, [VppRoutePath(self.ip6_nhop, self.pg1.sw_if_index)]
299 )
300 route.add_vpp_config()
Tetsuya Murakamibe872a82021-12-10 08:11:07 -0800301 self.logger.info(self.vapi.cli("show sr localsid"))
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800302
303 self.vapi.cli("clear errors")
304
305 self.pg0.add_stream(pkts)
306 self.pg_enable_capture(self.pg_interfaces)
307 self.pg_start()
308
309 self.logger.info(self.vapi.cli("show errors"))
310 self.logger.info(self.vapi.cli("show int address"))
311
312 capture = self.pg1.get_capture(len(pkts))
313
314 for pkt in capture:
315 self.logger.info(pkt.show2(dump=True))
316 self.assertEqual(pkt[IPv6].dst, "a1::1")
317 self.assertEqual(pkt[IPv6].src, str(self.ip6_src))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200318 self.assertEqual(pkt[GTP_U_Header].teid, 0xBBBBBBBB)
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800319
320
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000321@unittest.skipIf(
322 "srv6-mobile" in config.excluded_plugins, "Exclude srv6-mobile plugin tests"
323)
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800324class TestSRv6EndMGTP6D(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200325 """SRv6 End.M.GTP6.D"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800326
327 @classmethod
328 def setUpClass(cls):
329 super(TestSRv6EndMGTP6D, cls).setUpClass()
330 try:
331 cls.create_pg_interfaces(range(2))
332 cls.pg_if_i = cls.pg_interfaces[0]
333 cls.pg_if_o = cls.pg_interfaces[1]
334
335 cls.pg_if_i.config_ip6()
336 cls.pg_if_o.config_ip6()
337
338 cls.ip6_nhop = cls.pg_if_o.remote_ip6
339
340 cls.ip6_dst = "2001::1"
341 cls.ip6_src = "2002::1"
342
343 for pg_if in cls.pg_interfaces:
344 pg_if.admin_up()
345 pg_if.resolve_ndp(timeout=5)
346
347 except Exception:
348 super(TestSRv6EndMGTP6D, cls).tearDownClass()
349 raise
350
351 def create_packets(self, inner):
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800352 ip6_dst = IPv6Address(str(self.ip6_dst))
353
354 ip6_src = IPv6Address(str(self.ip6_src))
355
356 self.logger.info("ip6 dst: {}".format(ip6_dst))
357 self.logger.info("ip6 src: {}".format(ip6_src))
358
359 pkts = list()
360 for d, s in inner:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200361 pkt = (
Steven Luonge4238aa2024-04-19 09:49:20 -0700362 Ether(dst=self.pg0.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200363 / IPv6(dst=str(ip6_dst), src=str(ip6_src))
364 / UDP(sport=2152, dport=2152)
365 / GTP_U_Header(gtp_type="g_pdu", teid=200)
366 / IPv6(dst=d, src=s)
367 / UDP(sport=1000, dport=23)
368 )
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800369 self.logger.info(pkt.show2(dump=True))
370 pkts.append(pkt)
371
372 return pkts
373
374 def test_srv6_mobile(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200375 """test_srv6_mobile"""
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800376 pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")])
377
378 self.vapi.cli("set sr encaps source addr A1::1")
379 self.vapi.cli("sr policy add bsid D4:: next D2:: next D3::")
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800380
Takeru Hayasaka68ac2442022-10-28 04:26:05 +0900381 # "sr localsid prefix 2001::/64 behavior end.m.gtp6.d 4::/64 fib-table 0 drop-in"
382 # .format(self.ip6_nhop)
383 localsid = VppSRv6MobileLocalSID(
384 self,
385 localsid_prefix="{}/{}".format("2001::", 64),
386 behavior="end.m.gtp6.d",
387 fib_table=0,
388 drop_in=1,
389 sr_prefix="{}/{}".format("D4::", 64),
390 )
391 localsid.add_vpp_config()
392
393 # "ip route add D2::/64 via {}"
394 # .format(self.ip6_nhop))
395 route = VppIpRoute(
396 self, "D2::", 64, [VppRoutePath(self.ip6_nhop, self.pg1.sw_if_index)]
397 )
398 route.add_vpp_config()
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800399 self.logger.info(self.vapi.cli("show sr policies"))
Tetsuya Murakamibe872a82021-12-10 08:11:07 -0800400 self.logger.info(self.vapi.cli("show sr localsid"))
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800401
402 self.vapi.cli("clear errors")
403
404 self.pg0.add_stream(pkts)
405 self.pg_enable_capture(self.pg_interfaces)
406 self.pg_start()
407
408 self.logger.info(self.vapi.cli("show errors"))
409 self.logger.info(self.vapi.cli("show int address"))
410
411 capture = self.pg1.get_capture(len(pkts))
412
413 for pkt in capture:
414 self.logger.info(pkt.show2(dump=True))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200415 self.logger.info(
416 "GTP6.D SID0={}".format(str(pkt[IPv6ExtHdrSegmentRouting].addresses[0]))
417 )
418 self.logger.info(
419 "GTP6.D SID1={}".format(str(pkt[IPv6ExtHdrSegmentRouting].addresses[1]))
420 )
421 self.assertEqual(str(pkt[IPv6ExtHdrSegmentRouting].addresses[0]), "2001::1")
Tetsuya Murakami9e722bd2020-03-04 16:27:14 -0800422 self.assertEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200423 str(pkt[IPv6ExtHdrSegmentRouting].addresses[1]), "d4::c800:0"
424 )