/*
 * Copyright (c) 2003-2005 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.
 */

/* @file
 * Interface to connect a simulated ethernet device to the real world
 */

#include "dev/net/ethertap.hh"

#if defined(__OpenBSD__) || defined(__APPLE__)
#include <sys/param.h>

#endif

#if HAVE_TUNTAP && defined(__linux__)
#if 1 // Hide from the style checker since these have to be out of order.
#include <sys/socket.h> // Has to be included before if.h for some reason.

#endif

#include <linux/if.h>
#include <linux/if_tun.h>

#endif

#include <fcntl.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <cstring>
#include <deque>
#include <string>

#include "base/logging.hh"
#include "base/pollevent.hh"
#include "base/socket.hh"
#include "base/trace.hh"
#include "debug/Ethernet.hh"
#include "debug/EthernetData.hh"
#include "dev/net/etherdump.hh"
#include "dev/net/etherint.hh"
#include "dev/net/etherpkt.hh"
#include "sim/core.hh"
#include "sim/cur_tick.hh"

namespace gem5
{

class TapEvent : public PollEvent
{
  protected:
    EtherTapBase *tap;

  public:
    TapEvent(EtherTapBase *_tap, int fd, int e)
        : PollEvent(fd, e), tap(_tap) {}

    void
    process(int revent) override
    {
        // Ensure that our event queue is active. It may not be since we get
        // here from the PollQueue whenever a real packet happens to arrive.
        EventQueue::ScopedMigration migrate(tap->eventQueue());

        tap->recvReal(revent);
    }
};

EtherTapBase::EtherTapBase(const Params &p)
    : SimObject(p), buflen(p.bufsz), dump(p.dump), event(NULL),
      interface(NULL),
      txEvent([this]{ retransmit(); }, "EtherTapBase retransmit")
{
    buffer = new uint8_t[buflen];
    interface = new EtherTapInt(name() + ".interface", this);
}

EtherTapBase::~EtherTapBase()
{
    delete buffer;
    delete event;
    delete interface;
}

void
EtherTapBase::serialize(CheckpointOut &cp) const
{
    SERIALIZE_SCALAR(buflen);
    uint8_t *buffer = (uint8_t *)this->buffer;
    SERIALIZE_ARRAY(buffer, buflen);

    bool tapevent_present = false;
    if (event) {
        tapevent_present = true;
        SERIALIZE_SCALAR(tapevent_present);
        event->serialize(cp);
    } else {
        SERIALIZE_SCALAR(tapevent_present);
    }
}

void
EtherTapBase::unserialize(CheckpointIn &cp)
{
    UNSERIALIZE_SCALAR(buflen);
    uint8_t *buffer = (uint8_t *)this->buffer;
    UNSERIALIZE_ARRAY(buffer, buflen);

    bool tapevent_present;
    UNSERIALIZE_SCALAR(tapevent_present);
    if (tapevent_present) {
        event = new TapEvent(this, 0, 0);
        event->unserialize(cp);
        if (event->queued())
            pollQueue.schedule(event);
    }
}


void
EtherTapBase::pollFd(int fd)
{
    assert(!event);
    event = new TapEvent(this, fd, POLLIN|POLLERR);
    pollQueue.schedule(event);
}

void
EtherTapBase::stopPolling()
{
    assert(event);
    delete event;
    event = NULL;
}


Port &
EtherTapBase::getPort(const std::string &if_name, PortID idx)
{
    if (if_name == "tap")
        return *interface;
    return SimObject::getPort(if_name, idx);
}

bool
EtherTapBase::recvSimulated(EthPacketPtr packet)
{
    if (dump)
        dump->dump(packet);

    DPRINTF(Ethernet, "EtherTap sim->real len=%d\n", packet->length);
    DDUMP(EthernetData, packet->data, packet->length);

    bool success = sendReal(packet->data, packet->length);

    interface->recvDone();

    return success;
}

void
EtherTapBase::sendSimulated(void *data, size_t len)
{
    EthPacketPtr packet;
    packet = std::make_shared<EthPacketData>(len);
    packet->length = len;
    packet->simLength = len;
    memcpy(packet->data, data, len);

    DPRINTF(Ethernet, "EtherTap real->sim len=%d\n", packet->length);
    DDUMP(EthernetData, packet->data, packet->length);
    if (!packetBuffer.empty() || !interface->sendPacket(packet)) {
        DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
        packetBuffer.push(packet);
        if (!txEvent.scheduled())
            schedule(txEvent, curTick() + sim_clock::as_int::ns);
    } else if (dump) {
        dump->dump(packet);
    }
}

void
EtherTapBase::retransmit()
{
    if (packetBuffer.empty())
        return;

    EthPacketPtr packet = packetBuffer.front();
    if (interface->sendPacket(packet)) {
        if (dump)
            dump->dump(packet);
        DPRINTF(Ethernet, "EtherTap retransmit\n");
        packetBuffer.front() = NULL;
        packetBuffer.pop();
    }

    if (!packetBuffer.empty() && !txEvent.scheduled())
        schedule(txEvent, curTick() + sim_clock::as_int::ns);
}


class TapListener
{
  protected:
    class Event : public PollEvent
    {
      protected:
        TapListener *listener;

      public:
        Event(TapListener *l, int fd, int e) : PollEvent(fd, e), listener(l) {}

        void process(int revent) override { listener->accept(); }
    };

    friend class Event;
    Event *event;

    void accept();

  protected:
    ListenSocket listener;
    EtherTapStub *tap;
    int port;

  public:
    TapListener(EtherTapStub *t, int p) : event(NULL), tap(t), port(p) {}
    ~TapListener() { delete event; }

