/*
 * Copyright (c) 2015 FUJITSU LIMITED
 * Author: Yang Hongyang <yanghy@cn.fujitsu.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * later.  See the COPYING file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "net/filter.h"
#include "net/queue.h"
#include "qapi/error.h"
#include "qemu/timer.h"
#include "qemu/iov.h"
#include "qapi/qapi-builtin-visit.h"
#include "qapi/qmp/qerror.h"
#include "qom/object.h"

#define TYPE_FILTER_BUFFER "filter-buffer"

OBJECT_DECLARE_SIMPLE_TYPE(FilterBufferState, FILTER_BUFFER)

struct FilterBufferState {
    NetFilterState parent_obj;

    NetQueue *incoming_queue;
    uint32_t interval;
    QEMUTimer release_timer;
};

static void filter_buffer_flush(NetFilterState *nf)
{
    FilterBufferState *s = FILTER_BUFFER(nf);

    if (!qemu_net_queue_flush(s->incoming_queue)) {
        /* Unable to empty the queue, purge remaining packets */
        qemu_net_queue_purge(s->incoming_queue, nf->netdev);
    }
}

static void filter_buffer_release_timer(void *opaque)
{
    NetFilterState *nf = opaque;
    FilterBufferState *s = FILTER_BUFFER(nf);

    /*
     * Note: filter_buffer_flush() drops packets that can't be sent
     * TODO: We should leave them queued.  But currently there's no way
     * for the next filter or receiver to notify us that it can receive
     * more packets.
     */
    filter_buffer_flush(nf);
    /* Timer rearmed to fire again in s->interval microseconds. */
    timer_mod(&s->release_timer,
              qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
}

/* filter APIs */
static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
                                         NetClientState *sender,
                                         unsigned flags,
                                         const struct iovec *iov,
                                         int iovcnt,
                                         NetPacketSent *sent_cb)
{
    FilterBufferState *s = FILTER_BUFFER(nf);

    /*
     * We return size when buffer a packet, the sender will take it as
     * a already sent packet, so sent_cb should not be called later.
     *
     * FIXME: Even if the guest can't receive packets for some reasons,
     * the filter can still accept packets until its internal queue is full.
     * For example:
     *   For some reason, receiver could not receive more packets
     * (.can_receive() returns false). Without a filter, at most one packet
     * will be queued in incoming queue and sender's poll will be disabled
     * unit its sent_cb() was called. With a filter, it will keep receiving
     * the packets without caring about the receiver. This is suboptimal.
     * May need more thoughts (e.g keeping sent_cb).
     */
    qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
                              iov, iovcnt, NULL);
    return iov_size(iov, iovcnt);
}

static void filter_buffer_cleanup(NetFilterState *nf)
{
    FilterBufferState *s = FILTER_BUFFER(nf);

    if (s->interval) {
        timer_del(&s->release_timer);
    }

    /* flush packets */
    if (s->incoming_queue) {
        filter_buffer_flush(nf);
        g_free(s->incoming_queue);
    }
}

static void filter_buffer_setup_timer(NetFilterState *nf)
{
    FilterBufferState *s = FILTER_BUFFER(nf);

    if (s->interval) {
        timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
                      filter_buffer_release_timer, nf);
        /* Timer armed to fire in s->interval microseconds. */
        timer_mod(&s->release_timer,
                  qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
    }
}

static void filter_buffer_setup(NetFilterState *nf, Error **errp)
{
    FilterBufferState *s = FILTER_BUFFER(nf);

    /*
     * We may want to accept zero interval when VM FT solutions like MC
     * or COLO use this filter to release packets on demand.
     */
    if (!s->interval) {
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "interval",
                   "a non-zero interval");
        return;
    }

    s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
    filter_buffer_setup_timer(nf);
}

static void filter_buffer_status_changed(NetFilterState *nf, Error **errp)
{
    FilterBufferState *s = FILTER_BUFFER(nf);

    if (!nf->on) {
        if (s->interval) {
            timer_del(&s->release_timer);
        }
        filter_buffer_flush(nf);
    } else {
        filter_buffer_setup_timer(nf);
    }
}

static void filter_buffer_class_init(ObjectClass *oc, void *data)
{
    NetFilterClass *nfc = NETFILTER_CLASS(oc);

    nfc->setup = filter_buffer_setup;
    nfc->cleanup = filter_buffer_cleanup;
    nfc->receive_iov = filter_buffer_receive_iov;
    nfc->status_changed = filter_buffer_status_changed;
}

static void filter_buffer_get_interval(Object *obj, Visitor *v,
                                       const char *name, void *opaque,
                                       Error **errp)
{
    FilterBufferState *s = FILTER_BUFFER(obj);
    uint32_t value = s->interval;

    visit_type_uint32(v, name, &value, errp);
}

static void filter_buffer_set_interval(Object *obj, Visitor *v,
                                       const char *name, void *opaque,
                                       Error **errp)
{
    FilterBufferState *s = FILTER_BUFFER(obj);
    uint32_t value;

    if (!visit_type_uint32(v, name, &value, errp)) {
        return;
    }
    if (!value) {
        error_setg(errp, "Property '%s.%s' requires a positive value",
                   object_get_typename(obj), name);
        return;
    }
    s->interval = value;
}

static void filter_buffer_init(Object *obj)
{
    object_property_add(obj, "interval", "uint32",
                        filter_buffer_get_interval,
                        filter_buffer_set_interval, NULL, NULL);
}

static const TypeInfo filter_buffer_info = {
    .name = TYPE_FILTER_BUFFER,
    .parent = TYPE_NETFILTER,
    .class_init = filter_buffer_class_init,
    .instance_init = filter_buffer_init,
    .instance_size = sizeof(FilterBufferState),
};

static void register_types(void)
{
    type_register_static(&filter_buffer_info);
}

type_init(register_types);
