From 79639b4b88ae06ecce2d127e96c973bd76d5be31 Mon Sep 17 00:00:00 2001 From: Aleksandr Stepanov Date: Sun, 22 Dec 2024 15:10:09 +0300 Subject: [PATCH] Added autotests for vrf --- .../078_vrf_route/001-expect.pcap | Bin 0 -> 912 bytes .../001_one_port/078_vrf_route/001-send.pcap | Bin 0 -> 1060 bytes .../078_vrf_route/002-expect.pcap | Bin 0 -> 1152 bytes .../001_one_port/078_vrf_route/002-send.pcap | Bin 0 -> 1340 bytes .../078_vrf_route/003-expect.pcap | Bin 0 -> 838 bytes .../001_one_port/078_vrf_route/003-send.pcap | Bin 0 -> 1060 bytes .../078_vrf_route/004-expect.pcap | Bin 0 -> 1058 bytes .../001_one_port/078_vrf_route/004-send.pcap | Bin 0 -> 1340 bytes .../001_one_port/078_vrf_route/autotest.yaml | 68 +++++++ .../078_vrf_route/controlplane.conf | 67 +++++++ .../units/001_one_port/078_vrf_route/gen.py | 174 ++++++++++++++++++ .../001-expect.pcap | Bin 0 -> 284184 bytes .../078_vrf_route_nat64stateful/001-send.pcap | Bin 0 -> 360984 bytes .../002-expect.pcap | Bin 0 -> 72216 bytes .../078_vrf_route_nat64stateful/002-send.pcap | Bin 0 -> 56856 bytes .../003-expect.pcap | Bin 0 -> 227352 bytes .../078_vrf_route_nat64stateful/003-send.pcap | Bin 0 -> 288792 bytes .../078_vrf_route_nat64stateful/autotest.yaml | 23 +++ .../controlplane.conf | 82 +++++++++ .../078_vrf_route_nat64stateful/gen.py | 78 ++++++++ .../078_vrf_route_tunnel/001-expect.pcap | Bin 0 -> 870 bytes .../078_vrf_route_tunnel/001-send.pcap | Bin 0 -> 942 bytes .../078_vrf_route_tunnel/002-expect.pcap | Bin 0 -> 1338 bytes .../078_vrf_route_tunnel/002-send.pcap | Bin 0 -> 1230 bytes .../078_vrf_route_tunnel/autotest.yaml | 159 ++++++++++++++++ .../078_vrf_route_tunnel/controlplane.conf | 61 ++++++ .../001_one_port/078_vrf_route_tunnel/gen.py | 115 ++++++++++++ 27 files changed, 827 insertions(+) create mode 100644 autotest/units/001_one_port/078_vrf_route/001-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/001-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/002-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/002-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/003-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/003-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/004-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/004-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route/autotest.yaml create mode 100644 autotest/units/001_one_port/078_vrf_route/controlplane.conf create mode 100755 autotest/units/001_one_port/078_vrf_route/gen.py create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/001-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/001-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/002-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/002-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/003-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/003-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/autotest.yaml create mode 100644 autotest/units/001_one_port/078_vrf_route_nat64stateful/controlplane.conf create mode 100755 autotest/units/001_one_port/078_vrf_route_nat64stateful/gen.py create mode 100644 autotest/units/001_one_port/078_vrf_route_tunnel/001-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_tunnel/001-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_tunnel/002-expect.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_tunnel/002-send.pcap create mode 100644 autotest/units/001_one_port/078_vrf_route_tunnel/autotest.yaml create mode 100644 autotest/units/001_one_port/078_vrf_route_tunnel/controlplane.conf create mode 100755 autotest/units/001_one_port/078_vrf_route_tunnel/gen.py diff --git a/autotest/units/001_one_port/078_vrf_route/001-expect.pcap b/autotest/units/001_one_port/078_vrf_route/001-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..140b2de71fd6d847e22b5ceda8ad1e32c4b541fd GIT binary patch literal 912 zcmca|c+)~A1{MYw`2U}Qff2?5(pFFmq?DAD7zCA!T|yff7*237xH2$kfRx&^?G?NS z1VAPug9t+aOmhH}0>gy^Fdm9YE-o%GlNcu;o3saP5)&4a&SN)8P*4zN5gy^FdlIx?FO5~gvF%uB$~7fY!WjTlg<$~=>*k$hhh>%zC$sI z65lcEP|J6yCQ;%$RFf$3-2|%n4%H+^Xc`y9NaGs_rEx|SlXm}wnk0&0(i##?q9C`R Jx(R=X0{}%Nl79dI literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route/002-expect.pcap b/autotest/units/001_one_port/078_vrf_route/002-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..193d8e5b760cfc304d08306b83d95ceb39bcc5e4 GIT binary patch literal 1152 zcmca|c+)~A1{MYw`2U}Qff2?5(tc13q?DAD7zCA!T|yff7*4d^O#liph_KlMMUjA# zQXR5(kYOSW0WbvtObQHVEnqwp(_LI#V5T!pz+*ZSLN}0wX}UQ=9?9*3f`Ty98B*|= z&WzBF)pRq2Jd)|7A;WMMd&m$Q?&PHzV#A%hG-GUR3`;YNI#f?H#HM#x$Utanr+1j? ZkYtT%I`+IuY`CME4lFIuN&-s;1^^1pW+eas literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route/002-send.pcap b/autotest/units/001_one_port/078_vrf_route/002-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..16f3b350bd49ce18b93177dfce6afcffbf55246e GIT binary patch literal 1340 zcmca|c+)~A1{MYw`2U}Qff2?5(tc3PAgE;Q5(?x93JNwdFr>8IO#pHjMA#gZlt2s^ zP*SQx)($dEgdqSX8^EN%aMl9GBg=Fqgl-@U({yu$JQ;3hM(DGKt#wuaupfrosk&RA;}ukbb@)61k-_~1zJg9 SNhmkrHJ$QU#TPO}#3}$V400j> literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route/003-expect.pcap b/autotest/units/001_one_port/078_vrf_route/003-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..b34d500098c669e0f7ab5c5eabde26f0105e570d GIT binary patch literal 838 zcmca|c+)~A1{MYw`2U}Qff2?5(pFFmqyz;883dJ#T|yff7*aSGTp1WNKuYb|_6ptu z0w9x-L4+Xyra6E~f#Jdd7!SoH7Z(?pNsJSaP1*xCi3y8I=dqiF(@nde_ah$1OFC#Q%3Sy+p4OmkqPLuZhg_gy^FdlIx?FO5~gvF%uB$~7fY!WjTlg<$~=>*k$hhh>%zC$sI z65lcEP|J6yCQ;%$RFf$3-2|%n4%H+^Xc`y9NaGs_rEx|SlXm}wnk0&0(i##?q9C`R Jx(R=X0{}%Nl79dI literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route/004-expect.pcap b/autotest/units/001_one_port/078_vrf_route/004-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..05774885da5752972fead7d09eb2539e8ce2e2b4 GIT binary patch literal 1058 zcmca|c+)~A1{MYw`2U}Qff2?5(tc13qyz;883dJ#T|yff7*g8qCIE#PMA+<=lt2s^ zP*SQx)($dEgdqSX8^EN%aMl9GLowaO#RX8IO#pHjMA#gZlt2s^ zP*SQx)($dEgdqSX8^EN%aMl9GBg=Fqgl-@U({yu$JQ;3hM(DGKt#wuaupfrosk&RA;}ukbb@)61k-_~1zJg9 SNhmkrHJ$QU#TPO}#3}$V400j> literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route/autotest.yaml b/autotest/units/001_one_port/078_vrf_route/autotest.yaml new file mode 100644 index 00000000..513c6cc8 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route/autotest.yaml @@ -0,0 +1,68 @@ +steps: +- cli: + - rib static insert default 0.0.0.0/0 200.0.10.1 + - rib static insert default 1.0.0.0/24 200.0.20.1 + - rib static insert default 2.0.0.0/24 200.0.40.1 + - rib static insert red 0.0.0.0/0 200.0.30.1 + - rib static insert red 1.0.0.0/24 200.0.10.1 + - rib static insert red 2.0.0.0/24 200.0.20.1 + - rib static insert white 1.0.0.0/24 200.0.40.1 + - rib static insert white 1.0.0.16/28 200.0.10.1 + - rib static insert white 1.0.0.16/30 200.0.20.1 +- cli: + - rib static insert default ::/0 c0de::10:1 + - rib static insert default 7e01::/64 c0de::20:1 + - rib static insert default 7e02::/64 c0de::40:1 + - rib static insert red ::/0 c0de::30:1 + - rib static insert red 7e01::/64 c0de::10:1 + - rib static insert red 7e02::/64 c0de::20:1 + - rib static insert white 7e01::/64 c0de::40:1 + - rib static insert white 7e01::/96 c0de::10:1 + - rib static insert white 7e01::/128 c0de::20:1 +- cli: + - rib prefixes + +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap + +- cli: + - rib static remove default 1.0.0.0/24 200.0.20.1 + - rib static remove red 0.0.0.0/0 200.0.30.1 + - rib static remove white 1.0.0.16/30 200.0.20.1 + - rib static remove default 7e01::/64 c0de::20:1 + - rib static remove red ::/0 c0de::30:1 + - rib static remove white 7e01::/128 c0de::20:1 +- cli: + - rib prefixes + +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- sendPackets: + - port: kni0 + send: 004-send.pcap + expect: 004-expect.pcap + +- cli: + - rib static remove default 0.0.0.0/0 200.0.10.1 + - rib static remove default 2.0.0.0/24 200.0.40.1 + - rib static remove red 1.0.0.0/24 200.0.10.1 + - rib static remove red 2.0.0.0/24 200.0.20.1 + - rib static remove white 1.0.0.0/24 200.0.40.1 + - rib static remove white 1.0.0.16/28 200.0.10.1 +- cli: + - rib static remove default ::/0 c0de::10:1 + - rib static remove default 7e02::/64 c0de::40:1 + - rib static remove red 7e01::/64 c0de::10:1 + - rib static remove red 7e02::/64 c0de::20:1 + - rib static remove white 7e01::/64 c0de::40:1 + - rib static remove white 7e01::/96 c0de::10:1 +- cli: + - rib prefixes diff --git a/autotest/units/001_one_port/078_vrf_route/controlplane.conf b/autotest/units/001_one_port/078_vrf_route/controlplane.conf new file mode 100644 index 00000000..4a8eb240 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route/controlplane.conf @@ -0,0 +1,67 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0" + }, + "lp0.300": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "300", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0", + "vrf": "red" + }, + "lp0.400": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "400", + "macAddress": "00:11:22:33:44:55", + "nextModule": "route0", + "vrf": "white" + }, + "route0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv4Prefix": "200.0.10.0/24", + "neighborIPv4Address": "200.0.10.1", + "neighborIPv6Address": "c0de::10:1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.20.0/24", + "neighborIPv4Address": "200.0.20.1", + "neighborIPv6Address": "c0de::20:1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + }, + "kni0.300": { + "ipv4Prefix": "200.0.30.0/24", + "neighborIPv4Address": "200.0.30.1", + "neighborIPv6Address": "c0de::30:1", + "neighborMacAddress": "00:00:00:33:33:33", + "nextModule": "lp0.300" + }, + "kni0.400": { + "ipv4Prefix": "200.0.40.0/24", + "neighborIPv4Address": "200.0.40.1", + "neighborIPv6Address": "c0de::40:1", + "neighborMacAddress": "00:00:00:44:44:44", + "nextModule": "lp0.400" + } + } + } + } +} diff --git a/autotest/units/001_one_port/078_vrf_route/gen.py b/autotest/units/001_one_port/078_vrf_route/gen.py new file mode 100755 index 00000000..40f47d39 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route/gen.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from scapy.all import * +from scapy.contrib.mpls import MPLS + + +def write_pcap(filename, *packetsList): + if len(packetsList) == 0: + PcapWriter(filename)._write_header(Ether()) + return + + PcapWriter(filename) + + for packets in packetsList: + if type(packets) == list: + for packet in packets: + packet.time = 0 + wrpcap(filename, [p for p in packet], append=True) + else: + packets.time = 0 + wrpcap(filename, [p for p in packets], append=True) + +# IPv4 + +def write_pcap_ipv4(filename): + write_pcap(filename, + # vlan 100, 200 - default vrf + # + # 0.0.0.0/0 -> 200.0.10.1 + # 1.0.0.0/24 -> 200.0.20.1 ! only in 001 + # 2.0.0.0/24 -> 200.0.40.1 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + + # vlan 300 - vrf "red" + # + # 0.0.0.0/0 -> 200.0.30.1 ! only in 001 + # 1.0.0.0/24 -> 200.0.10.1 + # 2.0.0.0/24 -> 200.0.20.1 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + + # vlan 400 - vrf "white" + # + # 1.0.0.0/24 -> 200.0.40.1 + # 1.0.0.16/28 -> 200.0.10.1 ! only in 001 + # 1.0.0.16/30 -> 200.0.20.2 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IP(dst="1.0.0.17", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IP(dst="1.0.0.21", src="222.222.222.222", ttl=64)/TCP(), + # no route for these 2 packets: + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=64)/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=64)/TCP()) + +write_pcap_ipv4("001-send.pcap") +write_pcap("001-expect.pcap", + # vlan 100, 200 - default vrf + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + + # vlan 300 - vrf "red" + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:33:33:33", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + + # vlan 400 - vrf "white" + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="1.0.0.17", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.21", src="222.222.222.222", ttl=63)/TCP()) + +write_pcap_ipv4("003-send.pcap") +write_pcap("003-expect.pcap", + # vlan 100, 200 - default vrf + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="3.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + + # vlan 300 - vrf "red" + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="2.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + + # vlan 400 - vrf "white" + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IP(dst="1.0.0.1", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.17", src="222.222.222.222", ttl=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="1.0.0.21", src="222.222.222.222", ttl=63)/TCP()) + +# IPv6 + +def write_pcap_ipv6(filename): + write_pcap(filename, + # vlan 100, 200 - default vrf + # + # ::/0 -> c0de::10:1 + # 7e01::/64 -> c0de::20:1 ! only in 001 + # 7e02::/64 -> c0de::40:1 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IPv6(dst="7e03::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IPv6(dst="7e03::1", src="2222::2222")/TCP(), + + # vlan 300 - vrf "red" + # + # ::/0 -> c0de::30:1 ! only in 001 + # 7e01::/64 -> c0de::10:1 + # 7e02::/64 -> c0de::20:1 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IPv6(dst="7e03::1", src="2222::2222")/TCP(), + + # vlan 400 - vrf "white" + # + # 7e01::/64 -> c0de::40:1 + # 7e01::/96 -> c0de::10:1 + # 7e01::/128 -> c0de::20:1 ! only in 001 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IPv6(dst="7e01:0::1:0:0:1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IPv6(dst="7e01::0", src="2222::2222")/TCP(), + # no route for these 2 packets: + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=400)/IPv6(dst="7e03::1", src="2222::2222")/TCP()) + +write_pcap_ipv6("002-send.pcap") +write_pcap("002-expect.pcap", + # vlan 100, 200 - default vrf + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + + # vlan 300 - vrf "red" + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:33:33:33", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + + # vlan 400 - vrf "white" + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IPv6(dst="7e01:0::1:0:0:1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="7e01::0", src="2222::2222", hlim=63)/TCP()) + +write_pcap_ipv6("004-send.pcap") +write_pcap("004-expect.pcap", + # vlan 100, 200 - default vrf + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + + # vlan 300 - vrf "red" + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + + # vlan 400 - vrf "white" + Ether(dst="00:00:00:44:44:44", src="00:11:22:33:44:55")/Dot1Q(vlan=400)/IPv6(dst="7e01:0::1:0:0:1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="7e01::0", src="2222::2222", hlim=63)/TCP()) diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/001-expect.pcap b/autotest/units/001_one_port/078_vrf_route_nat64stateful/001-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..b0de9d1d1ef220bce5c439caf2228412f44508d7 GIT binary patch literal 284184 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 literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/001-send.pcap b/autotest/units/001_one_port/078_vrf_route_nat64stateful/001-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..5246ebc6688a8355ad8448a78883a1f4170aa8d8 GIT binary patch literal 360984 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 literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/002-expect.pcap b/autotest/units/001_one_port/078_vrf_route_nat64stateful/002-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..76766fff75f82d61b82b9b94f525ed293e56d916 GIT binary patch literal 72216 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 literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/003-expect.pcap b/autotest/units/001_one_port/078_vrf_route_nat64stateful/003-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..456db472f85e86a4b2b2ef0c5994f43e870fdace GIT binary patch literal 227352 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 literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/003-send.pcap b/autotest/units/001_one_port/078_vrf_route_nat64stateful/003-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..6431f2f2ed21ef5e671aeb87880ca49e8ec31c05 GIT binary patch literal 288792 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 literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/autotest.yaml b/autotest/units/001_one_port/078_vrf_route_nat64stateful/autotest.yaml new file mode 100644 index 00000000..8d36b34c --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route_nat64stateful/autotest.yaml @@ -0,0 +1,23 @@ +steps: +- ipv4Update: "0.0.0.0/0 -> 200.0.0.1" +- ipv6Update: "::/0 -> fe80::1" +- cli: + - rib static insert red 0.0.0.0/0 200.0.0.1 + - rib static insert blue 0.0.0.0/0 200.0.0.1 + - rib static insert white ::/0 fe80::1 + - rib static insert green ::/0 fe80::1 + - rib prefixes +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap +- cli: + - counter interface_lookupMisses diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/controlplane.conf b/autotest/units/001_one_port/078_vrf_route_nat64stateful/controlplane.conf new file mode 100644 index 00000000..142a75b0 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route_nat64stateful/controlplane.conf @@ -0,0 +1,82 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "nextModules": [ + "nat0", + "nat1", + "nat2" + ] + }, + "nat0": { + "type": "nat64stateful", + "ipv6_prefixes": [ + "2000:9999::/96" + ], + "ipv4_prefixes": [ + "122.122.122.122" + ], + "dscpMarkType": "never", + "nextModule": "vrf0" + }, + "nat1": { + "type": "nat64stateful", + "ipv6_prefixes": [ + "2000:2345::/96" + ], + "ipv4_prefixes": [ + "122.122.154.0/24" + ], + "vrfLan": "red", + "vrfWan": "white", + "dscpMarkType": "onlyDefault", + "dscp": 10, + "nextModule": "vrf0" + }, + "nat2": { + "type": "nat64stateful", + "ipv6_prefixes": [ + "2000:abcd::/96" + ], + "ipv4_prefixes": [ + "122.122.155.0/25" + ], + "vrfLan": "blue", + "vrfWan": "green", + "dscpMarkType": "always", + "dscp": 20, + "nextModule": "vrf0" + }, + "vrf0": { + "type": "route", + "interfaces": { + "kni0.100": { + "ipv6Prefix": "fe80::2/64", + "neighborIPv6Address": "fe80::1", + "neighborMacAddress": "00:00:00:11:11:11", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipv4Prefix": "200.0.0.2/24", + "neighborIPv4Address": "200.0.0.1", + "neighborMacAddress": "00:00:00:22:22:22", + "nextModule": "lp0.200" + } + } + } + } +} diff --git a/autotest/units/001_one_port/078_vrf_route_nat64stateful/gen.py b/autotest/units/001_one_port/078_vrf_route_nat64stateful/gen.py new file mode 100755 index 00000000..13a4f646 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route_nat64stateful/gen.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from scapy.all import * + + +def write_pcap(filename, *packetsList): + if len(packetsList) == 0: + PcapWriter(filename)._write_header(Ether()) + return + + PcapWriter(filename) + + for packets in packetsList: + if type(packets) == list: + for packet in packets: + packet.time = 0 + wrpcap(filename, [p for p in packet], append=True) + else: + packets.time = 0 + wrpcap(filename, [p for p in packets], append=True) + + +# check lan (ipv6 -> ipv4). create state, check source ip +write_pcap("001-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:9999::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:9999::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0x4, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:9999::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0x80, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:9999::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0xfc, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:9999::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0xff, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:2345::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:2345::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0x4, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:2345::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0x80, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:2345::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0xfc, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:2345::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0xff, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:abcd::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:abcd::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0x4, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:abcd::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0x80, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:abcd::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0xfc, hlim=64)/TCP(dport=443, sport=2048), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:abcd::102.124.0.0/120", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", tc=0xff, hlim=64)/TCP(dport=443, sport=2048)) + +write_pcap("001-expect.pcap", + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.122.122", ttl=63, id=0, tos=0)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.122.122", ttl=63, id=0, tos=0x4)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.122.122", ttl=63, id=0, tos=0x80)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.122.122", ttl=63, id=0, tos=0xfc)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.122.122", ttl=63, id=0, tos=0xff)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.154.171", ttl=63, id=0, tos=0x28)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.154.171", ttl=63, id=0, tos=0x4)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.154.171", ttl=63, id=0, tos=0x80)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.154.171", ttl=63, id=0, tos=0xfc)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.154.171", ttl=63, id=0, tos=0xff)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.155.43", ttl=63, id=0, tos=0x50)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.155.43", ttl=63, id=0, tos=0x50)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.155.43", ttl=63, id=0, tos=0x50)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.155.43", ttl=63, id=0, tos=0x50)/TCP(dport=443, sport=2048), + Ether(dst="00:00:00:22:22:22", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="102.124.0.0/24", src="122.122.155.43", ttl=63, id=0, tos=0x53)/TCP(dport=443, sport=2048)) + + +# check wan (ipv4 -> ipv6) +write_pcap("002-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="122.122.122.122", src="102.124.0.0/24", ttl=64)/TCP(dport=2048, sport=443), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="122.122.154.171", src="102.124.0.0/24", ttl=64)/TCP(dport=2048, sport=443), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="122.122.155.43", src="102.124.0.0/24", ttl=64)/TCP(dport=2048, sport=443)) + +write_pcap("002-expect.pcap", + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", src="2000:9999::102.124.0.0/120", hlim=63, fl=0)/TCP(dport=2048, sport=443), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", src="2000:2345::102.124.0.0/120", hlim=63, fl=0)/TCP(dport=2048, sport=443), + Ether(dst="00:00:00:11:11:11", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb", src="2000:abcd::102.124.0.0/120", hlim=63, fl=0)/TCP(dport=2048, sport=443)) + + +# check lan (ipv6 -> ipv4). create state, check source ip, check source port (1024 .. 65535) +write_pcap("003-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:9999::142.199.99.99", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb/118", tc=0x50, hlim=64)/TCP(dport=443, sport=4444), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:2345::142.199.99.99", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb/118", tc=0x50, hlim=64)/TCP(dport=443, sport=4444), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2000:abcd::142.199.99.99", src="bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb:bbbb/118", tc=0x50, hlim=64)/TCP(dport=443, sport=4444)) + +# 003-expect.pcap - dumped diff --git a/autotest/units/001_one_port/078_vrf_route_tunnel/001-expect.pcap b/autotest/units/001_one_port/078_vrf_route_tunnel/001-expect.pcap new file mode 100644 index 0000000000000000000000000000000000000000..ba1e5c53cc0e1021d826fe89213d72416cb8c765 GIT binary patch literal 870 zcmca|c+)~A1{MYw`2U}Qff2?5(tc137Gh!$R5Er6ZDe3b;b3rOV6Xuxbr3wD!ezw3 z7!eV{_$o*8HG>9Ft;@mxKzSLEygg&p1CVYYlaYhrJJ5UtAj))QsOd}>ilC-@Ga{K@ z`2b`d6S<}moF;URL5Wq&kO2UQn}Edt literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_tunnel/001-send.pcap b/autotest/units/001_one_port/078_vrf_route_tunnel/001-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..2bc66de6f257b4c091ecb63441f321cf21d14f30 GIT binary patch literal 942 zcmca|c+)~A1{MYw`2U}Qff2?5(qT}{AgE;Q5(<`JY-C_aX}g;M;>fT#fG8xusHB9% zV>olh6{reiqyuB+1CR`m$;iR*9cT{%P}7!*2Ox8qXlzS4*cN8uZ8<@g5F^VLl0%Fv XTSyHtMjd*D7=1dla*DVvB`0{}*(mS+F} literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_tunnel/002-send.pcap b/autotest/units/001_one_port/078_vrf_route_tunnel/002-send.pcap new file mode 100644 index 0000000000000000000000000000000000000000..8c67797bb213893a80508780b32f107d5388e9e9 GIT binary patch literal 1230 zcmca|c+)~A1{MYw`2U}Qff2?5(q&N0AgE;Q5(?x93JNwdFr>8IO#pHjY&0D}6cS)m zQbOV}oH>&K;)<|2po%Lg)gfC0vQ&g20H!m5NrB<41&l{iS1=)L0kSY%VUCceVOTID tY{BXZGlV=2SDY9WF+vSjP#z=Ha0SIN!l*MCVuUKLpg2aT;tC>S1OQ6IXM_L% literal 0 HcmV?d00001 diff --git a/autotest/units/001_one_port/078_vrf_route_tunnel/autotest.yaml b/autotest/units/001_one_port/078_vrf_route_tunnel/autotest.yaml new file mode 100644 index 00000000..0c129dce --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route_tunnel/autotest.yaml @@ -0,0 +1,159 @@ +steps: +- rib_insert: + attribute: + protocol: autotest + vrf: default + tables: + - table_name: ipv4 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 88.88.88.1 + prefix: 1.0.0.0/24 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 88.88.88.2 + prefix: 2.0.0.0/24 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - nexthop: 88.88.88.3 + prefix: 3.0.0.0/24 + path_information: 88.88.88.3:10001 + labels: + - 1300 +- rib_insert: + attribute: + protocol: autotest + vrf: red + tables: + - table_name: ipv4 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 88.88.88.2 + prefix: 1.0.0.0/24 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - nexthop: 88.88.88.3 + prefix: 2.0.0.0/24 + path_information: 88.88.88.3:10001 + labels: + - 1300 + - nexthop: 88.88.88.1 + prefix: 3.0.0.0/24 + path_information: 88.88.88.1:10001 + labels: + - 1100 +- rib_insert: + attribute: + protocol: autotest + vrf: white + tables: + - table_name: ipv4 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 88.88.88.3 + prefix: 1.0.0.0/24 + path_information: 88.88.88.3:10001 + labels: + - 1300 + - nexthop: 88.88.88.1 + prefix: 2.0.0.0/24 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 88.88.88.2 + prefix: 3.0.0.0/24 + path_information: 88.88.88.1:10001 + labels: + - 1200 +- rib_insert: + attribute: + protocol: autotest + vrf: default + tables: + - table_name: ipv6 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 8888::1 + prefix: 7e01::/16 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 8888::2 + prefix: 7e02::/16 + path_information: 88.88.88.2:10001 + labels: + - 1200 + - nexthop: 8888::3 + prefix: 7e03::/16 + path_information: 88.88.88.3:10001 + labels: + - 1300 +- rib_insert: + attribute: + protocol: autotest + vrf: red + tables: + - table_name: ipv6 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 8888::2 + prefix: 7e01::/16 + path_information: 88.88.88.3:10001 + labels: + - 1200 + - nexthop: 8888::3 + prefix: 7e02::/16 + path_information: 88.88.88.3:10001 + labels: + - 1300 + - nexthop: 8888::1 + prefix: 7e03::/16 + path_information: 88.88.88.1:10001 + labels: + - 1100 +- rib_insert: + attribute: + protocol: autotest + vrf: white + tables: + - table_name: ipv6 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 8888::3 + prefix: 7e01::/16 + path_information: 88.88.88.3:10001 + labels: + - 1300 + - nexthop: 8888::1 + prefix: 7e02::/16 + path_information: 88.88.88.1:10001 + labels: + - 1100 + - nexthop: 8888::2 + prefix: 7e03::/16 + path_information: 88.88.88.2:10001 + labels: + - 1200 +- cli: + - rib prefixes +- ipv4Update: + - "0.0.0.0/0 -> 100.0.0.1" +- ipv6Update: + - "::/0 -> c0de::100:1" +- sendPackets: + - port: kni0 + send: 001-send.pcap + expect: 001-expect.pcap +- sendPackets: + - port: kni0 + send: 002-send.pcap + expect: 002-expect.pcap diff --git a/autotest/units/001_one_port/078_vrf_route_tunnel/controlplane.conf b/autotest/units/001_one_port/078_vrf_route_tunnel/controlplane.conf new file mode 100644 index 00000000..66ac6ba7 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route_tunnel/controlplane.conf @@ -0,0 +1,61 @@ +{ + "modules": { + "lp0.100": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "100", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.200": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "200", + "vrf": "red", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "lp0.300": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "300", + "vrf": "white", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "nextModules": [ + "decap0" + ] + }, + "decap0": { + "type": "decap", + "ipv6DestinationPrefixes": [ + "2222::cccc/128" + ], + "ipv6_enabled": true, + "nextModule": "route0:tunnel" + }, + "route0": { + "type": "route", + "ipv4SourceAddress": "10.50.0.1", + "ipv6SourceAddress": "c0de::1", + "udpDestinationPort": 6635, + "interfaces": { + "kni0.100": { + "ipv4Prefix": "100.0.0.0/24", + "neighborIPv4Address": "100.0.0.1", + "neighborIPv6Address": "c0de::100:1", + "neighborMacAddress": "00:00:00:00:00:02", + "nextModule": "lp0.100" + } + }, + "peers": { + "1": "A", + "2": "B", + "3": "C" + } + } + } +} diff --git a/autotest/units/001_one_port/078_vrf_route_tunnel/gen.py b/autotest/units/001_one_port/078_vrf_route_tunnel/gen.py new file mode 100755 index 00000000..c6d81059 --- /dev/null +++ b/autotest/units/001_one_port/078_vrf_route_tunnel/gen.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from scapy.all import * +from scapy.contrib.mpls import MPLS + + +def write_pcap(filename, *packetsList): + if len(packetsList) == 0: + PcapWriter(filename)._write_header(Ether()) + return + + PcapWriter(filename) + + for packets in packetsList: + if type(packets) == list: + for packet in packets: + packet.time = 0 + wrpcap(filename, [p for p in packet], append=True) + else: + packets.time = 0 + wrpcap(filename, [p for p in packets], append=True) + +# IPv4 + +write_pcap("001-send.pcap", + # vlan 100 - default vrf + # + # 1.0.0.0/24 -> 88.88.88.1 + # 2.0.0.0/24 -> 88.88.88.2 + # 3.0.0.0/24 -> 88.88.88.3 + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1")/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1")/IP(dst="2.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1")/IP(dst="3.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + + # vlan 200 - red vrf + # + # 1.0.0.0/24 -> 88.88.88.2 + # 2.0.0.0/24 -> 88.88.88.3 + # 3.0.0.0/24 -> 88.88.88.1 + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=200)/IPv6(dst="2222::cccc", src="::1")/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=200)/IPv6(dst="2222::cccc", src="::1")/IP(dst="2.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=200)/IPv6(dst="2222::cccc", src="::1")/IP(dst="3.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + + # vlan 300 - white vrf + # + # 1.0.0.0/24 -> 88.88.88.3 + # 2.0.0.0/24 -> 88.88.88.1 + # 3.0.0.0/24 -> 88.88.88.2 + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=300)/IPv6(dst="2222::cccc", src="::1")/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=300)/IPv6(dst="2222::cccc", src="::1")/IP(dst="2.0.0.1", src="0.0.0.0", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=300)/IPv6(dst="2222::cccc", src="::1")/IP(dst="3.0.0.1", src="0.0.0.0", ttl=64)/ICMP()) + +write_pcap("001-expect.pcap", + # vlan 100 - default vrf + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1")/UDP(dport=6635, sport=0xaa6c | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1")/UDP(dport=6635, sport=0x1072 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="2.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.3", src="10.50.0.1")/UDP(dport=6635, sport=0x2bd7 | 0xc000, chksum=0)/MPLS(label=1300, ttl=255)/IP(dst="3.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + + # vlan 200 - red vrf + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1")/UDP(dport=6635, sport=0xaa6c | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.3", src="10.50.0.1")/UDP(dport=6635, sport=0x1072 | 0xc000, chksum=0)/MPLS(label=1300, ttl=255)/IP(dst="2.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1")/UDP(dport=6635, sport=0x2bd7 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="3.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + + # vlan 300 - white vrf + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.3", src="10.50.0.1")/UDP(dport=6635, sport=0xaa6c | 0xc000, chksum=0)/MPLS(label=1300, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.1", src="10.50.0.1")/UDP(dport=6635, sport=0x1072 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="2.0.0.1", src="0.0.0.0", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="88.88.88.2", src="10.50.0.1")/UDP(dport=6635, sport=0x2bd7 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="3.0.0.1", src="0.0.0.0", ttl=63)/ICMP()) + +# IPv6 + +write_pcap("002-send.pcap", + # vlan 100 - default vrf + # + # 7e01::/64 -> 8888::1 + # 7e02::/64 -> 8888::2 + # 7e03::/64 -> 8888::3 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=100)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e03::1", src="2222::2222")/TCP(), + + # vlan 100 - red vrf + # + # 7e01::/64 -> 8888::2 + # 7e02::/64 -> 8888::3 + # 7e03::/64 -> 8888::1 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=200)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e03::1", src="2222::2222")/TCP(), + + # vlan 100 - white vrf + # + # 7e01::/64 -> 8888::3 + # 7e02::/64 -> 8888::1 + # 7e03::/64 -> 8888::2 + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e01::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e02::1", src="2222::2222")/TCP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:11:11:11")/Dot1Q(vlan=300)/IPv6(dst="2222::cccc", src="::1")/IPv6(dst="7e03::1", src="2222::2222")/TCP()) + + +write_pcap("002-expect.pcap", + # vlan 100 - default vrf + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::1", src="c0de::1")/UDP(dport=6635, sport=0x1f99 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::2", src="c0de::1")/UDP(dport=6635, sport=0x0fd1 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::3", src="c0de::1")/UDP(dport=6635, sport=0x3fe9 | 0xc000, chksum=0)/MPLS(label=1300, ttl=255)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + + # vlan 100 - red vrf + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::2", src="c0de::1")/UDP(dport=6635, sport=0x1f99 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::3", src="c0de::1")/UDP(dport=6635, sport=0x0fd1 | 0xc000, chksum=0)/MPLS(label=1300, ttl=255)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::1", src="c0de::1")/UDP(dport=6635, sport=0x3fe9 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP(), + + # vlan 100 - white vrf + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::3", src="c0de::1")/UDP(dport=6635, sport=0x1f99 | 0xc000, chksum=0)/MPLS(label=1300, ttl=255)/IPv6(dst="7e01::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::1", src="c0de::1")/UDP(dport=6635, sport=0x0fd1 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IPv6(dst="7e02::1", src="2222::2222", hlim=63)/TCP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IPv6(dst="8888::2", src="c0de::1")/UDP(dport=6635, sport=0x3fe9 | 0xc000, chksum=0)/MPLS(label=1200, ttl=255)/IPv6(dst="7e03::1", src="2222::2222", hlim=63)/TCP())