aboutsummaryrefslogtreecommitdiffstats
path: root/resources/tools/wrk
AgeCommit message (Collapse)AuthorFilesLines
2020-07-16Remove remains of WRK testsTibor Frank6-1203/+0
Change-Id: If61783fb717757c6189f06924412bd079e15a08f Signed-off-by: Tibor Frank <tifrank@cisco.com>
2020-03-03perf: Clean up Hoststack testsDave Wallace1-2/+2
- Update test names with clients/streams - Convert test results to JSON output * iperf3 results include bits_per_second * vpp_echo results include both client and server output which includes time in seconds and rx_data/tx_data in bytes which can be used to calculate the average bits per second. Tx and Rx data will always be the same: BPS = (client tx_data * 8) / ((client time + server time) / 2) - Fix WRK test results data formatting errors Change-Id: Ie2aeb665e3cc0739b16f97ba2628eebe6e041d22 Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
2020-01-10Autogen: Generate also NIC drivers.Vratko Polak1-1/+1
+ Disallowed -avf- (or -rdma-) as "template" suites. + GBP suite switched to DPDK driver in repo. + Each NIC has its own list of supported drivers, in Constants. + Updated tag expressions for daily jobs: + Feature, ipsec, memif, scale, srv6, tunnels, vhost and vts are tested only with vfio-pci. + Other (base, dot1q, dot1ad) tested with all drivers. + Setup actions currently depend on driver, generated. - The performance_rdma action is trivial for now. - Several tests fail, to be fixed later, e.g. by performance_rdma. + Reconf tests are also supported. + Added DRV_VFIO_PCI tags missing, mainly in density tests. - Vhost suites (density, reconf) are failing, but suites look good. - TCP suites do not support NIC drivers yet. - DPDK obviously not supported. + Use Python 3 in regenerate scripts. + Fix typos binded => bound. + File open modes set either u"rt" or u"wt" everywhere. + Remove a trailing space in an environment variable name. Change-Id: I290470675dc5c9e88b2eaa5ab6285ecd9ed7827a Signed-off-by: Vratko Polak <vrpolak@cisco.com>
2019-12-16python3: fix wrk traffic profile YAML loadDave Wallace1-2/+2
Signed-off-by: Dave Wallace <dwallacelf@gmail.com> Change-Id: I3b7493221f3a0378b7f6cb0b0a21e8f18a0cc937
2019-11-28Python3: resources and librariesJan Gelety3-169/+192
Change-Id: I1392c06b1d64f62b141d24c0d42a8e36913b15e2 Signed-off-by: Jan Gelety <jgelety@cisco.com>
2019-08-15Refactor traffic profile verificationMiroslav Los1-94/+86
- CSIT-1194 Signed-off-by: Miroslav Los <miroslav.los@pantheon.tech> Change-Id: I0f4c234fb5f5f6543a5d525301f17f5a111e1053
2019-08-14VAT-to-PAPI: Fix HTTP/TCP testsDave Wallace2-4/+4
Change-Id: Ie728bc73eb7429d246e82dd195fc63191c3ac51d Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
2019-08-14Move: WRK installation into ansiblePeter Mikus2-83/+16
- Remove ability to install from framework. - Control via ansible with other dependencies. Signed-off-by: Peter Mikus <pmikus@cisco.com> Change-Id: I5fd0ca18b4f76c30b6c28b4dcd15e538e01cb315
2019-03-04Rename to Constants.pyVratko Polak1-1/+1
Motivation: Make the constants available also for Robot. Restraint: Robotframework user guide says: Because variable files are always imported using a file system path, creating them as classes has some restrictions: Python classes must have the same name as the module they are located. Change-Id: I638ef3fe045db132e366de2e2699638b8637e45e Signed-off-by: Vratko Polak <vrpolak@cisco.com>
2018-01-16CSIT-898: WRK improvmentsTibor Frank1-2/+26
Change-Id: I92aafaaedce5891727a983b8cf024a0fb0db7524 Signed-off-by: Tibor Frank <tifrank@cisco.com>
2018-01-10CSIT-866: wrk onboarding in CSITTibor Frank6-0/+1231
- CSIT-867: Low Level Description - CSIT-868: wrk traffic profile - parsing - CSIT-869: wrk implementation into CSIT Change-Id: I65e1037f5ae05b3a5b2020e4a6c54462766ae1b4 Signed-off-by: Tibor Frank <tifrank@cisco.com>
> 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773
from scapy.layers.dhcp6 import DHCP6_Advertise, DHCP6OptClientId, \
    DHCP6OptStatusCode, DHCP6OptPref, DHCP6OptIA_PD, DHCP6OptIAPrefix, \
    DHCP6OptServerId, DHCP6_Solicit, DHCP6_Reply, DHCP6_Request, DHCP6_Renew, \
    DHCP6_Rebind, DUID_LL, DHCP6_Release, DHCP6OptElapsedTime, DHCP6OptIA_NA, \
    DHCP6OptIAAddress
