-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1 iQEcBAABAgAGBQJW3oNAAAoJEO8Ells5jWIRCNIH/iJ7ZKfnhSxQB4/dJdPNA72N V8QA4Ta+FTV0yiEXBgoK1QyCOgs+GsJ8Ip6jBPz3B+tPhYaQl2L7QlqS3fdn73P6 9MwdzJp4LTB6txOw7YsxCEz3yRSNAfxPsAouIyeYROwuNnD8IOI4XxNTt7cig6Ku jm6KTNk5p4dacJD3HIFPzkqw63XkyyGpLzOjJWW7s3ZwafVlPKVLZCTXGIMmHE5L USQdR7Le5I9HsrsygdrDaXo1fopKdt56efPVm2lhpL1IJBkR21ixYqcdVGrOKwo2 KofLtUY/cHvGtluufU0FMih5OCg1q/Pz0NdTv29afWMQ0hiIuB5GhfptRdNdHKI= =ozGZ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging # gpg: Signature made Tue 08 Mar 2016 07:46:08 GMT using RSA key ID 398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * remotes/jasowang/tags/net-pull-request: net: check packet payload length filter-buffer: Add status_changed callback processing filter: Add 'status' property for filter object rocker: allow user to specify rocker world by property rocker: add name field into WorldOps ale let world specify its name rocker: return -ENOMEM in case of some world alloc fails rocker: forbid to change world type net: netmap: probe netmap interface for virtio-net header net: simplify net_init_tap_one logic MAINTAINERS: Add entries for include/net/ files net: filter: correctly remove filter from the list during finalization net: ne2000: check ring buffer control registers Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d1cc881d54
@ -1123,6 +1123,7 @@ Network device backends
|
||||
M: Jason Wang <jasowang@redhat.com>
|
||||
S: Maintained
|
||||
F: net/
|
||||
F: include/net/
|
||||
T: git git://github.com/jasowang/qemu.git net
|
||||
|
||||
Netmap network backend
|
||||
@ -1222,6 +1223,7 @@ M: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
S: Maintained
|
||||
F: slirp/
|
||||
F: net/slirp.c
|
||||
F: include/net/slirp.h
|
||||
T: git git://git.kiszka.org/qemu.git queues/slirp
|
||||
|
||||
Tracing
|
||||
|
@ -155,6 +155,10 @@ static int ne2000_buffer_full(NE2000State *s)
|
||||
{
|
||||
int avail, index, boundary;
|
||||
|
||||
if (s->stop <= s->start) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
index = s->curpag << 8;
|
||||
boundary = s->boundary << 8;
|
||||
if (index < boundary)
|
||||
|
@ -43,6 +43,7 @@ struct rocker {
|
||||
|
||||
/* switch configuration */
|
||||
char *name; /* switch name */
|
||||
char *world_name; /* world name */
|
||||
uint32_t fp_ports; /* front-panel port count */
|
||||
NICPeers *fp_ports_peers;
|
||||
MACAddr fp_start_macaddr; /* front-panel port 0 mac addr */
|
||||
@ -400,7 +401,13 @@ static int cmd_set_port_settings(Rocker *r,
|
||||
|
||||
if (tlvs[ROCKER_TLV_CMD_PORT_SETTINGS_MODE]) {
|
||||
mode = rocker_tlv_get_u8(tlvs[ROCKER_TLV_CMD_PORT_SETTINGS_MODE]);
|
||||
fp_port_set_world(fp_port, r->worlds[mode]);
|
||||
if (mode >= ROCKER_WORLD_TYPE_MAX) {
|
||||
return -ROCKER_EINVAL;
|
||||
}
|
||||
/* We don't support world change. */
|
||||
if (!fp_port_check_world(fp_port, r->worlds[mode])) {
|
||||
return -ROCKER_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (tlvs[ROCKER_TLV_CMD_PORT_SETTINGS_LEARNING]) {
|
||||
@ -1280,6 +1287,18 @@ static void rocker_msix_uninit(Rocker *r)
|
||||
rocker_msix_vectors_unuse(r, ROCKER_MSIX_VEC_COUNT(r->fp_ports));
|
||||
}
|
||||
|
||||
static World *rocker_world_type_by_name(Rocker *r, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
|
||||
if (strcmp(name, world_name(r->worlds[i])) == 0) {
|
||||
return r->worlds[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int pci_rocker_init(PCIDevice *dev)
|
||||
{
|
||||
Rocker *r = to_rocker(dev);
|
||||
@ -1291,14 +1310,27 @@ static int pci_rocker_init(PCIDevice *dev)
|
||||
/* allocate worlds */
|
||||
|
||||
r->worlds[ROCKER_WORLD_TYPE_OF_DPA] = of_dpa_world_alloc(r);
|
||||
r->world_dflt = r->worlds[ROCKER_WORLD_TYPE_OF_DPA];
|
||||
|
||||
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
|
||||
if (!r->worlds[i]) {
|
||||
err = -ENOMEM;
|
||||
goto err_world_alloc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!r->world_name) {
|
||||
r->world_name = g_strdup(world_name(r->worlds[ROCKER_WORLD_TYPE_OF_DPA]));
|
||||
}
|
||||
|
||||
r->world_dflt = rocker_world_type_by_name(r, r->world_name);
|
||||
if (!r->world_dflt) {
|
||||
fprintf(stderr,
|
||||
"rocker: requested world \"%s\" does not exist\n",
|
||||
r->world_name);
|
||||
err = -EINVAL;
|
||||
goto err_world_type_by_name;
|
||||
}
|
||||
|
||||
/* set up memory-mapped region at BAR0 */
|
||||
|
||||
memory_region_init_io(&r->mmio, OBJECT(r), &rocker_mmio_ops, r,
|
||||
@ -1432,6 +1464,7 @@ err_duplicate:
|
||||
err_msix_init:
|
||||
object_unparent(OBJECT(&r->msix_bar));
|
||||
object_unparent(OBJECT(&r->mmio));
|
||||
err_world_type_by_name:
|
||||
err_world_alloc:
|
||||
for (i = 0; i < ROCKER_WORLD_TYPE_MAX; i++) {
|
||||
if (r->worlds[i]) {
|
||||
@ -1503,6 +1536,7 @@ static void rocker_reset(DeviceState *dev)
|
||||
|
||||
static Property rocker_properties[] = {
|
||||
DEFINE_PROP_STRING("name", Rocker, name),
|
||||
DEFINE_PROP_STRING("world", Rocker, world_name),
|
||||
DEFINE_PROP_MACADDR("fp_start_macaddr", Rocker,
|
||||
fp_start_macaddr),
|
||||
DEFINE_PROP_UINT64("switch_id", Rocker,
|
||||
|
@ -186,6 +186,11 @@ void fp_port_set_world(FpPort *port, World *world)
|
||||
port->world = world;
|
||||
}
|
||||
|
||||
bool fp_port_check_world(FpPort *port, World *world)
|
||||
{
|
||||
return port->world == world;
|
||||
}
|
||||
|
||||
bool fp_port_enabled(FpPort *port)
|
||||
{
|
||||
return port->enabled;
|
||||
|
@ -40,6 +40,7 @@ int fp_port_set_settings(FpPort *port, uint32_t speed,
|
||||
bool fp_port_from_pport(uint32_t pport, uint32_t *port);
|
||||
World *fp_port_get_world(FpPort *port);
|
||||
void fp_port_set_world(FpPort *port, World *world);
|
||||
bool fp_port_check_world(FpPort *port, World *world);
|
||||
bool fp_port_enabled(FpPort *port);
|
||||
void fp_port_enable(FpPort *port);
|
||||
void fp_port_disable(FpPort *port);
|
||||
|
@ -2614,6 +2614,7 @@ RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
|
||||
}
|
||||
|
||||
static WorldOps of_dpa_ops = {
|
||||
.name = "ofdpa",
|
||||
.init = of_dpa_init,
|
||||
.uninit = of_dpa_uninit,
|
||||
.ig = of_dpa_ig,
|
||||
|
@ -98,10 +98,5 @@ enum rocker_world_type world_type(World *world)
|
||||
|
||||
const char *world_name(World *world)
|
||||
{
|
||||
switch (world->type) {
|
||||
case ROCKER_WORLD_TYPE_OF_DPA:
|
||||
return "OF_DPA";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
return world->ops->name;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ typedef int (world_cmd)(World *world, DescInfo *info,
|
||||
RockerTlv *cmd_info_tlv);
|
||||
|
||||
typedef struct world_ops {
|
||||
const char *name;
|
||||
world_init *init;
|
||||
world_uninit *uninit;
|
||||
world_ig *ig;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,11 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
int hlen, plen, proto, csum_offset;
|
||||
uint16_t csum;
|
||||
|
||||
/* Ensure data has complete L2 & L3 headers. */
|
||||
if (length < 14 + 20) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((data[14] & 0xf0) != 0x40)
|
||||
return; /* not IPv4 */
|
||||
hlen = (data[14] & 0x0f) * 4;
|
||||
@ -77,8 +82,9 @@ void net_checksum_calculate(uint8_t *data, int length)
|
||||
return;
|
||||
}
|
||||
|
||||
if (plen < csum_offset+2)
|
||||
return;
|
||||
if (plen < csum_offset + 2 || 14 + hlen + plen > length) {
|
||||
return;
|
||||
}
|
||||
|
||||
data[14+hlen+csum_offset] = 0;
|
||||
data[14+hlen+csum_offset+1] = 0;
|
||||
|
@ -100,6 +100,19 @@ static void filter_buffer_cleanup(NetFilterState *nf)
|
||||
}
|
||||
}
|
||||
|
||||
static void filter_buffer_setup_timer(NetFilterState *nf)
|
||||
{
|
||||
FilterBufferState *s = FILTER_BUFFER(nf);
|
||||
|
||||
if (s->interval) {
|
||||
timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
|
||||
filter_buffer_release_timer, nf);
|
||||
/* Timer armed to fire in s->interval microseconds. */
|
||||
timer_mod(&s->release_timer,
|
||||
qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
|
||||
}
|
||||
}
|
||||
|
||||
static void filter_buffer_setup(NetFilterState *nf, Error **errp)
|
||||
{
|
||||
FilterBufferState *s = FILTER_BUFFER(nf);
|
||||
@ -115,12 +128,20 @@ static void filter_buffer_setup(NetFilterState *nf, Error **errp)
|
||||
}
|
||||
|
||||
s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
|
||||
if (s->interval) {
|
||||
timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
|
||||
filter_buffer_release_timer, nf);
|
||||
/* Timer armed to fire in s->interval microseconds. */
|
||||
timer_mod(&s->release_timer,
|
||||
qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
|
||||
filter_buffer_setup_timer(nf);
|
||||
}
|
||||
|
||||
static void filter_buffer_status_changed(NetFilterState *nf, Error **errp)
|
||||
{
|
||||
FilterBufferState *s = FILTER_BUFFER(nf);
|
||||
|
||||
if (!nf->on) {
|
||||
if (s->interval) {
|
||||
timer_del(&s->release_timer);
|
||||
}
|
||||
filter_buffer_flush(nf);
|
||||
} else {
|
||||
filter_buffer_setup_timer(nf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,6 +152,7 @@ static void filter_buffer_class_init(ObjectClass *oc, void *data)
|
||||
nfc->setup = filter_buffer_setup;
|
||||
nfc->cleanup = filter_buffer_cleanup;
|
||||
nfc->receive_iov = filter_buffer_receive_iov;
|
||||
nfc->status_changed = filter_buffer_status_changed;
|
||||
}
|
||||
|
||||
static void filter_buffer_get_interval(Object *obj, Visitor *v,
|
||||
|
44
net/filter.c
44
net/filter.c
@ -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)
|
||||
@ -196,7 +237,8 @@ static void netfilter_finalize(Object *obj)
|
||||
nfc->cleanup(nf);
|
||||
}
|
||||
|
||||
if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
|
||||
if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters) &&
|
||||
nf->next.tqe_prev) {
|
||||
QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
|
||||
}
|
||||
g_free(nf->netdev_id);
|
||||
|
75
net/netmap.c
75
net/netmap.c
@ -323,30 +323,8 @@ static void netmap_cleanup(NetClientState *nc)
|
||||
}
|
||||
|
||||
/* Offloading manipulation support callbacks. */
|
||||
static bool netmap_has_ufo(NetClientState *nc)
|
||||
static int netmap_fd_set_vnet_hdr_len(NetmapState *s, int len)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netmap_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netmap_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
return len == 0 || len == sizeof(struct virtio_net_hdr) ||
|
||||
len == sizeof(struct virtio_net_hdr_mrg_rxbuf);
|
||||
}
|
||||
|
||||
static void netmap_using_vnet_hdr(NetClientState *nc, bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
|
||||
int err;
|
||||
struct nmreq req;
|
||||
|
||||
/* Issue a NETMAP_BDG_VNET_HDR command to change the virtio-net header
|
||||
@ -357,10 +335,50 @@ static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
req.nr_version = NETMAP_API;
|
||||
req.nr_cmd = NETMAP_BDG_VNET_HDR;
|
||||
req.nr_arg1 = len;
|
||||
err = ioctl(s->nmd->fd, NIOCREGIF, &req);
|
||||
|
||||
return ioctl(s->nmd->fd, NIOCREGIF, &req);
|
||||
}
|
||||
|
||||
static bool netmap_has_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
|
||||
int prev_len = s->vnet_hdr_len;
|
||||
|
||||
/* Check that we can set the new length. */
|
||||
if (netmap_fd_set_vnet_hdr_len(s, len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Restore the previous length. */
|
||||
if (netmap_fd_set_vnet_hdr_len(s, prev_len)) {
|
||||
error_report("Failed to restore vnet-hdr length %d on %s: %s",
|
||||
prev_len, s->ifname, strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* A netmap interface that supports virtio-net headers always
|
||||
* supports UFO, so we use this callback also for the has_ufo hook. */
|
||||
static bool netmap_has_vnet_hdr(NetClientState *nc)
|
||||
{
|
||||
return netmap_has_vnet_hdr_len(nc, sizeof(struct virtio_net_hdr));
|
||||
}
|
||||
|
||||
static void netmap_using_vnet_hdr(NetClientState *nc, bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
|
||||
{
|
||||
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
|
||||
int err;
|
||||
|
||||
err = netmap_fd_set_vnet_hdr_len(s, len);
|
||||
if (err) {
|
||||
error_report("Unable to execute NETMAP_BDG_VNET_HDR on %s: %s",
|
||||
s->ifname, strerror(errno));
|
||||
error_report("Unable to set vnet-hdr length %d on %s: %s",
|
||||
len, s->ifname, strerror(errno));
|
||||
} else {
|
||||
/* Keep track of the current length. */
|
||||
s->vnet_hdr_len = len;
|
||||
@ -373,8 +391,7 @@ static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
|
||||
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
|
||||
|
||||
/* Setting a virtio-net header length greater than zero automatically
|
||||
* enables the offloadings.
|
||||
*/
|
||||
* enables the offloadings. */
|
||||
if (!s->vnet_hdr_len) {
|
||||
netmap_set_vnet_hdr_len(nc, sizeof(struct virtio_net_hdr));
|
||||
}
|
||||
@ -388,7 +405,7 @@ static NetClientInfo net_netmap_info = {
|
||||
.receive_iov = netmap_receive_iov,
|
||||
.poll = netmap_poll,
|
||||
.cleanup = netmap_cleanup,
|
||||
.has_ufo = netmap_has_ufo,
|
||||
.has_ufo = netmap_has_vnet_hdr,
|
||||
.has_vnet_hdr = netmap_has_vnet_hdr,
|
||||
.has_vnet_hdr_len = netmap_has_vnet_hdr_len,
|
||||
.using_vnet_hdr = netmap_using_vnet_hdr,
|
||||
|
@ -662,7 +662,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
||||
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
|
||||
options.net_backend = &s->nc;
|
||||
|
||||
if (tap->has_vhostfd || tap->has_vhostfds) {
|
||||
if (vhostfdname) {
|
||||
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
|
||||
if (vhostfd == -1) {
|
||||
error_propagate(errp, err);
|
||||
@ -684,7 +684,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
||||
"vhost-net requested but could not be initialized");
|
||||
return;
|
||||
}
|
||||
} else if (tap->has_vhostfd || tap->has_vhostfds) {
|
||||
} else if (vhostfdname) {
|
||||
error_setg(errp, "vhostfd= is not valid without vhost");
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user