Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vxlan hw tc offload #342

Merged
merged 6 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions lnst/Recipes/ENRT/SRIOVNetnsVxlanTcRecipe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
from lnst.Common.IpAddress import interface_addresses, AF_INET
from lnst.Common.Parameters import IPv4NetworkParam
from lnst.Devices import VxlanDevice
from lnst.Recipes.ENRT.BaseSRIOVNetnsTcRecipe import BaseSRIOVNetnsTcRecipe


class SRIOVNetnsVxlanTcRecipe(
BaseSRIOVNetnsTcRecipe
):
"""
This recipe implements Enrt testing for a SRIOV network scenario
with VF located in the network namespace to mimic container network.
The traffic between the virtual functions is tunneled through VXLAN.
Tc rules are created to achieve full connectivity between VF of
the hosts.

.. code-block:: none

+--------+
+------+ switch +-------+
| +--------+ |
+-------|------+ +-------|------+
| +--|--+ | | +--|--+ |
+--|----|eth0|--- |--+ +--|----|eth0|--- |--+
| | +----+ | | | | +----+ | |
| | | | | | | | | |
| | vxlan10 | | | | vxlan10 | |
| | | | | | | | | |
| |vf_representor| | | |vf_representor| |
| | | | | | | |
| +--TC filter---+ | | +--TC filter---+ |
| | | | | |
| +-namespace-+ | | +-namespace-+ |
| | vf0 | | | | vf0 | |
| +-----------+ | | +-----------+ |
| host1 | | host2 |
+--------------------+ +--------------------+

All sub configurations are included via Mixin classes.

The actual test machinery is implemented in the :any:`BaseEnrtRecipe` class.
"""

tunnel_net_ipv4 = IPv4NetworkParam(default="192.168.200.0/24")

def add_network_layers(self, config):
"""
VXLAN tunnel is created between PFs on the hosts.
"""

host1, host2 = self.matched.host1, self.matched.host2

# TODO: support also IPv6
tunnel_network = interface_addresses(self.params.tunnel_net_ipv4)
for host in [host1, host2]:
config.configure_and_track_ip(host.eth0, next(tunnel_network))

for host in [host1, host2]:
# TODO: support also IPv6
ip_filter = {"family": AF_INET}
host.vxlan10 = VxlanDevice(
vxlan_id=10,
realdev=host.eth0,
remote=host2.eth0.ips_filter(**ip_filter)[0] if host == host1 else host1.eth0.ips_filter(**ip_filter)[0],
olichtne marked this conversation as resolved.
Show resolved Hide resolved
dst_port=4789,
)

for dev in [host.newns.vf_eth0, host.vf_representor_eth0]:
# TODO: support IPv6, set to 1430
dev.mtu = 1450

host.vxlan10.up()

self.wait_tentative_ips(config.configured_devices)

def add_tc_filter_rules(self, config):
"""
Encapsulation/decapsulation filters are added for ARP an IP traffic.
"""
host1, host2 = self.matched.host1, self.matched.host2

config.ingress_devices = []
# tc configuration
for host in [host1, host2]:
host.run(f"tc qdisc add dev {host.eth0.name} ingress")
host.run(f"tc qdisc add dev {host.vf_representor_eth0.name} ingress")
host.run(f"tc qdisc add dev {host.vxlan10.name} ingress")
config.ingress_devices.extend([host.eth0, host.vf_representor_eth0, host.vxlan10])

