net/filter-mirror: Change filter_mirror_send interface
[qemu/kevin.git] / net / filter-mirror.c
blob78969e80262771c04e2c82ecafe1493ea7606e70
1 /*
2 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
3 * Copyright (c) 2016 FUJITSU LIMITED
4 * Copyright (c) 2016 Intel Corporation
6 * Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
8 * This work is licensed under the terms of the GNU GPL, version 2 or
9 * later. See the COPYING file in the top-level directory.
12 #include "qemu/osdep.h"
13 #include "net/filter.h"
14 #include "net/net.h"
15 #include "qemu-common.h"
16 #include "qapi/error.h"
17 #include "qapi/qmp/qerror.h"
18 #include "qapi-visit.h"
19 #include "qom/object.h"
20 #include "qemu/main-loop.h"
21 #include "qemu/error-report.h"
22 #include "trace.h"
23 #include "sysemu/char.h"
24 #include "qemu/iov.h"
25 #include "qemu/sockets.h"
27 #define FILTER_MIRROR(obj) \
28 OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
30 #define TYPE_FILTER_MIRROR "filter-mirror"
32 typedef struct MirrorState {
33 NetFilterState parent_obj;
34 char *outdev;
35 CharDriverState *chr_out;
36 } MirrorState;
38 static int filter_mirror_send(CharDriverState *chr_out,
39 const struct iovec *iov,
40 int iovcnt)
42 int ret = 0;
43 ssize_t size = 0;
44 uint32_t len = 0;
45 char *buf;
47 size = iov_size(iov, iovcnt);
48 if (!size) {
49 return 0;
52 len = htonl(size);
53 ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)&len, sizeof(len));
54 if (ret != sizeof(len)) {
55 goto err;
58 buf = g_malloc(size);
59 iov_to_buf(iov, iovcnt, 0, buf, size);
60 ret = qemu_chr_fe_write_all(chr_out, (uint8_t *)buf, size);
61 g_free(buf);
62 if (ret != size) {
63 goto err;
66 return 0;
68 err:
69 return ret < 0 ? ret : -EIO;
72 static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
73 NetClientState *sender,
74 unsigned flags,
75 const struct iovec *iov,
76 int iovcnt,
77 NetPacketSent *sent_cb)
79 MirrorState *s = FILTER_MIRROR(nf);
80 int ret;
82 ret = filter_mirror_send(s->chr_out, iov, iovcnt);
83 if (ret) {
84 error_report("filter_mirror_send failed(%s)", strerror(-ret));
88 * we don't hope this error interrupt the normal
89 * path of net packet, so we always return zero.
91 return 0;
94 static void filter_mirror_cleanup(NetFilterState *nf)
96 MirrorState *s = FILTER_MIRROR(nf);
98 if (s->chr_out) {
99 qemu_chr_fe_release(s->chr_out);
103 static void filter_mirror_setup(NetFilterState *nf, Error **errp)
105 MirrorState *s = FILTER_MIRROR(nf);
107 if (!s->outdev) {
108 error_setg(errp, "filter filter mirror needs 'outdev' "
109 "property set");
110 return;
113 s->chr_out = qemu_chr_find(s->outdev);
114 if (s->chr_out == NULL) {
115 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
116 "Device '%s' not found", s->outdev);
117 return;
120 if (qemu_chr_fe_claim(s->chr_out) != 0) {
121 error_setg(errp, QERR_DEVICE_IN_USE, s->outdev);
122 return;
126 static void filter_mirror_class_init(ObjectClass *oc, void *data)
128 NetFilterClass *nfc = NETFILTER_CLASS(oc);
130 nfc->setup = filter_mirror_setup;
131 nfc->cleanup = filter_mirror_cleanup;
132 nfc->receive_iov = filter_mirror_receive_iov;
135 static char *filter_mirror_get_outdev(Object *obj, Error **errp)
137 MirrorState *s = FILTER_MIRROR(obj);
139 return g_strdup(s->outdev);
142 static void
143 filter_mirror_set_outdev(Object *obj, const char *value, Error **errp)
145 MirrorState *s = FILTER_MIRROR(obj);
147 g_free(s->outdev);
148 s->outdev = g_strdup(value);
149 if (!s->outdev) {
150 error_setg(errp, "filter filter mirror needs 'outdev' "
151 "property set");
152 return;
156 static void filter_mirror_init(Object *obj)
158 object_property_add_str(obj, "outdev", filter_mirror_get_outdev,
159 filter_mirror_set_outdev, NULL);
162 static void filter_mirror_fini(Object *obj)
164 MirrorState *s = FILTER_MIRROR(obj);
166 g_free(s->outdev);
169 static const TypeInfo filter_mirror_info = {
170 .name = TYPE_FILTER_MIRROR,
171 .parent = TYPE_NETFILTER,
172 .class_init = filter_mirror_class_init,
173 .instance_init = filter_mirror_init,
174 .instance_finalize = filter_mirror_fini,
175 .instance_size = sizeof(MirrorState),
178 static void register_types(void)
180 type_register_static(&filter_mirror_info);
183 type_init(register_types);