/*
 * 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();
    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
