[email protected] writes:

> From: Lin Huang <[email protected]>
>
> OvS has supported packet-per-second policer which can be set at ingress
> and egress side in kernel datapath. But the userspace datapath doesn't
> support for ingress and egress packet-per-second policing now.
>
> So, this patch add support for userspace egress pps policing by using
> native ovs token bucket library. Token bucket is accumulated by 'rate'
> tokens per millisecond and store maximum tokens at 'burst' bucket size.
> One token in the bucket means one packet (1 kpkts * millisecond) which
> will drop or pass by policer.
>
> This patch add a new egress Qos type called 'kpkts-policer'.
> the policer police the kilo-packet per second at which the token bucket
> be updated by 'kpkts_rate'. and the policer's burst size is defined by
> 'kpkts_burst'.
>
> Examples:
> $ovs-vsctl set port vhost-user0 qos=@newqos --
>            --id=@newqos create qos type=kpkts-policer \
>            other-config:kpkts_rate=123 other-config:kpkts_burst=123
>
> Add some unit tests for egress packet-per-second policing.
>
> Signed-off-by: Lin Huang <[email protected]>
> ---
>  Documentation/topics/dpdk/qos.rst |  21 +++
>  NEWS                              |   1 +
>  lib/netdev-dpdk.c                 | 159 +++++++++++++++++++
>  tests/system-dpdk.at              | 255 ++++++++++++++++++++++++++++++
>  vswitchd/vswitch.xml              |  32 ++++
>  5 files changed, 468 insertions(+)
>
> diff --git a/Documentation/topics/dpdk/qos.rst 
> b/Documentation/topics/dpdk/qos.rst
> index a98ec672f..6a4408127 100644
> --- a/Documentation/topics/dpdk/qos.rst
> +++ b/Documentation/topics/dpdk/qos.rst
> @@ -36,6 +36,9 @@ QoS (Egress Policing)
>  Single Queue Policer
>  ~~~~~~~~~~~~~~~~~~~~
>  
> +Bytes Per Second 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::
> @@ -52,6 +55,24 @@ To clear the QoS configuration from the port and ovsdb, 
> run::
>  
>      $ ovs-vsctl destroy QoS vhost-user0 -- clear Port vhost-user0 qos
>  
> +Packets Per Second Policer
> ++++++++++++++++++++
> +
> +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 packets per second::
> +
> +       ovs-vsctl set port vhost-user0 qos=@newqos -- \
> +          --id=@newqos create qos type=kpkts-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
> +
> +To clear the QoS configuration from the port and ovsdb, run::
> +
> +    $ ovs-vsctl destroy QoS vhost-user0 -- clear Port vhost-user0 qos
>  
>  Multi Queue Policer
>  ~~~~~~~~~~~~~~~~~~~
> diff --git a/NEWS b/NEWS
> index 7a852427e..3d1ab282e 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -63,6 +63,7 @@ v3.2.0 - xx xxx xxxx
>       * 'ovs-appctl dpif-netdev/pmd-sleep-show' command was added to get the
>         max sleep configuration of PMD thread cores.
>       * Removed experimental tag from PMD load based sleeping.
> +     * Added new Qos type 'pkts-policer' to support kilo packet-per-second 
> policing.
>     - Linux TC offload:
>       * Add support for offloading VXLAN tunnels with the GBP extensions.
>     - Python
> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
> index 7e3020a7d..e6b8922aa 100644
> --- a/lib/netdev-dpdk.c
> +++ b/lib/netdev-dpdk.c
> @@ -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.
> @@ -346,6 +350,7 @@ struct dpdk_qos_ops {
>  /* dpdk_qos_ops for each type of user space QoS implementation. */
>  static const struct dpdk_qos_ops egress_policer_ops;
>  static const struct dpdk_qos_ops trtcm_policer_ops;
> +static const struct dpdk_qos_ops kpkts_policer_ops;
>  
>  /*
>   * Array of dpdk_qos_ops, contains pointer to all supported QoS
> @@ -354,6 +359,7 @@ static const struct dpdk_qos_ops trtcm_policer_ops;
>  static const struct dpdk_qos_ops *const qos_confs[] = {
>      &egress_policer_ops,
>      &trtcm_policer_ops,
> +    &kpkts_policer_ops,
>      NULL
>  };
>  
> @@ -5572,6 +5578,159 @@ static const struct dpdk_qos_ops trtcm_policer_ops = {
>      .qos_queue_dump_state_init = trtcm_policer_qos_queue_dump_state_init
>  };
>  
> +/* kpkts-policer details */
> +struct kpkts_policer {
> +    struct qos_conf qos_conf;
> +    struct token_bucket tb;
> +    uint32_t kpkts_rate;
> +    uint32_t kpkts_burst;
> +};
> +
> +static int
> +kpkts_policer_run_single_packet(struct token_bucket *tb, struct rte_mbuf 
> **pkts,
> +                                int pkt_cnt, bool should_steal)
> +{
> +    struct rte_mbuf *batch[NETDEV_MAX_BURST] = {0};
> +    long long int now = time_msec();
> +    struct rte_mbuf *pkt = NULL;
> +    int i = 0, n = 0;
> +    int cnt = 0;
> +
> +    for (i = 0; i < pkt_cnt; i++) {
> +        pkt = pkts[i];
> +        /* Handle current packet. */
> +        if (token_bucket_withdraw(tb, 1, now)) {
> +            /* Count passed packets. */
> +            if (cnt != i) {
> +                pkts[cnt] = pkt;
> +            }
> +            cnt++;
> +        } else {
> +            /* Count dropped packets. */
> +            batch[n++] = pkt;
> +        }
> +    }
> +
> +    if (should_steal && n) {
> +        rte_pktmbuf_free_bulk(batch, n);
> +    }
> +
> +    return cnt;
> +}
> +
> +static int
> +kpkts_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 EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int
> +kpkts_policer_qos_construct(const struct smap *details, struct qos_conf 
> **conf)
> +{
> +    uint32_t kpkts_rate, kpkts_burst;
> +    struct kpkts_policer *policer;
> +    int err;
> +
> +    policer = xmalloc(sizeof *policer);
> +    kpkts_rate  = smap_get_uint(details, "kpkts_rate", 0);
> +    kpkts_burst = smap_get_uint(details, "kpkts_burst", 0);
> +
> +    /*
> +     * Force to 0 if no rate specified,
> +     * default to rate if burst is 0,
> +     * else stick with user-specified value.
> +     */
> +    kpkts_burst = (!kpkts_rate ? 0 : !kpkts_burst ? kpkts_rate : 
> kpkts_burst);
> +
> +    qos_conf_init(&policer->qos_conf, &kpkts_policer_ops);
> +    err = kpkts_policer_profile_config(&policer->tb, kpkts_rate, 
> kpkts_burst);
> +    if (err) {
> +        VLOG_DBG("Could not create token bucket for egress policer");

I didn't do an in-depth look at this yet, just noticed this needs free
here for policer object.

> +        return err;
> +    }
> +
> +    policer->kpkts_rate = kpkts_rate;
> +    policer->kpkts_burst = kpkts_burst;
> +
> +    *conf = &policer->qos_conf;
> +
> +    return err;
> +}
> +
> +static void
> +kpkts_policer_qos_destruct(struct qos_conf *conf)
> +{
> +    struct kpkts_policer *policer = CONTAINER_OF(conf, struct kpkts_policer,
> +                                                 qos_conf);
> +
> +    free(policer);
> +}
> +
> +static int
> +kpkts_policer_qos_get(const struct qos_conf *conf, struct smap *details)
> +{
> +    struct kpkts_policer *policer = CONTAINER_OF(conf, struct kpkts_policer,
> +                                                 qos_conf);
> +
> +    smap_add_format(details, "kpkts_rate", "%"PRIu32, policer->kpkts_rate);
> +    smap_add_format(details, "kpkts_burst", "%"PRIu32, policer->kpkts_burst);
> +
> +    return 0;
> +}
> +
> +static bool
> +kpkts_pkts_policer_qos_is_equal(const struct qos_conf *conf,
> +                                const struct smap *details)
> +{
> +    uint32_t rate, burst;
> +    struct kpkts_policer *policer = CONTAINER_OF(conf, struct kpkts_policer,
> +                                                 qos_conf);
> +
> +    rate  = smap_get_uint(details, "pkts_rate", 0);
> +    burst = smap_get_uint(details, "pkts_burst", 0);
> +
> +    return (policer->tb.rate == rate && policer->tb.burst == burst);
> +}
> +
> +static int
> +kpkts_policer_run(struct qos_conf *conf, struct rte_mbuf **pkts, int pkt_cnt,
> +                  bool should_steal)
> +{
> +    int cnt;
> +    struct kpkts_policer *policer = CONTAINER_OF(conf, struct kpkts_policer,
> +                                                 qos_conf);
> +
> +    cnt = kpkts_policer_run_single_packet(&policer->tb, pkts, pkt_cnt,
> +                                          should_steal);
> +
> +    return cnt;
> +}
> +
> +static const struct dpdk_qos_ops kpkts_policer_ops = {
> +    .qos_name = "kpkts-policer",
> +    .qos_construct = kpkts_policer_qos_construct,
> +    .qos_destruct = kpkts_policer_qos_destruct,
> +    .qos_get = kpkts_policer_qos_get,
> +    .qos_is_equal = kpkts_pkts_policer_qos_is_equal,
> +    .qos_run = kpkts_policer_run
> +};
> +
>  static int
>  dpdk_rx_steer_add_flow(struct netdev_dpdk *dev,
>                        const struct rte_flow_item items[],
> diff --git a/tests/system-dpdk.at b/tests/system-dpdk.at
> index 0f58e8574..8b80a31e6 100644
> --- a/tests/system-dpdk.at
> +++ b/tests/system-dpdk.at
> @@ -570,6 +570,261 @@ 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=kpkts-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 kpkts-policer on port dpdkvhostuserclient0: Invalid 
> argument@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=kpkts-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
> +\@Failed to set QoS type kpkts-policer on port dpdkvhostuserclient0: Invalid 
> argument@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=kpkts-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 Check egress policer was deleted
> +QOS_UUID=`ovs-vsctl get port dpdkvhostuserclient0 qos`
> +AT_CHECK([ovs-vsctl set qos $QOS_UUID other_config:kpkts_rate=0])
> +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 kpkts-policer on port dpdkvhostuserclient0: Invalid 
> argument@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=kpkts-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
> +\@Failed to set QoS type kpkts-policer on port dpdkvhostuserclient0: Invalid 
> argument@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=kpkts-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
> +\@Failed to set QoS type kpkts-policer on port dpdkvhostuserclient0: Invalid 
> argument@d
> +])")
> +AT_CLEANUP
> +dnl 
> --------------------------------------------------------------------------
> +
> +
> +dnl 
> --------------------------------------------------------------------------
> +dnl QoS (kpkts) testpmd flowgen test
> +AT_SETUP([OVS-DPDK - QoS (kpkts) police])
> +AT_KEYWORDS([dpdk])
> +
> +OVS_DPDK_PRE_CHECK()
> +AT_SKIP_IF([! which dpdk-testpmd >/dev/null 2>/dev/null])
> +OVS_DPDK_START([--no-pci])
> +
> +dnl Find number of sockets
> +AT_CHECK([lscpu], [], [stdout])
> +AT_CHECK([cat stdout | grep "NUMA node(s)" | awk '{c=1; while (c++<$(3)) 
> {printf "512,"}; print "512"}' > NUMA_NODE])
> +
> +dnl Add userspace bridge and attach it to OVS
> +AT_CHECK([ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev])
> +
> +dnl Parse log file
> +AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuser0 -- set Interface 
> dpdkvhostuser0 type=dpdkvhostuser], [], [stdout], [stderr])
> +AT_CHECK([ovs-vsctl add-port br10 dpdkvhostuser1 -- set Interface 
> dpdkvhostuser1 type=dpdkvhostuser], [], [stdout], [stderr])
> +AT_CHECK([ovs-vsctl show], [], [stdout])
> +
> +dnl Parse log file
> +AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostuser0) vhost-user 
> server: socket created" ovs-vswitchd.log], [], [stdout])
> +AT_CHECK([grep "Socket $OVS_RUNDIR/dpdkvhostuser0 created for vhost-user 
> port dpdkvhostuser0" ovs-vswitchd.log], [], [stdout])
> +AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostuser0) binding 
> succeeded" ovs-vswitchd.log], [], [stdout])
> +
> +dnl Parse log file
> +AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostuser1) vhost-user 
> server: socket created" ovs-vswitchd.log], [], [stdout])
> +AT_CHECK([grep "Socket $OVS_RUNDIR/dpdkvhostuser1 created for vhost-user 
> port dpdkvhostuser1" ovs-vswitchd.log], [], [stdout])
> +AT_CHECK([grep "VHOST_CONFIG: ($OVS_RUNDIR/dpdkvhostuser1) binding 
> succeeded" ovs-vswitchd.log], [], [stdout])
> +
> +dnl Configure the same QoS for both ports.
> +AT_CHECK([ovs-vsctl set port dpdkvhostuser0 qos=@newqos -- --id=@newqos 
> create qos type=kpkts-policer other-config:kpkts_rate=1 
> other-config:kpkts_burst=1], [0], [ignore])
> +
> +dnl add flows, only send packets from dpdkvhostuser1 to dpdkvhostuser0.
> +AT_DATA([flows.txt], [dnl
> +priority=100,in_port=dpdkvhostuser1,ip,actions=dpdkvhostuser0
> +])
> +
> +AT_CHECK([ovs-ofctl del-flows br10])
> +AT_CHECK([ovs-ofctl add-flows br10 flows.txt])
> +
> +dnl Execute testpmd in background
> +on_exit "pkill -f -x -9 'tail -f /dev/null'"
> +tail -f /dev/null | dpdk-testpmd --socket-mem="$(cat NUMA_NODE)" --no-pci\
> +           --vdev="net_virtio_user0,path=$OVS_RUNDIR/dpdkvhostuser0" \
> +           --vdev="net_virtio_user1,path=$OVS_RUNDIR/dpdkvhostuser1" \
> +           --single-file-segments -- --forward-mode=flowgen -a > 
> $OVS_RUNDIR/testpmd-dpdkvhostuser.log 2>&1 &
> +
> +dnl sent packet 10 second.
> +AT_CHECK([sleep 10])
> +
> +dnl Clean up the testpmd now
> +pkill -f -x -9 'tail -f /dev/null'
> +
> +dnl ---------------------- Forward statistics for port 0  
> ----------------------
> +dnl RX-packets: 9911           RX-dropped: 0             RX-total: 9911
> +dnl TX-packets: 15937632       TX-dropped: 226661984     TX-total: 242599616
> +dnl 
> ----------------------------------------------------------------------------
> +port0_rx_packets=`cat testpmd-dpdkvhostuser.log | grep "Forward statistics 
> for port 0" -A 1 | grep "RX-packets:" | awk '{print $2}'`
> +echo "port0_rx_packets=$port0_rx_packets"
> +
> +AT_CHECK([test $port0_rx_packets -lt 10500])
> +AT_CHECK([test $port0_rx_packets -gt 9500])
> +
> +OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
> +\@dpdkvhostuser ports are considered deprecated;  please migrate to 
> dpdkvhostuserclient ports.@d
> +])")
> +AT_CLEANUP
> +dnl 
> --------------------------------------------------------------------------
> +
> +
>  
>  dnl 
> --------------------------------------------------------------------------
>  dnl MTU increase phy port
> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> index cfcde34ff..19fc13873 100644
> --- a/vswitchd/vswitch.xml
> +++ b/vswitchd/vswitch.xml
> @@ -4874,6 +4874,19 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 
> type=patch options:peer=p1 \
>            created with the same <code>other_config</code> values as the
>            physical port.
>          </dd>
> +        <dt><code>kpkts-policer</code></dt>
> +        <dd>
> +          A DPDK egress packet per second policer algorithm using the ovs
> +          token bucket library. The token bucket library provides an
> +          implementation which allows the policing of packets traffic. The
> +          implementation in OVS essentially creates a single token bucket 
> used
> +          to police traffic. It should be noted that when the token bucket is
> +          configured as part of QoS there will be a performance overhead as 
> the
> +          token bucket itself will consume CPU cycles in order to police
> +          traffic. These CPU cycles ordinarily are used for packet 
> proccessing.
> +          As such the drop in performance will be noticed in terms of overall
> +          aggregate traffic throughput.
> +        </dd>
>        </dl>
>      </column>
>  
> @@ -4966,6 +4979,25 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 
> type=patch options:peer=p1 \
>        </column>
>      </group>
>  
> +    <group title="Configuration for kpkts-policer QoS">
> +      <p>
> +        <ref table="QoS"/> <ref table="QoS" column="type"/>
> +        <code>kpkts-policer</code> provides egress pkts policing for 
> userspace
> +        port types with DPDK.
> +
> +        It has the following key-value pairs defined.
> +      </p>
> +
> +      <column name="other_config" key="kpkts_rate" type='{"type": 
> "integer"}'>
> +        The Kilo Packets Per Second (kpps) 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"}'>
> +        The Packets Per Second Burst Size is measured in count and 
> represents a
> +        token bucket.
> +      </column>
> +    </group>
> +
>      <group title="Configuration for linux-sfq">
>        <p>
>          The <code>linux-sfq</code> QoS supports the following key-value 
> pairs:

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to