# Copyright (c) 2018 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*** Settings ***
| Resource | resources/libraries/robot/performance/performance_setup.robot
| Library | resources.libraries.python.QemuUtils
| ...
| Force Tags | 3_NODE_SINGLE_LINK_TOPO | PERFTEST | HW_ENV | MRR
| ... | NIC_Intel-X710 | ETH | IP4FWD | BASE | VHOST | 1VM | VHOST_1024
| ...
| Suite Setup | Set up 3-node performance topology with DUT's NIC model
| ... | L3 | Intel-X710
| Suite Teardown | Tear down 3-node performance topology
| ...
| Test Setup | Set up performance test
| Test Teardown | Tear down performance mrr test with vhost and VM with dpdk-testpmd
| ... | dut1_node=${dut1} | dut1_vm_refs=${dut1_vm_refs}
| ... | dut2_node=${dut2} | dut2_vm_refs=${dut2_vm_refs}
| ...
| Documentation | *Raw results IPv4 test cases with vhost*
| ...
| ... | *[Top] Network Topologies:* TG-DUT1-DUT2-TG 3-node circular topology
| ... | with single links between nodes.
| ... | *[Enc] Packet Encapsulations:* Eth-IPv4 for IPv4 routing.
| ... | *[Cfg] DUT configuration:* DUT1 and DUT2 are configured with IPv4
| ... | routing and two static IPv4 /24 route entries. Qemu Guest is connected
| ... | to VPP via vhost-user interfaces. Guest is running DPDK testpmd
| ... | interconnecting vhost-user interfaces using 5 cores pinned to cpus 5-9
| ... | and 2048M memory. Testpmd is using socket-mem=1024M (512x2M hugepages),
| ... | 5 cores (1 main core and 4 cores dedicated for io), forwarding mode is
| ... | set to mac, rxd/txd=1024, burst=64. DUT1, DUT2 are tested with 2p10GE
| ... | NIC X710 by Intel.
| ... | *[Ver] TG verification:* In MaxReceivedRate test TG sends traffic
| ... | at line rate and reports total received/sent packets over trial period.
| ... | Test packets are generated by TG on links to DUTs. TG traffic profile
| ... | contains two L3 flow-groups (flow-group per direction, 253 flows per
| ... | flow-group) with all packets containing Ethernet header, IPv4 header
| ... | with IP protocol=61 and static payload. MAC addresses are matching MAC
| ... | addresses of the TG node interfaces.
*** Variables ***
| ${perf_qemu_qsz}= | 1024
# Socket names
| ${sock1}= | /tmp/sock-1
| ${sock2}= | /tmp/sock-2
# FIB tables
| ${fib_table_1}= | 100
| ${fib_table_2}= | 101
# X710 bandwidth limit
| ${s_limit}= | ${10000000000}
# Traffic profile:
| ${traffic_profile} | trex-sl-3n-ethip4-ip4src253
*** Keywords ***
| Check RR for ethip4-ip4base-eth-2vhostvr1024-1vm
| | [Documentation]
| | ... | [Cfg] DUT runs IPv4 routing config with ${wt} thread, ${wt} phy\
| | ... | core, ${rxq} receive queue per NIC port.
| | ... | [Ver] Measure MaxReceivedRate for ${framesize
@media only all and (prefers-color-scheme: dark) {
.highlight .hll { background-color: #49483e }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .ch { color: #75715e } /* Comment.Hashbang */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .cpf { color: #75715e } /* Comment.PreprocFile */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sa { color: #e6db74 } /* Literal.String.Affix */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #a6e22e } /* Name.Function.Magic */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
}
@media (prefers-color-scheme: light) {
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
}
#!/usr/bin/env python3
"""GSO functional tests"""
#
# Add tests for:
# - GSO
# - Verify that sending Jumbo frame without GSO enabled correctly
# - Verify that sending Jumbo frame with GSO enabled correctly
# - Verify that sending Jumbo frame with GSO enabled only on ingress interface
#
import unittest
from scapy.packet import Raw
from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig
from scapy.layers.inet6 import ipv6nh, IPerror6
from scapy.layers.inet import TCP, ICMP
from scapy.layers.vxlan import VXLAN
from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
from scapy.layers.ipsec import SecurityAssociation, ESP
from vpp_papi import VppEnum
from framework import VppTestCase, VppTestRunner
from vpp_object import VppObject
from vpp_interface import VppInterface
from vpp_ip import DpoProto
from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
from vpp_ipip_tun_interface import VppIpIpTunInterface
from vpp_vxlan_tunnel import VppVxlanTunnel
from socket import AF_INET, AF_INET6, inet_pton
from util import reassemble4
from vpp_ipsec import VppIpsecSA, VppIpsecTunProtect
from template_ipsec import IPsecIPv4Params, IPsecIPv6Params, \
mk_scapy_crypt_key, config_tun_params
""" Test_gso is a subclass of VPPTestCase classes.
GSO tests.
"""
class TestGSO(VppTestCase):
""" GSO Test Case """
def __init__(self, *args):
VppTestCase.__init__(self, *args)
@classmethod
def setUpClass(self):
super(TestGSO, self).setUpClass()
res = self.create_pg_interfaces(range(2))
res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460)
self.create_pg_interfaces(range(4, 5), 1, 8940)
self.pg_interfaces.append(res[0])
self.pg_interfaces.append(res[1])
self.pg_interfaces.append(res_gso[0])
self.pg_interfaces.append(res_gso[1])
@classmethod
def tearDownClass(self):
super(TestGSO, self).tearDownClass()
def setUp(self):
super(TestGSO, self).setUp()
for i in self.pg_interfaces:
i.admin_up()
i.config_ip4()
i.config_ip6()
i.disable_ipv6_ra()
i.resolve_arp()
i.resolve_ndp()
self.single_tunnel_bd = 10
self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4,
dst=self.pg0.remote_ip4,
vni=self.single_tunnel_bd)
self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6,
dst=self.pg0.remote_ip6,
vni=self.single_tunnel_bd)
self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4,
self.pg0.remote_ip4)
self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6,
self.pg0.remote_ip6)
def tearDown(self):
super(TestGSO, self).tearDown()
if not self.vpp_dead:
for i in self.pg_interfaces:
i.unconfig_ip4()
i.unconfig_ip6()
i.admin_down()
def test_gso(self):
""" GSO test """
#
# Send jumbo frame with gso disabled and DF bit is set
#
p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4,
flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg0, [p4], self.pg0)
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assertEqual(rx[ICMP].type, 3) # "dest-unreach"
self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed"
#
# Send checksum offload frames
#
p40 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 1460))
rxs = self.send_and_expect(self.pg2, 100*[p40], self.pg0)
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
payload_len = rx[IP].len - 20 - 20
self.assert_ip_checksum_valid(rx)
self.assert_tcp_checksum_valid(rx)
self.assertEqual(payload_len, len(rx[Raw]))
p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 1440))
rxs = self.send_and_expect(self.pg2, 100*[p60], self.pg0)
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
payload_len = rx[IPv6].plen - 20
self.assert_tcp_checksum_valid(rx)
self.assertEqual(payload_len, len(rx[Raw]))
#
# Send jumbo frame with gso enabled and DF bit is set
# input and output interfaces support GSO
#
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg3.sw_if_index,
enable_disable=1)
p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4,
flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 100*[p41], self.pg3, 100)
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg3.local_mac)
self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP)
self.assertEqual(rx[TCP].sport, 1234)
self.assertEqual(rx[TCP].dport, 1234)
#
# ipv6
#
p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 100*[p61], self.pg3, 100)
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg3.local_mac)
self.assertEqual(rx[Ether].dst, self.pg3.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6)
self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP)
self.assertEqual(rx[TCP].sport, 1234)
self.assertEqual(rx[TCP].dport, 1234)
#
# Send jumbo frame with gso enabled only on input interface
# and DF bit is set. GSO packet will be chunked into gso_size
# data payload
#
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=1)
p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4,
flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p42], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP)
self.assert_ip_checksum_valid(rx)
self.assert_tcp_checksum_valid(rx)
self.assertEqual(rx[TCP].sport, 1234)
self.assertEqual(rx[TCP].dport, 1234)
self.assertEqual(payload_len, len(rx[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# ipv6
#
p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p62], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
payload_len = rx[IPv6].plen - 20
self.assert_tcp_checksum_valid(rx)
self.assertEqual(rx[TCP].sport, 1234)
self.assertEqual(rx[TCP].dport, 1234)
self.assertEqual(payload_len, len(rx[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# Send jumbo frame with gso enabled only on input interface
# and DF bit is unset. GSO packet will be fragmented.
#
self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
enable_disable=1)
p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p43], self.pg1, 5*119)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg1.local_mac)
self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
self.assertEqual(rx[IP].src, self.pg2.remote_ip4)
self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
self.assert_ip_checksum_valid(rx)
size += rx[IP].len - 20
size -= 20*5 # TCP header
self.assertEqual(size, 65200*5)
#
# IPv6
# Send jumbo frame with gso enabled only on input interface.
# ICMPv6 Packet Too Big will be sent back to sender.
#
self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) /
IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p63], self.pg2, 5)
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg2.local_mac)
self.assertEqual(rx[Ether].dst, self.pg2.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg2.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6)
self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header
self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6")
self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280)
self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6)
self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6)
self.assertEqual(rx[IPerror6].plen - 20, 65200)
#
# Send jumbo frame with gso enabled only on input interface with 9K MTU
# and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO
# size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size
#
self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0])
p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg4, 5*[p44], self.pg1, 165)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg1.local_mac)
self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
self.assertEqual(rx[IP].src, self.pg4.remote_ip4)
self.assertEqual(rx[IP].dst, self.pg1.remote_ip4)
payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP)
self.assert_ip_checksum_valid(rx)
self.assert_tcp_checksum_valid(rx)
self.assertEqual(payload_len, len(rx[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# IPv6
#
p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg4, 5*[p64], self.pg1, 170)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg1.local_mac)
self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6)
self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6)
payload_len = rx[IPv6].plen - 20
self.assert_tcp_checksum_valid(rx)
self.assertEqual(payload_len, len(rx[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=0)
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index,
enable_disable=0)
def test_gso_vxlan(self):
""" GSO VXLAN test """
self.logger.info(self.vapi.cli("sh int addr"))
#
# Send jumbo frame with gso enabled only on input interface and
# create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2
# into BD.
#
#
# enable ipv4/vxlan
#
self.vxlan.add_vpp_config()
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd)
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd)
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=1)
#
# IPv4/IPv4 - VXLAN
#
p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p45], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assert_ip_checksum_valid(rx)
self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
self.assertEqual(rx[VXLAN].vni, 10)
inner = rx[VXLAN].payload
self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.3.3")
self.assert_ip_checksum_valid(inner)
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IP].len - 20 - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# IPv4/IPv6 - VXLAN
#
p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p65], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assert_ip_checksum_valid(rx)
self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
self.assertEqual(rx[VXLAN].vni, 10)
inner = rx[VXLAN].payload
self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:3::3")
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IPv6].plen - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# disable ipv4/vxlan
#
self.vxlan.remove_vpp_config()
#
# enable ipv6/vxlan
#
self.vxlan2.add_vpp_config()
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.vxlan2.sw_if_index,
bd_id=self.single_tunnel_bd)
#
# IPv6/IPv4 - VXLAN
#
p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p46], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
self.assertEqual(rx[VXLAN].vni, 10)
inner = rx[VXLAN].payload
self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.3.3")
self.assert_ip_checksum_valid(inner)
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IP].len - 20 - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# IPv6/IPv6 - VXLAN
#
p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p66], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False)
self.assertEqual(rx[VXLAN].vni, 10)
inner = rx[VXLAN].payload
self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:3::3")
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IPv6].plen - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# disable ipv4/vxlan
#
self.vxlan2.remove_vpp_config()
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=0)
def test_gso_ipip(self):
""" GSO IPIP test """
self.logger.info(self.vapi.cli("sh int addr"))
#
# Send jumbo frame with gso enabled only on input interface and
# create IPIP tunnel on VPP pg0.
#
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=1)
#
# enable ipip4
#
self.ipip4.add_vpp_config()
# Set interface up and enable IP on it
self.ipip4.admin_up()
self.ipip4.set_unnumbered(self.pg0.sw_if_index)
# Add IPv4 routes via tunnel interface
self.ip4_via_ip4_tunnel = VppIpRoute(
self, "172.16.10.0", 24,
[VppRoutePath("0.0.0.0",
self.ipip4.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
self.ip4_via_ip4_tunnel.add_vpp_config()
#
# IPv4/IPv4 - IPIP
#
p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assert_ip_checksum_valid(rx)
self.assertEqual(rx[IP].proto, 4) # ipencap
inner = rx[IP].payload
self.assertEqual(rx[IP].len - 20, len(inner))
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.10.3")
self.assert_ip_checksum_valid(inner)
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IP].len - 20 - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
self.ip6_via_ip4_tunnel = VppIpRoute(
self, "fd01:10::", 64,
[VppRoutePath("::",
self.ipip4.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
self.ip6_via_ip4_tunnel.add_vpp_config()
#
# IPv4/IPv6 - IPIP
#
p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p67], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assert_ip_checksum_valid(rx)
self.assertEqual(rx[IP].proto, 41) # ipv6
inner = rx[IP].payload
self.assertEqual(rx[IP].len - 20, len(inner))
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:10::3")
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IPv6].plen - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# Send jumbo frame with gso enabled only on input interface and
# create IPIP tunnel on VPP pg0. Enable gso feature node on ipip
# tunnel - IPSec use case
#
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=0)
self.vapi.feature_gso_enable_disable(
sw_if_index=self.ipip4.sw_if_index,
enable_disable=1)
rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assert_ip_checksum_valid(rx)
self.assertEqual(rx[IP].proto, 4) # ipencap
inner = rx[IP].payload
self.assertEqual(rx[IP].len - 20, len(inner))
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.10.3")
self.assert_ip_checksum_valid(inner)
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IP].len - 20 - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# disable ipip4
#
self.vapi.feature_gso_enable_disable(
sw_if_index=self.ipip4.sw_if_index,
enable_disable=0)
self.ip4_via_ip4_tunnel.remove_vpp_config()
self.ip6_via_ip4_tunnel.remove_vpp_config()
self.ipip4.remove_vpp_config()
#
# enable ipip6
#
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=1)
self.ipip6.add_vpp_config()
# Set interface up and enable IP on it
self.ipip6.admin_up()
self.ipip6.set_unnumbered(self.pg0.sw_if_index)
# Add IPv4 routes via tunnel interface
self.ip4_via_ip6_tunnel = VppIpRoute(
self, "172.16.10.0", 24,
[VppRoutePath("0.0.0.0",
self.ipip6.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
self.ip4_via_ip6_tunnel.add_vpp_config()
#
# IPv6/IPv4 - IPIP
#
p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p48], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
self.assertEqual(ipv6nh[rx[IPv6].nh], "IP")
inner = rx[IPv6].payload
self.assertEqual(rx[IPv6].plen, len(inner))
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.10.3")
self.assert_ip_checksum_valid(inner)
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IP].len - 20 - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
self.ip6_via_ip6_tunnel = VppIpRoute(
self, "fd01:10::", 64,
[VppRoutePath("::",
self.ipip6.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
self.ip6_via_ip6_tunnel.add_vpp_config()
#
# IPv6/IPv6 - IPIP
#
p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, 5*[p68], self.pg0, 225)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6")
inner = rx[IPv6].payload
self.assertEqual(rx[IPv6].plen, len(inner))
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:10::3")
self.assert_tcp_checksum_valid(inner)
payload_len = inner[IPv6].plen - 20
self.assertEqual(payload_len, len(inner[Raw]))
size += payload_len
self.assertEqual(size, 65200*5)
#
# disable ipip6
#
self.ip4_via_ip6_tunnel.remove_vpp_config()
self.ip6_via_ip6_tunnel.remove_vpp_config()
self.ipip6.remove_vpp_config()
self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index,
enable_disable=0)
def test_gso_ipsec(self):
""" GSO IPSEC test """
#
# Send jumbo frame with gso enabled only on input interface and
# create IPIP tunnel on VPP pg0.
#
#
# enable ipip4
#
self.ipip4.add_vpp_config()
self.vapi.feature_gso_enable_disable(
sw_if_index=self.ipip4.sw_if_index, enable_disable=1)
# Add IPv4 routes via tunnel interface
self.ip4_via_ip4_tunnel = VppIpRoute(
self, "172.16.10.0", 24,
[VppRoutePath("0.0.0.0",
self.ipip4.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
self.ip4_via_ip4_tunnel.add_vpp_config()
# IPSec config
self.ipv4_params = IPsecIPv4Params()
self.encryption_type = ESP
config_tun_params(self.ipv4_params, self.encryption_type, self.ipip4)
self.tun_sa_in_v4 = VppIpsecSA(self, self.ipv4_params.vpp_tun_sa_id,
self.ipv4_params.vpp_tun_spi,
self.ipv4_params.auth_algo_vpp_id,
self.ipv4_params.auth_key,
self.ipv4_params.crypt_algo_vpp_id,
self.ipv4_params.crypt_key,
VppEnum.vl_api_ipsec_proto_t.
IPSEC_API_PROTO_ESP)
self.tun_sa_in_v4.add_vpp_config()
self.tun_sa_out_v4 = VppIpsecSA(self, self.ipv4_params.scapy_tun_sa_id,
self.ipv4_params.scapy_tun_spi,
self.ipv4_params.auth_algo_vpp_id,
self.ipv4_params.auth_key,
self.ipv4_params.crypt_algo_vpp_id,
self.ipv4_params.crypt_key,
VppEnum.vl_api_ipsec_proto_t.
IPSEC_API_PROTO_ESP)
self.tun_sa_out_v4.add_vpp_config()
self.tun_protect_v4 = VppIpsecTunProtect(self,
self.ipip4,
self.tun_sa_out_v4,
[self.tun_sa_in_v4])
self.tun_protect_v4.add_vpp_config()
# Set interface up and enable IP on it
self.ipip4.admin_up()
self.ipip4.set_unnumbered(self.pg0.sw_if_index)
#
# IPv4/IPv4 - IPSEC
#
ipsec44 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, [ipsec44], self.pg0, 45)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assertEqual(rx[IP].proto, 50) # ESP
self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi)
inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.10.3")
size += inner[IP].len - 20 - 20
self.assertEqual(size, 65200)
self.ip6_via_ip4_tunnel = VppIpRoute(
self, "fd01:10::", 64,
[VppRoutePath("::",
self.ipip4.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
self.ip6_via_ip4_tunnel.add_vpp_config()
#
# IPv4/IPv6 - IPSEC
#
ipsec46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, [ipsec46], self.pg0, 45)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IP].src, self.pg0.local_ip4)
self.assertEqual(rx[IP].dst, self.pg0.remote_ip4)
self.assertEqual(rx[IP].proto, 50) # ESP
self.assertEqual(rx[ESP].spi, self.ipv4_params.scapy_tun_spi)
inner = self.ipv4_params.vpp_tun_sa.decrypt(rx[IP])
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:10::3")
size += inner[IPv6].plen - 20
self.assertEqual(size, 65200)
# disable IPSec
self.tun_protect_v4.remove_vpp_config()
self.tun_sa_in_v4.remove_vpp_config()
self.tun_sa_out_v4.remove_vpp_config()
#
# disable ipip4
#
self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index,
enable_disable=0)
self.ip4_via_ip4_tunnel.remove_vpp_config()
self.ip6_via_ip4_tunnel.remove_vpp_config()
self.ipip4.remove_vpp_config()
#
# enable ipip6
#
self.ipip6.add_vpp_config()
self.vapi.feature_gso_enable_disable(self.ipip6.sw_if_index,
enable_disable=1)
# Set interface up and enable IP on it
self.ipip6.admin_up()
self.ipip6.set_unnumbered(self.pg0.sw_if_index)
# Add IPv4 routes via tunnel interface
self.ip4_via_ip6_tunnel = VppIpRoute(
self, "172.16.10.0", 24,
[VppRoutePath("0.0.0.0",
self.ipip6.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)])
self.ip4_via_ip6_tunnel.add_vpp_config()
# IPSec config
self.ipv6_params = IPsecIPv6Params()
self.encryption_type = ESP
config_tun_params(self.ipv6_params, self.encryption_type, self.ipip6)
self.tun_sa_in_v6 = VppIpsecSA(self, self.ipv6_params.vpp_tun_sa_id,
self.ipv6_params.vpp_tun_spi,
self.ipv6_params.auth_algo_vpp_id,
self.ipv6_params.auth_key,
self.ipv6_params.crypt_algo_vpp_id,
self.ipv6_params.crypt_key,
VppEnum.vl_api_ipsec_proto_t.
IPSEC_API_PROTO_ESP)
self.tun_sa_in_v6.add_vpp_config()
self.tun_sa_out_v6 = VppIpsecSA(self, self.ipv6_params.scapy_tun_sa_id,
self.ipv6_params.scapy_tun_spi,
self.ipv6_params.auth_algo_vpp_id,
self.ipv6_params.auth_key,
self.ipv6_params.crypt_algo_vpp_id,
self.ipv6_params.crypt_key,
VppEnum.vl_api_ipsec_proto_t.
IPSEC_API_PROTO_ESP)
self.tun_sa_out_v6.add_vpp_config()
self.tun_protect_v6 = VppIpsecTunProtect(self,
self.ipip6,
self.tun_sa_out_v6,
[self.tun_sa_in_v6])
self.tun_protect_v6.add_vpp_config()
#
# IPv6/IPv4 - IPSEC
#
ipsec64 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, [ipsec64], self.pg0, 45)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi)
inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.10.3")
size += inner[IP].len - 20 - 20
self.assertEqual(size, 65200)
self.ip6_via_ip6_tunnel = VppIpRoute(
self, "fd01:10::", 64,
[VppRoutePath("::",
self.ipip6.sw_if_index,
proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)])
self.ip6_via_ip6_tunnel.add_vpp_config()
#
# IPv6/IPv6 - IPSEC
#
ipsec66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") /
IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") /
TCP(sport=1234, dport=1234) /
Raw(b'\xa5' * 65200))
rxs = self.send_and_expect(self.pg2, [ipsec66], self.pg0, 45)
size = 0
for rx in rxs:
self.assertEqual(rx[Ether].src, self.pg0.local_mac)
self.assertEqual(rx[Ether].dst, self.pg0.remote_mac)
self.assertEqual(rx[IPv6].src, self.pg0.local_ip6)
self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6)
self.assertEqual(ipv6nh[rx[IPv6].nh], "ESP Header")
self.assertEqual(rx[ESP].spi, self.ipv6_params.scapy_tun_spi)
inner = self.ipv6_params.vpp_tun_sa.decrypt(rx[IPv6])
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:10::3")
size += inner[IPv6].plen - 20
self.assertEqual(size, 65200)
# disable IPSec
self.tun_protect_v6.remove_vpp_config()
self.tun_sa_in_v6.remove_vpp_config()
self.tun_sa_out_v6.remove_vpp_config()
#
# disable ipip6
#
self.ip4_via_ip6_tunnel.remove_vpp_config()
self.ip6_via_ip6_tunnel.remove_vpp_config()
self.ipip6.remove_vpp_config()
self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index,
enable_disable=0)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)