/*
 * 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"

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