# encap rules
# host1
host1.run(
f"tc filter add dev {host1.vf_representor_eth0.name} protocol ip ingress prio 1 "
f"flower src_mac {host1.newns.vf_eth0.hwaddr} dst_mac {host2.newns.vf_eth0.hwaddr} "
f"action tunnel_key set src_ip {host1.eth0.ips_filter(family=AF_INET)[0]} dst_ip {host2.eth0.ips_filter(family=AF_INET)[0]} "
olichtne marked this conversation as resolved.
Show resolved Hide resolved
f"dst_port 4789 id 10 "
f"action mirred egress redirect dev {host1.vxlan10.name} "
)
host1.run(
f"tc filter add dev {host1.vf_representor_eth0.name} protocol arp ingress prio 2 "
f"flower src_mac {host1.newns.vf_eth0.hwaddr} dst_mac {host2.newns.vf_eth0.hwaddr} "
f"action tunnel_key set src_ip {host1.eth0.ips_filter(family=AF_INET)[0]} dst_ip {host2.eth0.ips_filter(family=AF_INET)[0]} "
f"dst_port 4789 id 10 "
f"action mirred egress redirect dev {host1.vxlan10.name} "
)
host1.run(
f"tc filter add dev {host1.vf_representor_eth0.name} protocol arp ingress prio 3 "
f"flower src_mac {host1.newns.vf_eth0.hwaddr} dst_mac ff:ff:ff:ff:ff:ff "
f"action tunnel_key set src_ip {host1.eth0.ips_filter(family=AF_INET)[0]} dst_ip {host2.eth0.ips_filter(family=AF_INET)[0]} "
f"dst_port 4789 id 10 "
f"action mirred egress redirect dev {host1.vxlan10.name} "
)

# host2
host2.run(
f"tc filter add dev {host2.vf_representor_eth0.name} protocol ip ingress prio 1 "
f"flower src_mac {host2.newns.vf_eth0.hwaddr} dst_mac {host1.newns.vf_eth0.hwaddr} "
f"action tunnel_key set src_ip {host2.eth0.ips_filter(family=AF_INET)[0]} dst_ip {host1.eth0.ips_filter(family=AF_INET)[0]} "
f"dst_port 4789 id 10 "
f"action mirred egress redirect dev {host2.vxlan10.name} "
)
host2.run(
f"tc filter add dev {host2.vf_representor_eth0.name} protocol arp ingress prio 2 "
f"flower src_mac {host2.newns.vf_eth0.hwaddr} dst_mac {host1.newns.vf_eth0.hwaddr} "
f"action tunnel_key set src_ip {host2.eth0.ips_filter(family=AF_INET)[0]} dst_ip {host1.eth0.ips_filter(family=AF_INET)[0]} "
f"dst_port 4789 id 10 "
f"action mirred egress redirect dev {host2.vxlan10.name} "
)
host2.run(
f"tc filter add dev {host2.vf_representor_eth0.name} protocol arp ingress prio 3 "
f"flower src_mac {host2.newns.vf_eth0.hwaddr} dst_mac ff:ff:ff:ff:ff:ff "
f"action tunnel_key set src_ip {host2.eth0.ips_filter(family=AF_INET)[0]} dst_ip {host1.eth0.ips_filter(family=AF_INET)[0]} "
f"dst_port 4789 id 10 "
f"action mirred egress redirect dev {host2.vxlan10.name} "
)

# decap rules
# host1
host1.run(
f"tc filter add dev {host1.vxlan10.name} protocol ip ingress prio 1 "
f"flower src_mac {host2.newns.vf_eth0.hwaddr} dst_mac {host1.newns.vf_eth0.hwaddr} "
f"enc_src_ip {host2.eth0.ips_filter(family=AF_INET)[0]} enc_dst_ip {host1.eth0.ips_filter(family=AF_INET)[0]} "
f"enc_dst_port 4789 enc_key_id 10 "
f"action tunnel_key unset "
f"action mirred egress redirect dev {host1.vf_representor_eth0.name} "
)
host1.run(
f"tc filter add dev {host1.vxlan10.name} protocol arp ingress prio 2 "
f"flower src_mac {host2.newns.vf_eth0.hwaddr} dst_mac {host1.newns.vf_eth0.hwaddr} "
f"enc_src_ip {host2.eth0.ips_filter(family=AF_INET)[0]} enc_dst_ip {host1.eth0.ips_filter(family=AF_INET)[0]} "
f"enc_dst_port 4789 enc_key_id 10 "
f"action tunnel_key unset "
f"action mirred egress redirect dev {host1.vf_representor_eth0.name} "
)
host1.run(
f"tc filter add dev {host1.vxlan10.name} protocol arp ingress prio 3 "
f"flower src_mac {host2.newns.vf_eth0.hwaddr} dst_mac ff:ff:ff:ff:ff:ff "
f"enc_src_ip {host2.eth0.ips_filter(family=AF_INET)[0]} enc_dst_ip {host1.eth0.ips_filter(family=AF_INET)[0]} "
f"enc_dst_port 4789 enc_key_id 10 "
f"action tunnel_key unset "
f"action mirred egress redirect dev {host1.vf_representor_eth0.name} "
)

