xref: /dpdk/examples/ipsec-secgw/test/pkttest.py (revision 1dc48bce518de1d8cb73f961404a47311c4a248d)
19a18283aSMarcin Smoczynski#!/usr/bin/env python3
2*1dc48bceSStephen Hemminger# SPDX-License-Identifier: BSD-3-Clause
39a18283aSMarcin Smoczynski
49a18283aSMarcin Smoczynskiimport fcntl
59a18283aSMarcin Smoczynskiimport pkg_resources
69a18283aSMarcin Smoczynskiimport socket
79a18283aSMarcin Smoczynskiimport struct
89a18283aSMarcin Smoczynskiimport sys
99a18283aSMarcin Smoczynskiimport unittest
109a18283aSMarcin Smoczynski
119a18283aSMarcin Smoczynski
129a18283aSMarcin Smoczynskiif sys.version_info < (3, 0):
139a18283aSMarcin Smoczynski    print("Python3 is required to run this script")
149a18283aSMarcin Smoczynski    sys.exit(1)
159a18283aSMarcin Smoczynski
169a18283aSMarcin Smoczynski
179a18283aSMarcin Smoczynskitry:
189a18283aSMarcin Smoczynski    from scapy.all import Ether
199a18283aSMarcin Smoczynskiexcept ImportError:
209a18283aSMarcin Smoczynski    print("Scapy module is required")
219a18283aSMarcin Smoczynski    sys.exit(1)
229a18283aSMarcin Smoczynski
239a18283aSMarcin Smoczynski
249a18283aSMarcin SmoczynskiPKTTEST_REQ = [
25f9ee2da6SMarcin Smoczynski    "scapy>=2.4.3",
269a18283aSMarcin Smoczynski]
279a18283aSMarcin Smoczynski
289a18283aSMarcin Smoczynski
299a18283aSMarcin Smoczynskidef assert_requirements(req):
309a18283aSMarcin Smoczynski    """
319a18283aSMarcin Smoczynski    assert requirement is met
329a18283aSMarcin Smoczynski    req can hold a string or a list of strings
339a18283aSMarcin Smoczynski    """
349a18283aSMarcin Smoczynski    try:
359a18283aSMarcin Smoczynski        pkg_resources.require(req)
369a18283aSMarcin Smoczynski    except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict) as e:
379a18283aSMarcin Smoczynski        print("Requirement assertion: " + str(e))
389a18283aSMarcin Smoczynski        sys.exit(1)
399a18283aSMarcin Smoczynski
409a18283aSMarcin Smoczynski
419a18283aSMarcin SmoczynskiTAP_UNPROTECTED = "dtap1"
429a18283aSMarcin SmoczynskiTAP_PROTECTED = "dtap0"
439a18283aSMarcin Smoczynski
449a18283aSMarcin Smoczynski
459a18283aSMarcin Smoczynskiclass Interface(object):
469a18283aSMarcin Smoczynski    ETH_P_ALL = 3
479a18283aSMarcin Smoczynski    MAX_PACKET_SIZE = 1280
489a18283aSMarcin Smoczynski    IOCTL_GET_INFO = 0x8927
499a18283aSMarcin Smoczynski    SOCKET_TIMEOUT = 0.5
509a18283aSMarcin Smoczynski    def __init__(self, ifname):
519a18283aSMarcin Smoczynski        self.name = ifname
529a18283aSMarcin Smoczynski
539a18283aSMarcin Smoczynski        # create and bind socket to specified interface
549a18283aSMarcin Smoczynski        self.s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(Interface.ETH_P_ALL))
559a18283aSMarcin Smoczynski        self.s.settimeout(Interface.SOCKET_TIMEOUT)
569a18283aSMarcin Smoczynski        self.s.bind((self.name, 0, socket.PACKET_OTHERHOST))
579a18283aSMarcin Smoczynski
589a18283aSMarcin Smoczynski        # get interface MAC address
599a18283aSMarcin Smoczynski        info = fcntl.ioctl(self.s.fileno(), Interface.IOCTL_GET_INFO,  struct.pack('256s', bytes(ifname[:15], encoding='ascii')))
609a18283aSMarcin Smoczynski        self.mac = ':'.join(['%02x' % i for i in info[18:24]])
619a18283aSMarcin Smoczynski
629a18283aSMarcin Smoczynski    def __del__(self):
639a18283aSMarcin Smoczynski        self.s.close()
649a18283aSMarcin Smoczynski
659a18283aSMarcin Smoczynski    def send_l3packet(self, pkt, mac):
669a18283aSMarcin Smoczynski        e = Ether(src=self.mac, dst=mac)
679a18283aSMarcin Smoczynski        self.send_packet(e/pkt)
689a18283aSMarcin Smoczynski
699a18283aSMarcin Smoczynski    def send_packet(self, pkt):
709a18283aSMarcin Smoczynski        self.send_bytes(bytes(pkt))
719a18283aSMarcin Smoczynski
729a18283aSMarcin Smoczynski    def send_bytes(self, bytedata):
739a18283aSMarcin Smoczynski        self.s.send(bytedata)
749a18283aSMarcin Smoczynski
759a18283aSMarcin Smoczynski    def recv_packet(self):
769a18283aSMarcin Smoczynski        return Ether(self.recv_bytes())
779a18283aSMarcin Smoczynski
789a18283aSMarcin Smoczynski    def recv_bytes(self):
799a18283aSMarcin Smoczynski        return self.s.recv(Interface.MAX_PACKET_SIZE)
809a18283aSMarcin Smoczynski
819a18283aSMarcin Smoczynski    def get_mac(self):
829a18283aSMarcin Smoczynski        return self.mac
839a18283aSMarcin Smoczynski
849a18283aSMarcin Smoczynski
859a18283aSMarcin Smoczynskiclass PacketXfer(object):
869a18283aSMarcin Smoczynski    def __init__(self, protected_iface=TAP_PROTECTED, unprotected_iface=TAP_UNPROTECTED):
879a18283aSMarcin Smoczynski        self.protected_port = Interface(protected_iface)
889a18283aSMarcin Smoczynski        self.unprotected_port = Interface(unprotected_iface)
899a18283aSMarcin Smoczynski
909a18283aSMarcin Smoczynski    def send_to_protected_port(self, pkt, remote_mac=None):
919a18283aSMarcin Smoczynski        if remote_mac is None:
929a18283aSMarcin Smoczynski            remote_mac = self.unprotected_port.get_mac()
939a18283aSMarcin Smoczynski        self.protected_port.send_l3packet(pkt, remote_mac)
949a18283aSMarcin Smoczynski
959a18283aSMarcin Smoczynski    def send_to_unprotected_port(self, pkt, remote_mac=None):
969a18283aSMarcin Smoczynski        if remote_mac is None:
979a18283aSMarcin Smoczynski            remote_mac = self.protected_port.get_mac()
989a18283aSMarcin Smoczynski        self.unprotected_port.send_l3packet(pkt, remote_mac)
999a18283aSMarcin Smoczynski
1009a18283aSMarcin Smoczynski    def xfer_unprotected(self, pkt):
1019a18283aSMarcin Smoczynski        self.send_to_unprotected_port(pkt)
1029a18283aSMarcin Smoczynski        return self.protected_port.recv_packet()
1039a18283aSMarcin Smoczynski
1049a18283aSMarcin Smoczynski    def xfer_protected(self, pkt):
1059a18283aSMarcin Smoczynski        self.send_to_protected_port(pkt)
1069a18283aSMarcin Smoczynski        return self.unprotected_port.recv_packet()
1079a18283aSMarcin Smoczynski
1089a18283aSMarcin Smoczynski
1099a18283aSMarcin Smoczynskidef pkttest():
1109a18283aSMarcin Smoczynski    if len(sys.argv) == 1:
1119a18283aSMarcin Smoczynski        sys.exit(unittest.main(verbosity=2))
1129a18283aSMarcin Smoczynski    elif len(sys.argv) == 2:
1139a18283aSMarcin Smoczynski        if sys.argv[1] == "config":
1149a18283aSMarcin Smoczynski            module = __import__('__main__')
1159a18283aSMarcin Smoczynski            try:
1169a18283aSMarcin Smoczynski                print(module.config())
1179a18283aSMarcin Smoczynski            except AttributeError:
1189a18283aSMarcin Smoczynski                sys.stderr.write("Cannot find \"config()\" in a test")
1199a18283aSMarcin Smoczynski                sys.exit(1)
1209a18283aSMarcin Smoczynski    else:
1219a18283aSMarcin Smoczynski        sys.exit(1)
1229a18283aSMarcin Smoczynski
1239a18283aSMarcin Smoczynski
1249a18283aSMarcin Smoczynskiif __name__ == "__main__":
1259a18283aSMarcin Smoczynski    if len(sys.argv) == 2 and sys.argv[1] == "check_reqs":
1269a18283aSMarcin Smoczynski        assert_requirements(PKTTEST_REQ)
1279a18283aSMarcin Smoczynski    else:
1289a18283aSMarcin Smoczynski        print("Usage: " + sys.argv[0] + " check_reqs")
129