}
}
+static char *netfilter_get_position(Object *obj, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ return g_strdup(nf->position);
+}
+
+static void netfilter_set_position(Object *obj, const char *str, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ nf->position = g_strdup(str);
+}
+
+static char *netfilter_get_insert(Object *obj, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ return nf->insert_before_flag ? g_strdup("before") : g_strdup("behind");
+}
+
+static void netfilter_set_insert(Object *obj, const char *str, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ if (strcmp(str, "before") && strcmp(str, "behind")) {
+ error_setg(errp, "Invalid value for netfilter insert, "
+ "should be 'before' or 'behind'");
+ return;
+ }
+
+ nf->insert_before_flag = !strcmp(str, "before");
+}
+
static void netfilter_init(Object *obj)
{
NetFilterState *nf = NETFILTER(obj);
nf->on = true;
+ nf->insert_before_flag = false;
+ nf->position = g_strdup("tail");
object_property_add_str(obj, "netdev",
netfilter_get_netdev_id, netfilter_set_netdev_id,
object_property_add_str(obj, "status",
netfilter_get_status, netfilter_set_status,
NULL);
+ object_property_add_str(obj, "position",
+ netfilter_get_position, netfilter_set_position,
+ NULL);
+ object_property_add_str(obj, "insert",
+ netfilter_get_insert, netfilter_set_insert,
+ NULL);
}
static void netfilter_complete(UserCreatable *uc, Error **errp)
{
NetFilterState *nf = NETFILTER(uc);
+ NetFilterState *position = NULL;
NetClientState *ncs[MAX_QUEUE_NUM];
NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
int queues;
return;
}
+ if (strcmp(nf->position, "head") && strcmp(nf->position, "tail")) {
+ Object *container;
+ Object *obj;
+ char *position_id;
+
+ if (!g_str_has_prefix(nf->position, "id=")) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "position",
+ "'head', 'tail' or 'id=<id>'");
+ return;
+ }
+
+ /* get the id from the string */
+ position_id = g_strndup(nf->position + 3, strlen(nf->position) - 3);
+
+ /* Search for the position to insert before/behind */
+ container = object_get_objects_root();
+ obj = object_resolve_path_component(container, position_id);
+ if (!obj) {
+ error_setg(errp, "filter '%s' not found", position_id);
+ g_free(position_id);
+ return;
+ }
+
+ position = NETFILTER(obj);
+
+ if (position->netdev != ncs[0]) {
+ error_setg(errp, "filter '%s' belongs to a different netdev",
+ position_id);
+ g_free(position_id);
+ return;
+ }
+
+ g_free(position_id);
+ }
+
nf->netdev = ncs[0];
if (nfc->setup) {
return;
}
}
- QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
+
+ if (position) {
+ if (nf->insert_before_flag) {
+ QTAILQ_INSERT_BEFORE(position, nf, next);
+ } else {
+ QTAILQ_INSERT_AFTER(&nf->netdev->filters, position, nf, next);
+ }
+ } else if (!strcmp(nf->position, "head")) {
+ QTAILQ_INSERT_HEAD(&nf->netdev->filters, nf, next);
+ } else if (!strcmp(nf->position, "tail")) {
+ QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
+ }
}
static void netfilter_finalize(Object *obj)
QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
}
g_free(nf->netdev_id);
+ g_free(nf->position);
}
static void default_handle_event(NetFilterState *nf, int event, Error **errp)
a gnutls priority string as described at
@url{https://gnutls.org/manual/html_node/Priority-Strings.html}.
-@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{on|off}]
+@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{on|off}][,position=@var{head|tail|id=<id>}][,insert=@var{behind|before}]
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
@option{tx}: the filter is attached to the transmit queue of the netdev,
where it will receive packets sent by the netdev.
-@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
+position @var{head|tail|id=<id>} is an option to specify where the
+filter should be inserted in the filter list. It can be applied to any
+netfilter.
+
+@option{head}: the filter is inserted at the head of the filter
+ list, before any existing filters.
+
+@option{tail}: the filter is inserted at the tail of the filter
+ list, behind any existing filters (default).
+
+@option{id=<id>}: the filter is inserted before or behind the filter
+ specified by <id>, see the insert option below.
+
+insert @var{behind|before} is an option to specify where to insert the
+new filter relative to the one specified with position=id=<id>. It can
+be applied to any netfilter.
+
+@option{before}: insert before the specified filter.
+
+@option{behind}: insert behind the specified filter (default).
+
+@item -object filter-mirror,id=@var{id},netdev=@var{netdevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support][,position=@var{head|tail|id=<id>}][,insert=@var{behind|before}]
filter-mirror on netdev @var{netdevid},mirror net packet to chardev@var{chardevid}, if it has the vnet_hdr_support flag, filter-mirror will mirror packet with vnet_hdr_len.
-@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support]
+@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid},queue=@var{all|rx|tx}[,vnet_hdr_support][,position=@var{head|tail|id=<id>}][,insert=@var{behind|before}]
filter-redirector on netdev @var{netdevid},redirect filter's net packet to chardev
@var{chardevid},and redirect indev's packet to filter.if it has the vnet_hdr_support flag,
be the same. we can just use indev or outdev, but at least one of indev or outdev
need to be specified.
-@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_hdr_support]
+@item -object filter-rewriter,id=@var{id},netdev=@var{netdevid},queue=@var{all|rx|tx},[vnet_hdr_support][,position=@var{head|tail|id=<id>}][,insert=@var{behind|before}]
Filter-rewriter is a part of COLO project.It will rewrite tcp packet to
secondary from primary to keep secondary tcp connection,and rewrite
-object filter-redirector,id=f2,netdev=hn0,queue=rx,outdev=red1
-object filter-rewriter,id=rew0,netdev=hn0,queue=all
-@item -object filter-dump,id=@var{id},netdev=@var{dev}[,file=@var{filename}][,maxlen=@var{len}]
+@item -object filter-dump,id=@var{id},netdev=@var{dev}[,file=@var{filename}][,maxlen=@var{len}][,position=@var{head|tail|id=<id>}][,insert=@var{behind|before}]
Dump the network traffic on netdev @var{dev} to the file specified by
@var{filename}. At most @var{len} bytes (64k by default) per packet are stored.