[ovs-dev] [PATCH v2] dpif-netdev: Introduce a classifier in userspace datapath.

Ben Pfaff blp at nicira.com
Wed Nov 13 18:20:53 UTC 2013


On Wed, Nov 13, 2013 at 08:32:32AM -0800, Gurucharan Shetty wrote:
> On Tue, Nov 12, 2013 at 3:59 PM, Ben Pfaff <blp at nicira.com> wrote:
> > On Mon, Nov 04, 2013 at 06:23:54AM -0800, Gurucharan Shetty wrote:
> >> Instead of an exact match flow table, we introduce a classifier.
> >> This enables mega-flows in userspace datapath.
> >>
> >> Signed-off-by: Gurucharan Shetty <gshetty at nicira.com>
> >
> > dp_netdev_lookup_flow() now makes less sense to me than before.  Can
> > the HMAP_FOR_EACH_WITH_HASH loop in there ever fail to find the
> > 'dp_netdev_flow' that contains 'cr'?
> >
> > In other words, can we equivalently fold in this?
> Yes. That will work.
> >
> > diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> > index bd6da5e..b7acbbb 100644
> > --- a/lib/dpif-netdev.c
> > +++ b/lib/dpif-netdev.c
> > @@ -749,23 +749,15 @@ dpif_netdev_port_poll_wait(const struct dpif *dpif_)
> >  static struct dp_netdev_flow *
> >  dp_netdev_lookup_flow(const struct dp_netdev *dp, const struct flow *flow)
> >  {
> > -    struct dp_netdev_flow *netdev_flow;
> >      struct cls_rule *cr;
> >
> >      ovs_rwlock_wrlock(&dp->cls.rwlock);
> >      cr = classifier_lookup(&dp->cls, flow, NULL);
> >      ovs_rwlock_unlock(&dp->cls.rwlock);
> > -    if (!cr) {
> > -        return NULL;
> > -    }
> >
> > -    HMAP_FOR_EACH_WITH_HASH (netdev_flow, node, cls_rule_hash(cr, 0),
> > -                             &dp->flow_table) {
> > -        if (cls_rule_equal(&netdev_flow->cr, cr)) {
> > -            return netdev_flow;
> > -        }
> > -    }
> > -    return NULL;
> > +    return (cr
> > +            ? CONTAINER_OF(cr, struct dp_netdev_flow, cr)
> > +            : NULL);
> >  }
> >
> >  static void
> >
> >
> > Once we do that, it makes me see that hashing based on the classifier
> > rule is kind of odd.  We don't do any lookups based on that hmap, we
> > only use it for iteration.  But the "get" and "del" operations could
> > usefully use that hmap for lookups, if the hmap actually contained the
> > flows instead of the cls_rules, if we fold in the following:
> >
> > diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> > index b7acbbb..3007d9f 100644
> > --- a/lib/dpif-netdev.c
> > +++ b/lib/dpif-netdev.c
> > @@ -123,10 +123,13 @@ struct dp_netdev_port {
> >
> >  /* A flow in dp_netdev's 'flow_table'. */
> >  struct dp_netdev_flow {
> > -    struct hmap_node node;      /* Element in dp_netdev's 'flow_table'. */
> > +    /* Packet classification. */
> > +    struct cls_rule cr;         /* In owning dp_netdev's 'cls'. */
> > +
> > +    /* Hash table index by unmasked flow.*/
> > +    struct hmap_node node;      /* In owning dp_netdev's 'flow_table'. */
> >      struct flow flow;           /* The flow that created this entry. */
> > -    struct cls_rule cr;         /* The rule created for the 'flow' and inserted
> > -                                   into dp_netdev's classifier. */
> > +
> >      /* Statistics. */
> >      long long int used;         /* Last used time, in monotonic msecs. */
> >      long long int packet_count; /* Number of packets matched. */
> > @@ -760,6 +763,20 @@ dp_netdev_lookup_flow(const struct dp_netdev *dp, const struct flow *flow)
> >              : NULL);
> >  }
> >
> > +static struct dp_netdev_flow *
> > +dp_netdev_find_flow(const struct dp_netdev *dp, const struct flow *flow)
> > +{
> > +    struct dp_netdev_flow *netdev_flow;
> > +
> > +    HMAP_FOR_EACH_WITH_HASH (netdev_flow, node, flow_hash(flow, 0),
> > +                             &dp->flow_table) {
> > +        if (flow_equal(&netdev_flow->flow, flow)) {
> > +            return netdev_flow;
> > +        }
> > +    }
> > +    return NULL;
> > +}
> > +
> >  static void
> >  get_dpif_flow_stats(struct dp_netdev_flow *netdev_flow,
> >                      struct dpif_flow_stats *stats)
> > @@ -838,8 +855,8 @@ dpif_netdev_flow_get(const struct dpif *dpif,
> >      }
> >
> >      ovs_mutex_lock(&dp_netdev_mutex);
> > -    netdev_flow = dp_netdev_lookup_flow(dp, &key);
> > -    if (netdev_flow && flow_equal(&key, &netdev_flow->flow)) {
> > +    netdev_flow = dp_netdev_find_flow(dp, &key);
> > +    if (netdev_flow) {
> >          if (stats) {
> >              get_dpif_flow_stats(netdev_flow, stats);
> >          }
> > @@ -895,8 +912,7 @@ dp_netdev_flow_add(struct dp_netdev *dp, const struct flow *flow,
> >          return error;
> >      }
> >
> > -    hmap_insert(&dp->flow_table, &netdev_flow->node,
> > -                cls_rule_hash(&netdev_flow->cr, 0));
> > +    hmap_insert(&dp->flow_table, &netdev_flow->node, flow_hash(flow, 0));
> >      return 0;
> >  }
> >
> > @@ -979,8 +995,8 @@ dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
> >      }
> >
> >      ovs_mutex_lock(&dp_netdev_mutex);
> > -    netdev_flow = dp_netdev_lookup_flow(dp, &key);
> > -    if (netdev_flow && flow_equal(&key, &netdev_flow->flow)) {
> > +    netdev_flow = dp_netdev_find_flow(dp, &key);
> > +    if (netdev_flow) {
> >          if (del->stats) {
> >              get_dpif_flow_stats(netdev_flow, del->stats);
> >          }
> >
> > What do you think?
> This looks fine to me as well (tests pass). If you find everything
> else alright, can you please fold this in and apply?

Done.



More information about the dev mailing list