# 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)
