/*
 * Copyright (c) 2014 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Anthony Gutierrez
 *          Mohammad Alian
 */

/* @file
 * Device model for an ethernet switch
 */

#include "dev/net/etherswitch.hh"

#include "base/random.hh"
#include "base/trace.hh"
#include "debug/EthernetAll.hh"
#include "sim/core.hh"

using namespace std;

EtherSwitch::EtherSwitch(const Params *p)
    : SimObject(p), ttl(p->time_to_live)
{
    for (int i = 0; i < p->port_interface_connection_count; ++i) {
        std::string interfaceName = csprintf("%s.interface%d", name(), i);
        Interface *interface = new Interface(interfaceName, this,
                                        p->output_buffer_size, p->delay,
                                        p->delay_var, p->fabric_speed, i);
        interfaces.push_back(interface);
    }
}

EtherSwitch::~EtherSwitch()
{
    for (auto it : interfaces)
        delete it;

    interfaces.clear();
}

EtherInt*
EtherSwitch::getEthPort(const std::string &if_name, int idx)
{
    if (idx < 0 || idx >= interfaces.size())
        return nullptr;

    Interface *interface = interfaces.at(idx);
    panic_if(interface->getPeer(), "interface already connected\n");

    return interface;
}

bool
EtherSwitch::Interface::PortFifo::push(EthPacketPtr ptr, unsigned senderId)
{
    assert(ptr->length);

    _size += ptr->length;
    fifo.emplace_hint(fifo.end(), ptr, curTick(), senderId);

    // Drop the extra pushed packets from end of the fifo
    while (avail() < 0) {
        DPRINTF(Ethernet, "Fifo is full. Drop packet: len=%d\n",
                std::prev(fifo.end())->packet->length);

        _size -= std::prev(fifo.end())->packet->length;
        fifo.erase(std::prev(fifo.end()));
    }

    if (empty()) {
        warn("EtherSwitch: Packet length (%d) exceeds the maximum storage "
             "capacity of port fifo (%d)", ptr->length, _maxsize);
    }

    // Return true if the newly pushed packet gets inserted
    // at the head of the queue, otherwise return false
    // We need this information to deschedule the event that has been
    // scheduled for the old head of queue packet and schedule a new one
    if (!empty() && fifo.begin()->packet == ptr) {
        return true;
    }
    return false;
}

void
EtherSwitch::Interface::PortFifo::pop()
{
    if (empty())
        return;

    assert(_size >= fifo.begin()->packet->length);
    // Erase the packet at the head of the queue
    _size -= fifo.begin()->packet->length;
    fifo.erase(fifo.begin());
}

void
EtherSwitch::Interface::PortFifo::clear()
{
    fifo.clear();
    _size = 0;
}

EtherSwitch::Interface::Interface(const std::string &name,
                                  EtherSwitch *etherSwitch,
                                  uint64_t outputBufferSize, Tick delay,
                                  Tick delay_var, double rate, unsigned id)
    : EtherInt(name), ticksPerByte(rate), switchDelay(delay),
      delayVar(delay_var), interfaceId(id), parent(etherSwitch),
      outputFifo(name + ".outputFifo", outputBufferSize),
      txEvent([this]{ transmit(); }, name)
{
}

bool
EtherSwitch::Interface::recvPacket(EthPacketPtr packet)
{
    Net::EthAddr destMacAddr(packet->data);
    Net::EthAddr srcMacAddr(&packet->data[6]);

    learnSenderAddr(srcMacAddr, this);
    Interface *receiver = lookupDestPort(destMacAddr);

    if (!receiver || destMacAddr.multicast() || destMacAddr.broadcast()) {
        for (auto it : parent->interfaces)
            if (it != this)
                it->enqueue(packet, interfaceId);
    } else {
        DPRINTF(Ethernet, "sending packet from MAC %x on port "
                "%s to MAC %x on port %s\n", uint64_t(srcMacAddr),
                this->name(), uint64_t(destMacAddr), receiver->name());

        receiver->enqueue(packet, interfaceId);
    }
    // At the output port, we either have buffer space (no drop) or
    // don't (drop packet); in both cases packet is received on
    // the interface successfully and there is no notion of busy
    // interface here (as we don't have inputFifo)
    return true;
}

void
EtherSwitch::Interface::enqueue(EthPacketPtr packet, unsigned senderId)
{
    // assuming per-interface transmission events,
    // if the newly push packet gets inserted at the head of the queue
    // (either there was nothing in the queue or the priority of the new
    // packet was higher than the packets already in the fifo)
    // then we need to schedule an event at
    // "curTick" + "switchingDelay of the packet at the head of the fifo"
    // to send this packet out the external link
    // otherwise, there is already a txEvent scheduled
    if (outputFifo.push(packet, senderId)) {
        parent->reschedule(txEvent, curTick() + switchingDelay(), true);
    }
}

