datapath: Enable usage of cached flows.
authorJesse Gross <jesse@nicira.com>
Sun, 29 Aug 2010 17:49:11 +0000 (10:49 -0700)
committerJesse Gross <jesse@nicira.com>
Wed, 22 Sep 2010 20:43:01 +0000 (13:43 -0700)
An upcoming commit will add support for supplying cached flows for
packets entering the datapath.  This adds the code in the datapath
itself to recognize these cached flows and use them instead of
extracting the flow fields and doing a lookup.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Reviewed-by: Ben Pfaff <blp@nicira.com>
datapath/datapath.c
datapath/datapath.h
datapath/vport-internal_dev.c
datapath/vport.c
datapath/vport.h

index 06e1006a88c3a668be2ddfad7a47944ac8cd6d4c..390acc8a4e5f8a029fbf207b58c6eb45593aab3a 100644 (file)
@@ -543,40 +543,44 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
        struct datapath *dp = p->dp;
        struct dp_stats_percpu *stats;
        int stats_counter_off;
-       struct odp_flow_key key;
-       struct tbl_node *flow_node;
-       struct sw_flow *flow;
        struct sw_flow_actions *acts;
        struct loop_counter *loop;
        int error;
 
        OVS_CB(skb)->dp_port = p;
 
-       /* Extract flow from 'skb' into 'key'. */
-       error = flow_extract(skb, p ? p->port_no : ODPP_NONE, &key);
-       if (unlikely(error)) {
-               kfree_skb(skb);
-               return;
-       }
+       if (!OVS_CB(skb)->flow) {
+               struct odp_flow_key key;
+               struct tbl_node *flow_node;
 
-       if (OVS_CB(skb)->is_frag && dp->drop_frags) {
-               kfree_skb(skb);
-               stats_counter_off = offsetof(struct dp_stats_percpu, n_frags);
-               goto out;
-       }
+               /* Extract flow from 'skb' into 'key'. */
+               error = flow_extract(skb, p ? p->port_no : ODPP_NONE, &key);
+               if (unlikely(error)) {
+                       kfree_skb(skb);
+                       return;
+               }
 
-       /* Look up flow. */
-       flow_node = tbl_lookup(rcu_dereference(dp->table), &key, flow_hash(&key), flow_cmp);
-       if (unlikely(!flow_node)) {
-               dp_output_control(dp, skb, _ODPL_MISS_NR, OVS_CB(skb)->tun_id);
-               stats_counter_off = offsetof(struct dp_stats_percpu, n_missed);
-               goto out;
+               if (OVS_CB(skb)->is_frag && dp->drop_frags) {
+                       kfree_skb(skb);
+                       stats_counter_off = offsetof(struct dp_stats_percpu, n_frags);
+                       goto out;
+               }
+
+               /* Look up flow. */
+               flow_node = tbl_lookup(rcu_dereference(dp->table), &key,
+                                       flow_hash(&key), flow_cmp);
+               if (unlikely(!flow_node)) {
+                       dp_output_control(dp, skb, _ODPL_MISS_NR, OVS_CB(skb)->tun_id);
+                       stats_counter_off = offsetof(struct dp_stats_percpu, n_missed);
+                       goto out;
+               }
+
+               OVS_CB(skb)->flow = flow_cast(flow_node);
        }
 
-       flow = flow_cast(flow_node);
-       flow_used(flow, skb);
+       flow_used(OVS_CB(skb)->flow, skb);
 
-       acts = rcu_dereference(flow->sf_acts);
+       acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
 
        /* Check whether we've looped too much. */
        loop = &get_cpu_var(dp_loop_counters).counters[!!in_interrupt()];
@@ -588,7 +592,8 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
        }
 
        /* Execute actions. */
-       execute_actions(dp, skb, &key, acts->actions, acts->n_actions, GFP_ATOMIC);
+       execute_actions(dp, skb, &OVS_CB(skb)->flow->key, acts->actions,
+                       acts->n_actions, GFP_ATOMIC);
        stats_counter_off = offsetof(struct dp_stats_percpu, n_hit);
 
        /* Check whether sub-actions looped too much. */
index abc6aeab2af415a77811eef5f39df955711d915f..dacc3a42c301c1c11d90d395f729c5006254f8fb 100644 (file)
@@ -146,17 +146,19 @@ enum csum_type {
 /**
  * struct ovs_skb_cb - OVS data in skb CB
  * @dp_port: The datapath port on which the skb entered the switch.
+ * @flow: The flow associated with this packet.  May be %NULL if no flow.
+ * @is_frag: %true if this packet is an IPv4 fragment, %false otherwise.
  * @ip_summed: Consistently stores L4 checksumming status across different
  * kernel versions.
  * @tun_id: ID (in network byte order) of the tunnel that encapsulated this
  * packet. It is 0 if the packet was not received on a tunnel.
- * @is_frag: %true if this packet is an IPv4 fragment, %false otherwise.
  */
 struct ovs_skb_cb {
        struct dp_port          *dp_port;
+       struct sw_flow          *flow;
+       bool                    is_frag;
        enum csum_type          ip_summed;
        __be32                  tun_id;
-       bool                    is_frag;
 };
 #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
 
index 6cbfdf80db3bc1172268f5f3032db023a98cd199..514d00cb3b9d488614103eac7386e4ca27bffe0a 100644 (file)
@@ -82,6 +82,7 @@ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
 
        skb_reset_mac_header(skb);
        compute_ip_summed(skb, true);
+       OVS_CB(skb)->flow = NULL;
 
        vport_receive(vport, skb);
 
@@ -293,7 +294,7 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb)
 
 struct vport_ops internal_vport_ops = {
        .type           = "internal",
-       .flags          = VPORT_F_REQUIRED | VPORT_F_GEN_STATS,
+       .flags          = VPORT_F_REQUIRED | VPORT_F_GEN_STATS | VPORT_F_FLOW,
        .create         = internal_dev_create,
        .destroy        = internal_dev_destroy,
        .attach         = internal_dev_attach,
index 91b650e54695f751b26dcec98e526b8282eb2159..6c8eb0845aec6dff26031cbabb1b329afa6789d1 100644 (file)
@@ -1217,6 +1217,9 @@ void vport_receive(struct vport *vport, struct sk_buff *skb)
                local_bh_enable();
        }
 
+       if (!(vport->ops->flags & VPORT_F_FLOW))
+               OVS_CB(skb)->flow = NULL;
+
        if (!(vport->ops->flags & VPORT_F_TUN_ID))
                OVS_CB(skb)->tun_id = 0;
 
index fca5f1abe940aed730aec6b205c42c4dd6780039..30b0cc6b36e6972386d7347d5f0efd96996d9102 100644 (file)
@@ -112,7 +112,8 @@ struct vport {
 
 #define VPORT_F_REQUIRED       (1 << 0) /* If init fails, module loading fails. */
 #define VPORT_F_GEN_STATS      (1 << 1) /* Track stats at the generic layer. */
-#define VPORT_F_TUN_ID         (1 << 2) /* Sets OVS_CB(skb)->tun_id. */
+#define VPORT_F_FLOW           (1 << 2) /* Sets OVS_CB(skb)->flow. */
+#define VPORT_F_TUN_ID         (1 << 3) /* Sets OVS_CB(skb)->tun_id. */
 
 /**
  * struct vport_ops - definition of a type of virtual port