@@ -36,12 +36,15 @@ typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
int iovcnt,
NetPacketSent *sent_cb);
+typedef void (FilterStatusChanged) (NetFilterState *nf, Error **errp);
+
typedef struct NetFilterClass {
ObjectClass parent_class;
/* optional */
FilterSetup *setup;
FilterCleanup *cleanup;
+ FilterStatusChanged *status_changed;
/* mandatory */
FilterReceiveIOV *receive_iov;
} NetFilterClass;
@@ -55,6 +58,7 @@ struct NetFilterState {
char *netdev_id;
NetClientState *netdev;
NetFilterDirection direction;
+ bool on;
QTAILQ_ENTRY(NetFilterState) next;
};
@@ -17,6 +17,11 @@
#include "qom/object_interfaces.h"
#include "qemu/iov.h"
+static inline bool qemu_can_skip_netfilter(NetFilterState *nf)
+{
+ return !nf->on;
+}
+
ssize_t qemu_netfilter_receive(NetFilterState *nf,
NetFilterDirection direction,
NetClientState *sender,
@@ -25,6 +30,9 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
int iovcnt,
NetPacketSent *sent_cb)
{
+ if (qemu_can_skip_netfilter(nf)) {
+ return 0;
+ }
if (nf->direction == direction ||
nf->direction == NET_FILTER_DIRECTION_ALL) {
return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
@@ -134,8 +142,38 @@ static void netfilter_set_direction(Object *obj, int direction, Error **errp)
nf->direction = direction;
}
+static char *netfilter_get_status(Object *obj, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ return nf->on ? g_strdup("on") : g_strdup("off");
+}
+
+static void netfilter_set_status(Object *obj, const char *str, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+ NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
+
+ if (strcmp(str, "on") && strcmp(str, "off")) {
+ error_setg(errp, "Invalid value for netfilter status, "
+ "should be 'on' or 'off'");
+ return;
+ }
+ if (nf->on == !strcmp(str, "on")) {
+ return;
+ }
+ nf->on = !nf->on;
+ if (nfc->status_changed) {
+ nfc->status_changed(nf, errp);
+ }
+}
+
static void netfilter_init(Object *obj)
{
+ NetFilterState *nf = NETFILTER(obj);
+
+ nf->on = true;
+
object_property_add_str(obj, "netdev",
netfilter_get_netdev_id, netfilter_set_netdev_id,
NULL);
@@ -143,6 +181,9 @@ static void netfilter_init(Object *obj)
NetFilterDirection_lookup,
netfilter_get_direction, netfilter_set_direction,
NULL);
+ object_property_add_str(obj, "status",
+ netfilter_get_status, netfilter_set_status,
+ NULL);
}
static void netfilter_complete(UserCreatable *uc, Error **errp)
@@ -3788,11 +3788,13 @@ version by providing the @var{passwordid} parameter. This provides
the ID of a previously created @code{secret} object containing the
password for decryption.
-@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}]
+@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{on|off}]
Interval @var{t} can't be 0, this filter batches the packet delivery: all
packets arriving in a given interval on netdev @var{netdevid} are delayed
until the end of the interval. Interval is in microseconds.
+@option{status} is optional that indicate whether the netfilter is
+on (enabled) or off (disabled), the default status for netfilter will be 'on'.
queue @var{all|rx|tx} is an option that can be applied to any netfilter.