Thanks for the comments Miguel. Responses inline.

Ian
> -----Original Message-----
> From: Miguel Angel Ajo Pelayo [mailto:majop...@redhat.com]
> Sent: Friday, April 15, 2016 9:32 AM
> To: Stokes, Ian
> Cc: dev@openvswitch.org
> Subject: Re: [ovs-dev] [PATCH v1 2/2] netdev-dpdk.c: Add ingress-
> policing functionality.
> 
> On Wed, Apr 13, 2016 at 4:48 PM, Ian Stokes <ian.sto...@intel.com>
> wrote:
> > This patch provides the modifications required in netdev-dpdk.c and
> > vswitch.xml to enable ingress policing for DPDK interfaces.
> >
> > This patch implements the necessary netdev functions to netdev-dpdk.c
> > as well as various helper functions required for ingress policing.
> >
> > The vswitch.xml has been modified to explain the expected parameters
> > and behaviour when using ingress policing.
> >
> > The INSTALL.DPDK.md guide has been modified to provide an example
> > configuration of ingress policing.
> >
> > Signed-off-by: Ian Stokes <ian.sto...@intel.com>
> > ---
> >
> > v1:
> >
> > *INSTALL.DPDK.md
> > - Add ingress_policing usage example.
> >
> > *NEWS
> > - Add support for ingress_policing to DPDK section.
> >
> > *netdev-dpdk.c
> > - Add ingress_policer struct.
> > - Modify struct netdev-dpdk to include a ovsrcu pointer to an ingress
> >   policer.
> > - Modify netdev_dpdk_init() to initialise ingress policer to null.
> > - Add function 'ingress_policer_run()'to process packets with a given
> >   netdev, rte_mbuf and packet count.
> > - Modified 'netdev_dpdk_vhost_update_rx_counters()' to accept new
> >   parameter int dropped representing number of packets dropped.
> > - Modified 'netdev_dpdk_vhost_update_rx_counters()' to update number
> of
> >   dropped packets in stats->rx_dropped.
> > - Modified 'netdev_dpdk_vhost_rxq_recv()' to check and call
> >   ingress_policing functionality with 'ingress_policer_run()'.
> > - Modified 'netdev_dpdk_rxq_recv()' to check and call
> >   ingress_policing functionality with 'ingress_policer_run()'.
> > - Modified 'netdev_dpdk_rxq_recv()' to update rx dropped stats.
> > - Modified 'netdev_dpdk_vhost_get_stats()' to add support for
> rx_dropped.
> > - Add function 'netdev_dpdk_policer_construct__()' to create an
> >   ingress_policer.
> > - Add function 'netdev_dpdk_policer_destruct__()' to destroy an
> ingress
> >   policer.
> > - Add function 'netdev_dpdk_set_policing()' responsible for calling
> >   helper functions to create and destroy an ingress policer for the
> >   device.
> > - Add function 'netdev_dpdk_get_ingress_policer()' to return a pointer
> >   to the ingress_policer using the ovsrcu_get function.
> >
> > *vswitch.xml
> > - Modify ingress policing section to include support in OVS with DPDK.
> > ---
> >  INSTALL.DPDK.md      |   19 ++++++
> >  NEWS                 |    1 +
> >  lib/netdev-dpdk.c    |  173
> ++++++++++++++++++++++++++++++++++++++++++++++++--
> >  vswitchd/vswitch.xml |    4 +-
> >  4 files changed, 190 insertions(+), 7 deletions(-)
> >
> > diff --git a/INSTALL.DPDK.md b/INSTALL.DPDK.md index 9ec8bf6..df2c6cd
> > 100644
> > --- a/INSTALL.DPDK.md
> > +++ b/INSTALL.DPDK.md
> > @@ -227,6 +227,25 @@ Using the DPDK with ovs-vswitchd:
> >     For more details regarding egress-policer parameters please refer
> to the
> >     vswitch.xml.
> >
> > +9. Ingress Policing Example
> > +
> > +   Assuming you have a vhost-user port receiving traffic consisting
> of
> > +   packets of size 64 bytes, the following command would limit the
> reception
> > +   rate of the port to ~1,000,000 packets per second:
> > +
> > +   `ovs-vsctl set interface vhost-user0 ingress_policing_rate=368000
> > +    ingress_policing_burst=1000`
> > +
> > +   To examine the ingress policer configuration of the port:
> > +
> > +   `ovs-vsctl list interface vhost-user0`
> > +
> > +   To clear the ingress policer configuration from the port use the
> following:
> > +
> > +   `ovs-vsctl set interface vhost-user0 ingress_policing_rate=0`
> > +
> > +   For more details regarding ingress-policer see the vswitch.xml.
> > +
> >  Performance Tuning:
> >  -------------------
> >
> > diff --git a/NEWS b/NEWS
> > index ea7f3a1..d0283fa 100644
> > --- a/NEWS
> > +++ b/NEWS
> > @@ -26,6 +26,7 @@ Post-v2.5.0
> >         assignment.
> >       * Type of log messages from PMD threads changed from INFO to
> DBG.
> >       * QoS functionality with sample egress-policer implementation.
> > +     * Add ingress policing functionality.
> >     - ovs-benchmark: This utility has been removed due to lack of use
> and
> >       bitrot.
> >     - ovs-appctl:
> > diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index
> > fe9c9cb..2d955d3 100644
> > --- a/lib/netdev-dpdk.c
> > +++ b/lib/netdev-dpdk.c
> > @@ -297,6 +297,12 @@ struct dpdk_ring {
> >      struct ovs_list list_node OVS_GUARDED_BY(dpdk_mutex);  };
> >
> > +struct ingress_policer {
> > +    struct rte_meter_srtcm_params app_srtcm_params;
> > +    struct rte_meter_srtcm in_policer;
> > +    rte_spinlock_t policer_lock;
> > +};
> > +
> >  struct netdev_dpdk {
> >      struct netdev up;
> >      int port_id;
> > @@ -342,6 +348,10 @@ struct netdev_dpdk {
> >      struct qos_conf *qos_conf;
> >      rte_spinlock_t qos_lock;
> >
> > +    /* Ingress Policer */
> > +    OVSRCU_TYPE(struct ingress_policer *) ingress_policer;
> > +    uint32_t policer_rate;
> > +    uint32_t policer_burst;
> >  };
> >
> >  struct netdev_rxq_dpdk {
> > @@ -355,6 +365,9 @@ static int netdev_dpdk_construct(struct netdev *);
> >
> >  struct virtio_net * netdev_dpdk_get_virtio(const struct netdev_dpdk
> > *dev);
> >
> > +struct ingress_policer *
> > +netdev_dpdk_get_ingress_policer(const struct netdev_dpdk *dev);
> > +
> >  static bool
> >  is_dpdk_class(const struct netdev_class *class)  { @@ -721,6 +734,11
> > @@ netdev_dpdk_init(struct netdev *netdev, unsigned int port_no,
> >      dev->qos_conf = NULL;
> >      rte_spinlock_init(&dev->qos_lock);
> >
> > +    /* Initialise rcu pointer for ingress policer to NULL */
> > +    ovsrcu_init(&dev->ingress_policer, NULL);
> > +    dev->policer_rate = 0;
> > +    dev->policer_burst = 0;
> > +
> >      netdev->n_txq = NR_QUEUE;
> >      netdev->n_rxq = NR_QUEUE;
> >      netdev->requested_n_rxq = NR_QUEUE; @@ -1152,6 +1170,22 @@
> > netdev_dpdk_policer_run__(struct rte_meter_srtcm *meter,
> >      return cnt;
> >  }
> >
> > +static int
> > +ingress_policer_run(struct netdev_dpdk *dev, struct rte_mbuf **pkts,
> > +                        int pkt_cnt)
> > +{
> > +    int cnt = 0;
> > +    struct ingress_policer *policer =
> > +netdev_dpdk_get_ingress_policer(dev);
> > +
> > +    if (policer) {
> > +        rte_spinlock_lock(&policer->policer_lock);
> > +        cnt = netdev_dpdk_policer_run__(&policer->in_policer, pkts,
> pkt_cnt);
> > +        rte_spinlock_unlock(&policer->policer_lock);
> > +    }
> > +
> > +    return cnt;
> > +}
> > +
> >  static bool
> >  is_vhost_running(struct virtio_net *virtio_dev)  { @@ -1160,12
> > +1194,14 @@ is_vhost_running(struct virtio_net *virtio_dev)
> >
> >  static inline void
> >  netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats,
> > -                                     struct dp_packet **packets, int
> count)
> > +                                     struct dp_packet **packets, int
> count,
> > +                                     int dropped)
> >  {
> >      int i;
> >      struct dp_packet *packet;
> >
> >      stats->rx_packets += count;
> > +    stats->rx_dropped += dropped;
> >      for (i = 0; i < count; i++) {
> >          packet = packets[i];
> >
> > @@ -1197,7 +1233,9 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq
> *rxq,
> >      struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev);
> >      struct virtio_net *virtio_dev = netdev_dpdk_get_virtio(dev);
> >      int qid = rxq->queue_id;
> > +    struct ingress_policer *policer =
> > + netdev_dpdk_get_ingress_policer(dev);
> >      uint16_t nb_rx = 0;
> > +    uint16_t dropped = 0;
> >
> >      if (OVS_UNLIKELY(!is_vhost_running(virtio_dev))) {
> >          return EAGAIN;
> > @@ -1215,8 +1253,14 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq
> *rxq,
> >          return EAGAIN;
> >      }
> >
> > +    if (policer != NULL) {
> > +        dropped = nb_rx;
> > +        nb_rx = ingress_policer_run(dev, (struct rte_mbuf **)packets,
> nb_rx);
> > +        dropped -= nb_rx;
> > +    }
> > +
> >      rte_spinlock_lock(&dev->stats_lock);
> > -    netdev_dpdk_vhost_update_rx_counters(&dev->stats, packets,
> nb_rx);
> > +    netdev_dpdk_vhost_update_rx_counters(&dev->stats, packets, nb_rx,
> > + dropped);
> >      rte_spinlock_unlock(&dev->stats_lock);
> >
> >      *c = (int) nb_rx;
> > @@ -1229,7 +1273,9 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq,
> > struct dp_packet **packets,  {
> >      struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq);
> >      struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev);
> > +    struct ingress_policer *policer =
> > + netdev_dpdk_get_ingress_policer(dev);
> >      int nb_rx;
> > +    int dropped = 0;
> >
> >      /* There is only one tx queue for this core.  Do not flush other
> >       * queues.
> > @@ -1247,6 +1293,19 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq,
> struct dp_packet **packets,
> >          return EAGAIN;
> >      }
> >
> > +    if (policer != NULL) {
> > +        dropped = nb_rx;
> > +        nb_rx = ingress_policer_run(dev, (struct rte_mbuf **)
> packets, nb_rx);
> > +        dropped -= nb_rx;
> > +    }
> > +
> > +    /* Update stats to reflect dropped packets */
> > +    if (OVS_UNLIKELY(dropped)) {
> > +        rte_spinlock_lock(&dev->stats_lock);
> > +        dev->stats.rx_dropped += dropped;
> > +        rte_spinlock_unlock(&dev->stats_lock);
> > +    }
> > +
> >      *c = nb_rx;
> >
> >      return 0;
> > @@ -1689,13 +1748,13 @@ netdev_dpdk_vhost_get_stats(const struct
> netdev *netdev,
> >      stats->tx_fifo_errors = UINT64_MAX;
> >      stats->tx_heartbeat_errors = UINT64_MAX;
> >      stats->tx_window_errors = UINT64_MAX;
> > -    stats->rx_dropped += UINT64_MAX;
> >
> >      rte_spinlock_lock(&dev->stats_lock);
> >      /* Supported Stats */
> >      stats->rx_packets += dev->stats.rx_packets;
> >      stats->tx_packets += dev->stats.tx_packets;
> >      stats->tx_dropped += dev->stats.tx_dropped;
> > +    stats->rx_dropped = dev->stats.rx_dropped;
> >      stats->multicast = dev->stats.multicast;
> >      stats->rx_bytes = dev->stats.rx_bytes;
> >      stats->tx_bytes = dev->stats.tx_bytes; @@ -1736,7 +1795,7 @@
> > netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats
> > *stats)
> >
> >      /* These are the available DPDK counters for packets not received
> due to
> >       * local resource constraints in DPDK and NIC respectively. */
> > -    stats->rx_dropped = rte_stats.rx_nombuf + rte_stats.imissed;
> > +    stats->rx_dropped += rte_stats.rx_nombuf + rte_stats.imissed;
> >      stats->collisions = UINT64_MAX;
> >
> >      stats->rx_length_errors = UINT64_MAX; @@ -1804,6 +1863,104 @@
> > netdev_dpdk_get_features(const struct netdev *netdev,  }
> >
> >  static int
> > +netdev_dpdk_policer_construct__(struct netdev *netdev_, uint32_t
> rate,
> > +                                uint32_t burst) {
> > +    struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
> > +    struct ingress_policer *policer;
> > +    uint64_t rate_bytes;
> > +    uint64_t burst_bytes;
> > +    int err = 0;
> > +
> > +    policer = xmalloc(sizeof *policer);
> > +    rte_spinlock_init(&policer->policer_lock);
> > +
> > +    /* rte_meter requires bytes so convert kbits rate and burst to
> bytes. */
> > +    rate_bytes = rate * 125;
> > +    burst_bytes = burst * 125;
> 
> Nit suggestion: I'd use * 1000/8 instead to make it clearer, the
> compiler optimizes that back to 125.

No problem. Will be in the v2.

> 
> > +
> > +    policer->app_srtcm_params.cir = rate_bytes;
> > +    policer->app_srtcm_params.cbs = burst_bytes;
> > +    policer->app_srtcm_params.ebs = 0;
> > +    err = rte_meter_srtcm_config(&policer->in_policer,
> > +                                    &policer->app_srtcm_params);
> > +    ovsrcu_set(&netdev->ingress_policer, policer);
> > +
> > +    return err;
> > +}
> > +
> > +static int netdev_dpdk_policer_destruct__(struct ingress_policer *
> > +policer) {
> > +    if (policer == NULL) {
> > +        return 0;
> > +    }
> > +    else {
> > +        free(policer);
> > +    }
> > +    return 0;
> > +}
> > +
> > +static int
> > +netdev_dpdk_set_policing(struct netdev* netdev_, uint32_t
> policer_rate,
> > +                            uint32_t policer_burst) {
> > +    struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
> > +    struct ingress_policer *policer;
> > +    int err = 0;
> > +
> > +    /* Force to 0 if no rate specified,
> > +     * default to 1000 kbits if burst is 0,
> > +     * else stick with user-specified value.
> > +     */
> > +    policer_burst = (!policer_rate ? 0
> > +                    : !policer_burst ? 1000
> 
> Please note, that in this patch here I'm considering to raise the burst
> to 8000 kbits instead, (since the TC linux-dev version was setting that
> before because of the *8 bug).
> 
> https://patchwork.ozlabs.org/patch/610408/
> 

OK, I'll make the same change for the v2.

> > +                    : policer_burst);
> > +
> > +    ovs_mutex_lock(&netdev->mutex);
> > +
> > +    policer = ovsrcu_get_protected(struct ingress_policer *,
> > +                                    &netdev->ingress_policer);
> > +
> > +    if (netdev->policer_rate == policer_rate &&
> > +    netdev->policer_burst == policer_burst) {
> > +        /* Assume that settings haven't changed since we last set
> them. */
> > +        ovs_mutex_unlock(&netdev->mutex);
> > +        return err;
> > +    }
> > +
> > +    /* Destroy any existing ingress policer for the device if one
> exists
> > +     * and the policer_rate and policer_burst are being set to 0
> > +     */
> > +    if ((policer != NULL) && (policer_rate == 0) && (policer_burst ==
> 0)) {
> > +        /* User has set rate and burst to 0, destroy the policer */
> > +        ovsrcu_postpone(netdev_dpdk_policer_destruct__, policer);
> > +        ovsrcu_set(&netdev->ingress_policer, NULL);
> > +        netdev->policer_rate = 0;
> > +        netdev->policer_burst = 0;
> > +        ovs_mutex_unlock(&netdev->mutex);
> > +        return err;
> > +    }
> > +
> > +    /* Destroy existing policer before adding new policer */
> > +    if (policer != NULL) {
> > +        ovsrcu_postpone(netdev_dpdk_policer_destruct__, policer);
> > +        ovsrcu_set(&netdev->ingress_policer, NULL);
> > +        netdev->policer_rate = 0;
> > +        netdev->policer_burst = 0;
> > +    }
> > +
> > +    /* Add an ingress policer */
> > +    err = netdev_dpdk_policer_construct__(netdev_, policer_rate,
> > +                                            policer_burst);
> > +
> > +    /* Update policer_rate and policer_burst for the netdev */
> > +    netdev->policer_rate = policer_rate;
> > +    netdev->policer_burst = policer_burst;
> > +    ovs_mutex_unlock(&netdev->mutex);
> > +    return err;
> > +}
> > +
> > +static int
> >  netdev_dpdk_get_ifindex(const struct netdev *netdev)  {
> >      struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); @@ -2250,6
> > +2407,12 @@ netdev_dpdk_get_virtio(const struct netdev_dpdk *dev)
> >      return ovsrcu_get(struct virtio_net *, &dev->virtio_dev);  }
> >
> > +struct ingress_policer *
> > +netdev_dpdk_get_ingress_policer(const struct netdev_dpdk *dev) {
> > +    return ovsrcu_get(struct ingress_policer *,
> > +&dev->ingress_policer); }
> > +
> >  /*
> >   * These callbacks allow virtio-net devices to be added to vhost
> ports when
> >   * configuration has been fully complete.
> > @@ -2703,7 +2866,7 @@ static const struct dpdk_qos_ops
> egress_policer_ops = {
> >      GET_FEATURES,                                             \
> >      NULL,                       /* set_advertisements */      \
> >                                                                \
> > -    NULL,                       /* set_policing */            \
> > +    netdev_dpdk_set_policing,   /* set_policing */            \
> >      netdev_dpdk_get_qos_types,                                \
> >      NULL,                       /* get_qos_capabilities */    \
> >      netdev_dpdk_get_qos,                                      \
> > diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index
> > 7d6976f..a7d2391 100644
> > --- a/vswitchd/vswitch.xml
> > +++ b/vswitchd/vswitch.xml
> > @@ -2388,8 +2388,8 @@
> >          table="Queue"/> tables).
> >        </p>
> >        <p>
> > -        Policing is currently implemented only on Linux.  The Linux
> > -        implementation uses a simple ``token bucket'' approach:
> > +        Policing is currently implemented on Linux and OVS with DPDK.
> Both
> > +        implementations use a simple ``token bucket'' approach:
> >        </p>
> >        <ul>
> >          <li>
> > --
> > 1.7.4.1
> >
> > _______________________________________________
> > dev mailing list
> > dev@openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to