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"
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"
23 #include "sysemu/char.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
;
35 CharDriverState
*chr_out
;
38 static int filter_mirror_send(CharDriverState
*chr_out
,
39 const struct iovec
*iov
,
47 size
= iov_size(iov
, iovcnt
);
53 ret
= qemu_chr_fe_write_all(chr_out
, (uint8_t *)&len
, sizeof(len
));
54 if (ret
!= sizeof(len
)) {
59 iov_to_buf(iov
, iovcnt
, 0, buf
, size
);
60 ret
= qemu_chr_fe_write_all(chr_out
, (uint8_t *)buf
, size
);
69 return ret
< 0 ? ret
: -EIO
;
72 static ssize_t
filter_mirror_receive_iov(NetFilterState
*nf
,
73 NetClientState
*sender
,
75 const struct iovec
*iov
,
77 NetPacketSent
*sent_cb
)
79 MirrorState
*s
= FILTER_MIRROR(nf
);
82 ret
= filter_mirror_send(s
->chr_out
, iov
, iovcnt
);
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.
94 static void filter_mirror_cleanup(NetFilterState
*nf
)
96 MirrorState
*s
= FILTER_MIRROR(nf
);
99 qemu_chr_fe_release(s
->chr_out
);
103 static void filter_mirror_setup(NetFilterState
*nf
, Error
**errp
)
105 MirrorState
*s
= FILTER_MIRROR(nf
);
108 error_setg(errp
, "filter filter mirror needs 'outdev' "
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
);
120 if (qemu_chr_fe_claim(s
->chr_out
) != 0) {
121 error_setg(errp
, QERR_DEVICE_IN_USE
, s
->outdev
);
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
);
143 filter_mirror_set_outdev(Object
*obj
, const char *value
, Error
**errp
)
145 MirrorState
*s
= FILTER_MIRROR(obj
);
148 s
->outdev
= g_strdup(value
);
150 error_setg(errp
, "filter filter mirror needs 'outdev' "
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
);
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
);