void
EtherSwitch::Interface::transmit()
{
    // there should be something in the output queue
    assert(!outputFifo.empty());

    if (!sendPacket(outputFifo.front())) {
        DPRINTF(Ethernet, "output port busy...retry later\n");
        if (!txEvent.scheduled())
            parent->schedule(txEvent, curTick() + retryTime);
    } else {
        DPRINTF(Ethernet, "packet sent: len=%d\n", outputFifo.front()->length);
        outputFifo.pop();
        // schedule an event to send the pkt at
        // the head of queue, if there is any
        if (!outputFifo.empty()) {
            parent->schedule(txEvent, curTick() + switchingDelay());
        }
    }
}

Tick
EtherSwitch::Interface::switchingDelay()
{
    Tick delay = (Tick)ceil(((double)outputFifo.front()->simLength
                                     * ticksPerByte) + 1.0);
    if (delayVar != 0)
                delay += random_mt.random<Tick>(0, delayVar);
    delay += switchDelay;
    return delay;
}

EtherSwitch::Interface*
EtherSwitch::Interface::lookupDestPort(Net::EthAddr destMacAddr)
{
    auto it = parent->forwardingTable.find(uint64_t(destMacAddr));

    if (it == parent->forwardingTable.end()) {
        DPRINTF(Ethernet, "no entry in forwaring table for MAC: "
                "%x\n", uint64_t(destMacAddr));
        return nullptr;
    }

    // check if this entry is valid based on TTL and lastUseTime
    if ((curTick() - it->second.lastUseTime) > parent->ttl) {
        // TTL for this mapping has been expired, so this item is not
        // valide anymore, let's remove it from the map
        parent->forwardingTable.erase(it);
        return nullptr;
    }

    DPRINTF(Ethernet, "found entry for MAC address %x on port %s\n",
            uint64_t(destMacAddr), it->second.interface->name());
    return it->second.interface;
}

void
EtherSwitch::Interface::learnSenderAddr(Net::EthAddr srcMacAddr,
                                          Interface *sender)
{
    // learn the port for the sending MAC address
    auto it = parent->forwardingTable.find(uint64_t(srcMacAddr));

    // if the port for sender's MAC address is not cached,
    // cache it now, otherwise just update lastUseTime time
    if (it == parent->forwardingTable.end()) {
        DPRINTF(Ethernet, "adding forwarding table entry for MAC "
                " address %x on port %s\n", uint64_t(srcMacAddr),
                sender->name());
        EtherSwitch::SwitchTableEntry forwardingTableEntry;
        forwardingTableEntry.interface = sender;
        forwardingTableEntry.lastUseTime = curTick();
        parent->forwardingTable.insert(std::make_pair(uint64_t(srcMacAddr),
            forwardingTableEntry));
    } else {
        it->second.lastUseTime = curTick();
    }
}

void
EtherSwitch::serialize(CheckpointOut &cp) const
{
    for (auto it : interfaces)
        it->serializeSection(cp, it->name());

}

void
EtherSwitch::unserialize(CheckpointIn &cp)
{
    for (auto it : interfaces)
        it->unserializeSection(cp, it->name());

}

void
EtherSwitch::Interface::serialize(CheckpointOut &cp) const
{
    bool event_scheduled = txEvent.scheduled();
    SERIALIZE_SCALAR(event_scheduled);

    if (event_scheduled) {
        Tick event_time = txEvent.when();
        SERIALIZE_SCALAR(event_time);
    }
    outputFifo.serializeSection(cp, "outputFifo");
}

void
EtherSwitch::Interface::unserialize(CheckpointIn &cp)
{
    bool event_scheduled;
    UNSERIALIZE_SCALAR(event_scheduled);

    if (event_scheduled) {
        Tick event_time;
        UNSERIALIZE_SCALAR(event_time);
        parent->schedule(txEvent, event_time);
    }
    outputFifo.unserializeSection(cp, "outputFifo");
}

void
EtherSwitch::Interface::PortFifoEntry::serialize(CheckpointOut &cp) const
{
    packet->serialize("packet", cp);
    SERIALIZE_SCALAR(recvTick);
    SERIALIZE_SCALAR(srcId);
}

void
EtherSwitch::Interface::PortFifoEntry::unserialize(CheckpointIn &cp)
{
    packet = make_shared<EthPacketData>(16384);
    packet->unserialize("packet", cp);
    UNSERIALIZE_SCALAR(recvTick);
    UNSERIALIZE_SCALAR(srcId);
}

void
EtherSwitch::Interface::PortFifo::serialize(CheckpointOut &cp) const
{
    SERIALIZE_SCALAR(_size);
    int fifosize = fifo.size();

    SERIALIZE_SCALAR(fifosize);

    int i = 0;
    for (const auto &entry : fifo)
        entry.serializeSection(cp, csprintf("entry%d", i++));
}

void
EtherSwitch::Interface::PortFifo::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_SCALAR(_size);
    int fifosize;

    UNSERIALIZE_SCALAR(fifosize);
    fifo.clear();

    for (int i = 0; i < fifosize; ++i) {
        PortFifoEntry entry(nullptr, 0, 0);

        entry.unserializeSection(cp, csprintf("entry%d", i));

        fifo.insert(entry);

    }
}

EtherSwitch *
EtherSwitchParams::create()
{
    return new EtherSwitch(this);
}
