1/*
2 * replay-net.c
3 *
4 * Copyright (c) 2010-2016 Institute for System Programming
5 * of the Russian Academy of Sciences.
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 *
10 */
11
12#include "qemu/osdep.h"
13#include "qemu/error-report.h"
14#include "sysemu/replay.h"
15#include "replay-internal.h"
16#include "net/net.h"
17#include "net/filter.h"
18#include "qemu/iov.h"
19
20struct ReplayNetState {
21 NetFilterState *nfs;
22 int id;
23};
24
25typedef struct NetEvent {
26 uint8_t id;
27 uint32_t flags;
28 uint8_t *data;
29 size_t size;
30} NetEvent;
31
32static NetFilterState **network_filters;
33static int network_filters_count;
34
35ReplayNetState *replay_register_net(NetFilterState *nfs)
36{
37 ReplayNetState *rns = g_new0(ReplayNetState, 1);
38 rns->nfs = nfs;
39 rns->id = network_filters_count++;
40 network_filters = g_realloc(network_filters,
41 network_filters_count
42 * sizeof(*network_filters));
43 network_filters[network_filters_count - 1] = nfs;
44 return rns;
45}
46
47void replay_unregister_net(ReplayNetState *rns)
48{
49 network_filters[rns->id] = NULL;
50 g_free(rns);
51}
52
53void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
54 const struct iovec *iov, int iovcnt)
55{
56 NetEvent *event = g_new(NetEvent, 1);
57 event->flags = flags;
58 event->data = g_malloc(iov_size(iov, iovcnt));
59 event->size = iov_size(iov, iovcnt);
60 event->id = rns->id;
61 iov_to_buf(iov, iovcnt, 0, event->data, event->size);
62
63 replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
64}
65
66void replay_event_net_run(void *opaque)
67{
68 NetEvent *event = opaque;
69 struct iovec iov = {
70 .iov_base = (void *)event->data,
71 .iov_len = event->size
72 };
73
74 assert(event->id < network_filters_count);
75
76 qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
77 event->flags, &iov, 1, network_filters[event->id]);
78
79 g_free(event->data);
80 g_free(event);
81}
82
83void replay_event_net_save(void *opaque)
84{
85 NetEvent *event = opaque;
86
87 replay_put_byte(event->id);
88 replay_put_dword(event->flags);
89 replay_put_array(event->data, event->size);
90}
91
92void *replay_event_net_load(void)
93{
94 NetEvent *event = g_new(NetEvent, 1);
95
96 event->id = replay_get_byte();
97 event->flags = replay_get_dword();
98 replay_get_array_alloc(&event->data, &event->size);
99
100 return event;
101}
102