xref: /qemu/replay/replay-net.c (revision 33848cee)
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 "sysemu/sysemu.h"
17 #include "net/net.h"
18 #include "net/filter.h"
19 #include "qemu/iov.h"
20 
21 struct ReplayNetState {
22     NetFilterState *nfs;
23     int id;
24 };
25 
26 typedef struct NetEvent {
27     uint8_t id;
28     uint32_t flags;
29     uint8_t *data;
30     size_t size;
31 } NetEvent;
32 
33 static NetFilterState **network_filters;
34 static int network_filters_count;
35 
36 ReplayNetState *replay_register_net(NetFilterState *nfs)
37 {
38     ReplayNetState *rns = g_new0(ReplayNetState, 1);
39     rns->nfs = nfs;
40     rns->id = network_filters_count++;
41     network_filters = g_realloc(network_filters,
42                                 network_filters_count
43                                     * sizeof(*network_filters));
44     network_filters[network_filters_count - 1] = nfs;
45     return rns;
46 }
47 
48 void replay_unregister_net(ReplayNetState *rns)
49 {
50     network_filters[rns->id] = NULL;
51     g_free(rns);
52 }
53 
54 void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
55                              const struct iovec *iov, int iovcnt)
56 {
57     NetEvent *event = g_new(NetEvent, 1);
58     event->flags = flags;
59     event->data = g_malloc(iov_size(iov, iovcnt));
60     event->size = iov_size(iov, iovcnt);
61     event->id = rns->id;
62     iov_to_buf(iov, iovcnt, 0, event->data, event->size);
63 
64     replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
65 }
66 
67 void replay_event_net_run(void *opaque)
68 {
69     NetEvent *event = opaque;
70     struct iovec iov = {
71         .iov_base = (void *)event->data,
72         .iov_len = event->size
73     };
74 
75     assert(event->id < network_filters_count);
76 
77     qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
78         event->flags, &iov, 1, network_filters[event->id]);
79 
80     g_free(event->data);
81     g_free(event);
82 }
83 
84 void replay_event_net_save(void *opaque)
85 {
86     NetEvent *event = opaque;
87 
88     replay_put_byte(event->id);
89     replay_put_dword(event->flags);
90     replay_put_array(event->data, event->size);
91 }
92 
93 void *replay_event_net_load(void)
94 {
95     NetEvent *event = g_new(NetEvent, 1);
96 
97     event->id = replay_get_byte();
98     event->flags = replay_get_dword();
99     replay_get_array_alloc(&event->data, &event->size);
100 
101     return event;
102 }
103