blob: 02c424ac0565f8c843172f4286831b658d948407 [file] [log] [blame] [edit]
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2020 Nvidia All rights reserved. See COPYING file
"""
Test module for pyverbs' flow module.
"""
from tests.base import RDMATestCase, RawResources, PyverbsRDMAError
from pyverbs.spec import EthSpec, Ipv4ExtSpec, Ipv6Spec, TcpUdpSpec
from tests.utils import requires_cap_net_raw, PacketConsts, requires_eth
from pyverbs.flow import FlowAttr, Flow
from pyverbs.libibverbs_enums import ibv_flow_spec_type
import tests.utils as u
import unittest
import socket
import errno
class FlowRes(RawResources):
def __init__(self, dev_name, ib_port, gid_index):
"""
Initialize Flow resources based on Raw resources that include Raw QP.
:param dev_name: Device name to be used
:param ib_port: IB port of the device to use
:param gid_index: Which GID index to use
"""
super().__init__(dev_name=dev_name, ib_port=ib_port,
gid_index=gid_index)
@requires_cap_net_raw()
@requires_eth()
def create_qps(self):
super().create_qps()
@staticmethod
def create_eth_spec(ether_type=PacketConsts.ETHER_TYPE_IPV4):
"""
Creates ethernet spec that matches on ethertype, source and destination
macs.
:param ether_type: IPv4 or IPv6
:return: created ethernet spec
"""
eth_spec = EthSpec(ether_type=ether_type, dst_mac=PacketConsts.DST_MAC)
eth_spec.src_mac = PacketConsts.SRC_MAC
eth_spec.src_mac_mask = PacketConsts.SRC_MAC
return eth_spec
def create_ip_spec(self, ver=PacketConsts.IP_V4,
next_hdr=socket.IPPROTO_UDP):
"""
Creates IPv4 or IPv6 spec that matches on source and destination ips.
:param ver: IP version
:param next_hdr: Next header type
:return: created IPv4 or IPv6 spec
"""
if ver == PacketConsts.IP_V4:
ip_spec = Ipv4ExtSpec(src_ip=PacketConsts.SRC_IP,
dst_ip=PacketConsts.DST_IP, proto=next_hdr)
else:
ip_spec = Ipv6Spec(src_ip=PacketConsts.SRC_IP6,
dst_ip=PacketConsts.DST_IP6, next_hdr=next_hdr)
return ip_spec
@staticmethod
def create_tcp_udp_spec(spec_type):
"""
Creates TcpUdp spec that matches on ethertype, source and destination
macs.
:param spec_type: Spec type TCP or UDP
:return: TCP or UDP spec
"""
spec = TcpUdpSpec(spec_type, src_port=PacketConsts.SRC_PORT,
dst_port=PacketConsts.DST_PORT)
return spec
def create_flow(self, specs=None):
"""
Creates flow to match on provided specs.
:param specs: list of specs to match on
:return: created flow
"""
specs = [] if specs is None else specs
flow_attr = FlowAttr(num_of_specs=len(specs), port=self.ib_port)
for spec in specs:
flow_attr.specs.append(spec)
try:
flow = self._create_flow(flow_attr)
except PyverbsRDMAError as ex:
if ex.error_code == errno.EOPNOTSUPP:
raise unittest.SkipTest('Flow creation is not supported')
raise ex
return flow
def _create_flow(self, flow_attr):
return Flow(self.qp, flow_attr)
class FlowTest(RDMATestCase):
"""
Test various functionalities of the Flow class.
"""
def setUp(self):
super().setUp()
self.iters = 10
self.server = None
self.client = None
def flow_traffic(self, specs, l3=PacketConsts.IP_V4,
l4=PacketConsts.UDP_PROTO):
"""
Execute raw ethernet traffic with given specs flow.
:param specs: list of specs
:param l3: Packet layer 3 type: 4 for IPv4 or 6 for IPv6
:param l4: Packet layer 4 type: 'tcp' or 'udp'
:return: None
"""
self.flow = self.server.create_flow(specs)
u.raw_traffic(self.client, self.server, self.iters, l3, l4)
def test_eth_spec_flow_traffic(self):
self.create_players(FlowRes)
self.flow_traffic([self.server.create_eth_spec()])
def test_ipv4_spec_flow_traffic(self):
self.create_players(FlowRes)
if self.is_eth_and_has_roce_hw_bug():
raise unittest.SkipTest(f'Device {self.dev_name} doesn\'t support Ipv4ExtSpec')
self.flow_traffic([self.server.create_ip_spec()])
def test_ipv6_spec_flow_traffic(self):
self.create_players(FlowRes)
eth_spec = self.server.create_eth_spec(PacketConsts.ETHER_TYPE_IPV6)
if self.is_eth_and_has_roce_hw_bug():
raise unittest.SkipTest(f'Device {self.dev_name} doesn\'t support Ipv6Spec')
ip_spec = self.server.create_ip_spec(PacketConsts.IP_V6)
self.flow_traffic([eth_spec, ip_spec], PacketConsts.IP_V6)
def test_udp_spec_flow_traffic(self):
self.create_players(FlowRes)
eth_spec = self.server.create_eth_spec()
if self.is_eth_and_has_roce_hw_bug():
raise unittest.SkipTest(f'Device {self.dev_name} doesn\'t support Ipv4ExtSpec')
ip_spec = self.server.create_ip_spec()
udp_spec = self.server.create_tcp_udp_spec(ibv_flow_spec_type.IBV_FLOW_SPEC_UDP)
self.flow_traffic([eth_spec, ip_spec, udp_spec], PacketConsts.IP_V4,
PacketConsts.UDP_PROTO)
def test_tcp_spec_flow_traffic(self):
self.create_players(FlowRes)
eth_spec = self.server.create_eth_spec(PacketConsts.ETHER_TYPE_IPV6)
if self.is_eth_and_has_roce_hw_bug():
raise unittest.SkipTest(f'Device {self.dev_name} doesn\'t support Ipv6Spec')
ip_spec = self.server.create_ip_spec(PacketConsts.IP_V6,
socket.IPPROTO_TCP)
tcp_spec = self.server.create_tcp_udp_spec(ibv_flow_spec_type.IBV_FLOW_SPEC_TCP)
self.flow_traffic([eth_spec, ip_spec, tcp_spec], PacketConsts.IP_V6,
PacketConsts.TCP_PROTO)