# host2
host2.run(
f"tc filter add dev {host2.vxlan10.name} protocol ip ingress prio 1 "
f"flower src_mac {host1.newns.vf_eth0.hwaddr} dst_mac {host2.newns.vf_eth0.hwaddr} "
f"enc_src_ip {host1.eth0.ips_filter(family=AF_INET)[0]} enc_dst_ip {host2.eth0.ips_filter(family=AF_INET)[0]} "
f"enc_dst_port 4789 enc_key_id 10 "
f"action tunnel_key unset "
f"action mirred egress redirect dev {host2.vf_representor_eth0.name} "
)
host2.run(
f"tc filter add dev {host2.vxlan10.name} protocol arp ingress prio 2 "
f"flower src_mac {host1.newns.vf_eth0.hwaddr} dst_mac {host2.newns.vf_eth0.hwaddr} "
f"enc_src_ip {host1.eth0.ips_filter(family=AF_INET)[0]} enc_dst_ip {host2.eth0.ips_filter(family=AF_INET)[0]} "
f"enc_dst_port 4789 enc_key_id 10 "
f"action tunnel_key unset "
f"action mirred egress redirect dev {host2.vf_representor_eth0.name} "
)
host2.run(
f"tc filter add dev {host2.vxlan10.name} protocol arp ingress prio 3 "
f"flower src_mac {host1.newns.vf_eth0.hwaddr} dst_mac ff:ff:ff:ff:ff:ff "
f"enc_src_ip {host1.eth0.ips_filter(family=AF_INET)[0]} enc_dst_ip {host2.eth0.ips_filter(family=AF_INET)[0]} "
f"enc_dst_port 4789 enc_key_id 10 "
f"action tunnel_key unset "
f"action mirred egress redirect dev {host2.vf_representor_eth0.name} "
)

@property
def dump_tc_rules_devices(self):
return [dev for host in self.matched for dev in [host.vxlan10, host.vf_representor_eth0]]

@property
def pause_frames_dev_list(self):
return [self.matched.host1.newns.vf_eth0, self.matched.host2.newns.vf_eth0]

@property
def offload_nics(self):
return [self.matched.host1.newns.vf_eth0, self.matched.host2.newns.vf_eth0]

@property
def mtu_hw_config_dev_list(self):
return [self.matched.host1.newns.vf_eth0, self.matched.host2.newns.vf_eth0]

@property
def coalescing_hw_config_dev_list(self):
return [self.matched.host1.newns.vf_eth0, self.matched.host2.newns.vf_eth0]

@property
def dev_interrupt_hw_config_dev_list(self):
return [self.matched.host1.newns.vf_eth0, self.matched.host2.newns.vf_eth0]

@property
def parallel_stream_qdisc_hw_config_dev_list(self):
return [self.matched.host1.newns.vf_eth0, self.matched.host2.newns.vf_eth0]
1 change: 1 addition & 0 deletions lnst/Recipes/ENRT/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
from lnst.Recipes.ENRT.MPTCPRecipe import MPTCPRecipe
from lnst.Recipes.ENRT.SRIOVNetnsOvSRecipe import SRIOVNetnsOvSRecipe
from lnst.Recipes.ENRT.SRIOVNetnsTcRecipe import SRIOVNetnsTcRecipe
from lnst.Recipes.ENRT.SRIOVNetnsVxlanTcRecipe import SRIOVNetnsVxlanTcRecipe
from lnst.Recipes.ENRT.LinuxBridgeRecipe import LinuxBridgeRecipe
from lnst.Recipes.ENRT.LinuxBridgeOverBondRecipe import LinuxBridgeOverBondRecipe
from lnst.Recipes.ENRT.TrafficControlRecipe import TrafficControlRecipe
Expand Down