#!/usr/bin/env python3

import unittest

from scapy.layers.l2 import Ether

from framework import VppTestCase
from asfframework import VppTestRunner
from util import Host


class TestL2LearnLimit(VppTestCase):
    """L2 Learn no limit Test Case"""

    @classmethod
    def setUpClass(self):
        super(TestL2LearnLimit, self).setUpClass()
        self.create_pg_interfaces(range(3))

    @classmethod
    def tearDownClass(cls):
        super(TestL2LearnLimit, cls).tearDownClass()

    def create_hosts(self, pg_if, n_hosts_per_if, subnet):
        """
        Create required number of host MAC addresses and distribute them among
        interfaces. Create host IPv4 address for every host MAC address.

        :param int n_hosts_per_if: Number of per interface hosts to
            create MAC/IPv4 addresses for.
        """

        hosts = dict()
        swif = pg_if.sw_if_index

        def mac(j):
            return "00:00:%02x:ff:%02x:%02x" % (subnet, swif, j)

        def ip(j):
            return "172.%02u.1%02x.%u" % (subnet, swif, j)

        def h(j):
            return Host(mac(j), ip(j))

        hosts[swif] = [h(j) for j in range(n_hosts_per_if)]

        return hosts

    def learn_hosts(self, pg_if, bd_id, hosts):
        """
        Create and send per interface L2 MAC broadcast packet stream to
        let the bridge domain learn these MAC addresses.

        :param int bd_id: BD to teach
        :param dict hosts: dict of hosts per interface
        """

        self.vapi.bridge_flags(bd_id=bd_id, is_set=1, flags=1)

        swif = pg_if.sw_if_index
        packets = [Ether(dst="ff:ff:ff:ff:ff:ff", src=host.mac) for host in hosts[swif]]
        pg_if.add_stream(packets)
        self.logger.info("Sending broadcast eth frames for MAC learning")
        self.pg_start()

    def test_l2bd_learnlimit(self):
        """L2BD test without learn Limit"""
        hosts = self.create_hosts(self.pg_interfaces[0], 20, 1)
        self.learn_hosts(self.pg_interfaces[0], 1, hosts)
        lfs = self.vapi.l2_fib_table_dump(1)

        # check that 20 macs are learned.
        self.assertEqual(len(lfs), 20)

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

        self.vapi.bridge_domain_add_del_v2(
            bd_id=1, is_add=1, flood=1, forward=1, learn=1, uu_flood=1
        )
        self.vapi.bridge_domain_add_del_v2(
            bd_id=2, is_add=1, flood=1, forward=1, learn=1, uu_flood=1
        )

        self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[0].sw_if_index, bd_id=1)
        self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[1].sw_if_index, bd_id=2)

    def tearDown(self):
        super(TestL2LearnLimit, self).tearDown()
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg_interfaces[0].sw_if_index, bd_id=1, enable=0
        )
        self.vapi.sw_interface_set_l2_bridge(
            rx_sw_if_index=self.pg_interfaces[1].sw_if_index, bd_id=2, enable=0
        )
        self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
        self.vapi.bridge_domain_add_del_v2(bd_id=2, is_add=0)


if __name__ == "__main__":
    unittest.main(testRunner=VppTestRunner)
