xref: /qemu/replay/replay-net.c (revision 65cb7129f4160c7e07a0da107f888ec73ae96776)
1646c5478SPavel Dovgalyuk /*
2646c5478SPavel Dovgalyuk  * replay-net.c
3646c5478SPavel Dovgalyuk  *
4646c5478SPavel Dovgalyuk  * Copyright (c) 2010-2016 Institute for System Programming
5646c5478SPavel Dovgalyuk  *                         of the Russian Academy of Sciences.
6646c5478SPavel Dovgalyuk  *
7646c5478SPavel Dovgalyuk  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8646c5478SPavel Dovgalyuk  * See the COPYING file in the top-level directory.
9646c5478SPavel Dovgalyuk  *
10646c5478SPavel Dovgalyuk  */
11646c5478SPavel Dovgalyuk 
12646c5478SPavel Dovgalyuk #include "qemu/osdep.h"
13646c5478SPavel Dovgalyuk #include "qemu/error-report.h"
14*32cad1ffSPhilippe Mathieu-Daudé #include "system/replay.h"
15646c5478SPavel Dovgalyuk #include "replay-internal.h"
16646c5478SPavel Dovgalyuk #include "net/net.h"
17646c5478SPavel Dovgalyuk #include "net/filter.h"
18646c5478SPavel Dovgalyuk #include "qemu/iov.h"
19646c5478SPavel Dovgalyuk 
20646c5478SPavel Dovgalyuk struct ReplayNetState {
21646c5478SPavel Dovgalyuk     NetFilterState *nfs;
22646c5478SPavel Dovgalyuk     int id;
23646c5478SPavel Dovgalyuk };
24646c5478SPavel Dovgalyuk 
25646c5478SPavel Dovgalyuk typedef struct NetEvent {
26646c5478SPavel Dovgalyuk     uint8_t id;
27646c5478SPavel Dovgalyuk     uint32_t flags;
28646c5478SPavel Dovgalyuk     uint8_t *data;
29646c5478SPavel Dovgalyuk     size_t size;
30646c5478SPavel Dovgalyuk } NetEvent;
31646c5478SPavel Dovgalyuk 
32646c5478SPavel Dovgalyuk static NetFilterState **network_filters;
33646c5478SPavel Dovgalyuk static int network_filters_count;
34646c5478SPavel Dovgalyuk 
replay_register_net(NetFilterState * nfs)35646c5478SPavel Dovgalyuk ReplayNetState *replay_register_net(NetFilterState *nfs)
36646c5478SPavel Dovgalyuk {
37646c5478SPavel Dovgalyuk     ReplayNetState *rns = g_new0(ReplayNetState, 1);
38646c5478SPavel Dovgalyuk     rns->nfs = nfs;
39646c5478SPavel Dovgalyuk     rns->id = network_filters_count++;
40646c5478SPavel Dovgalyuk     network_filters = g_realloc(network_filters,
41646c5478SPavel Dovgalyuk                                 network_filters_count
42646c5478SPavel Dovgalyuk                                     * sizeof(*network_filters));
43646c5478SPavel Dovgalyuk     network_filters[network_filters_count - 1] = nfs;
44646c5478SPavel Dovgalyuk     return rns;
45646c5478SPavel Dovgalyuk }
46646c5478SPavel Dovgalyuk 
replay_unregister_net(ReplayNetState * rns)47646c5478SPavel Dovgalyuk void replay_unregister_net(ReplayNetState *rns)
48646c5478SPavel Dovgalyuk {
49646c5478SPavel Dovgalyuk     network_filters[rns->id] = NULL;
50646c5478SPavel Dovgalyuk     g_free(rns);
51646c5478SPavel Dovgalyuk }
52646c5478SPavel Dovgalyuk 
replay_net_packet_event(ReplayNetState * rns,unsigned flags,const struct iovec * iov,int iovcnt)53646c5478SPavel Dovgalyuk void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
54646c5478SPavel Dovgalyuk                              const struct iovec *iov, int iovcnt)
55646c5478SPavel Dovgalyuk {
56646c5478SPavel Dovgalyuk     NetEvent *event = g_new(NetEvent, 1);
57646c5478SPavel Dovgalyuk     event->flags = flags;
58646c5478SPavel Dovgalyuk     event->data = g_malloc(iov_size(iov, iovcnt));
59646c5478SPavel Dovgalyuk     event->size = iov_size(iov, iovcnt);
60646c5478SPavel Dovgalyuk     event->id = rns->id;
61646c5478SPavel Dovgalyuk     iov_to_buf(iov, iovcnt, 0, event->data, event->size);
62646c5478SPavel Dovgalyuk 
63646c5478SPavel Dovgalyuk     replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
64646c5478SPavel Dovgalyuk }
65646c5478SPavel Dovgalyuk 
replay_event_net_run(void * opaque)66646c5478SPavel Dovgalyuk void replay_event_net_run(void *opaque)
67646c5478SPavel Dovgalyuk {
68646c5478SPavel Dovgalyuk     NetEvent *event = opaque;
69646c5478SPavel Dovgalyuk     struct iovec iov = {
70646c5478SPavel Dovgalyuk         .iov_base = (void *)event->data,
71646c5478SPavel Dovgalyuk         .iov_len = event->size
72646c5478SPavel Dovgalyuk     };
73646c5478SPavel Dovgalyuk 
74646c5478SPavel Dovgalyuk     assert(event->id < network_filters_count);
75646c5478SPavel Dovgalyuk 
76646c5478SPavel Dovgalyuk     qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
77646c5478SPavel Dovgalyuk         event->flags, &iov, 1, network_filters[event->id]);
78646c5478SPavel Dovgalyuk 
79646c5478SPavel Dovgalyuk     g_free(event->data);
80646c5478SPavel Dovgalyuk     g_free(event);
81646c5478SPavel Dovgalyuk }
82646c5478SPavel Dovgalyuk 
replay_event_net_save(void * opaque)83646c5478SPavel Dovgalyuk void replay_event_net_save(void *opaque)
84646c5478SPavel Dovgalyuk {
85646c5478SPavel Dovgalyuk     NetEvent *event = opaque;
86646c5478SPavel Dovgalyuk 
87646c5478SPavel Dovgalyuk     replay_put_byte(event->id);
88646c5478SPavel Dovgalyuk     replay_put_dword(event->flags);
89646c5478SPavel Dovgalyuk     replay_put_array(event->data, event->size);
90646c5478SPavel Dovgalyuk }
91646c5478SPavel Dovgalyuk 
replay_event_net_load(void)92646c5478SPavel Dovgalyuk void *replay_event_net_load(void)
93646c5478SPavel Dovgalyuk {
94646c5478SPavel Dovgalyuk     NetEvent *event = g_new(NetEvent, 1);
95646c5478SPavel Dovgalyuk 
96646c5478SPavel Dovgalyuk     event->id = replay_get_byte();
97646c5478SPavel Dovgalyuk     event->flags = replay_get_dword();
98646c5478SPavel Dovgalyuk     replay_get_array_alloc(&event->data, &event->size);
99646c5478SPavel Dovgalyuk 
100646c5478SPavel Dovgalyuk     return event;
101646c5478SPavel Dovgalyuk }
102