import oftest.base_tests as base_tests
from oftest import config
import ofp
from oltconstants import *
from oftest.testutils import *
import copy
import logging
from IGMP import IGMPv3, IGMPv3gr, IGMP_TYPE_MEMBERSHIP_QUERY, \
     IGMP_TYPE_V3_MEMBERSHIP_REPORT, IGMP_V3_GR_TYPE_EXCLUDE, \
     IGMP_V3_GR_TYPE_INCLUDE


class OltBaseTest(base_tests.SimpleDataPlane):

    next_cookie_block = 40

    def getCookieBlock(self):
        """Returns the starting value of the next 100 cookies"""
        c = self.next_cookie_block
        OltBaseTest.next_cookie_block += 100
        return c

    def resetOlt(self):
        """Reset the OLT into a clean healthy state"""
        delete_all_flows(self.controller)
        delete_all_groups(self.controller)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

    def testPacketIn(self, match, parsed_pkt):
        delete_all_flows(self.controller)

        pkt = str(parsed_pkt)

        for of_port in config["port_map"]:
            m = copy.deepcopy(match)
            m.oxm_list.append(ofp.oxm.in_port(of_port))
            request = ofp.message.flow_add(
                table_id=test_param_get("table", 0),
                cookie=42,
                match=m,
                instructions=[
                    ofp.instruction.apply_actions(
                        actions=[
                            ofp.action.output(
                                port=ofp.OFPP_CONTROLLER,
                                max_len=ofp.OFPCML_NO_BUFFER)])],
                buffer_id=ofp.OFP_NO_BUFFER,
                priority=1000)
            logging.info("Inserting flow sending matching packets to controller")
            self.controller.message_send(request)
            do_barrier(self.controller)

        for of_port in config["port_map"]:
            logging.info("PacketInExact test, port %d", of_port)
            self.dataplane.send(of_port, pkt)
            verify_packet_in(self, pkt, of_port, ofp.OFPR_ACTION)
            verify_packets(self, pkt, [])

    def installEapolRule(self, in_port=None, install=True):
        in_port = onu_port if in_port is None else in_port
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.eth_type(0x888e))
        match.oxm_list.append(ofp.oxm.in_port(in_port))
        if install:
            request = ofp.message.flow_add(
                    table_id=test_param_get("table", 0),
                    cookie=42,
                    match=match,
                    instructions=[
                        ofp.instruction.apply_actions(
                            actions=[
                                ofp.action.output(
                                    port=ofp.OFPP_CONTROLLER,
                                    max_len=ofp.OFPCML_NO_BUFFER)])],
                    buffer_id=ofp.OFP_NO_BUFFER,
                    priority=1000)
        else:
            request = ofp.message.flow_delete_strict(
                    table_id=test_param_get("table", 0),
                    cookie=42,
                    match=match,
                    instructions=[
                        ofp.instruction.apply_actions(
                            actions=[
                                ofp.action.output(
                                    port=ofp.OFPP_CONTROLLER,
                                    max_len=ofp.OFPCML_NO_BUFFER)])],
                    buffer_id=ofp.OFP_NO_BUFFER,
                    priority=1000)
        logging.info("%s flow sending matching packets to controller" % "Install" if install else "Remove")
        self.controller.message_send(request)
        do_barrier(self.controller)

    def sendEapolIn(self, in_port=None):
        """Send in an EAPOL frame and verify that the controller receives it"""

        in_port = onu_port if in_port is None else in_port
        pkt = str(simple_eth_packet(eth_dst='01:00:5e:7f:ff:ff', eth_type=0x888e, pktlen=60))
        self.dataplane.send(in_port, pkt)
        verify_packet_in(self, pkt, in_port, ofp.OFPR_ACTION)
        verify_packets(self, pkt, [])

    def sendEapolOut(self, out_port=None):
        """Send out an EAPOL frame and verify that it is sent out at the given ONU port"""
        out_port = onu_port if out_port is None else out_port
        pkt = simple_eth_packet(eth_dst='01:02:03:04:05:06', eth_src='01:02:03:de:ad:be',
                                eth_type=0x888e, pktlen=300)
        
        msg = ofp.message.packet_out(
            in_port=ofp.OFPP_CONTROLLER,
            actions=[ofp.action.output(port=out_port)],
            buffer_id=ofp.OFP_NO_BUFFER,
            data=str(pkt))

        rv = self.controller.message_send(msg)
        self.assertTrue(rv == 0, "Error sending output message")
        verify_no_errors(self.controller)

        verify_packet(self, pkt, out_port)

    def testPacketFlow(self,
                       s_vlan_id,
                       c_vlan_id,
                       onu=None,
                       verify_blocked_flows=True,
                       pktlen=96):

        incorrectTagPkt = simple_udp_packet(
            pktlen=pktlen+4, dl_vlan_enable=True, vlan_vid=s_vlan_id, vlan_pcp=1)
        zeroTaggedPkt = simple_udp_packet(
            pktlen=pktlen+4, dl_vlan_enable=True, vlan_vid=0, vlan_pcp=0)
        untaggedPkt = simple_udp_packet(pktlen=pktlen)
        upstreamDoubleTaggedPkt = double_vlan_udp_packet(
            pktlen=pktlen+8, dl_vlan_enable=True, c_vlan_vid=c_vlan_id, s_vlan_vid=s_vlan_id,
            c_vlan_pcp=0, s_vlan_pcp=0)

        inport = onu_port if onu is None else onu

        logging.info("Testing s-tag %d, c-tag %d" % (s_vlan_id, c_vlan_id))

        # test upstream untagged packet got double tag at OLT
        self.dataplane.send(inport, str(zeroTaggedPkt))
        verify_packet(self, upstreamDoubleTaggedPkt, olt_port)

        # test downstream doubletagged packet got untagged at ONU
        self.dataplane.send(olt_port, str(upstreamDoubleTaggedPkt))
        if device_type == "pmc":
            verify_packet(self, zeroTaggedPkt, inport)
        else:
            verify_packet(self, untaggedPkt, inport)

        if verify_blocked_flows:
            # test upstream doubletagged packet got dropped
            self.dataplane.send(inport, str(upstreamDoubleTaggedPkt))
            verify_no_packet(self, upstreamDoubleTaggedPkt, olt_port)

            # test downstream untagged packet got dropped at ONU
            self.dataplane.send(olt_port, str(untaggedPkt))
            verify_no_packet(self, untaggedPkt, inport)

            # test upstream icorrectly tagged packet; should get dropped
            self.dataplane.send(inport, str(incorrectTagPkt))
            verify_no_packet(self, upstreamDoubleTaggedPkt, olt_port)

    def testSustainedPacketFlow(self, s_vlan_id, c_vlan_id, number_of_roundtrips=10, onu=None):
        for i in xrange(number_of_roundtrips):
            print "pkt # %d" % (i+1,)
            self.testPacketFlow(s_vlan_id, c_vlan_id, onu=onu, verify_blocked_flows=False)

    def installDoubleTaggingRules(self, s_vlan_id, c_vlan_id, cookie=42, onu=None):

        inport = onu_port if onu is None else onu

        # upstream flow rule
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.in_port(inport))
        if device_type == "cpqd":
            match.oxm_list.append(ofp.oxm.vlan_vid(value=ofp.OFPVID_NONE))
            actions = [
                ofp.action.push_vlan(ethertype=0x8100),
                ofp.action.set_field(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | c_vlan_id)),
                ofp.action.set_field(ofp.oxm.vlan_pcp(0))
            ]
        else:  # "pmc", "normal"
            match.oxm_list.append(ofp.oxm.vlan_vid(value=ofp.OFPVID_PRESENT))
            match.oxm_list.append(ofp.oxm.vlan_pcp(value=0))
            actions = [
                ofp.action.set_field(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | c_vlan_id))
            ]
        cookie += 1

        # push inner vlan (c-vlan) for upstream
        request = ofp.message.flow_add(
            table_id=test_param_get("table", 0),
            cookie=cookie,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(actions=actions),
                ofp.instruction.goto_table(1)],
            buffer_id=ofp.OFP_NO_BUFFER,
            priority=1000)

        self.controller.message_send(request)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

        # push outer vlan (s-vlan) for upstream
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.in_port(inport))
        match.oxm_list.append(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | c_vlan_id))
        match.oxm_list.append(ofp.oxm.vlan_pcp(0))
        cookie += 1

        request = ofp.message.flow_add(
            table_id=test_param_get("table", 1),
            cookie=cookie,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(
                    actions=[
                        ofp.action.push_vlan(ethertype=0x8100),
                        ofp.action.set_field(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | s_vlan_id)),
                        ofp.action.set_field(ofp.oxm.vlan_pcp(0)),
                        ofp.action.output(port=olt_port)]),
            ],
            buffer_id=ofp.OFP_NO_BUFFER,
            priority=1000)

        self.controller.message_send(request)
        do_barrier(self.controller)
        verify_no_errors(self.controller)
        cookie += 1

        # strip outer vlan (s-vlan) for downstream
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.in_port(olt_port))
        match.oxm_list.append(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | s_vlan_id))
        match.oxm_list.append(ofp.oxm.vlan_pcp(0))
        request = ofp.message.flow_add(
            table_id=test_param_get("table", 0),
            cookie=cookie,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(
                    actions=[ofp.action.pop_vlan()]),
                ofp.instruction.goto_table(1)],
            buffer_id=ofp.OFP_NO_BUFFER,
            priority=1000)

        self.controller.message_send(request)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

        # rewrite inner vlan (c-vlan) to default (0) for downstream
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.in_port(olt_port))
        match.oxm_list.append(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | c_vlan_id))
        match.oxm_list.append(ofp.oxm.vlan_pcp(0))
        cookie += 1

        request = ofp.message.flow_add(
            table_id=test_param_get("table", 1),
            cookie=cookie,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(
                    actions=[
                        ofp.action.pop_vlan(),
                        ofp.action.output(port=inport)])
            ],
            buffer_id=ofp.OFP_NO_BUFFER,
            priority=1000)

        self.controller.message_send(request)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

    def installIgmpRule(self, cookie):
        """Etsablish flow rules that will forward any incoming
           IGMP packets to controller (from any port, OLT and ONUs)
        """
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.eth_type(0x800))
        match.oxm_list.append(ofp.oxm.ip_proto(2))
        request = ofp.message.flow_add(
            table_id=test_param_get("table", 0),
            cookie=42,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(
                    actions=[
                        ofp.action.output(
                            port=ofp.OFPP_CONTROLLER,
                            max_len=ofp.OFPCML_NO_BUFFER)])],
            buffer_id=ofp.OFP_NO_BUFFER,
            priority=2000)
        logging.info("Inserting flow sending matching packets to controller")
        self.controller.message_send(request)
        do_barrier(self.controller)

    def testIgmpQueryOut(self, onu=None):
        """Send an IGMP Query out to given onu and verify that it arrives"""

        outport = onu_port if onu is None else onu

        igmp = IGMPv3()  # by default this is a query
        pkt = self.buildIgmp(igmp)

        msg = ofp.message.packet_out(
            in_port=ofp.OFPP_CONTROLLER,
            actions=[ofp.action.output(port=outport)],
            buffer_id=ofp.OFP_NO_BUFFER,
            data=str(pkt))

        self.controller.message_send(msg)

        rv = self.controller.message_send(msg)
        self.assertTrue(rv == 0, "Error sending output message")
        verify_no_errors(self.controller)

        verify_packet(self, pkt, outport)

    def sendIgmpReport(self, join=[], leave=[], onu=None, srcmac=None,
                     ip_src='1.2.3.4', ip_dst='2440.0.0.22', pad_to=None):
        """Send an IGMP Join request from given onu to given mcast group"""

        # construct packet
        in_port = onu_port if onu is None else onu
        src_mac = '00:00:00:00:be:ef' if srcmac is None else srcmac
        pkt = str(self.buildIgmpReport(ip_src, ip_dst, src_mac, join, leave, pad_to=pad_to))

        # send packet via in_port
        self.dataplane.send(in_port, pkt)

        # verify it is received by controller and not by some other port
        verify_packet_in(self, pkt, in_port, ofp.OFPR_ACTION)
        verify_packets(self, pkt, [])

    def buildIgmpReport(self, ip_src, ip_dst, srcmac, join=[], leave=[], sources={}, pad_to=None):
        """ Return an IGMPv4 Membership Report as a scapy Ethernet frame
            join:    a list of multicast addresses that shall be joined
            leave:   a list of multicast addresses that shall be left
            sources: a dict of source lists keyed by the mcast address that needs to be joined
            or left.
        """

        assert join or leave, "Either join or leave must be a non-empty list"

        igmp = IGMPv3(type=IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30, gaddr="224.0.0.1")

        for mcast_group in join:
            srcs = sources.get(mcast_group, [])
            if len(srcs):
                gr = IGMPv3gr(rtype=IGMP_V3_GR_TYPE_INCLUDE, mcaddr=mcast_group)
                gr.sources = srcs
            else:
                gr = IGMPv3gr(rtype=IGMP_V3_GR_TYPE_EXCLUDE, mcaddr=mcast_group)
            igmp.grps.append(gr)

        for mcast_group in leave:
            gr = IGMPv3gr(rtype=IGMP_V3_GR_TYPE_INCLUDE, mcaddr=mcast_group)
            igmp.grps.append(gr)

        pkt = IGMPv3.fixup( scapy.Ether(src=srcmac) / scapy.IP() / igmp )
        pkt = self.padPktTo(pkt, pad_to)
        return pkt

    def buildIgmp(self, payload, pad_to=None):
        pkt = IGMPv3.fixup(scapy.Ether() / scapy.IP() / payload)
        return self.padPktTo(pkt, pad_to)

    def padPktTo(self, pkt, pad_to=None):
        """If pad_to is provided, it shall be an integer. If pkt is smaller than that number,
           it will be properly padded (ethernet padding) and returned. Otherwise the original
           pkt is returned.
        """
        if pad_to is None:
            return pkt

        pad_len = pad_to - len(pkt)
        if pad_len > 0:
            pad = scapy.scapy.layers.l2.Padding()
            pad.load = '\x00' * pad_len
            pkt = pkt / pad
        return pkt

    def setupMcastChannel(self, mcast_addr, mcast_vlan_id, port_list, group_id=1, cookie=100):
        """Setup multicast forwarding for the mcast address using mcast vlan id
           and given port list.
        """

        # setup group first with given port list

        buckets = [
            ofp.common.bucket(
                watch_port=ofp.OFPP_ANY,
                watch_group=ofp.OFPG_ANY,
                actions=[
                    ofp.action.pop_vlan(),
                    ofp.action.output(port=port)
                ])
            for port in port_list
        ]

        msg = ofp.message.group_add(
            group_type=ofp.OFPGT_ALL,
            group_id=group_id,
            buckets=buckets
        )

        self.controller.message_send(msg)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

        # Then setup flow rule pointing to group

        match = ofp.match()
        match.oxm_list.append(ofp.oxm.in_port(olt_port))
        match.oxm_list.append(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | mcast_vlan_id))
        match.oxm_list.append(ofp.oxm.eth_type(0x800))
        match.oxm_list.append(ofp.oxm.ipv4_dst(self.ip2int(mcast_addr)))
        request = ofp.message.flow_add(
            table_id=test_param_get("table", 0),
            cookie=cookie,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(
                    actions=[ofp.action.group(group_id=group_id)]),
            ],
            buffer_id=ofp.OFP_NO_BUFFER, priority=1000)
        self.controller.message_send(request)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

    def removeMcastChannel(self, mcast_addr, mcast_vlan_id, port_list, group_id, cookie):
        """Remove mumticast forwarding for given mcast address"""

        # Remove flow first
        match = ofp.match()
        match.oxm_list.append(ofp.oxm.in_port(olt_port))
        match.oxm_list.append(ofp.oxm.vlan_vid(ofp.OFPVID_PRESENT | mcast_vlan_id))
        match.oxm_list.append(ofp.oxm.eth_type(0x800))
        match.oxm_list.append(ofp.oxm.ipv4_dst(self.ip2int(mcast_addr)))
        request = ofp.message.flow_delete(
            table_id=test_param_get("table", 0),
            cookie=cookie,
            match=match,
            instructions=[
                ofp.instruction.apply_actions(
                    actions=[ofp.action.group(group_id=group_id)]),
            ],
            buffer_id=ofp.OFP_NO_BUFFER, priority=1000)
        self.controller.message_send(request)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

        # Then remove the group
        group_delete = ofp.message.group_delete(group_id=group_id)
        self.controller.message_send(group_delete)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

    def updateMcastChannel(self, group_id, port_list):
        """Modify the group port list by adding/removing ports"""

        buckets = [
            ofp.common.bucket(
                watch_port=ofp.OFPP_ANY,
                watch_group=ofp.OFPG_ANY,
                actions=[
                    ofp.action.pop_vlan(),
                    ofp.action.output(port=port)
                ])
            for port in port_list
        ]

        msg = ofp.message.group_mod(
            command=ofp.OFPGC_MODIFY,
            group_type=ofp.OFPGT_ALL,
            group_id=group_id,
            buckets=buckets)

        self.controller.message_send(msg)
        do_barrier(self.controller)
        verify_no_errors(self.controller)

    def ip2int(self, ip):
        """Convert a dot-notated string IP address"""
        digits = [int(d) for d in ip.split('.')]
        assert len(digits) == 4
        val = (
            (digits[0] & 0xff) << 24 |
            (digits[1] & 0xff) << 16 |
            (digits[2] & 0xff) << 8  |
            (digits[3] & 0xff))
        return val

    def mcastIp2McastMac(self, ip):
        """ Convert a dot-notated IPv4 multicast address string into an multicast MAC address"""
        digits = [int(d) for d in ip.split('.')]
        return '01:00:5e:%02x:%02x:%02x' % (digits[1] & 0x7f, digits[2] & 0xff, digits[3] & 0xff)

    def testMcastFlow(self, mcast_addr, mcast_vlan_id, ports=None, numpkt=1, ip_src="66.77.88.99",
                      expect_to_be_blocked=False):
        """ Send given number of mcast packets using mcast address and vlan_id
            and check they arrive to given port(s).
        """

        # construct mcast packet
        pktlen = 250
        pktToSend = simple_udp_packet(
            eth_dst=self.mcastIp2McastMac(mcast_addr),
            ip_src=ip_src,
            ip_dst=mcast_addr,
            pktlen=pktlen+4,
            dl_vlan_enable=True,
            vlan_vid=mcast_vlan_id,
            vlan_pcp=0)

        if device_type == "pmc":
            pktToReceive = simple_udp_packet(
                eth_dst=self.mcastIp2McastMac(mcast_addr),
                ip_src=ip_src,
                ip_dst=mcast_addr,
                pktlen=pktlen+4,
                dl_vlan_enable=True,
                vlan_vid=0,
                vlan_pcp=0)
        else:
            pktToReceive = simple_udp_packet(
                eth_dst=self.mcastIp2McastMac(mcast_addr),
                ip_src=ip_src,
                ip_dst=mcast_addr,
                pktlen=pktlen)

        # send mcast packet to olt
        self.dataplane.send(olt_port, str(pktToSend))

        # test that packet is received on each designated port
        ports = [onu_port] if ports is None else ports
        for port in ports:
            if expect_to_be_blocked:
                verify_no_packet(self, pktToReceive, port)
            else:
                verify_packet(self, pktToReceive, port)
