On Tue, Nov 12, 2013 at 3:59 PM, Ben Pfaff <[email protected]> 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 <[email protected]>
>
> 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?
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev