
# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""
Dummy platform

This platform uses Open vSwitch dummy interfaces.
"""

import logging
import os
import select
import socket
import struct
import sys
import time
from threading import Thread
from threading import Lock

RCV_TIMEOUT = 10000
RUN_DIR = os.environ.get("OVS_RUNDIR", "/var/run/openvswitch")

class DataPlanePortOVSDummy:
    """
    Class defining a port monitoring object that uses Unix domain
    sockets for ports, intended for connecting to Open vSwitch "dummy"
    netdevs.
    """

    def __init__(self, interface_name, port_number, max_pkts=1024):
        """
        Set up a port monitor object
        @param interface_name The name of the physical interface like eth1
        @param port_number The port number associated with this port
        @param max_pkts Maximum number of pkts to keep in queue
        """
        self.interface_name = interface_name
        self.max_pkts = max_pkts
        self.port_number = port_number
        self.txq = []
        self.rxbuf = ""
        logname = "dp-" + interface_name
        self.logger = logging.getLogger(logname)
        try:
            self.socket = DataPlanePortOVSDummy.interface_open(interface_name)
        except:
            self.logger.info("Could not open socket")
            raise
        self.logger.info("Opened port monitor (class %s)", type(self).__name__)

    @staticmethod
    def interface_open(interface_name):
        """
        Open a Unix domain socket interface.
        @param interface_name port name as a string such as 'eth1'
        @retval s socket
        """
        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.settimeout(RCV_TIMEOUT)
        s.setblocking(0)
        s.connect("%s/%s" % (RUN_DIR, interface_name))
        return s

    def __del__(self):
        if self.socket:
            self.socket.close()

    def fileno(self):
        """
        Return an integer file descriptor that can be passed to select(2).
        """
        return self.socket.fileno()

    def recv(self):
        while True:
            rout, wout, eout = select.select([self.socket], [], [], 0)
            if not rout:
                return

            if len(self.rxbuf) < 2:
                n = 2 - len(self.rxbuf)
            else:
                frame_len = struct.unpack('>h', self.rxbuf[:2])[0]
                n = (2 + frame_len) - len(self.rxbuf)

            data = self.socket.recv(n)
            self.rxbuf += data
            if len(data) == n and len(self.rxbuf) > 2:
                rcvtime = time.time()
                packet = self.rxbuf[2:]
                self.logger.debug("Pkt len " + str(len(packet)) +
                         " in at " + str(rcvtime) + " on port " +
                         str(self.port_number))
                self.rxbuf = ""
                return (packet, rcvtime)

    def send(self, packet):
        if len(self.txq) < self.max_pkts:
            self.txq.append(struct.pack('>h', len(packet)) + packet)
            retval = len(packet)
        else:
            retval = 0
        self.__run_tx()
        return retval

    def __run_tx(self):
        while self.txq:
            rout, wout, eout = select.select([], [self.socket], [], 0)
            if not wout:
                return

            retval = self.socket.send(self.txq[0])
            if retval > 0:
                self.txq[0] = self.txq[0][retval:]
                if len(self.txq[0]) == 0:
                    self.txq = self.txq[1:]
        
    def down(self):
        pass

    def up(self):
        pass

# Update this dictionary to suit your environment.
dummy_port_map = {
    1 : "p1",
    2 : "p2",
    3 : "p3",
    4 : "p4"
}

def platform_config_update(config):
    """
    Update configuration for the dummy platform

    @param config The configuration dictionary to use/update
    """
    global dummy_port_map
    config["port_map"] = dummy_port_map.copy()
    config["caps_table_idx"] = 0
    config["dataplane"] = {"portclass": DataPlanePortOVSDummy}
    config["allow_user"] = True
