diff --git a/autotest/units/001_one_port/076_rfc_5549_route/autotest.yaml b/autotest/units/001_one_port/076_rfc_5549_route/autotest.yaml index b7bc5c1a..09c3df3d 100644 --- a/autotest/units/001_one_port/076_rfc_5549_route/autotest.yaml +++ b/autotest/units/001_one_port/076_rfc_5549_route/autotest.yaml @@ -13,4 +13,6 @@ steps: - port: kni0 send: 001-send.pcap expect: 001-expect.pcap - +- cli: + - rib static remove default 1.0.0.0/24 c0de::200:1 1001 + \ No newline at end of file diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-expect.pcap index a42bec74..38c3ddf6 100644 Binary files a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-expect.pcap and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-send.pcap index cb6a66eb..93ee0ede 100644 Binary files a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-send.pcap and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/001-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/002-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/002-expect.pcap new file mode 100644 index 00000000..7bc5e572 Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/002-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/002-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/002-send.pcap new file mode 100644 index 00000000..d57f8e0c Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/002-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/autotest.yaml b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/autotest.yaml index da5f45f7..8c97eecc 100644 --- a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/autotest.yaml +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/autotest.yaml @@ -1,9 +1,7 @@ steps: +- ipv6Update: "::/0 -> 3333::2" - cli: - - neighbor insert route0 kni0.200 c0de::200:1 00:00:00:00:00:02 - - neighbor flush -- cli: - - rib static insert default 1.0.0.0/24 8888::1 1100 10000 1 1 + - rib static insert default 0.0.0.0/0 4444::1 1100 10000 1 1 - rib_insert: attribute: protocol: autotest @@ -12,19 +10,16 @@ steps: large_communities: - 13238:1:1 prefixes: - - nexthop: 8888::2 + - nexthop: 5555::1 prefix: 2.0.0.0/24 - path_information: 88.88.88.1:10001 + path_information: 55.55.55.1:10001 labels: - 1200 -- ipv6Update: - - "::/0 -> c0de::200:1" -- cli: - - rib prefixes - - route tunnel lookup route0 1.0.0.1 - - route tunnel lookup route0 2.0.0.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/076_rfc_5549_route_tunnel/controlplane.conf b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/controlplane.conf index f3a7e8c0..2068edbd 100644 --- a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/controlplane.conf +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/controlplane.conf @@ -14,44 +14,70 @@ "macAddress": "00:11:22:33:44:55", "nextModule": "acl0" }, + "lp0.300": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "300", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, "acl0": { "type": "acl", "nextModules": [ - "decap0" + "decap0", + "route0:tunnel" ] }, "decap0": { "type": "decap", "ipv6DestinationPrefixes": [ - "2222::cccc/128" + "3333::1" ], - "ipv6_enabled": true, - "nextModule": "route0:tunnel" + "nextModule": "route0" }, "route0": { "type": "route", "ipv4SourceAddress": "10.50.0.1", - "ipv6SourceAddress": "2222:1111:0:1234:5678:0101:ca11:ca11", + "ipv6SourceAddress": "3333::1", "udpDestinationPort": 6635, "interfaces": { "kni0.100": { "ipAddresses": [ - "11.0.0.2/24" + "10.0.1.1/24" ], + "acl": "acl0", + "neighborIPv4Address": "10.0.1.2", + "neighborMacAddress": "00:00:00:00:00:01", "nextModule": "lp0.100" }, "kni0.200": { "ipAddresses": [ - "c0de::200:2/96" + "10.0.2.1/24" ], + "acl": "acl0", + "neighborIPv4Address": "10.0.2.2", + "neighborMacAddress": "00:00:00:00:00:02", "nextModule": "lp0.200" + }, + "kni0.300": { + "ipAddresses": [ + "3333::1/96" + ], + "acl": "acl0", + "neighborIPv6Address": "3333::2", + "neighborMacAddress": "00:00:00:00:00:03", + "nextModule": "lp0.300" } }, "peers": { "1": "A", "2": "B", "3": "C" - } + }, + "localPrefixes": [ + "10.0.1.0/24", + "10.0.2.0/24" + ] } } } diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/gen.py b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/gen.py index 1bbb7c13..b8c81373 100755 --- a/autotest/units/001_one_port/076_rfc_5549_route_tunnel/gen.py +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel/gen.py @@ -22,12 +22,24 @@ def write_pcap(filename, *packetsList): wrpcap(filename, [p for p in packets], append=True) +# Check route tunnel mpls over udp 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="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", fl=1)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=64, tos=17)/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)/IP(dst="1.0.0.1", src="10.0.1.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IP(dst="2.0.0.1", src="10.0.1.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="1.0.0.1", src="10.0.2.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="2.0.0.1", src="10.0.2.2", ttl=64)/ICMP()) write_pcap("001-expect.pcap", - Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="8888::1", src="2222:1111:0:1234:5678:0101:ca11:ca11")/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=200)/IPv6(dst="8888::1", src="2222:1111:0:1234:5678:0101:ca11:ca11", tc=17)/UDP(dport=6635, sport=0x00d4 | 0xc000, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="0.0.0.0", ttl=63, tos=17)/ICMP(), - Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IPv6(dst="8888::2", src="2222:1111:0:1234:5678:0101:ca11:ca11")/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:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="4444::1", src="3333::1")/UDP(dport=6635, sport=0xca71, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="10.0.1.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="5555::1", src="3333::1")/UDP(dport=6635, sport=0xf06f, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="2.0.0.1", src="10.0.1.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="4444::1", src="3333::1")/UDP(dport=6635, sport=0xf621, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="10.0.2.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="5555::1", src="3333::1")/UDP(dport=6635, sport=0xcc3f, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="2.0.0.1", src="10.0.2.2", ttl=63)/ICMP()) + +# No tunnel is established between local prefixes +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="10.0.1.2", src="10.0.2.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:03")/Dot1Q(vlan=100)/IP(dst="10.0.2.2", src="10.0.1.2", ttl=64)/ICMP()) + +write_pcap("002-expect.pcap", + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="10.0.1.2", src="10.0.2.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="10.0.2.2", src="10.0.1.2", ttl=63)/ICMP()) diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/001-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/001-expect.pcap new file mode 100644 index 00000000..425b8318 Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/001-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/001-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/001-send.pcap new file mode 100644 index 00000000..9cb86fd8 Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/001-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/002-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/002-expect.pcap new file mode 100644 index 00000000..4b58a7be Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/002-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/002-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/002-send.pcap new file mode 100644 index 00000000..93ee0ede Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/002-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/003-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/003-expect.pcap new file mode 100644 index 00000000..7bc5e572 Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/003-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/003-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/003-send.pcap new file mode 100644 index 00000000..d57f8e0c Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/003-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/autotest.yaml b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/autotest.yaml new file mode 100644 index 00000000..29cf28dc --- /dev/null +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/autotest.yaml @@ -0,0 +1,15 @@ +steps: +- 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 +- sendPackets: + - port: kni0 + send: 003-send.pcap + expect: 003-expect.pcap diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/controlplane.conf b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/controlplane.conf new file mode 100644 index 00000000..6f869a79 --- /dev/null +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/controlplane.conf @@ -0,0 +1,101 @@ +{ + "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" + }, + "lp0.300": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "300", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "nextModules": [ + "decap0", + "route0:tunnel_ipip" + ] + }, + "decap0": { + "type": "decap", + "ipv6DestinationPrefixes": [ + "3333::1" + ], + "nextModule": "route0" + }, + "route0": { + "type": "route", + "ipv4SourceAddress": "10.50.0.1", + "ipv6SourceAddress": "3333::1", + "udpDestinationPort": 6635, + "interfaces": { + "kni0.100": { + "ipAddresses": [ + "10.0.1.1/24" + ], + "acl": "acl0", + "neighborIPv4Address": "10.0.1.2", + "neighborMacAddress": "00:00:00:00:00:01", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipAddresses": [ + "10.0.2.1/24" + ], + "acl": "acl0", + "neighborIPv4Address": "10.0.2.2", + "neighborMacAddress": "00:00:00:00:00:02", + "nextModule": "lp0.200" + }, + "kni0.300": { + "ipAddresses": [ + "3333::1/96" + ], + "acl": "acl0", + "neighborIPv6Address": "3333::2", + "neighborMacAddress": "00:00:00:00:00:03", + "nextModule": "lp0.300" + } + }, + "peers": { + "1": "A", + "2": "B", + "3": "C" + }, + "localPrefixes": [ + "10.0.1.0/24", + "10.0.2.0/24" + ] + } + }, + "rib": { + "defaullt": [ + { + "prefix": "::/0", + "nexthop": "3333::2" + }, + { + "prefix": "1.0.0.0/24", + "nexthop": "4444::1", + "tunnel": true + }, + { + "prefix": "2.0.0.0/24", + "nexthop": "5555::1", + "tunnel": true + } + ] + } +} diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/gen.py b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/gen.py new file mode 100755 index 00000000..7916db14 --- /dev/null +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_ipip/gen.py @@ -0,0 +1,54 @@ +#!/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) + + +# Check decapsulator for IpIp tunnel +write_pcap("001-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:0c:00")/Dot1Q(vlan=300)/IPv6(dst="3333::1", src="4444::1")/IP(dst="10.0.1.2", src="10.10.0.10", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:0c:00")/Dot1Q(vlan=300)/IPv6(dst="3333::1", src="4444::1")/IP(dst="10.0.2.2", src="10.10.0.10", ttl=64)/ICMP()) + +write_pcap("001-expect.pcap", + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="10.0.1.2", src="10.10.0.10", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="10.0.2.2", src="10.10.0.10", ttl=63)/ICMP()) + +# Check route tunnel ipip +write_pcap("002-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="10.0.1.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IP(dst="2.0.0.1", src="10.0.1.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="1.0.0.1", src="10.0.2.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="2.0.0.1", src="10.0.2.2", ttl=64)/ICMP()) + +write_pcap("002-expect.pcap", + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="4444::1", src="3333::1")/IP(dst="1.0.0.1", src="10.0.1.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="5555::1", src="3333::1")/IP(dst="2.0.0.1", src="10.0.1.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="4444::1", src="3333::1")/IP(dst="1.0.0.1", src="10.0.2.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="5555::1", src="3333::1")/IP(dst="2.0.0.1", src="10.0.2.2", ttl=63)/ICMP()) + +# No tunnel is established between local prefixes +write_pcap("003-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="10.0.1.2", src="10.0.2.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:03")/Dot1Q(vlan=100)/IP(dst="10.0.2.2", src="10.0.1.2", ttl=64)/ICMP()) + +write_pcap("003-expect.pcap", + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="10.0.1.2", src="10.0.2.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="10.0.2.2", src="10.0.1.2", ttl=63)/ICMP()) diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/001-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/001-expect.pcap new file mode 100644 index 00000000..c46b874d Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/001-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/001-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/001-send.pcap new file mode 100644 index 00000000..93ee0ede Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/001-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/002-expect.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/002-expect.pcap new file mode 100644 index 00000000..7bc5e572 Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/002-expect.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/002-send.pcap b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/002-send.pcap new file mode 100644 index 00000000..d57f8e0c Binary files /dev/null and b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/002-send.pcap differ diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/autotest.yaml b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/autotest.yaml new file mode 100644 index 00000000..42d558b3 --- /dev/null +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/autotest.yaml @@ -0,0 +1,27 @@ +steps: +- ipv6Update: "::/0 -> 3333::2" +- cli: + - rib static insert default 1.0.0.0/24 4444::1 1100 10000 1 1 +- rib_insert: + attribute: + protocol: autotest + tables: + - table_name: ipv6 mpls-vpn + large_communities: + - 13238:1:1 + prefixes: + - nexthop: 5555::1 + prefix: 2.0.0.0/24 + path_information: 55.55.55.1:10001 + labels: + - 1200 +- 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 diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/controlplane.conf b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/controlplane.conf new file mode 100644 index 00000000..05045144 --- /dev/null +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/controlplane.conf @@ -0,0 +1,84 @@ +{ + "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" + }, + "lp0.300": { + "type": "logicalPort", + "physicalPort": "kni0", + "vlanId": "300", + "macAddress": "00:11:22:33:44:55", + "nextModule": "acl0" + }, + "acl0": { + "type": "acl", + "nextModules": [ + "decap0", + "route0:tunnel" + ] + }, + "decap0": { + "type": "decap", + "ipv6DestinationPrefixes": [ + "3333::1" + ], + "nextModule": "route0" + }, + "route0": { + "type": "route", + "ipv4SourceAddress": "10.50.0.1", + "ipv6SourceAddress": "3333::1", + "udpDestinationPort": 6635, + "random_source": true, + "interfaces": { + "kni0.100": { + "ipAddresses": [ + "10.0.1.1/24" + ], + "acl": "acl0", + "neighborIPv4Address": "10.0.1.2", + "neighborMacAddress": "00:00:00:00:00:01", + "nextModule": "lp0.100" + }, + "kni0.200": { + "ipAddresses": [ + "10.0.2.1/24" + ], + "acl": "acl0", + "neighborIPv4Address": "10.0.2.2", + "neighborMacAddress": "00:00:00:00:00:02", + "nextModule": "lp0.200" + }, + "kni0.300": { + "ipAddresses": [ + "3333::1/96" + ], + "acl": "acl0", + "neighborIPv6Address": "3333::2", + "neighborMacAddress": "00:00:00:00:00:03", + "nextModule": "lp0.300" + } + }, + "peers": { + "1": "A", + "2": "B", + "3": "C" + }, + "localPrefixes": [ + "10.0.1.0/24", + "10.0.2.0/24" + ] + } + } +} diff --git a/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/gen.py b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/gen.py new file mode 100755 index 00000000..31969c73 --- /dev/null +++ b/autotest/units/001_one_port/076_rfc_5549_route_tunnel_random_source/gen.py @@ -0,0 +1,45 @@ +#!/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) + + +# Check route tunnel mpls over udp +write_pcap("001-send.pcap", + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IP(dst="1.0.0.1", src="10.0.1.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:01")/Dot1Q(vlan=100)/IP(dst="2.0.0.1", src="10.0.1.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="1.0.0.1", src="10.0.2.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:02")/Dot1Q(vlan=200)/IP(dst="2.0.0.1", src="10.0.2.2", ttl=64)/ICMP()) + +write_pcap("001-expect.pcap", + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="4444::1", src="3333::a00:102:0:1")/UDP(dport=6635, sport=0xca71, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="10.0.1.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="5555::1", src="3333::a00:102:0:1")/UDP(dport=6635, sport=0xf06f, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="2.0.0.1", src="10.0.1.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="4444::1", src="3333::a00:202:0:1")/UDP(dport=6635, sport=0xf621, chksum=0)/MPLS(label=1100, ttl=255)/IP(dst="1.0.0.1", src="10.0.2.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:03", src="00:11:22:33:44:55")/Dot1Q(vlan=300)/IPv6(dst="5555::1", src="3333::a00:202:0:1")/UDP(dport=6635, sport=0xcc3f, chksum=0)/MPLS(label=1200, ttl=255)/IP(dst="2.0.0.1", src="10.0.2.2", ttl=63)/ICMP()) + +# No tunnel is established between local prefixes +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="10.0.1.2", src="10.0.2.2", ttl=64)/ICMP(), + Ether(dst="00:11:22:33:44:55", src="00:00:00:00:00:03")/Dot1Q(vlan=100)/IP(dst="10.0.2.2", src="10.0.1.2", ttl=64)/ICMP()) + +write_pcap("002-expect.pcap", + Ether(dst="00:00:00:00:00:01", src="00:11:22:33:44:55")/Dot1Q(vlan=100)/IP(dst="10.0.1.2", src="10.0.2.2", ttl=63)/ICMP(), + Ether(dst="00:00:00:00:00:02", src="00:11:22:33:44:55")/Dot1Q(vlan=200)/IP(dst="10.0.2.2", src="10.0.1.2", ttl=63)/ICMP()) diff --git a/cli/rib.h b/cli/rib.h index 0b83b248..4d24c21e 100644 --- a/cli/rib.h +++ b/cli/rib.h @@ -263,7 +263,7 @@ void insert(const std::string& vrf, std::set large_communities; if (weight) { - large_communities.emplace(13238, 1, *weight); ///< @todo: DEFINE + large_communities.emplace(YANET_DEFAULT_BGP_AS, 1, *weight); } common::icp::rib_update::insert insert = {"static", diff --git a/common/controlplaneconfig.h b/common/controlplaneconfig.h index da9a6d4d..a8986568 100644 --- a/common/controlplaneconfig.h +++ b/common/controlplaneconfig.h @@ -128,6 +128,7 @@ class config_t std::set local_prefixes; ///< for fallback to default std::map peers; std::map interfaces; + bool random_source{}; }; } diff --git a/common/define.h b/common/define.h index 47cc5fd0..e8a5e2ef 100644 --- a/common/define.h +++ b/common/define.h @@ -119,6 +119,10 @@ extern LogPriority logPriority; #define YANET_RIB_PRIORITY_ROUTE_TUNNEL_FALLBACK ((uint32_t)11000) #define YANET_RIB_PRIORITY_ROUTE_REPEAT ((uint32_t)12000) +#define YANET_DEFAULT_BGP_AS ((uint32_t)13238) +#define YANET_DEFAULT_ROUTE_TUNNEL_LABEL ((uint32_t)3199) +#define YANET_DEFAULT_ROUTE_TUNNEL_PATH_INFORMATION "127.0.0.1:10000" + #define YANET_NETWORK_FLAG_FRAGMENT ((uint8_t)(1u << 0)) #define YANET_NETWORK_FLAG_NOT_FIRST_FRAGMENT ((uint8_t)(1u << 1)) #define YANET_NETWORK_FLAG_HAS_EXTENSION ((uint8_t)(1u << 2)) diff --git a/common/idp.h b/common/idp.h index 8719cd0d..4db088b2 100644 --- a/common/idp.h +++ b/common/idp.h @@ -199,7 +199,8 @@ namespace update_route { using tunnel = std::tuple; ///< udpDestinationPort + uint16_t, ///< udpDestinationPort + bool>; ///< srcRndEnabled using request = std::tuple>; diff --git a/common/type.h b/common/type.h index 051ef803..4eea30a4 100644 --- a/common/type.h +++ b/common/type.h @@ -2018,6 +2018,7 @@ enum class eFlowType : uint8_t route, route_local, route_tunnel, + route_tunnel_ipip, acl_egress, dregress, controlPlane, @@ -2084,6 +2085,8 @@ inline const char* eFlowType_toString(eFlowType t) return "route_local"; case eFlowType::route_tunnel: return "route_tunnel"; + case eFlowType::route_tunnel_ipip: + return "route_tunnel_ipip"; case eFlowType::acl_egress: return "acl_egress"; case eFlowType::dregress: diff --git a/controlplane/base.h b/controlplane/base.h index 7f96a5e4..12b4b3d1 100644 --- a/controlplane/base.h +++ b/controlplane/base.h @@ -395,6 +395,9 @@ class base_rib public: ip_prefix_t prefix; ip_address_t nexthop; + bool is_tunnel; + std::string path_information; + uint32_t label; }; // diff --git a/controlplane/configconverter.cpp b/controlplane/configconverter.cpp index 7062dcdb..ce96bbc3 100644 --- a/controlplane/configconverter.cpp +++ b/controlplane/configconverter.cpp @@ -113,9 +113,9 @@ void config_converter_t::convertToFlow(const std::string& nextModule, { flow.type = common::globalBase::eFlowType::route_local; } - else if (entry == "tunnel") + else if (entry == "tunnel" || entry == "tunnel_ipip") { - flow.type = common::globalBase::eFlowType::route_tunnel; + flow.type = (entry == "tunnel" ? common::globalBase::eFlowType::route_tunnel : common::globalBase::eFlowType::route_tunnel_ipip); if (!it->second.tunnel_enabled) { @@ -432,7 +432,8 @@ void config_converter_t::serializeRoutes() { tunnel = {route.ipv4_source_address, route.ipv6_source_address, - route.udp_destination_port}; + route.udp_destination_port, + route.random_source}; } globalbase.emplace_back(common::idp::updateGlobalBase::requestType::update_route, @@ -458,6 +459,7 @@ void config_converter_t::processDecap() if (decap.flow.type != common::globalBase::eFlowType::route && decap.flow.type != common::globalBase::eFlowType::route_tunnel && + decap.flow.type != common::globalBase::eFlowType::route_tunnel_ipip && decap.flow.type != common::globalBase::eFlowType::controlPlane && decap.flow.type != common::globalBase::eFlowType::drop) { @@ -488,6 +490,7 @@ void config_converter_t::processNat64stateful() if (nat64stateful.flow.type != common::globalBase::eFlowType::route && nat64stateful.flow.type != common::globalBase::eFlowType::route_tunnel && + nat64stateful.flow.type != common::globalBase::eFlowType::route_tunnel_ipip && nat64stateful.flow.type != common::globalBase::eFlowType::controlPlane && nat64stateful.flow.type != common::globalBase::eFlowType::drop) { @@ -513,6 +516,7 @@ void config_converter_t::processTun64() if (tunnel.flow.type != common::globalBase::eFlowType::route && tunnel.flow.type != common::globalBase::eFlowType::route_tunnel && + tunnel.flow.type != common::globalBase::eFlowType::route_tunnel_ipip && tunnel.flow.type != common::globalBase::eFlowType::controlPlane && tunnel.flow.type != common::globalBase::eFlowType::drop) { @@ -537,6 +541,7 @@ void config_converter_t::processNat64() if (nat64stateless.flow.type != common::globalBase::eFlowType::route && nat64stateless.flow.type != common::globalBase::eFlowType::route_tunnel && + nat64stateless.flow.type != common::globalBase::eFlowType::route_tunnel_ipip && nat64stateless.flow.type != common::globalBase::eFlowType::controlPlane && nat64stateless.flow.type != common::globalBase::eFlowType::drop) { @@ -596,6 +601,7 @@ void config_converter_t::processNat46clat() if (nat46clat.flow.type != common::globalBase::eFlowType::route && nat46clat.flow.type != common::globalBase::eFlowType::route_tunnel && + nat46clat.flow.type != common::globalBase::eFlowType::route_tunnel_ipip && nat46clat.flow.type != common::globalBase::eFlowType::controlPlane && nat46clat.flow.type != common::globalBase::eFlowType::drop) { @@ -766,6 +772,10 @@ void config_converter_t::processAcl() { acl_rules_route_forward(acl, nextModule); } + else if (entry == "tunnel_ipip") + { + acl_rules_route_forward(acl, nextModule); + } else { acl_rules_route_local(acl, nextModule); diff --git a/controlplane/configparser.cpp b/controlplane/configparser.cpp index 92054e4c..3531f6a9 100644 --- a/controlplane/configparser.cpp +++ b/controlplane/configparser.cpp @@ -367,6 +367,11 @@ void config_parser_t::loadConfig_route(controlplane::base_t& baseNext, route.tunnel_enabled = false; } + if (exist(moduleJson, "random_source")) + { + route.random_source = moduleJson["random_source"].get(); + } + // route.routeId = routeId; @@ -1900,6 +1905,12 @@ void config_parser_t::loadConfig_rib(controlplane::base_t& baseNext, controlplane::base_rib base_rib; base_rib.prefix = json_rib_item["prefix"].get(); base_rib.nexthop = json_rib_item["nexthop"].get(); + base_rib.is_tunnel = (exist(json_rib_item, "tunnel") && json_rib_item["tunnel"].get()); + if (base_rib.is_tunnel) + { + base_rib.path_information = (exist(json_rib_item, "path_information") ? json_rib_item["path_information"].get() : YANET_DEFAULT_ROUTE_TUNNEL_PATH_INFORMATION); + base_rib.label = (exist(json_rib_item, "label") ? json_rib_item["label"].get() : YANET_DEFAULT_ROUTE_TUNNEL_LABEL); + } vrf.emplace_back(std::move(base_rib)); } diff --git a/controlplane/dregress.cpp b/controlplane/dregress.cpp index 21156075..a9eb8b8f 100644 --- a/controlplane/dregress.cpp +++ b/controlplane/dregress.cpp @@ -82,7 +82,7 @@ void dregress_t::prefix_insert(const std::tuple& vrf_prio { try { - communities.emplace(13238, std::stoll(path_info.substr(pi_it + 1), nullptr, 0)); ///< @todo: remove 13238, and use RD + communities.emplace(YANET_DEFAULT_BGP_AS, std::stoll(path_info.substr(pi_it + 1), nullptr, 0)); } catch (...) { diff --git a/controlplane/rib.cpp b/controlplane/rib.cpp index 2576a699..032305bc 100644 --- a/controlplane/rib.cpp +++ b/controlplane/rib.cpp @@ -84,10 +84,21 @@ void rib_t::reload([[maybe_unused]] const controlplane::base_t& base_prev, for (const auto& rib_item : rib_items) { - auto& prefixes = std::get<3>(request_insert)[{ip_address_t("::"), "", 0, {}, {}, {}, 0}] - [""] - [rib_item.nexthop]; - prefixes.emplace_back(rib_item.prefix, "", std::vector()); + if (rib_item.is_tunnel) + { + common::large_community_t large_community(YANET_DEFAULT_BGP_AS, 1, 1); + auto& prefixes = std::get<3>(request_insert)[{ip_address_t("::"), "", 0, {}, {}, {large_community}, 0}] + [""] + [rib_item.nexthop]; + prefixes.emplace_back(rib_item.prefix, rib_item.path_information, std::vector(1, rib_item.label)); + } + else + { + auto& prefixes = std::get<3>(request_insert)[{ip_address_t("::"), "", 0, {}, {}, {}, 0}] + [""] + [rib_item.nexthop]; + prefixes.emplace_back(rib_item.prefix, "", std::vector()); + } } request.emplace_back(std::move(request_insert)); diff --git a/controlplane/route.cpp b/controlplane/route.cpp index 73e0380b..fc5dd54c 100644 --- a/controlplane/route.cpp +++ b/controlplane/route.cpp @@ -78,7 +78,10 @@ eResult route_t::init() return eResult::success; } -void route_t::prefix_update(const std::tuple& vrf_priority, const ip_prefix_t& prefix, const std::vector& pptns, const std::variant& value) +void route_t::prefix_update(const rib::vrf_priority_t& vrf_priority, + const ip_prefix_t& prefix, + const std::vector& pptns, + const std::variant& value) { const auto& [vrf, priority] = vrf_priority; @@ -189,7 +192,9 @@ void route_t::prefix_update(const std::tuple& vrf_priorit } } -void route_t::tunnel_prefix_update(const std::tuple& vrf_priority_orig, const ip_prefix_t& prefix, const std::variant>& value) +void route_t::tunnel_prefix_update(const rib::vrf_priority_t& vrf_priority_orig, + const ip_prefix_t& prefix, + const std::variant>& value) { auto vrf_priority = vrf_priority_orig; auto& [vrf, priority] = vrf_priority; @@ -247,13 +252,13 @@ void route_t::tunnel_prefix_update(const std::tuple& vrf_ for (const auto& large_community : large_communities) { - if (large_community.value[0] == 13238 && ///< @todo: DEFINE + if (large_community.value[0] == YANET_DEFAULT_BGP_AS && large_community.value[1] == 1) ///< @todo: DEFINE { weight = large_community.value[2]; } - if (large_community.value[0] == 13238 && ///< @todo: DEFINE + if (large_community.value[0] == YANET_DEFAULT_BGP_AS && large_community.value[1] == 1000) ///< @todo: DEFINE { override_length = large_community.value[2]; @@ -315,6 +320,10 @@ void route_t::tunnel_prefix_update(const std::tuple& vrf_ destination_next = destination_legacy_next.begin()->second; } } + else if (const auto directly_connected = std::get_if(&value)) + { + destination_next = *directly_connected; + } else if (const auto virtual_port_id = std::get_if(&value)) { destination_next = *virtual_port_id; @@ -968,6 +977,10 @@ void route_t::reload(const controlplane::base_t& base_prev, ip_prefix.applyMask(ip_prefix.mask()), {}, std::monostate()); + + tunnel_prefix_update({"default", YANET_RIB_PRIORITY_ROUTE_REPEAT}, + ip_prefix.applyMask(ip_prefix.mask()), + std::monostate()); } } } @@ -990,6 +1003,10 @@ void route_t::reload(const controlplane::base_t& base_prev, ip_prefix.applyMask(ip_prefix.mask()), {}, directly_connected); + + tunnel_prefix_update({"default", YANET_RIB_PRIORITY_ROUTE_REPEAT}, + ip_prefix.applyMask(ip_prefix.mask()), + directly_connected); } } } @@ -1711,6 +1728,19 @@ void route_t::tunnel_value_compile(common::idp::updateGlobalBase::request& globa } } } + else if (const auto directly_connected = std::get_if(&destination)) + { + const auto& [interface_id, interface_name] = *directly_connected; + + request_interface.emplace_back(ipv4_address_t(), ///< default + interface_id, + 3, ///< @todo: DEFINE + interface_name, + 0, + 0, + 1, + ipv4_address_t()); ///< default + } else if (const auto virtual_port_id = std::get_if(&destination)) { controlPlane->forEachSocket([this, &value_id, &globalbase](const tSocketId& socket_id) { diff --git a/controlplane/route.h b/controlplane/route.h index 890bb7e9..3e1e1d66 100644 --- a/controlplane/route.h +++ b/controlplane/route.h @@ -30,21 +30,20 @@ using destination_t = std::variant; ///< virtual_port_id -using value_key_t = std::tuple, ///< priority - route::destination_t, +using value_key_t = std::tuple; ///< fallback -using value_interface_t = std::tuple, +using value_interface_t = std::tuple, ///< labels ip_address_t, ///< neighbor_address uint32_t, ///< peer_id ip_prefix_t>; ///< prefix using lookup_t = std::tuple>; ///< labels using route_counter_key_t = std::tuple; ///< nexthop using tunnel_destination_default_t = std::tuple<>; using tunnel_destination_t = std::variant< - tunnel_destination_interface_t, + tunnel_destination_interface_t, ///< nexthops tunnel_destination_legacy_t, tunnel_destination_default_t, + directly_connected_destination_t, ///< via interface uint32_t>; ///< virtual_port_id -using tunnel_value_key_t = std::tuple, ///< priority - route::tunnel_destination_t, +using tunnel_value_key_t = std::tuple; ///< fallback using tunnel_value_interface_t = std::tuple& vrf_priority, const ip_prefix_t& prefix, const std::vector& pptns, const std::variant& value); - void tunnel_prefix_update(const std::tuple& vrf_priority_orig, const ip_prefix_t& prefix, const std::variant>& value); + void prefix_update(const rib::vrf_priority_t& vrf_priority, + const ip_prefix_t& prefix, + const std::vector& pptns, + const std::variant& value); + void tunnel_prefix_update(const rib::vrf_priority_t& vrf_priority_orig, + const ip_prefix_t& prefix, + const std::variant>& value); void prefix_flush(); @@ -246,13 +250,27 @@ class route_t : public module_t std::optional value_insert(const route::value_key_t& value_key); void value_remove(const uint32_t& value_id); - void value_compile(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, const route::value_key_t& value_key); - void value_compile_label(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, const std::vector& service_labels, std::vector& request_interface, const ip_address_t& first_nexthop); - void value_compile_fallback(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, std::vector& request_interface); + void value_compile(common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + const uint32_t& value_id, + const route::value_key_t& value_key); + void value_compile_label(common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + const uint32_t& value_id, + const std::vector& service_labels, + std::vector& request_interface, + const ip_address_t& first_nexthop); + void value_compile_fallback(common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + const uint32_t& value_id, + std::vector& request_interface); std::optional tunnel_value_insert(const route::tunnel_value_key_t& value_key); void tunnel_value_remove(const uint32_t& value_id); - void tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, const route::generation_t& generation, const uint32_t& value_id, const route::tunnel_value_key_t& value); + void tunnel_value_compile(common::idp::updateGlobalBase::request& globalbase, + const route::generation_t& generation, + const uint32_t& value_id, + const route::tunnel_value_key_t& value); std::set get_ingress_physical_ports(const tSocketId& socket_id); diff --git a/dataplane/globalbase.cpp b/dataplane/globalbase.cpp index e199c004..3afbcc67 100644 --- a/dataplane/globalbase.cpp +++ b/dataplane/globalbase.cpp @@ -635,7 +635,8 @@ static bool checkFlow(const common::globalBase::tFlow& flow) } } else if (flow.type == common::globalBase::eFlowType::route || - flow.type == common::globalBase::eFlowType::route_tunnel) + flow.type == common::globalBase::eFlowType::route_tunnel || + flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { if (flow.data.routeId >= CONFIG_YADECAP_ROUTES_SIZE) { @@ -837,6 +838,7 @@ eResult generation::tun64_update(const common::idp::updateGlobalBase::tun64_upda if (flow.type != common::globalBase::eFlowType::route && flow.type != common::globalBase::eFlowType::route_tunnel && + flow.type != common::globalBase::eFlowType::route_tunnel_ipip && flow.type != common::globalBase::eFlowType::controlPlane && flow.type != common::globalBase::eFlowType::drop) { @@ -939,6 +941,7 @@ eResult generation::updateDecap(const common::idp::updateGlobalBase::updateDecap } if (flow.type != common::globalBase::eFlowType::route && flow.type != common::globalBase::eFlowType::route_tunnel && + flow.type != common::globalBase::eFlowType::route_tunnel_ipip && flow.type != common::globalBase::eFlowType::controlPlane && flow.type != common::globalBase::eFlowType::drop) { @@ -1039,11 +1042,12 @@ eResult generation::update_route(const common::idp::updateGlobalBase::update_rou if (tunnel) { - const auto& [ipv4AddressSource, ipv6AddressSource, udpDestinationPort] = *tunnel; + const auto& [ipv4AddressSource, ipv6AddressSource, udpDestinationPort, randomSource] = *tunnel; route.ipv4AddressSource = ipv4_address_t::convert(ipv4AddressSource); route.ipv6AddressSource = ipv6_address_t::convert(ipv6AddressSource); route.udpDestinationPort = rte_cpu_to_be_16(udpDestinationPort); + route.randomSource = randomSource; } return eResult::success; @@ -1109,6 +1113,7 @@ eResult generation::nat64stateful_update(const common::idp::updateGlobalBase::na } if (flow.type != common::globalBase::eFlowType::route && flow.type != common::globalBase::eFlowType::route_tunnel && + flow.type != common::globalBase::eFlowType::route_tunnel_ipip && flow.type != common::globalBase::eFlowType::controlPlane && flow.type != common::globalBase::eFlowType::drop) { @@ -1210,6 +1215,7 @@ eResult generation::updateNat64stateless(const common::idp::updateGlobalBase::up } if (flow.type != common::globalBase::eFlowType::route && flow.type != common::globalBase::eFlowType::route_tunnel && + flow.type != common::globalBase::eFlowType::route_tunnel_ipip && flow.type != common::globalBase::eFlowType::controlPlane && flow.type != common::globalBase::eFlowType::drop) { @@ -1318,6 +1324,7 @@ eResult generation::nat46clat_update(const common::idp::updateGlobalBase::nat46c if (flow.type != common::globalBase::eFlowType::route && flow.type != common::globalBase::eFlowType::route_tunnel && + flow.type != common::globalBase::eFlowType::route_tunnel_ipip && flow.type != common::globalBase::eFlowType::controlPlane && flow.type != common::globalBase::eFlowType::drop) { diff --git a/dataplane/report.cpp b/dataplane/report.cpp index 3339c625..ce483613 100644 --- a/dataplane/report.cpp +++ b/dataplane/report.cpp @@ -554,6 +554,11 @@ static inline nlohmann::json convertFlow(const common::globalBase::tFlow& flow) result["type"] = "route_tunnel"; result["id"] = flow.data.routeId; } + else if (flow.type == common::globalBase::eFlowType::route_tunnel_ipip) + { + result["type"] = "route_tunnel_ipip"; + result["id"] = flow.data.routeId; + } else if (flow.type == common::globalBase::eFlowType::acl_egress) { result["type"] = "acl_egress"; diff --git a/dataplane/type.h b/dataplane/type.h index cf55b213..3c2bf8ff 100644 --- a/dataplane/type.h +++ b/dataplane/type.h @@ -287,6 +287,7 @@ struct route_t ipv4_address_t ipv4AddressSource; ipv6_address_t ipv6AddressSource; uint16_t udpDestinationPort; + bool randomSource; }; struct tInterface diff --git a/dataplane/worker.cpp b/dataplane/worker.cpp index 88f3f720..9fd81cd9 100644 --- a/dataplane/worker.cpp +++ b/dataplane/worker.cpp @@ -1223,7 +1223,7 @@ inline void cWorker::logicalPort_ingress_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -1774,7 +1774,7 @@ inline void cWorker::acl_ingress_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -1951,7 +1951,7 @@ inline void cWorker::tun64_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -2021,7 +2021,7 @@ inline void cWorker::decap_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -2720,6 +2720,7 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, return; } + bool is_ipip_tunnel = (metadata->flow.type == common::globalBase::eFlowType::route_tunnel_ipip); uint16_t payload_length = 0; bool is_ipv4 = metadata->network_headerType == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); if (is_ipv4 && !nexthop.is_ipv6) @@ -2727,9 +2728,10 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, rte_ipv4_hdr* ipv4HeaderInner = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); /// @todo: mpls_header_t - rte_pktmbuf_prepend(mbuf, sizeof(rte_ipv4_hdr) + sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE); + size_t size_mbuf = sizeof(rte_ipv4_hdr) + (is_ipip_tunnel ? 0 : sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE); + rte_pktmbuf_prepend(mbuf, size_mbuf); rte_memcpy(rte_pktmbuf_mtod(mbuf, char*), - rte_pktmbuf_mtod_offset(mbuf, char*, sizeof(rte_ipv4_hdr) + sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE), + rte_pktmbuf_mtod_offset(mbuf, char*, size_mbuf), metadata->network_headerOffset); /// @todo: check for ethernetHeader or vlanHeader @@ -2740,11 +2742,11 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, ipv4Header->version_ihl = 0x45; ipv4Header->type_of_service = ipv4HeaderInner->type_of_service; - ipv4Header->total_length = rte_cpu_to_be_16((sizeof(rte_ipv4_hdr) + sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE) + rte_be_to_cpu_16(ipv4HeaderInner->total_length)); + ipv4Header->total_length = rte_cpu_to_be_16(size_mbuf + rte_be_to_cpu_16(ipv4HeaderInner->total_length)); ipv4Header->packet_id = ipv4HeaderInner->packet_id; ipv4Header->fragment_offset = 0; ipv4Header->time_to_live = 64; - ipv4Header->next_proto_id = IPPROTO_UDP; + ipv4Header->next_proto_id = (is_ipip_tunnel ? IPPROTO_IPIP : IPPROTO_UDP); ipv4Header->hdr_checksum = 0; ipv4Header->src_addr = route.ipv4AddressSource.address; ipv4Header->dst_addr = nexthop.nexthop_address.mapped_ipv4_address.address; @@ -2759,12 +2761,14 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, { uint32_t vtc_flow = 0; uint16_t payload_len = 0; + uint32_t ipv4_src_addr; if (is_ipv4) { rte_ipv4_hdr* ipv4HeaderInner = rte_pktmbuf_mtod_offset(mbuf, rte_ipv4_hdr*, metadata->network_headerOffset); vtc_flow = rte_cpu_to_be_32((0x6 << 28) | (ipv4HeaderInner->type_of_service << 20)); ///< @todo: flow label - payload_len = rte_cpu_to_be_16(sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE + rte_be_to_cpu_16(ipv4HeaderInner->total_length)); + payload_len = rte_cpu_to_be_16((is_ipip_tunnel ? 0 : sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE) + rte_be_to_cpu_16(ipv4HeaderInner->total_length)); payload_length = rte_be_to_cpu_16(ipv4HeaderInner->total_length); + ipv4_src_addr = ipv4HeaderInner->src_addr; } else { @@ -2775,9 +2779,10 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, } /// @todo: mpls_header_t - rte_pktmbuf_prepend(mbuf, sizeof(rte_ipv6_hdr) + sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE); + size_t size_mbuf = sizeof(rte_ipv6_hdr) + (is_ipip_tunnel ? 0 : sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE); + rte_pktmbuf_prepend(mbuf, size_mbuf); rte_memcpy(rte_pktmbuf_mtod(mbuf, char*), - rte_pktmbuf_mtod_offset(mbuf, char*, sizeof(rte_ipv6_hdr) + sizeof(rte_udp_hdr) + YADECAP_MPLS_HEADER_SIZE), + rte_pktmbuf_mtod_offset(mbuf, char*, size_mbuf), metadata->network_headerOffset); /// @todo: check for ethernetHeader or vlanHeader @@ -2789,14 +2794,20 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, ipv6Header->vtc_flow = vtc_flow; ipv6Header->payload_len = payload_len; - ipv6Header->proto = IPPROTO_UDP; + ipv6Header->proto = (is_ipip_tunnel ? IPPROTO_IPIP : IPPROTO_UDP); ipv6Header->hop_limits = 64; rte_memcpy(ipv6Header->src_addr, route.ipv6AddressSource.bytes, 16); rte_memcpy(ipv6Header->dst_addr, nexthop.nexthop_address.bytes, 16); + if (route.randomSource && is_ipv4) + { + ((uint32_t*)ipv6Header->src_addr)[2] = ipv4_src_addr; + } + metadata->transport_headerOffset = metadata->network_headerOffset + sizeof(rte_ipv6_hdr); } + if (!is_ipip_tunnel) { rte_udp_hdr* udpHeader = rte_pktmbuf_mtod_offset(mbuf, rte_udp_hdr*, metadata->transport_headerOffset); @@ -2806,6 +2817,7 @@ inline void cWorker::route_tunnel_nexthop(rte_mbuf* mbuf, udpHeader->dgram_cksum = 0; } + if (!is_ipip_tunnel) { uint32_t* mplsHeaderTransport = rte_pktmbuf_mtod_offset(mbuf, uint32_t*, metadata->transport_headerOffset + sizeof(rte_udp_hdr)); @@ -3176,7 +3188,7 @@ inline void cWorker::nat64stateful_lan_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -3335,7 +3347,7 @@ inline void cWorker::nat64stateful_wan_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -3415,7 +3427,7 @@ inline void cWorker::nat64stateless_ingress_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -3534,7 +3546,7 @@ inline void cWorker::nat64stateless_egress_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -3706,7 +3718,7 @@ inline void cWorker::nat46clat_lan_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -3785,7 +3797,7 @@ inline void cWorker::nat46clat_wan_flow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); } @@ -5829,7 +5841,7 @@ YANET_NEVER_INLINE void cWorker::slowWorkerFlow(rte_mbuf* mbuf, { route_entry(mbuf); } - else if (flow.type == common::globalBase::eFlowType::route_tunnel) + else if (flow.type == common::globalBase::eFlowType::route_tunnel || flow.type == common::globalBase::eFlowType::route_tunnel_ipip) { route_tunnel_entry(mbuf); }