    void listen();
};

void
TapListener::listen()
{
    while (!listener.listen(port, true)) {
        DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port);
        port++;
    }

    ccprintf(std::cerr, "Listening for tap connection on port %d\n", port);
    event = new Event(this, listener.getfd(), POLLIN|POLLERR);
    pollQueue.schedule(event);
}

void
TapListener::accept()
{
    // As a consequence of being called from the PollQueue, we might
    // have been called from a different thread. Migrate to "our"
    // thread.
    EventQueue::ScopedMigration migrate(tap->eventQueue());

    if (!listener.islistening())
        panic("TapListener(accept): cannot accept if we're not listening!");

    int sfd = listener.accept(true);
    if (sfd != -1)
        tap->attach(sfd);
}


EtherTapStub::EtherTapStub(const Params &p) : EtherTapBase(p), socket(-1)
{
    if (ListenSocket::allDisabled())
        fatal("All listeners are disabled! EtherTapStub can't work!");

    listener = new TapListener(this, p.port);
    listener->listen();
}

EtherTapStub::~EtherTapStub()
{
    delete listener;
}

void
EtherTapStub::serialize(CheckpointOut &cp) const
{
    EtherTapBase::serialize(cp);

    SERIALIZE_SCALAR(socket);
    SERIALIZE_SCALAR(buffer_used);
    SERIALIZE_SCALAR(frame_len);
}

void
EtherTapStub::unserialize(CheckpointIn &cp)
{
    EtherTapBase::unserialize(cp);

    UNSERIALIZE_SCALAR(socket);
    UNSERIALIZE_SCALAR(buffer_used);
    UNSERIALIZE_SCALAR(frame_len);
}


void
EtherTapStub::attach(int fd)
{
    if (socket != -1)
        close(fd);

    buffer_used = 0;
    frame_len = 0;
    socket = fd;
    DPRINTF(Ethernet, "EtherTapStub attached\n");
    pollFd(socket);
}

void
EtherTapStub::detach()
{
    DPRINTF(Ethernet, "EtherTapStub detached\n");
    stopPolling();
    close(socket);
    socket = -1;
}

void
EtherTapStub::recvReal(int revent)
{
    if (revent & POLLERR) {
        detach();
        return;
    }

    if (!(revent & POLLIN))
        return;

    // Read in as much of the new data as we can.
    int len = read(socket, buffer + buffer_used, buflen - buffer_used);
    if (len == 0) {
        detach();
        return;
    }
    buffer_used += len;

    // If there's not enough data for the frame length, wait for more.
    if (buffer_used < sizeof(uint32_t))
        return;

    if (frame_len == 0)
        frame_len = ntohl(*(uint32_t *)buffer);

    DPRINTF(Ethernet, "Received data from peer: len=%d buffer_used=%d "
            "frame_len=%d\n", len, buffer_used, frame_len);

    uint8_t *frame_start = &buffer[sizeof(uint32_t)];
    while (frame_len != 0 && buffer_used >= frame_len + sizeof(uint32_t)) {
        sendSimulated(frame_start, frame_len);

        // Bookkeeping.
        buffer_used -= frame_len + sizeof(uint32_t);
        if (buffer_used > 0) {
            // If there's still any data left, move it into position.
            memmove(buffer, frame_start + frame_len, buffer_used);
        }
        frame_len = 0;

        if (buffer_used >= sizeof(uint32_t))
            frame_len = ntohl(*(uint32_t *)buffer);
    }
}

bool
EtherTapStub::sendReal(const void *data, size_t len)
{
    uint32_t frame_len = htonl(len);
    ssize_t ret = write(socket, &frame_len, sizeof(frame_len));
    if (ret != sizeof(frame_len))
        return false;
    return write(socket, data, len) == len;
}


#if HAVE_TUNTAP

EtherTap::EtherTap(const Params &p) : EtherTapBase(p)
{
    int fd = open(p.tun_clone_device.c_str(), O_RDWR | O_NONBLOCK);
    if (fd < 0)
        panic("Couldn't open %s.\n", p.tun_clone_device);

    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    strncpy(ifr.ifr_name, p.tap_device_name.c_str(), IFNAMSIZ - 1);

    if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0)
        panic("Failed to access tap device %s.\n", ifr.ifr_name);
    // fd now refers to the tap device.
    tap = fd;
    pollFd(tap);
}

EtherTap::~EtherTap()
{
    stopPolling();
    close(tap);
    tap = -1;
}

void
EtherTap::recvReal(int revent)
{
    if (revent & POLLERR)
        panic("Error polling for tap data.\n");

    if (!(revent & POLLIN))
        return;

    ssize_t ret;
    while ((ret = read(tap, buffer, buflen))) {
        if (ret < 0) {
            if (errno == EAGAIN)
                break;
            panic("Failed to read from tap device.\n");
        }

        sendSimulated(buffer, ret);
    }
}

bool
EtherTap::sendReal(const void *data, size_t len)
{
    int n;
    pollfd pfd[1];
    pfd->fd = tap;
    pfd->events = POLLOUT;

    // `tap` is a nonblock fd. Here we try to write until success, and use
    // poll to make a blocking wait.
    while ((n = write(tap, data, len)) != len) {
        if (errno != EAGAIN)
            panic("Failed to write data to tap device.\n");
        pfd->revents = 0;
        int ret = poll(pfd, 1, -1);
        // timeout is set to inf, we shouldn't get 0 in any case.
        assert(ret != 0);
        if (ret == -1 || (ret == 1 && (pfd->revents & POLLERR))) {
            panic("Failed when polling to write data to tap device.\n");
        }
    }
    return true;
}

#endif // HAVE_TUNTAP

} // namespace gem5
