| /* |
| * replay-net.c |
| * |
| * Copyright (c) 2010-2016 Institute for System Programming |
| * of the Russian Academy of Sciences. |
| * |
| * 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 "qemu/error-report.h" |
| #include "sysemu/replay.h" |
| #include "replay-internal.h" |
| #include "net/net.h" |
| #include "net/filter.h" |
| #include "qemu/iov.h" |
| |
| struct ReplayNetState { |
| NetFilterState *nfs; |
| int id; |
| }; |
| |
| typedef struct NetEvent { |
| uint8_t id; |
| uint32_t flags; |
| uint8_t *data; |
| size_t size; |
| } NetEvent; |
| |
| static NetFilterState **network_filters; |
| static int network_filters_count; |
| |
| ReplayNetState *replay_register_net(NetFilterState *nfs) |
| { |
| ReplayNetState *rns = g_new0(ReplayNetState, 1); |
| rns->nfs = nfs; |
| rns->id = network_filters_count++; |
| network_filters = g_realloc(network_filters, |
| network_filters_count |
| * sizeof(*network_filters)); |
| network_filters[network_filters_count - 1] = nfs; |
| return rns; |
| } |
| |
| void replay_unregister_net(ReplayNetState *rns) |
| { |
| network_filters[rns->id] = NULL; |
| g_free(rns); |
| } |
| |
| void replay_net_packet_event(ReplayNetState *rns, unsigned flags, |
| const struct iovec *iov, int iovcnt) |
| { |
| NetEvent *event = g_new(NetEvent, 1); |
| event->flags = flags; |
| event->data = g_malloc(iov_size(iov, iovcnt)); |
| event->size = iov_size(iov, iovcnt); |
| event->id = rns->id; |
| iov_to_buf(iov, iovcnt, 0, event->data, event->size); |
| |
| replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0); |
| } |
| |
| void replay_event_net_run(void *opaque) |
| { |
| NetEvent *event = opaque; |
| struct iovec iov = { |
| .iov_base = (void *)event->data, |
| .iov_len = event->size |
| }; |
| |
| assert(event->id < network_filters_count); |
| |
| qemu_netfilter_pass_to_next(network_filters[event->id]->netdev, |
| event->flags, &iov, 1, network_filters[event->id]); |
| |
| g_free(event->data); |
| g_free(event); |
| } |
| |
| void replay_event_net_save(void *opaque) |
| { |
| NetEvent *event = opaque; |
| |
| replay_put_byte(event->id); |
| replay_put_dword(event->flags); |
| replay_put_array(event->data, event->size); |
| } |
| |
| void *replay_event_net_load(void) |
| { |
| NetEvent *event = g_new(NetEvent, 1); |
| |
| event->id = replay_get_byte(); |
| event->flags = replay_get_dword(); |
| replay_get_array_alloc(&event->data, &event->size); |
| |
| return event; |
| } |