@@ -36,14 +36,21 @@ QoS (Egress Policing)
Single Queue Policer
~~~~~~~~~~~~~~~~~~~~
-Assuming you have a :doc:`vhost-user port <vhost-user>` transmitting traffic
-consisting of packets of size 64 bytes, the following command would limit the
-egress transmission rate of the port to ~1,000,000 packets per second::
+Assuming you have a :doc:`vhost-user port <vhost-user>` transmitting traffic,
+the following command would limit the egress transmission rate of the port to
+~1,000,000 bytes per second:
$ ovs-vsctl set port vhost-user0 qos=@newqos -- \
- --id=@newqos create qos type=egress-policer other-config:cir=46000000 \
+ --id=@newqos create qos type=egress-policer other-config:cir=1000000 \
other-config:cbs=2048`
+or, the following command would limit the egress transmission rate of the port
+to ~1,000,000 packets per second:
+
+ ovs-vsctl set port vhost-user0 qos=@newqos -- \
+ --id=@newqos create qos type=egress-policer \
+ other-config:kpkts_rate=1000 other-config:kpkts_burst=1000
+
To examine the QoS configuration of the port, run::
$ ovs-appctl -t ovs-vswitchd qos/show vhost-user0
@@ -36,6 +36,9 @@ Post-v3.1.0
process extra privileges when mapping physical interconnect memory.
- SRv6 Tunnel Protocol
* Added support for userspace datapath (only).
+ - Userspace datapath:
+ * Added new configuration options 'kpkts_rate' and 'kpkts_burst' for
+ 'egress-policer' to support packet-per-second policing.
v3.1.0 - 16 Feb 2023
@@ -19,6 +19,7 @@
#include <errno.h>
#include <signal.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -59,6 +60,7 @@
#include "openvswitch/ofp-parse.h"
#include "openvswitch/ofp-print.h"
#include "openvswitch/shash.h"
+#include "openvswitch/token-bucket.h"
#include "openvswitch/vlog.h"
#include "ovs-numa.h"
#include "ovs-rcu.h"
@@ -91,6 +93,8 @@ static bool per_port_memory = false; /* Status of per port memory support */
#define OVS_CACHE_LINE_SIZE CACHE_LINE_SIZE
#define OVS_VPORT_DPDK "ovs_dpdk"
+#define MAX_KPKTS_PARAMETER 4294967U /* UINT32_MAX / 1000 */
+
/*
* need to reserve tons of extra space in the mbufs so we can align the
* DMA addresses to 4KB.
@@ -400,6 +404,11 @@ struct dpdk_tx_queue {
);
};
+enum policer_type {
+ POLICER_BPS = 1 << 0, /* Rate value in bytes/sec. */
+ POLICER_PKTPS = 1 << 1, /* Rate value in packet/sec. */
+};
+
struct ingress_policer {
struct rte_meter_srtcm_params app_srtcm_params;
struct rte_meter_srtcm in_policer;
@@ -2335,6 +2344,45 @@ srtcm_policer_run_single_packet(struct rte_meter_srtcm *meter,
return cnt;
}
+static int
+pkts_policer_run_single_packet(struct token_bucket *tb, struct rte_mbuf **pkts,
+ unsigned int pkt_cnt, bool should_steal)
+{
+ int cnt = 0;
+
+ if (token_bucket_withdraw(tb, pkt_cnt)) {
+ /* Handle packet by batch. */
+ cnt = pkt_cnt;
+ } else if (should_steal) {
+ rte_pktmbuf_free_bulk(pkts, pkt_cnt);
+ }
+
+ return cnt;
+}
+
+static int
+pkts_policer_profile_config(struct token_bucket *tb,
+ uint32_t kpkts_rate, uint32_t kpkts_burst)
+{
+ if (kpkts_rate > MAX_KPKTS_PARAMETER ||
+ kpkts_burst > MAX_KPKTS_PARAMETER) {
+ return EINVAL;
+ }
+
+ /* Rate in kilo-packets/second, bucket 1000 packets. */
+ /* msec * kilo-packets/sec = 1 packets. */
+ if (kpkts_rate) {
+ /* Parameters between (1 ~ MAX_KPKTS_PARAMETER). */
+ token_bucket_init(tb, kpkts_rate, kpkts_burst * 1000);
+ } else {
+ /* Zero means not to police the traffic. */
+ /* Return a error to not set POLICER_PKTPS valid. */
+ return EINVAL;
+ }
+
+ return 0;
+}
+
static int
ingress_policer_run(struct ingress_policer *policer, struct rte_mbuf **pkts,
int pkt_cnt, bool should_steal)
@@ -4754,24 +4802,37 @@ netdev_dpdk_queue_dump_done(const struct netdev *netdev OVS_UNUSED,
/* egress-policer details */
+struct egress_policer_params {
+ struct rte_meter_srtcm_params app_srtcm_params;
+ uint32_t kpkts_rate;
+ uint32_t kpkts_burst;
+};
struct egress_policer {
struct qos_conf qos_conf;
- struct rte_meter_srtcm_params app_srtcm_params;
+ enum policer_type type;
+ struct token_bucket egress_tb;
+ struct egress_policer_params params;
struct rte_meter_srtcm egress_meter;
struct rte_meter_srtcm_profile egress_prof;
};
static void
egress_policer_details_to_param(const struct smap *details,
- struct rte_meter_srtcm_params *params)
+ struct egress_policer_params *params)
{
- memset(params, 0, sizeof *params);
- params->cir = smap_get_ullong(details, "cir", 0);
- params->cbs = smap_get_ullong(details, "cbs", 0);
- params->ebs = 0;
+ struct rte_meter_srtcm_params *srtcm_params = ¶ms->app_srtcm_params;
+
+ memset(srtcm_params, 0, sizeof *srtcm_params);
+ srtcm_params->cir = smap_get_ullong(details, "cir", 0);
+ srtcm_params->cbs = smap_get_ullong(details, "cbs", 0);
+ srtcm_params->ebs = 0;
+
+ params->kpkts_rate = smap_get_uint(details, "kpkts_rate", 0);
+ params->kpkts_burst = smap_get_uint(details, "kpkts_burst", 0);
}
+
static int
egress_policer_qos_construct(const struct smap *details,
struct qos_conf **conf)
@@ -4779,23 +4840,39 @@ egress_policer_qos_construct(const struct smap *details,
struct egress_policer *policer;
int err = 0;
- policer = xmalloc(sizeof *policer);
+ policer = xzalloc(sizeof *policer);
qos_conf_init(&policer->qos_conf, &egress_policer_ops);
- egress_policer_details_to_param(details, &policer->app_srtcm_params);
+ egress_policer_details_to_param(details, &policer->params);
+
err = rte_meter_srtcm_profile_config(&policer->egress_prof,
- &policer->app_srtcm_params);
+ &policer->params.app_srtcm_params);
if (!err) {
err = rte_meter_srtcm_config(&policer->egress_meter,
&policer->egress_prof);
}
+ if (err) {
+ VLOG_DBG("Could not create rte meter for egress policer");
+ err = -err;
+ } else {
+ policer->type |= POLICER_BPS;
+ }
- if (!err) {
- *conf = &policer->qos_conf;
+ err = pkts_policer_profile_config(&policer->egress_tb,
+ policer->params.kpkts_rate,
+ policer->params.kpkts_burst);
+ if (err) {
+ VLOG_DBG("Could not create token bucket for egress policer");
} else {
- VLOG_ERR("Could not create rte meter for egress policer");
+ policer->type |= POLICER_PKTPS;
+ }
+
+ if (!policer->type) {
+ /* both bps and kpkts contrsruction failed.*/
free(policer);
*conf = NULL;
- err = -err;
+ } else {
+ err = 0;
+ *conf = &policer->qos_conf;
}
return err;
@@ -4814,9 +4891,12 @@ egress_policer_qos_get(const struct qos_conf *conf, struct smap *details)
{
struct egress_policer *policer =
CONTAINER_OF(conf, struct egress_policer, qos_conf);
+ struct egress_policer_params *params = &policer->params;
- smap_add_format(details, "cir", "%"PRIu64, policer->app_srtcm_params.cir);
- smap_add_format(details, "cbs", "%"PRIu64, policer->app_srtcm_params.cbs);
+ smap_add_format(details, "cir", "%"PRIu64, params->app_srtcm_params.cir);
+ smap_add_format(details, "cbs", "%"PRIu64, params->app_srtcm_params.cbs);
+ smap_add_format(details, "kpkts_rate", "%"PRIu32, params->kpkts_rate);
+ smap_add_format(details, "kpkts_burst", "%"PRIu32, params->kpkts_burst);
return 0;
}
@@ -4827,26 +4907,32 @@ egress_policer_qos_is_equal(const struct qos_conf *conf,
{
struct egress_policer *policer =
CONTAINER_OF(conf, struct egress_policer, qos_conf);
- struct rte_meter_srtcm_params params;
+ struct egress_policer_params params;
egress_policer_details_to_param(details, ¶ms);
- return !memcmp(¶ms, &policer->app_srtcm_params, sizeof params);
+ return !memcmp(¶ms, &policer->params, sizeof params);
}
static int
egress_policer_run(struct qos_conf *conf, struct rte_mbuf **pkts, int pkt_cnt,
bool should_steal)
{
- int cnt = 0;
struct egress_policer *policer =
CONTAINER_OF(conf, struct egress_policer, qos_conf);
- cnt = srtcm_policer_run_single_packet(&policer->egress_meter,
- &policer->egress_prof, pkts,
- pkt_cnt, should_steal);
+ if (policer->type & POLICER_BPS) {
+ pkt_cnt = srtcm_policer_run_single_packet(&policer->egress_meter,
+ &policer->egress_prof, pkts,
+ pkt_cnt, should_steal);
+ }
+
+ if (policer->type & POLICER_PKTPS) {
+ pkt_cnt = pkts_policer_run_single_packet(&policer->egress_tb, pkts,
+ pkt_cnt, should_steal);
+ }
- return cnt;
+ return pkt_cnt;
}
static const struct dpdk_qos_ops egress_policer_ops = {
@@ -435,6 +435,7 @@ OVS_DPDK_PRE_PHY_SKIP()
OVS_DPDK_START()
dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
AT_CHECK([ovs-vsctl add-port br10 phy0 -- set Interface phy0 type=dpdk options:dpdk-devargs=$(cat PCI_ADDR)], [], [stdout], [stderr])
OVS_WAIT_UNTIL([ovs-vsctl set port phy0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:cir=1250000 other-config:cbs=2048])
@@ -453,7 +454,9 @@ AT_CHECK([grep -E 'QoS not configured on phy0' stdout], [], [stdout])
dnl Clean up
AT_CHECK([ovs-vsctl del-port br10 phy0], [], [stdout], [stderr])
-OVS_VSWITCHD_STOP("[SYSTEM_DPDK_ALLOWED_LOGS]")
+OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@Could not create token bucket for egress policer@d
+])")
AT_CLEANUP
dnl --------------------------------------------------------------------------
@@ -468,6 +471,7 @@ OVS_DPDK_PRE_CHECK()
OVS_DPDK_START()
dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:cir=1250000 \
@@ -493,6 +497,7 @@ AT_CHECK([grep -E 'QoS not configured on dpdkvhostuserclient0' stdout], [], [std
dnl Clean up
AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@Could not create token bucket for egress policer@d
\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
])")
AT_CLEANUP
@@ -509,6 +514,7 @@ OVS_DPDK_PRE_CHECK()
OVS_DPDK_START()
dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:cbs=2048])
@@ -528,6 +534,7 @@ AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
\@Could not create rte meter for egress policer@d
+\@Could not create token bucket for egress policer@d
\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0: Invalid argument@d
])")
AT_CLEANUP
@@ -544,6 +551,7 @@ OVS_DPDK_PRE_CHECK()
OVS_DPDK_START()
dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:cir=1250000])
@@ -563,6 +571,7 @@ AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
\@Could not create rte meter for egress policer@d
+\@Could not create token bucket for egress policer@d
\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0: Invalid argument@d
])")
AT_CLEANUP
@@ -570,6 +579,189 @@ dnl --------------------------------------------------------------------------
+dnl --------------------------------------------------------------------------
+dnl QoS (kpkts) create delete vport port
+AT_SETUP([OVS-DPDK - QoS (kpkts) create delete vport port])
+AT_KEYWORDS([dpdk])
+
+OVS_DPDK_PRE_CHECK()
+OVS_DPDK_START()
+
+dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
+AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
+AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
+OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:kpkts_rate=123 other-config:kpkts_burst=456])
+AT_CHECK([ovs-appctl -t ovs-vswitchd qos/show dpdkvhostuserclient0], [], [stdout])
+sleep 2
+
+dnl Parse log file
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) vhost-user client: socket created" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "vHost User device 'dpdkvhostuserclient0' created in 'client' mode, using client socket" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) reconnecting..." ovs-vswitchd.log], [], [stdout])
+
+dnl Remove egress policer
+AT_CHECK([ovs-vsctl destroy QoS dpdkvhostuserclient0 -- clear Port dpdkvhostuserclient0 qos])
+
+dnl Check egress policer was removed correctly
+AT_CHECK([ovs-appctl -t ovs-vswitchd qos/show dpdkvhostuserclient0], [], [stdout])
+AT_CHECK([grep -E 'QoS not configured on dpdkvhostuserclient0' stdout], [], [stdout])
+
+dnl Clean up
+AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
+OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
+\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0@d
+\@Could not create rte meter for egress policer@d
+])")
+AT_CLEANUP
+dnl --------------------------------------------------------------------------
+
+
+
+dnl --------------------------------------------------------------------------
+dnl QoS (kpkts) no rate
+AT_SETUP([OVS-DPDK - QoS (kpkts) no rate])
+AT_KEYWORDS([dpdk])
+
+OVS_DPDK_PRE_CHECK()
+OVS_DPDK_START()
+
+dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
+AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
+AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
+OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:kpkts_burst=123])
+sleep 2
+
+dnl Parse log file
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) vhost-user client: socket created" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "vHost User device 'dpdkvhostuserclient0' created in 'client' mode, using client socket" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) reconnecting..." ovs-vswitchd.log], [], [stdout])
+
+dnl Check egress policer was not created
+AT_CHECK([ovs-appctl -t ovs-vswitchd qos/show dpdkvhostuserclient0], [], [stdout])
+AT_CHECK([grep -E 'QoS not configured on dpdkvhostuserclient0' stdout], [], [stdout])
+
+dnl Clean up
+AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
+OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
+\@Could not create rte meter for egress policer@d
+\@Could not create token bucket for egress policer@d
+\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0@d
+])")
+AT_CLEANUP
+dnl --------------------------------------------------------------------------
+
+
+
+dnl --------------------------------------------------------------------------
+dnl QoS (kpkts) no burst
+AT_SETUP([OVS-DPDK - QoS (kpkts) no burst])
+AT_KEYWORDS([dpdk])
+
+OVS_DPDK_PRE_CHECK()
+OVS_DPDK_START()
+
+dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
+AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
+AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
+OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:kpkts_rate=123])
+sleep 2
+
+dnl Parse log file
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) vhost-user client: socket created" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "vHost User device 'dpdkvhostuserclient0' created in 'client' mode, using client socket" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) reconnecting..." ovs-vswitchd.log], [], [stdout])
+
+dnl Check egress policer was created
+AT_CHECK([ovs-appctl -t ovs-vswitchd qos/show dpdkvhostuserclient0], [], [stdout])
+AT_CHECK([grep -E 'kpkts_rate: 123' stdout], [], [stdout])
+
+dnl Clean up
+AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
+OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
+\@Could not create rte meter for egress policer@d
+\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0@d
+])")
+AT_CLEANUP
+dnl --------------------------------------------------------------------------
+
+
+
+dnl --------------------------------------------------------------------------
+dnl QoS (kpkts) max rate
+AT_SETUP([OVS-DPDK - QoS (kpkts) max rate])
+AT_KEYWORDS([dpdk])
+
+OVS_DPDK_PRE_CHECK()
+OVS_DPDK_START()
+
+dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
+AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
+AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
+OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:kpkts_rate=42949671])
+sleep 2
+
+dnl Parse log file
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) vhost-user client: socket created" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "vHost User device 'dpdkvhostuserclient0' created in 'client' mode, using client socket" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) reconnecting..." ovs-vswitchd.log], [], [stdout])
+
+dnl Check egress policer was not created
+AT_CHECK([ovs-appctl -t ovs-vswitchd qos/show dpdkvhostuserclient0], [], [stdout])
+AT_CHECK([grep -E 'QoS not configured on dpdkvhostuserclient0' stdout], [], [stdout])
+
+dnl Clean up
+AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
+OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
+\@Could not create rte meter for egress policer@d
+\@Could not create token bucket for egress policer@d
+\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0@d
+])")
+AT_CLEANUP
+dnl --------------------------------------------------------------------------
+
+
+dnl --------------------------------------------------------------------------
+dnl QoS (kpkts) max burst
+AT_SETUP([OVS-DPDK - QoS (kpkts) max burst])
+AT_KEYWORDS([dpdk])
+
+OVS_DPDK_PRE_CHECK()
+OVS_DPDK_START()
+
+dnl Add userspace bridge and attach it to OVS and add egress policer
+AT_CHECK([ovs-appctl vlog/set netdev_dpdk:dbg])
+AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
+AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuserclient0 -- set Interface dpdkvhostuserclient0 type=dpdkvhostuserclient options:vhost-server-path=$OVS_RUNDIR/dpdkvhostclient0], [], [stdout], [stderr])
+OVS_WAIT_UNTIL([ovs-vsctl set port dpdkvhostuserclient0 qos=@newqos -- --id=@newqos create qos type=egress-policer other-config:kpkts_burst=42949671])
+sleep 2
+
+dnl Parse log file
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) vhost-user client: socket created" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "vHost User device 'dpdkvhostuserclient0' created in 'client' mode, using client socket" ovs-vswitchd.log], [], [stdout])
+AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) reconnecting..." ovs-vswitchd.log], [], [stdout])
+
+dnl Check egress policer was not created
+AT_CHECK([ovs-appctl -t ovs-vswitchd qos/show dpdkvhostuserclient0], [], [stdout])
+AT_CHECK([grep -E 'QoS not configured on dpdkvhostuserclient0' stdout], [], [stdout])
+
+dnl Clean up
+AT_CHECK([ovs-vsctl del-port br10 dpdkvhostuserclient0], [], [stdout], [stderr])
+OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
+\@VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostclient0) failed to connect: No such file or directory@d
+\@Could not create rte meter for egress policer@d
+\@Could not create token bucket for egress policer@d
+\@Failed to set QoS type egress-policer on port dpdkvhostuserclient0@d
+])")
+AT_CLEANUP
+dnl --------------------------------------------------------------------------
dnl --------------------------------------------------------------------------
dnl MTU increase phy port
@@ -4894,6 +4894,16 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
bytes/tokens of the packet. If there are not enough tokens in the cbs
bucket the packet might be dropped.
</column>
+ <column name="other_config" key="kpkts_rate"
+ type='{"type": "integer", "minInteger": 0, "maxInteger": 4294967}'>
+ The Packets Per Second (PPS) represents the packet per second rate at
+ which the token bucket will be updated.
+ </column>
+ <column name="other_config" key="kpkts_burst"
+ type='{"type": "integer", "minInteger": 0, "maxInteger": 4294967}'>
+ The Packets Per Second Burst Size is measured in count and represents a
+ token bucket.
+ </column>
</group>
<group title="Configuration for linux-sfq">