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