from scapy.layers.inet6 import IPv6, Ether, UDP
from scapy.utils6 import in6_mactoifaceid
from scapy.utils import inet_ntop, inet_pton
from socket import AF_INET6
from framework import VppTestCase


def ip6_normalize(ip6):
    return inet_ntop(AF_INET6, inet_pton(AF_INET6, ip6))


def mk_ll_addr(mac):
    euid = in6_mactoifaceid(mac)
    addr = "fe80::" + euid
    return addr


class TestDHCPv6DataPlane(VppTestCase):
    """ DHCPv6 Data Plane Test Case """

    @classmethod
    def setUpClass(cls):
        super(TestDHCPv6DataPlane, cls).setUpClass()

    def setUp(self):
        super(TestDHCPv6DataPlane, self).setUp()

        self.create_pg_interfaces(range(1))
        self.interfaces = list(self.pg_interfaces)
        for i in self.interfaces:
            i.admin_up()
            i.config_ip6()

        self.server_duid = DUID_LL(lladdr=self.pg0.remote_mac)

    def tearDown(self):
        for i in self.interfaces:
            i.unconfig_ip6()
            i.admin_down()
        super(TestDHCPv6DataPlane, self).tearDown()

    def test_dhcp_ia_na_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 IA NA Solicit packet and Advertise envent """

        self.vapi.dhcp6_clients_enable_disable()

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        address_bin = '\00\01\00\02\00\03' + '\00' * 8 + '\00\05'
        address = {'address': address_bin,
                   'preferred_time': 60,
                   'valid_time': 120}
        self.vapi.dhcp6_send_client_message(1, self.pg0.sw_if_index,
                                            T1=20, T2=40, addresses=[address])
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertTrue(packet.haslayer(IPv6))
        self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit))

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_na = packet[DHCP6OptIA_NA]
        self.assert_equal(ia_na.T1, 20)
        self.assert_equal(ia_na.T2, 40)
        self.assert_equal(len(ia_na.ianaopts), 1)
        address = ia_na.ianaopts[0]
        self.assert_equal(address.addr, '1:2:3::5')
        self.assert_equal(address.preflft, 60)
        self.assert_equal(address.validlft, 120)

        self.vapi.want_dhcp6_reply_events()

        try:
            ia_na_opts = DHCP6OptIAAddress(addr='7:8::2', preflft=60,
                                           validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) /
                 UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) /
                 DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_NA(iaid=1, T1=20, T2=40, ianaopts=ia_na_opts)
                 )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_address = ev.addresses[0]
            address = inet_pton(AF_INET6, ia_na_opts.getfieldval("addr"))
            self.assert_equal(reported_address.address, address)
            self.assert_equal(reported_address.preferred_time,
                              ia_na_opts.getfieldval("preflft"))
            self.assert_equal(reported_address.valid_time,
                              ia_na_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_reply_events(enable_disable=0)

    def test_dhcp_pd_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 PD Solicit packet and Advertise envent """

        self.vapi.dhcp6_clients_enable_disable()

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        prefix_bin = '\00\01\00\02\00\03' + '\00' * 10
        prefix = {'prefix': prefix_bin,
                  'prefix_length': 50,
                  'preferred_time': 60,
                  'valid_time': 120}
        self.vapi.dhcp6_pd_send_client_message(1, self.pg0.sw_if_index,
                                               T1=20, T2=40, prefixes=[prefix])
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertTrue(packet.haslayer(IPv6))
        self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit))

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_pd = packet[DHCP6OptIA_PD]
        self.assert_equal(ia_pd.T1, 20)
        self.assert_equal(ia_pd.T2, 40)
        self.assert_equal(len(ia_pd.iapdopt), 1)
        prefix = ia_pd.iapdopt[0]
        self.assert_equal(prefix.prefix, '1:2:3::')
        self.assert_equal(prefix.plen, 50)
        self.assert_equal(prefix.preflft, 60)
        self.assert_equal(prefix.validlft, 120)

        self.vapi.want_dhcp6_pd_reply_events()

        try:
            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=60,
                                          validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) /
                 UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) /
                 DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts)
                 )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_prefix = ev.prefixes[0]
            prefix = inet_pton(AF_INET6, ia_pd_opts.getfieldval("prefix"))
            self.assert_equal(reported_prefix.prefix, prefix)
            self.assert_equal(reported_prefix.prefix_length,
                              ia_pd_opts.getfieldval("plen"))
            self.assert_equal(reported_prefix.preferred_time,
                              ia_pd_opts.getfieldval("preflft"))
            self.assert_equal(reported_prefix.valid_time,
                              ia_pd_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_pd_reply_events(enable_disable=0)


class TestDHCPv6IANAControlPlane(VppTestCase):
    """ DHCPv6 IA NA Control Plane Test Case """

    @classmethod
    def setUpClass(cls):
        super(TestDHCPv6IANAControlPlane, cls).setUpClass()

    def setUp(self):
        super(TestDHCPv6IANAControlPlane, self).setUp()

        self.create_pg_interfaces(range(1))
        self.interfaces = list(self.pg_interfaces)
        for i in self.interfaces:
            i.admin_up()

        self.server_duid = DUID_LL(lladdr=self.pg0.remote_mac)
        self.client_duid = None
        self.T1 = 1
        self.T2 = 2

        fib = self.vapi.ip6_fib_dump()
        self.initial_addresses = set(self.get_interface_addresses(fib,
                                                                  self.pg0))

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        self.vapi.dhcp6_client_enable_disable(self.pg0.sw_if_index)

    def tearDown(self):
        self.vapi.dhcp6_client_enable_disable(self.pg0.sw_if_index, enable=0)

        for i in self.interfaces:
            i.admin_down()

        super(TestDHCPv6IANAControlPlane, self).tearDown()

    @staticmethod
    def get_interface_addresses(fib, pg):
        lst = []
        for entry in fib:
            if entry.address_length == 128:
                path = entry.path[0]
                if path.sw_if_index == pg.sw_if_index:
                    lst.append(entry.address)
        return lst

    def get_addresses(self):
        fib = self.vapi.ip6_fib_dump()
        addresses = set(self.get_interface_addresses(fib, self.pg0))
        return addresses.difference(self.initial_addresses)

    def validate_duid_ll(self, duid):
        DUID_LL(duid)

    def validate_packet(self, packet, msg_type, is_resend=False):
        try:
            self.assertTrue(packet.haslayer(msg_type))
            client_duid = packet[DHCP6OptClientId].duid
            if self.client_duid is None:
                self.client_duid = client_duid
                self.validate_duid_ll(client_duid)
            else:
                self.assertEqual(self.client_duid, client_duid)
            if msg_type != DHCP6_Solicit and msg_type != DHCP6_Rebind:
                server_duid = packet[DHCP6OptServerId].duid
                self.assertEqual(server_duid, self.server_duid)
            if is_resend:
                self.assertEqual(self.trid, packet[msg_type].trid)
            else:
                self.trid = packet[msg_type].trid
            ip = packet[IPv6]
            udp = packet[UDP]
            self.assertEqual(ip.dst, 'ff02::1:2')
            self.assertEqual(udp.sport, 546)
            self.assertEqual(udp.dport, 547)
            dhcpv6 = packet[msg_type]
            elapsed_time = dhcpv6[DHCP6OptElapsedTime]
            if (is_resend):
                self.assertNotEqual(elapsed_time.elapsedtime, 0)
            else:
                self.assertEqual(elapsed_time.elapsedtime, 0)
        except:
            packet.show()
            raise

    def wait_for_packet(self, msg_type, timeout=None, is_resend=False):
        if timeout is None:
            timeout = 3
        rx_list = self.pg0.get_capture(1, timeout=timeout)
        packet = rx_list[0]
        self.validate_packet(packet, msg_type, is_resend=is_resend)

    def wait_for_solicit(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Solicit, timeout, is_resend=is_resend)

    def wait_for_request(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Request, timeout, is_resend=is_resend)

    def wait_for_renew(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Renew, timeout, is_resend=is_resend)

    def wait_for_rebind(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Rebind, timeout, is_resend=is_resend)

    def wait_for_release(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Release, timeout, is_resend=is_resend)

    def send_packet(self, msg_type, t1=None, t2=None, ianaopts=None):
        if t1 is None:
            t1 = self.T1
        if t2 is None:
            t2 = self.T2
        if ianaopts is None:
            opt_ia_na = DHCP6OptIA_NA(iaid=1, T1=t1, T2=t2)
        else:
            opt_ia_na = DHCP6OptIA_NA(iaid=1, T1=t1, T2=t2, ianaopts=ianaopts)
        p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
             IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                  dst=self.pg0.local_ip6_ll) /
             UDP(sport=547, dport=546) /
             msg_type(trid=self.trid) /
             DHCP6OptServerId(duid=self.server_duid) /
             DHCP6OptClientId(duid=self.client_duid) /
             opt_ia_na
             )
        self.pg0.add_stream([p])
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

    def send_advertise(self, t1=None, t2=None, ianaopts=None):
        self.send_packet(DHCP6_Advertise, t1, t2, ianaopts)

    def send_reply(self, t1=None, t2=None, ianaopts=None):
        self.send_packet(DHCP6_Reply, t1, t2, ianaopts)

    def test_T1_and_T2_timeouts(self):
        """ Test T1 and T2 timeouts """

        self.wait_for_solicit()
        self.send_advertise()
        self.wait_for_request()
        self.send_reply()

        self.sleep(1)

        self.wait_for_renew()

        self.pg_enable_capture(self.pg_interfaces)

        self.sleep(1)

        self.wait_for_rebind()

    def test_addresses(self):
        """ Test handling of addresses """

        ia_na_opts = DHCP6OptIAAddress(addr='7:8::2', preflft=1,
                                       validlft=2)

        self.wait_for_solicit()
        self.send_advertise(t1=20, t2=40, ianaopts=ia_na_opts)
        self.wait_for_request()
        self.send_reply(t1=20, t2=40, ianaopts=ia_na_opts)
        self.sleep(0.1)

        # check FIB for new address
        new_addresses = self.get_addresses()
        self.assertEqual(len(new_addresses), 1)
        addr = list(new_addresses)[0]
        self.assertEqual(inet_ntop(AF_INET6, addr), '7:8::2')

        self.sleep(2)

        # check that the address is deleted
        fib = self.vapi.ip6_fib_dump()
        addresses = set(self.get_interface_addresses(fib, self.pg0))
        new_addresses = addresses.difference(self.initial_addresses)
        self.assertEqual(len(new_addresses), 0)

    def test_sending_client_messages_solicit(self):
        """ VPP receives messages from DHCPv6 client """

        self.wait_for_solicit()
        self.send_packet(DHCP6_Solicit)
        self.send_packet(DHCP6_Request)
        self.send_packet(DHCP6_Renew)
        self.send_packet(DHCP6_Rebind)
        self.sleep(1)
        self.wait_for_solicit(is_resend=True)

    def test_sending_inappropriate_packets(self):
        """ Server sends messages with inappropriate message types """

        self.wait_for_solicit()
        self.send_reply()
        self.wait_for_solicit(is_resend=True)
        self.send_advertise()
        self.wait_for_request()
        self.send_advertise()
        self.wait_for_request(is_resend=True)
        self.send_reply()
        self.wait_for_renew()

    def test_no_address_available_in_advertise(self):
        """ Advertise message contains NoAddrsAvail status code """

        self.wait_for_solicit()
        noavail = DHCP6OptStatusCode(statuscode=2)  # NoAddrsAvail
        self.send_advertise(ianaopts=noavail)
        self.wait_for_solicit(is_resend=True)

    def test_preferred_greater_than_valit_lifetime(self):
        """ Preferred lifetime is greater than valid lifetime """

        self.wait_for_solicit()
        self.send_advertise()
        self.wait_for_request()
        ia_na_opts = DHCP6OptIAAddress(addr='7:8::2', preflft=4, validlft=3)
        self.send_reply(ianaopts=ia_na_opts)

        self.sleep(0.5)

        # check FIB contains no addresses
        fib = self.vapi.ip6_fib_dump()
        addresses = set(self.get_interface_addresses(fib, self.pg0))
        new_addresses = addresses.difference(self.initial_addresses)
        self.assertEqual(len(new_addresses), 0)

    def test_T1_greater_than_T2(self):
        """ T1 is greater than T2 """

        self.wait_for_solicit()
        self.send_advertise()
        self.wait_for_request()
        ia_na_opts = DHCP6OptIAAddress(addr='7:8::2', preflft=4, validlft=8)
        self.send_reply(t1=80, t2=40, ianaopts=ia_na_opts)

        self.sleep(0.5)

        # check FIB contains no addresses
        fib = self.vapi.ip6_fib_dump()
        addresses = set(self.get_interface_addresses(fib, self.pg0))
        new_addresses = addresses.difference(self.initial_addresses)
        self.assertEqual(len(new_addresses), 0)


