From 57584d99dd8a8524db90c67c88525d58879d9b8e Mon Sep 17 00:00:00 2001 From: Tetsuya Murakami Date: Thu, 9 Jan 2020 14:22:04 -0800 Subject: srv6-mobile: Type: feature Add new functions in SRv6 Mobile Plug-in GTP4.DT and GTP6.DT Signed-off-by: Tetsuya Murakami Change-Id: I573a0c27bd463dd56a4d11b940941b8a8c826e08 Signed-off-by: Tetsuya Murakami --- src/plugins/srv6-mobile/extra/README.md | 209 +++++---- src/plugins/srv6-mobile/extra/runner.py | 477 ++++++++++++++++++++- src/plugins/srv6-mobile/extra/runner_doc.md | 105 +++++ src/plugins/srv6-mobile/extra/topo-init.png | Bin 0 -> 121503 bytes src/plugins/srv6-mobile/extra/topo-test_gtp4d.png | Bin 0 -> 138014 bytes src/plugins/srv6-mobile/extra/topo-test_gtp6.png | Bin 0 -> 131731 bytes src/plugins/srv6-mobile/extra/topo-test_gtp6d.png | Bin 0 -> 127820 bytes .../srv6-mobile/extra/topo-test_gtp6ip6.png | Bin 0 -> 116633 bytes 8 files changed, 678 insertions(+), 113 deletions(-) create mode 100644 src/plugins/srv6-mobile/extra/runner_doc.md (limited to 'src/plugins/srv6-mobile/extra') diff --git a/src/plugins/srv6-mobile/extra/README.md b/src/plugins/srv6-mobile/extra/README.md index 3b24dea6fd6..ed6bb40f7ff 100644 --- a/src/plugins/srv6-mobile/extra/README.md +++ b/src/plugins/srv6-mobile/extra/README.md @@ -1,173 +1,168 @@ -# What's `runner.py` doing? +Test and Demonstrate SRv6 Mobile User Plane Plugin +======================== -## Common configurations -### VPP1 -``` -create host-interface name eth1 -set int ip addr host-eth1 A1::1/120 -set int state host-eth1 up -ip route add ::/0 via host-eth1 A1::2 -``` +## Getting started +To play with SRv6 Mobile User Plane on VPP, you need to install following packages: + docker + python3 + pip3 -### VPP2 + Python packages (use pip): + docker + scapy + jinja2 -``` -create host-interface name eth1 -set int ip addr host-eth1 A1::2/120 -create host-interface name eth2 -set int ip addr host-eth2 A2::1/120 -set int state host-eth1 up -set int state host-eth2 up -ip route add ::/0 via host-eth2 A2::2 -``` +### Quick-start -### VPP3 +1. Build up the docker container image as following: ``` -create host-interface name eth1 -set int ip addr host-eth1 A2::2/120 -create host-interface name eth2 -set int ip addr host-eth2 A3::1/120 -set int state host-eth1 up -set int state host-eth2 up -ip route add ::/0 via host-eth1 A2::1 -``` +$ git clone https://github.com/filvarga/srv6-mobile.git +$ cd ./srv6-mobile/src/plugins/srv6-mobile/extra +$ ./runner.py infra build -### VPP4 +$ docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +srv6m-image latest 577e786b7ec6 2 days ago 8GB +ubuntu 18.04 4c108a37151f 4 weeks ago 64.2MB ``` -create host-interface name eth1 -set int ip addr host-eth1 A3::2/120 -set int state host-eth1 up -ip route add ::/0 via host-eth1 A3::1 -``` +The runner script [runner.py](runner.py) has features to automate configurations and procedures for the test. -## Drop-in for GTP-U over IPv4 +2. Instantiate test Scenario -What's happened when you run `test tmap`: +Let's try following command to instantiate a topology: - $ ./runner.py test tmap +``` +$ ./runner.py infra start +``` +This command instantiates 4 VPP containers with following topology: -Setting up a virtual interface of packet generator: +![Topology Diagram](topo-init.png) + +You can check the instantiated docker instances with "docker ps". -#### VPP1 ``` -create packet-generator interface pg0 -set int mac address pg0 aa:bb:cc:dd:ee:01 -set int ip addr pg0 172.16.0.1/30 -set ip arp pg0 172.16.0.2/30 aa:bb:cc:dd:ee:02 +$ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +44cb98994500 srv6m-image "/bin/sh -c 'vpp -c …" About a minute ago Up About a minute hck-vpp-4 +6d65fff8aee9 srv6m-image "/bin/sh -c 'vpp -c …" About a minute ago Up About a minute hck-vpp-3 +ad123b516b24 srv6m-image "/bin/sh -c 'vpp -c …" About a minute ago Up About a minute hck-vpp-2 +5efed405b96a srv6m-image "/bin/sh -c 'vpp -c …" About a minute ago Up About a minute hck-vpp-1 + ``` -#### VPP4 +You can login to and configure each instantiated container. ``` -create packet-generator interface pg0 -set int mac address pg0 aa:bb:cc:dd:ee:11 -set int ip addr pg0 1.0.0.2/30 -set ip arp pg0 1.0.0.1 aa:bb:cc:dd:ee:22 +$ ./runner.py cmd vppctl 0 + +Verified image: None +connecting to: hck-vpp-1 + _______ _ _ _____ ___ + __/ __/ _ \ (_)__ | | / / _ \/ _ \ + _/ _// // / / / _ \ | |/ / ___/ ___/ + /_/ /____(_)_/\___/ |___/_/ /_/ + +vpp# ``` -SRv6 and IP routing settings: +## Test Scenarios +### SRv6 Drop-in between GTP-U tunnel -#### VPP1 +This test scenario introduces SRv6 path between GTP-U tunnel transparently. A GTP-U packet sent out from one end to another is translated to SRv6 and then back to GTP-U. All GTP-U tunnel identifiers are preserved in IPv6 header and SRH. -``` -sr policy add bsid D1:: next D2:: next D3:: gtp4_removal sr_prefix D4::/32 v6src_prefix C1::/64 -sr steer l3 172.20.0.1/32 via bsid D1:: -``` +#### GTP-U over UDP/IPv4 case + +This case uses SRv6 end functions, T.M.GTP4.D and End.M.GTP4.E. -#### VPP2 +![Topology Diagram](topo-test_gtp4d.png) + +VPP1 is configured with "T.M.GTP4.D", and VPP4 is configured with "End.M.GTP4.E". Others are configured with "End". The packet generator sends a GTP-U packet over UDP/IPv4 toward the packet capture. VPP1 translates it to SRv6 toward D4::TEID with SR policy in SRH. VPP4 translates the SRv6 packet to the original GTP-U packet and send out to the packet capture. + +To start this case with IPv4 payload over GTP-U, you can run: ``` -sr localsid address D2:: behavior end -ip route add D3::/128 via host-eth2 A2::2 +$ ./runner.py test gtp4 ``` -#### VPP3 +If you want to use IPv6 payload instead of IPv4, you can run: ``` -sr localsid address D3:: behavior end -ip route add D4::/32 via host-eth2 A3::2 +$ ./runner.py test gtp4_ipv6 ``` -#### VPP4 +If you use the latest scapy codes from the master branch, you can test the functions with GTP-U packet in 5G format: ``` -sr localsid prefix D4::/32 behavior end.m.gtp4.e v4src_position 64 -ip route add 172.20.0.1/32 via pg0 1.0.0.1 +$ ./runner.py test gtp4_5g ``` +#### GTP-U over UDP/IPv6 case -## Packet generator and testing +This case uses SRv6 end functions, End.M.GTP6.D.Di and End.M.GTP6.E. - Example how to build custom SRv6 packet in scapy and ipaddress pkgs +![Topology Diagram](topo-test_gtp6d.png) - s = '\x11' * 4 + IPv4Address(u"192.168.192.10").packed + '\x11' * 8 - ip6 = IPv6Address(s) - IPv6(dst=ip6, src=ip6) +VPP1 is configured with "End.M.GTP6.D.Di", and VPP4 is configured with "End.M.GTP4.E". Others are configured with "End". The packet generator sends a GTP-U packet over UDP/IPv6 toward D:: of the packet capture. VPP1 translates it to SRv6 toward D:: with SR policy in SRH. VPP4 translates the SRv6 packet to the original GTP-U packet and send out to the packet capture. +To start this case with IPv4 payload over GTP-U, you can run: -## end.m.gtp4.e +``` +$ ./runner.py test gtp6_drop_in +``` - First set behavior so our localsid node is called with the packet - matching C1::1 in fib table - sr localsid address C1::1 behavior end.m.gtp4.ess +If you want to use IPv6 payload instead of IPv4, you can run: - show sr localsids behaviors - show sr localsid +``` +$ ./runner.py test gtp6_drop_in_ipv6 +``` - We should send a well formated packet to C::1 destination address - that contains the correct spec as for end.m.gtp4.e with encapsulated - ipv4 src and dst address and teid with port for the conversion to - GTPU IPv4 packet +### GTP-U to SRv6 -## additional commands +This test scenario demonstrates GTP-U to SRv6 translation. A GTP-U packet sent out from one end to another is translated to SRv6. - gdb - breakpoint +#### GTP-U over UDP/IPv6 case - break sr_policy_rewrite.c:1620 +##### IPv4 payload - break src/plugins/srv6-end/node.c:84 +This case uses SRv6 end functions, End.M.GTP6.D and End.DT4. - TMAP - Linux: +![Topology Diagram](topo-test_gtp6.png) - ip link add tmp1 type veth peer name tmp2 - ip link set dev tmp1 up - ip link set dev tmp2 up - ip addr add 172.20.0.2/24 dev tmp2 +VPP1 is configured with "End.M.GTP6.D", and VPP4 is configured with "End.DT4". Others are configured with "End". The packet generator sends a GTP-U packet over UDP/IPv6 toward D::2. VPP1 translates it to SRv6 toward the IPv6 destination consists of D4:: and TEID of GTP-U with SR policy in SRH. VPP4 decapsulates the SRv6 packet and lookup the table for the inner IPv4 packet and send out to the packet capture. - create host-interface name tmp1 - set int mac address host-tmp1 02:fe:98:c6:c8:7b - set interface ip address host-tmp1 172.20.0.1/24 - set interface state host-tmp1 up +To start this case, you can run: - VPP - set sr encaps source addr C1:: - sr policy add bsid D1::999:2 next D2:: next D3:: gtp4_removal sr-prefix fc34:5678::/64 local-prefix C1::/64 - sr steer l3 172.21.0.0/24 via bsid d1::999:2 +``` +$ ./runner.py test gtp6 +``` - END - Linux - create host-interface name tmp1 - set int mac address host-tmp1 02:fe:98:c6:c8:7b - set interface ip address host-tmp1 A1::1/64 - set interface state host-tmp1 up +##### IPv6 payload - VPP - sr localsid address 1111:1111:c0a8:c00a:1122:1111:1111:1111 behavior end.m.gtp4.e +This case uses SRv6 end functions, End.M.GTP6.D and End.DT6. + + +![Topology Diagram](topo-test_gtp6ip6.png) + +The configurations are same with IPv4 payload case, except D4:: is configured as "End.DT6" in VPP4. VPP4 decapsulates the SRv6 packet and lookup the table for the inner IPv6 packet and send out to the packet capture. + +If you want to use IPv6 payload instead of IPv4, you can run: + +``` +$ ./runner.py test gtp6_ipv6 +``` - trace add af-packet-input 10 +## More information - sr localsid address C3:: behavior end.m.gtp4.e - sr localsid address 2001:200:0:1ce1:3000:757f:0:2 behavior end.m.gtp4.e +- @subpage runner_doc.md diff --git a/src/plugins/srv6-mobile/extra/runner.py b/src/plugins/srv6-mobile/extra/runner.py index 79ec2d007c5..c438fb161b7 100755 --- a/src/plugins/srv6-mobile/extra/runner.py +++ b/src/plugins/srv6-mobile/extra/runner.py @@ -135,7 +135,7 @@ class Container(object): self.vppctl_exec("set int mac address pg0 {}".format(local_mac)) self.vppctl_exec("set int ip addr pg0 {}".format(local_ip)) self.vppctl_exec( - "set ip6 neighbor pg0 {} {}".format(remote_ip, remote_mac)) + "set ip neighbor pg0 {} {}".format(remote_ip, remote_mac)) self.vppctl_exec("set int state pg0 up") def pg_create_interface4(self, local_ip, remote_ip, local_mac, remote_mac): @@ -145,7 +145,7 @@ class Container(object): self.vppctl_exec("create packet-generator interface pg0") self.vppctl_exec("set int mac address pg0 {}".format(local_mac)) self.vppctl_exec("set int ip addr pg0 {}".format(local_ip)) - self.vppctl_exec("set ip arp pg0 {} {}".format(remote_ip, remote_mac)) + self.vppctl_exec("set ip neighbor pg0 {} {}".format(remote_ip, remote_mac)) self.vppctl_exec("set int state pg0 up") def pg_create_interface6(self, local_ip, remote_ip, local_mac, remote_mac): @@ -154,10 +154,30 @@ class Container(object): time.sleep(2) self.vppctl_exec("create packet-generator interface pg0") self.vppctl_exec("set int mac address pg0 {}".format(local_mac)) - self.vppctl_exec("set int ip6 addr pg0 {}".format(local_ip)) - self.vppctl_exec("set ip6 arp pg0 {} {}".format(remote_ip, remote_mac)) + self.vppctl_exec("set int ip addr pg0 {}".format(local_ip)) + self.vppctl_exec("set ip neighbor pg0 {} {}".format(remote_ip, remote_mac)) self.vppctl_exec("set int state pg0 up") + def pg_create_interface4_name(self, ifname, local_ip, remote_ip, local_mac, remote_mac): + # remote_ip can't have subnet mask + + time.sleep(2) + self.vppctl_exec("create packet-generator interface {}".format(ifname)) + self.vppctl_exec("set int mac address {} {}".format(ifname, local_mac)) + self.vppctl_exec("set int ip addr {} {}".format(ifname, local_ip)) + self.vppctl_exec("set ip neighbor {} {} {}".format(ifname, remote_ip, remote_mac)) + self.vppctl_exec("set int state {} up".format(ifname)) + + def pg_create_interface6_name(self, ifname, local_ip, remote_ip, local_mac, remote_mac): + # remote_ip can't have subnet mask + + time.sleep(2) + self.vppctl_exec("create packet-generator interface {}".format(ifname)) + self.vppctl_exec("set int mac address {} {}".format(ifname, local_mac)) + self.vppctl_exec("set int ip addr {} {}".format(ifname, local_ip)) + self.vppctl_exec("set ip neighbor {} {} {}".format(ifname, remote_ip, remote_mac)) + self.vppctl_exec("set int state {} up".format(ifname)) + def pg_enable(self): # start packet generator self.vppctl_exec("packet-generator enable") @@ -176,6 +196,13 @@ class Container(object): "packet-generator capture pg0 pcap {}".format( self.pg_output_file_in)) + def pg_start_capture_name(self, ifname): + if exists(self.pg_output_file): + remove(self.pg_output_file) + self.vppctl_exec( + "packet-generator capture {} pcap {}".format( + ifname, self.pg_output_file_in)) + def pg_read_packets(self): return rdpcap(self.pg_output_file) @@ -184,6 +211,11 @@ class Container(object): "ip route add {} via host-{} {}".format( subnet, out_if_name, next_hop_ip)) + def set_ipv6_route2(self, out_if_name, next_hop_ip, subnet): + self.vppctl_exec( + "ip route add {} via {} {}".format( + subnet, out_if_name, next_hop_ip)) + def set_ip_pgroute(self, out_if_name, next_hop_ip, subnet): self.vppctl_exec("ip route add {} via {} {}".format( subnet, out_if_name, next_hop_ip)) @@ -1089,6 +1121,142 @@ class Program(object): for p in c4.pg_read_packets(): p.show2() + def test_gtp4_reply(self): + # TESTS: + # trace add af-packet-input 10 + # pg interface on c1 172.20.0.1 + # pg interface on c4 B::1/120 + + self.start_containers() + + c1 = self.containers.get(self.get_name(self.instance_names[0])) + c2 = self.containers.get(self.get_name(self.instance_names[1])) + c3 = self.containers.get(self.get_name(self.instance_names[2])) + c4 = self.containers.get(self.get_name(self.instance_names[-1])) + + c1.pg_create_interface4( + local_ip="172.16.0.1/30", + remote_ip="172.16.0.2/30", + local_mac="aa:bb:cc:dd:ee:01", + remote_mac="aa:bb:cc:dd:ee:02") + c4.pg_create_interface4( + local_ip="1.0.0.2/30", + remote_ip="1.0.0.1", + local_mac="aa:bb:cc:dd:ee:11", + remote_mac="aa:bb:cc:dd:ee:22") + + c1.vppctl_exec("set sr encaps source addr A1::1") + c1.vppctl_exec("sr policy add bsid D4:: next D2:: next D3::") + c1.vppctl_exec("sr policy add bsid D5:: behavior t.m.gtp4.d D4::/32 v6src_prefix C1::/64 nhtype ipv4") + c1.vppctl_exec("sr steer l3 172.20.0.1/32 via bsid D5::") + + c2.vppctl_exec("sr localsid address D2:: behavior end") + + c3.vppctl_exec("sr localsid address D3:: behavior end") + + c4.vppctl_exec( + "sr localsid prefix D4::/32 " + "behavior end.m.gtp4.e v4src_position 64") + + c2.set_ipv6_route("eth2", "A2::2", "D3::/128") + c2.set_ipv6_route("eth1", "A1::1", "C::/120") + c3.set_ipv6_route("eth2", "A3::2", "D4::/32") + c3.set_ipv6_route("eth1", "A2::1", "C::/120") + c4.set_ip_pgroute("pg0", "1.0.0.1", "172.20.0.1/32") + + p = (Ether(src="aa:bb:cc:dd:ee:02", dst="aa:bb:cc:dd:ee:01") / + IP(src="172.20.0.2", dst="172.20.0.1") / + UDP(sport=2152, dport=2152) / + GTP_U_Header(gtp_type="echo_response", S=1, teid=200, seq=200)) + + print("Sending packet on {}:".format(c1.name)) + p.show2() + + c1.enable_trace(10) + c4.enable_trace(10) + + c4.pg_start_capture() + + c1.pg_create_stream(p) + c1.pg_enable() + + # timeout (sleep) if needed + print("Sleeping") + time.sleep(5) + + print("Receiving packet on {}:".format(c4.name)) + for p in c4.pg_read_packets(): + p.show2() + + def test_gtp4_error(self): + # TESTS: + # trace add af-packet-input 10 + # pg interface on c1 172.20.0.1 + # pg interface on c4 B::1/120 + + self.start_containers() + + c1 = self.containers.get(self.get_name(self.instance_names[0])) + c2 = self.containers.get(self.get_name(self.instance_names[1])) + c3 = self.containers.get(self.get_name(self.instance_names[2])) + c4 = self.containers.get(self.get_name(self.instance_names[-1])) + + c1.pg_create_interface4( + local_ip="172.16.0.1/30", + remote_ip="172.16.0.2/30", + local_mac="aa:bb:cc:dd:ee:01", + remote_mac="aa:bb:cc:dd:ee:02") + c4.pg_create_interface4( + local_ip="1.0.0.2/30", + remote_ip="1.0.0.1", + local_mac="aa:bb:cc:dd:ee:11", + remote_mac="aa:bb:cc:dd:ee:22") + + c1.vppctl_exec("set sr encaps source addr A1::1") + c1.vppctl_exec("sr policy add bsid D4:: next D2:: next D3::") + c1.vppctl_exec("sr policy add bsid D5:: behavior t.m.gtp4.d D4::/32 v6src_prefix C1::/64 nhtype ipv4") + c1.vppctl_exec("sr steer l3 172.20.0.1/32 via bsid D5::") + + c2.vppctl_exec("sr localsid address D2:: behavior end") + + c3.vppctl_exec("sr localsid address D3:: behavior end") + + c4.vppctl_exec( + "sr localsid prefix D4::/32 " + "behavior end.m.gtp4.e v4src_position 64") + + c2.set_ipv6_route("eth2", "A2::2", "D3::/128") + c2.set_ipv6_route("eth1", "A1::1", "C::/120") + c3.set_ipv6_route("eth2", "A3::2", "D4::/32") + c3.set_ipv6_route("eth1", "A2::1", "C::/120") + c4.set_ip_pgroute("pg0", "1.0.0.1", "172.20.0.1/32") + + p = (Ether(src="aa:bb:cc:dd:ee:02", dst="aa:bb:cc:dd:ee:01") / + IP(src="172.20.0.2", dst="172.20.0.1") / + UDP(sport=2152, dport=2152) / + GTP_U_Header(gtp_type="error_indication", S=1, teid=200, seq=200)/ + IE_TEIDI(TEIDI=65535)/IE_GSNAddress(address="1.1.1.1")/ + IE_PrivateExtension(extention_value="z")) + + print("Sending packet on {}:".format(c1.name)) + p.show2() + + c1.enable_trace(10) + c4.enable_trace(10) + + c4.pg_start_capture() + + c1.pg_create_stream(p) + c1.pg_enable() + + # timeout (sleep) if needed + print("Sleeping") + time.sleep(5) + + print("Receiving packet on {}:".format(c4.name)) + for p in c4.pg_read_packets(): + p.show2() + def test_gtp4_ipv6(self): # TESTS: # trace add af-packet-input 10 @@ -1452,6 +1620,154 @@ class Program(object): for p in c4.pg_read_packets(): p.show2() + def test_gtp6_drop_in_reply(self): + # TESTS: + # trace add af-packet-input 10 + # pg interface on c1 172.20.0.1 + # pg interface on c4 B::1/120 + + self.start_containers() + + print("Deleting the old containers...") + time.sleep(30) + print("Starting the new containers...") + + c1 = self.containers.get(self.get_name(self.instance_names[0])) + c2 = self.containers.get(self.get_name(self.instance_names[1])) + c3 = self.containers.get(self.get_name(self.instance_names[2])) + c4 = self.containers.get(self.get_name(self.instance_names[-1])) + + c1.pg_create_interface( + local_ip="C::1/120", + remote_ip="C::2", + local_mac="aa:bb:cc:dd:ee:01", + remote_mac="aa:bb:cc:dd:ee:02") + c4.pg_create_interface( + local_ip="B::1/120", + remote_ip="B::2", + local_mac="aa:bb:cc:dd:ee:11", + remote_mac="aa:bb:cc:dd:ee:22") + + c1.vppctl_exec("set sr encaps source addr A1::1") + c1.vppctl_exec("sr policy add bsid D4:: next D2:: next D3::") + + c1.vppctl_exec( + "sr localsid prefix D::/64 behavior end.m.gtp6.d.di D4::/64") + + c2.vppctl_exec("sr localsid address D2:: behavior end") + + c3.vppctl_exec("sr localsid address D3:: behavior end") + + c4.vppctl_exec("sr localsid prefix D4::/64 behavior end.m.gtp6.e") + + c2.set_ipv6_route("eth2", "A2::2", "D3::/128") + c2.set_ipv6_route("eth1", "A1::1", "C::/120") + c3.set_ipv6_route("eth2", "A3::2", "D4::/32") + c3.set_ipv6_route("eth1", "A2::1", "C::/120") + c4.set_ip_pgroute("pg0", "B::2", "D::2/128") + + print("Waiting...") + time.sleep(30) + + p = (Ether(src="aa:bb:cc:dd:ee:02", dst="aa:bb:cc:dd:ee:01") / + IPv6(src="C::2", dst="D::2") / + UDP(sport=2152, dport=2152) / + GTP_U_Header(gtp_type="echo_response", S=1, teid=200, seq=300)) + + print("Sending packet on {}:".format(c1.name)) + p.show2() + + c1.enable_trace(10) + c4.enable_trace(10) + + c4.pg_start_capture() + + c1.pg_create_stream(p) + c1.pg_enable() + + # timeout (sleep) if needed + print("Sleeping") + time.sleep(5) + + print("Receiving packet on {}:".format(c4.name)) + for p in c4.pg_read_packets(): + p.show2() + + def test_gtp6_drop_in_error(self): + # TESTS: + # trace add af-packet-input 10 + # pg interface on c1 172.20.0.1 + # pg interface on c4 B::1/120 + + self.start_containers() + + print("Deleting the old containers...") + time.sleep(30) + print("Starting the new containers...") + + c1 = self.containers.get(self.get_name(self.instance_names[0])) + c2 = self.containers.get(self.get_name(self.instance_names[1])) + c3 = self.containers.get(self.get_name(self.instance_names[2])) + c4 = self.containers.get(self.get_name(self.instance_names[-1])) + + c1.pg_create_interface( + local_ip="C::1/120", + remote_ip="C::2", + local_mac="aa:bb:cc:dd:ee:01", + remote_mac="aa:bb:cc:dd:ee:02") + c4.pg_create_interface( + local_ip="B::1/120", + remote_ip="B::2", + local_mac="aa:bb:cc:dd:ee:11", + remote_mac="aa:bb:cc:dd:ee:22") + + c1.vppctl_exec("set sr encaps source addr A1::1") + c1.vppctl_exec("sr policy add bsid D4:: next D2:: next D3::") + + c1.vppctl_exec( + "sr localsid prefix D::/64 behavior end.m.gtp6.d.di D4::/64") + + c2.vppctl_exec("sr localsid address D2:: behavior end") + + c3.vppctl_exec("sr localsid address D3:: behavior end") + + c4.vppctl_exec("sr localsid prefix D4::/64 behavior end.m.gtp6.e") + + c2.set_ipv6_route("eth2", "A2::2", "D3::/128") + c2.set_ipv6_route("eth1", "A1::1", "C::/120") + c3.set_ipv6_route("eth2", "A3::2", "D4::/32") + c3.set_ipv6_route("eth1", "A2::1", "C::/120") + c4.set_ip_pgroute("pg0", "B::2", "D::2/128") + + print("Waiting...") + time.sleep(30) + + p = (Ether(src="aa:bb:cc:dd:ee:02", dst="aa:bb:cc:dd:ee:01") / + IPv6(src="C::2", dst="D::2") / + UDP(sport=2152, dport=2152) / + GTP_U_Header(gtp_type="error_indication", S=1, teid=200, seq=300)/ + IE_TEIDI(TEIDI=65535)/IE_GSNAddress(address="1.1.1.1")/ + IE_PrivateExtension(extention_value="z")) + + print("Sending packet on {}:".format(c1.name)) + p.show2() + + c1.enable_trace(10) + c4.enable_trace(10) + + c4.pg_start_capture() + + c1.pg_create_stream(p) + c1.pg_enable() + + # timeout (sleep) if needed + print("Sleeping") + time.sleep(5) + + print("Receiving packet on {}:".format(c4.name)) + for p in c4.pg_read_packets(): + p.show2() + def test_gtp6_drop_in_ipv6(self): # TESTS: # trace add af-packet-input 10 @@ -1641,6 +1957,7 @@ class Program(object): c3.vppctl_exec("sr localsid address D3:: behavior end") + c4.vppctl_exec("set ip neighbor pg0 1.0.0.1 aa:bb:cc:dd:ee:22") c4.vppctl_exec("sr localsid prefix D4::/64 behavior end.dt4 2") c2.set_ipv6_route("eth2", "A2::2", "D3::/128") @@ -1716,6 +2033,7 @@ class Program(object): c3.vppctl_exec("sr localsid address D3:: behavior end") + c4.vppctl_exec("set ip neighbor pg0 1.0.0.1 aa:bb:cc:dd:ee:22") c4.vppctl_exec("sr localsid prefix D4::/64 behavior end.dt4 2") c2.set_ipv6_route("eth2", "A2::2", "D3::/128") @@ -1792,6 +2110,7 @@ class Program(object): c3.vppctl_exec("sr localsid address D3:: behavior end") + c4.vppctl_exec("set ip neighbor pg0 B::2 aa:bb:cc:dd:ee:22") c4.vppctl_exec("sr localsid prefix D4::/64 behavior end.dt6 2") c2.set_ipv6_route("eth2", "A2::2", "D3::/128") @@ -1867,6 +2186,7 @@ class Program(object): c3.vppctl_exec("sr localsid address D3:: behavior end") + c4.vppctl_exec("set ip neighbor pg0 B::2 aa:bb:cc:dd:ee:22") c4.vppctl_exec("sr localsid prefix D4::/64 behavior end.dt6 2") c2.set_ipv6_route("eth2", "A2::2", "D3::/128") @@ -1905,6 +2225,133 @@ class Program(object): for p in c4.pg_read_packets(): p.show2() + def test_gtp6_dt(self): + # TESTS: + # trace add af-packet-input 10 + # pg interface on c1 172.20.0.1 + # pg interface on c4 B::1/120 + + self.start_containers() + + print("Deleting the old containers...") + time.sleep(30) + print("Starting the new containers...") + + c1 = self.containers.get(self.get_name(self.instance_names[0])) + + c1.pg_create_interface6_name( + ifname="pg0", + local_ip="C::1/120", + remote_ip="C::2", + local_mac="aa:bb:cc:dd:ee:01", + remote_mac="aa:bb:cc:dd:ee:02") + + c1.pg_create_interface4_name( + ifname="pg1", + local_ip="1.0.0.2/30", + remote_ip="1.0.0.1", + local_mac="aa:bb:cc:dd:ee:11", + remote_mac="aa:bb:cc:dd:ee:22") + + c1.vppctl_exec("set sr encaps source addr A1::1") + + c1.vppctl_exec( + "sr localsid prefix D::/64 behavior end.m.gtp6.dt46 fib-table 0 local-fib-table 0") + + c1.vppctl_exec("set ip neighbor pg1 1.0.0.1 aa:bb:cc:dd:ee:22") + c1.set_ip_pgroute("pg1", "1.0.0.1", "172.200.0.1/32") + + print("Waiting...") + time.sleep(30) + + p = (Ether(src="aa:bb:cc:dd:ee:02", dst="aa:bb:cc:dd:ee:01") / + IPv6(src="C::2", dst="D::2") / + UDP(sport=2152, dport=2152) / + GTP_U_Header(gtp_type="g_pdu", teid=200) / + IP(src="172.100.0.1", dst="172.200.0.1") / + ICMP()) + + print("Sending packet on {}:".format(c1.name)) + p.show2() + + c1.enable_trace(10) + + c1.pg_start_capture_name(ifname="pg1") + + c1.pg_create_stream(p) + c1.pg_enable() + + # timeout (sleep) if needed + print("Sleeping") + time.sleep(5) + + print("Receiving packet on {}:".format(c1.name)) + for p in c1.pg_read_packets(): + p.show2() + + def test_gtp4_dt(self): + # TESTS: + # trace add af-packet-input 10 + # pg interface on c1 172.20.0.1 + # pg interface on c4 B::1/120 + + self.start_containers() + + print("Deleting the old containers...") + time.sleep(30) + print("Starting the new containers...") + + c1 = self.containers.get(self.get_name(self.instance_names[0])) + + c1.pg_create_interface4_name( + ifname="pg0", + local_ip="172.16.0.1/30", + remote_ip="172.16.0.2", + local_mac="aa:bb:cc:dd:ee:01", + remote_mac="aa:bb:cc:dd:ee:02") + + c1.pg_create_interface4_name( + ifname="pg1", + local_ip="1.0.0.2/30", + remote_ip="1.0.0.1", + local_mac="aa:bb:cc:dd:ee:11", + remote_mac="aa:bb:cc:dd:ee:22") + + c1.vppctl_exec("set sr encaps source addr A1::1") + c1.vppctl_exec("sr policy add bsid D5:: behavior t.m.gtp4.dt4 fib-table 0") + c1.vppctl_exec("sr steer l3 172.20.0.1/32 via bsid D5::") + + c1.vppctl_exec("set ip neighbor pg1 1.0.0.1 aa:bb:cc:dd:ee:22") + c1.set_ip_pgroute("pg1", "1.0.0.1", "172.200.0.1/32") + + print("Waiting...") + time.sleep(30) + + p = (Ether(src="aa:bb:cc:dd:ee:02", dst="aa:bb:cc:dd:ee:01") / + IP(src="172.20.0.2", dst="172.20.0.1") / + UDP(sport=2152, dport=2152) / + GTP_U_Header(gtp_type="g_pdu", teid=200) / + IP(src="172.100.0.1", dst="172.200.0.1") / + ICMP()) + + print("Sending packet on {}:".format(c1.name)) + p.show2() + + c1.enable_trace(10) + + c1.pg_start_capture_name(ifname="pg1") + + c1.pg_create_stream(p) + c1.pg_enable() + + # timeout (sleep) if needed + print("Sleeping") + time.sleep(5) + + print("Receiving packet on {}:".format(c1.name)) + for p in c1.pg_read_packets(): + p.show2() + def status_containers(self): print("Instances:") @@ -2008,17 +2455,23 @@ def get_args(): "gtp4_usid", "gtp4_5g", "gtp4_echo", + "gtp4_reply", + "gtp4_error", "gtp4_ipv6", "gtp4_ipv6_5g", "gtp6_drop_in", "gtp6_drop_in_5g", "gtp6_drop_in_echo", + "gtp6_drop_in_reply", + "gtp6_drop_in_error", "gtp6_drop_in_ipv6", "gtp6_drop_in_ipv6_5g", "gtp6", "gtp6_5g", "gtp6_ipv6", - "gtp6_ipv6_5g"]) + "gtp6_ipv6_5g", + "gtp6_dt", + "gtp4_dt"]) args = parser.parse_args() if not hasattr(args, "op") or not args.op: @@ -2038,7 +2491,7 @@ def main(op=None, prefix=None, verbose=None, image = "srv6m-release-image" elif image == 'debug': image = "srv6m-image" - else + else: image = "srv6m-image" print("Target image: {}".format(image)) @@ -2080,6 +2533,10 @@ def main(op=None, prefix=None, verbose=None, program.test_gtp4_5g() elif op == 'gtp4_echo': program.test_gtp4_echo() + elif op == 'gtp4_reply': + program.test_gtp4_reply() + elif op == 'gtp4_error': + program.test_gtp4_error() elif op == 'gtp4_ipv6': program.test_gtp4_ipv6() elif op == 'gtp4_ipv6_5g': @@ -2090,6 +2547,10 @@ def main(op=None, prefix=None, verbose=None, program.test_gtp6_drop_in_5g() elif op == 'gtp6_drop_in_echo': program.test_gtp6_drop_in_echo() + elif op == 'gtp6_drop_in_reply': + program.test_gtp6_drop_in_reply() + elif op == 'gtp6_drop_in_error': + program.test_gtp6_drop_in_error() elif op == 'gtp6_drop_in_ipv6': program.test_gtp6_drop_in_ipv6() elif op == 'gtp6_drop_in_ipv6_5g': @@ -2102,6 +2563,10 @@ def main(op=None, prefix=None, verbose=None, program.test_gtp6_ipv6() elif op == 'gtp6_ipv6_5g': program.test_gtp6_ipv6_5g() + elif op == 'gtp6_dt': + program.test_gtp6_dt() + elif op == 'gtp4_dt': + program.test_gtp4_dt() except Exception: program.logger.exception("") diff --git a/src/plugins/srv6-mobile/extra/runner_doc.md b/src/plugins/srv6-mobile/extra/runner_doc.md new file mode 100644 index 00000000000..a6fb0277378 --- /dev/null +++ b/src/plugins/srv6-mobile/extra/runner_doc.md @@ -0,0 +1,105 @@ +# What's `runner.py` doing? + +## Common configurations + +### VPP1 +``` +create host-interface name eth1 +set int ip addr host-eth1 A1::1/120 +set int state host-eth1 up +ip route add ::/0 via host-eth1 A1::2 +``` + + +### VPP2 + +``` +create host-interface name eth1 +set int ip addr host-eth1 A1::2/120 +create host-interface name eth2 +set int ip addr host-eth2 A2::1/120 +set int state host-eth1 up +set int state host-eth2 up +ip route add ::/0 via host-eth2 A2::2 +``` + + +### VPP3 + +``` +create host-interface name eth1 +set int ip addr host-eth1 A2::2/120 +create host-interface name eth2 +set int ip addr host-eth2 A3::1/120 +set int state host-eth1 up +set int state host-eth2 up +ip route add ::/0 via host-eth1 A2::1 +``` + +### VPP4 + +``` +create host-interface name eth1 +set int ip addr host-eth1 A3::2/120 +set int state host-eth1 up +ip route add ::/0 via host-eth1 A3::1 +``` + + +## Drop-in for GTP-U over IPv4 + +Drop-in mode is handy to test both GTP-U-to-SRv6 and SRv6-to-GTP-U functions at same time. Let's see what's happened when you run `test gtp4`: + + $ ./runner.py test gtp4 + + +Setting up a virtual interface of packet generator: + +#### VPP1 + +``` +create packet-generator interface pg0 +set int mac address pg0 aa:bb:cc:dd:ee:01 +set int ip addr pg0 172.16.0.1/30 +set ip arp pg0 172.16.0.2/30 aa:bb:cc:dd:ee:02 +``` + +#### VPP4 + +``` +create packet-generator interface pg0 +set int mac address pg0 aa:bb:cc:dd:ee:11 +set int ip addr pg0 1.0.0.2/30 +set ip arp pg0 1.0.0.1 aa:bb:cc:dd:ee:22 +``` + +SRv6 and IP routing settings: + +#### VPP1 + +``` +sr policy add bsid D4:: next D2:: next D3:: +sr policy add bsid D5:: behavior t.m.gtp4.d D4::/32 v6src_prefix C1::/64 nhtype ipv4 +sr steer l3 172.20.0.1/32 via bsid D5:: +``` + +#### VPP2 + +``` +sr localsid address D2:: behavior end +ip route add D3::/128 via host-eth2 A2::2 +``` + +#### VPP3 + +``` +sr localsid address D3:: behavior end +ip route add D4::/32 via host-eth2 A3::2 +``` + +#### VPP4 + +``` +sr localsid prefix D4::/32 behavior end.m.gtp4.e v4src_position 64 +ip route add 172.20.0.1/32 via pg0 1.0.0.1 +``` diff --git a/src/plugins/srv6-mobile/extra/topo-init.png b/src/plugins/srv6-mobile/extra/topo-init.png index e69de29bb2d..dc9603ba290 100644 Binary files a/src/plugins/srv6-mobile/extra/topo-init.png and b/src/plugins/srv6-mobile/extra/topo-init.png differ diff --git a/src/plugins/srv6-mobile/extra/topo-test_gtp4d.png b/src/plugins/srv6-mobile/extra/topo-test_gtp4d.png index e69de29bb2d..d60beb23093 100644 Binary files a/src/plugins/srv6-mobile/extra/topo-test_gtp4d.png and b/src/plugins/srv6-mobile/extra/topo-test_gtp4d.png differ diff --git a/src/plugins/srv6-mobile/extra/topo-test_gtp6.png b/src/plugins/srv6-mobile/extra/topo-test_gtp6.png index e69de29bb2d..2cad260215a 100644 Binary files a/src/plugins/srv6-mobile/extra/topo-test_gtp6.png and b/src/plugins/srv6-mobile/extra/topo-test_gtp6.png differ diff --git a/src/plugins/srv6-mobile/extra/topo-test_gtp6d.png b/src/plugins/srv6-mobile/extra/topo-test_gtp6d.png index e69de29bb2d..78b083daa8a 100644 Binary files a/src/plugins/srv6-mobile/extra/topo-test_gtp6d.png and b/src/plugins/srv6-mobile/extra/topo-test_gtp6d.png differ diff --git a/src/plugins/srv6-mobile/extra/topo-test_gtp6ip6.png b/src/plugins/srv6-mobile/extra/topo-test_gtp6ip6.png index e69de29bb2d..fe78f673787 100644 Binary files a/src/plugins/srv6-mobile/extra/topo-test_gtp6ip6.png and b/src/plugins/srv6-mobile/extra/topo-test_gtp6ip6.png differ -- cgit 1.2.3-korg