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