class TestDHCPv6PDControlPlane(VppTestCase):
    """ DHCPv6 PD Control Plane Test Case """

    @classmethod
    def setUpClass(cls):
        super(TestDHCPv6PDControlPlane, cls).setUpClass()

    def setUp(self):
        super(TestDHCPv6PDControlPlane, self).setUp()

        self.create_pg_interfaces(range(2))
        self.interfaces = list(self.pg_interfaces)
        for i in self.interfaces:
            i.admin_up()

        self.server_duid = DUID_LL(lladdr=self.pg0.remote_mac)
        self.client_duid = None
        self.T1 = 1
        self.T2 = 2

        fib = self.vapi.ip6_fib_dump()
        self.initial_addresses = set(self.get_interface_addresses(fib,
                                                                  self.pg1))

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        self.prefix_group = 'my-pd-prefix-group'

        self.vapi.dhcp6_pd_client_enable_disable(
            self.pg0.sw_if_index,
            prefix_group=self.prefix_group)

    def tearDown(self):
        self.vapi.dhcp6_pd_client_enable_disable(self.pg0.sw_if_index,
                                                 enable=0)

        for i in self.interfaces:
            i.admin_down()

        super(TestDHCPv6PDControlPlane, self).tearDown()

    @staticmethod
    def get_interface_addresses(fib, pg):
        lst = []
        for entry in fib:
            if entry.address_length == 128:
                path = entry.path[0]
                if path.sw_if_index == pg.sw_if_index:
                    lst.append(entry.address)
        return lst

    def get_addresses(self):
        fib = self.vapi.ip6_fib_dump()
        addresses = set(self.get_interface_addresses(fib, self.pg1))
        return addresses.difference(self.initial_addresses)

    def validate_duid_ll(self, duid):
        DUID_LL(duid)

    def validate_packet(self, packet, msg_type, is_resend=False):
        try:
            self.assertTrue(packet.haslayer(msg_type))
            client_duid = packet[DHCP6OptClientId].duid
            if self.client_duid is None:
                self.client_duid = client_duid
                self.validate_duid_ll(client_duid)
            else:
                self.assertEqual(self.client_duid, client_duid)
            if msg_type != DHCP6_Solicit and msg_type != DHCP6_Rebind:
                server_duid = packet[DHCP6OptServerId].duid
                self.assertEqual(server_duid, self.server_duid)
            if is_resend:
                self.assertEqual(self.trid, packet[msg_type].trid)
            else:
                self.trid = packet[msg_type].trid
            ip = packet[IPv6]
            udp = packet[UDP]
            self.assertEqual(ip.dst, 'ff02::1:2')
            self.assertEqual(udp.sport, 546)
            self.assertEqual(udp.dport, 547)
            dhcpv6 = packet[msg_type]
            elapsed_time = dhcpv6[DHCP6OptElapsedTime]
            if (is_resend):
                self.assertNotEqual(elapsed_time.elapsedtime, 0)
            else:
                self.assertEqual(elapsed_time.elapsedtime, 0)
        except:
            packet.show()
            raise

    def wait_for_packet(self, msg_type, timeout=None, is_resend=False):
        if timeout is None:
            timeout = 3
        rx_list = self.pg0.get_capture(1, timeout=timeout)
        packet = rx_list[0]
        self.validate_packet(packet, msg_type, is_resend=is_resend)

    def wait_for_solicit(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Solicit, timeout, is_resend=is_resend)

    def wait_for_request(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Request, timeout, is_resend=is_resend)

    def wait_for_renew(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Renew, timeout, is_resend=is_resend)

    def wait_for_rebind(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Rebind, timeout, is_resend=is_resend)

    def wait_for_release(self, timeout=None, is_resend=False):
        self.wait_for_packet(DHCP6_Release, timeout, is_resend=is_resend)

    def send_packet(self, msg_type, t1=None, t2=None, iapdopt=None):
        if t1 is None:
            t1 = self.T1
        if t2 is None:
            t2 = self.T2
        if iapdopt is None:
            opt_ia_pd = DHCP6OptIA_PD(iaid=1, T1=t1, T2=t2)
        else:
            opt_ia_pd = DHCP6OptIA_PD(iaid=1, T1=t1, T2=t2, iapdopt=iapdopt)
        p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
             IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                  dst=self.pg0.local_ip6_ll) /
             UDP(sport=547, dport=546) /
             msg_type(trid=self.trid) /
             DHCP6OptServerId(duid=self.server_duid) /
             DHCP6OptClientId(duid=self.client_duid) /
             opt_ia_pd
             )
        self.pg0.add_stream([p])
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

    def send_advertise(self, t1=None, t2=None, iapdopt=None):
        self.send_packet(DHCP6_Advertise, t1, t2, iapdopt)

    def send_reply(self, t1=None, t2=None, iapdopt=None):
        self.send_packet(DHCP6_Reply, t1, t2, iapdopt)

    def test_T1_and_T2_timeouts(self):
        """ Test T1 and T2 timeouts """

        self.wait_for_solicit()
        self.send_advertise()
        self.wait_for_request()
        self.send_reply()

        self.sleep(1)

        self.wait_for_renew()

        self.pg_enable_capture(self.pg_interfaces)

        self.sleep(1)

        self.wait_for_rebind()

    def test_prefixes(self):
        """ Test handling of prefixes """

        address_bin_1 = None
        address_bin_2 = None
        try:
            address_bin_1 = '\x00' * 6 + '\x00\x02' + '\x00' * 6 + '\x04\x05'
            address_prefix_length_1 = 60
            self.vapi.ip6_add_del_address_using_prefix(self.pg1.sw_if_index,
                                                       address_bin_1,
                                                       address_prefix_length_1,
                                                       self.prefix_group)

            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=2,
                                          validlft=3)

            self.wait_for_solicit()
            self.send_advertise(t1=20, t2=40, iapdopt=ia_pd_opts)
            self.wait_for_request()
            self.send_reply(t1=20, t2=40, iapdopt=ia_pd_opts)
            self.sleep(0.1)

            # check FIB for new address
            new_addresses = self.get_addresses()
            self.assertEqual(len(new_addresses), 1)
            addr = list(new_addresses)[0]
            self.assertEqual(inet_ntop(AF_INET6, addr), '7:8:0:2::405')

            self.sleep(1)

            address_bin_2 = '\x00' * 6 + '\x00\x76' + '\x00' * 6 + '\x04\x06'
            address_prefix_length_2 = 62
            self.vapi.ip6_add_del_address_using_prefix(self.pg1.sw_if_index,
                                                       address_bin_2,
                                                       address_prefix_length_2,
                                                       self.prefix_group)

            self.sleep(1)

            # check FIB contains 2 addresses
            fib = self.vapi.ip6_fib_dump()
            addresses = set(self.get_interface_addresses(fib, self.pg1))
            new_addresses = addresses.difference(self.initial_addresses)
            self.assertEqual(len(new_addresses), 2)
            addr1 = list(new_addresses)[0]
            addr2 = list(new_addresses)[1]
            if inet_ntop(AF_INET6, addr1) == '7:8:0:76::406':
                addr1, addr2 = addr2, addr1
            self.assertEqual(inet_ntop(AF_INET6, addr1), '7:8:0:2::405')
            self.assertEqual(inet_ntop(AF_INET6, addr2), '7:8:0:76::406')

            self.sleep(1)

            # check that the addresses are deleted
            fib = self.vapi.ip6_fib_dump()
            addresses = set(self.get_interface_addresses(fib, self.pg1))
            new_addresses = addresses.difference(self.initial_addresses)
            self.assertEqual(len(new_addresses), 0)

        finally:
            if address_bin_1 is not None:
                self.vapi.ip6_add_del_address_using_prefix(
                    self.pg1.sw_if_index, address_bin_1,
                    address_prefix_length_1, self.prefix_group, is_add=0)
            if address_bin_2 is not None:
                self.vapi.ip6_add_del_address_using_prefix(
                    self.pg1.sw_if_index, address_bin_2,
                    address_prefix_length_2, self.prefix_group, is_add=0)

    def test_sending_client_messages_solicit(self):
        """ VPP receives messages from DHCPv6 client """

        self.wait_for_solicit()
        self.send_packet(DHCP6_Solicit)
        self.send_packet(DHCP6_Request)
        self.send_packet(DHCP6_Renew)
        self.send_packet(DHCP6_Rebind)
        self.sleep(1)
        self.wait_for_solicit(is_resend=True)

    def test_sending_inappropriate_packets(self):
        """ Server sends messages with inappropriate message types """

        self.wait_for_solicit()
        self.send_reply()
        self.wait_for_solicit(is_resend=True)
        self.send_advertise()
        self.wait_for_request()
        self.send_advertise()
        self.wait_for_request(is_resend=True)
        self.send_reply()
        self.wait_for_renew()

    def test_no_prefix_available_in_advertise(self):
        """ Advertise message contains NoPrefixAvail status code """

        self.wait_for_solicit()
        noavail = DHCP6OptStatusCode(statuscode=6)  # NoPrefixAvail
        self.send_advertise(iapdopt=noavail)
        self.wait_for_solicit(is_resend=True)

    def test_preferred_greater_than_valit_lifetime(self):
        """ Preferred lifetime is greater than valid lifetime """

        try:
            address_bin = '\x00' * 6 + '\x00\x02' + '\x00' * 6 + '\x04\x05'
            address_prefix_length = 60
            self.vapi.ip6_add_del_address_using_prefix(self.pg1.sw_if_index,
                                                       address_bin,
                                                       address_prefix_length,
                                                       self.prefix_group)

            self.wait_for_solicit()
            self.send_advertise()
            self.wait_for_request()
            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=4,
                                          validlft=3)
            self.send_reply(iapdopt=ia_pd_opts)

            self.sleep(0.5)

            # check FIB contains no addresses
            fib = self.vapi.ip6_fib_dump()
            addresses = set(self.get_interface_addresses(fib, self.pg1))
            new_addresses = addresses.difference(self.initial_addresses)
            self.assertEqual(len(new_addresses), 0)

        finally:
            self.vapi.ip6_add_del_address_using_prefix(self.pg1.sw_if_index,
                                                       address_bin,
                                                       address_prefix_length,
                                                       self.prefix_group,
                                                       is_add=0)

    def test_T1_greater_than_T2(self):
        """ T1 is greater than T2 """

        try:
            address_bin = '\x00' * 6 + '\x00\x02' + '\x00' * 6 + '\x04\x05'
            address_prefix_length = 60
            self.vapi.ip6_add_del_address_using_prefix(self.pg1.sw_if_index,
                                                       address_bin,
                                                       address_prefix_length,
                                                       self.prefix_group)

            self.wait_for_solicit()
            self.send_advertise()
            self.wait_for_request()
            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=4,
                                          validlft=8)
            self.send_reply(t1=80, t2=40, iapdopt=ia_pd_opts)

            self.sleep(0.5)

            # check FIB contains no addresses
            fib = self.vapi.ip6_fib_dump()
            addresses = set(self.get_interface_addresses(fib, self.pg1))
            new_addresses = addresses.difference(self.initial_addresses)
            self.assertEqual(len(new_addresses), 0)

        finally:
            self.vapi.ip6_add_del_address_using_prefix(self.pg1.sw_if_index,
                                                       address_bin,
                                                       address_prefix_length,
                                                       self.prefix_group,
                                                       is_add=0)