diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/Makefile.objs | 1 | ||||
| -rw-r--r-- | net/checksum.c | 21 | ||||
| -rw-r--r-- | net/filter-replay.c | 92 | ||||
| -rw-r--r-- | net/tap.c | 8 |
4 files changed, 112 insertions, 10 deletions
diff --git a/net/Makefile.objs b/net/Makefile.objs index 2a80df5fa7..2e2fd43014 100644 --- a/net/Makefile.objs +++ b/net/Makefile.objs @@ -19,3 +19,4 @@ common-obj-y += filter-mirror.o common-obj-y += colo-compare.o common-obj-y += colo.o common-obj-y += filter-rewriter.o +common-obj-y += filter-replay.o diff --git a/net/checksum.c b/net/checksum.c index 23323b0760..4da72a6a6c 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -22,17 +22,22 @@ uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq) { - uint32_t sum = 0; + uint32_t sum1 = 0, sum2 = 0; int i; - for (i = seq; i < seq + len; i++) { - if (i & 1) { - sum += (uint32_t)buf[i - seq]; - } else { - sum += (uint32_t)buf[i - seq] << 8; - } + for (i = 0; i < len - 1; i += 2) { + sum1 += (uint32_t)buf[i]; + sum2 += (uint32_t)buf[i + 1]; + } + if (i < len) { + sum1 += (uint32_t)buf[i]; + } + + if (seq & 1) { + return sum1 + (sum2 << 8); + } else { + return sum2 + (sum1 << 8); } - return sum; } uint16_t net_checksum_finish(uint32_t sum) diff --git a/net/filter-replay.c b/net/filter-replay.c new file mode 100644 index 0000000000..cff65f86e5 --- /dev/null +++ b/net/filter-replay.c @@ -0,0 +1,92 @@ +/* + * filter-replay.c + * + * Copyright (c) 2010-2016 Institute for System Programming + * of the Russian Academy of Sciences. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "clients.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "qemu/error-report.h" +#include "qemu/iov.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "net/filter.h" +#include "sysemu/replay.h" + +#define TYPE_FILTER_REPLAY "filter-replay" + +#define FILTER_REPLAY(obj) \ + OBJECT_CHECK(NetFilterReplayState, (obj), TYPE_FILTER_REPLAY) + +struct NetFilterReplayState { + NetFilterState nfs; + ReplayNetState *rns; +}; +typedef struct NetFilterReplayState NetFilterReplayState; + +static ssize_t filter_replay_receive_iov(NetFilterState *nf, + NetClientState *sndr, + unsigned flags, + const struct iovec *iov, + int iovcnt, NetPacketSent *sent_cb) +{ + NetFilterReplayState *nfrs = FILTER_REPLAY(nf); + switch (replay_mode) { + case REPLAY_MODE_RECORD: + if (nf->netdev == sndr) { + replay_net_packet_event(nfrs->rns, flags, iov, iovcnt); + return iov_size(iov, iovcnt); + } + return 0; + case REPLAY_MODE_PLAY: + /* Drop all packets in replay mode. + Packets from the log will be injected by the replay module. */ + return iov_size(iov, iovcnt); + default: + /* Pass all the packets. */ + return 0; + } +} + +static void filter_replay_instance_init(Object *obj) +{ + NetFilterReplayState *nfrs = FILTER_REPLAY(obj); + nfrs->rns = replay_register_net(&nfrs->nfs); +} + +static void filter_replay_instance_finalize(Object *obj) +{ + NetFilterReplayState *nfrs = FILTER_REPLAY(obj); + replay_unregister_net(nfrs->rns); +} + +static void filter_replay_class_init(ObjectClass *oc, void *data) +{ + NetFilterClass *nfc = NETFILTER_CLASS(oc); + + nfc->receive_iov = filter_replay_receive_iov; +} + +static const TypeInfo filter_replay_info = { + .name = TYPE_FILTER_REPLAY, + .parent = TYPE_NETFILTER, + .class_init = filter_replay_class_init, + .instance_init = filter_replay_instance_init, + .instance_finalize = filter_replay_instance_finalize, + .instance_size = sizeof(NetFilterReplayState), +}; + +static void filter_replay_register_types(void) +{ + type_register_static(&filter_replay_info); +} + +type_init(filter_replay_register_types); diff --git a/net/tap.c b/net/tap.c index b6896a7b7c..979e622e60 100644 --- a/net/tap.c +++ b/net/tap.c @@ -696,6 +696,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, "tap: open vhost char device failed"); return; } + fcntl(vhostfd, F_SETFL, O_NONBLOCK); } options.opaque = (void *)(uintptr_t)vhostfd; @@ -788,8 +789,8 @@ int net_init_tap(const Netdev *netdev, const char *name, return -1; } } else if (tap->has_fds) { - char **fds = g_new0(char *, MAX_TAP_QUEUES); - char **vhost_fds = g_new0(char *, MAX_TAP_QUEUES); + char **fds; + char **vhost_fds; int nfds, nvhosts; if (tap->has_ifname || tap->has_script || tap->has_downscript || @@ -801,6 +802,9 @@ int net_init_tap(const Netdev *netdev, const char *name, return -1; } + fds = g_new0(char *, MAX_TAP_QUEUES); + vhost_fds = g_new0(char *, MAX_TAP_QUEUES); + nfds = get_fds(tap->fds, fds, MAX_TAP_QUEUES); if (tap->has_vhostfds) { nvhosts = get_fds(tap->vhostfds, vhost_fds, MAX_TAP_QUEUES); |