[ovs-dev] [PATCH 1/6] ofproto-dpif: New function ofproto_receive().

Ethan Jackson ethan at nicira.com
Thu Dec 27 01:16:41 UTC 2012


Before translating a datapath flow key into actions, ofproto-dpif
must parse it, tweak it, and figure out what ofproto_dpif it
belongs to.  This patch brings all this logic into one place where
it will be easier to extend in the future.

Signed-off-by: Ethan Jackson <ethan at nicira.com>
---
 ofproto/ofproto-dpif.c |  128 +++++++++++++++++++++++-------------------------
 1 file changed, 61 insertions(+), 67 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d5155cf..58ba575 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3393,32 +3393,62 @@ handle_flow_miss(struct flow_miss *miss, struct flow_miss_op *ops,
     handle_flow_miss_with_facet(miss, facet, now, ops, n_ops);
 }
 
-/* This function does post-processing on data returned from
- * odp_flow_key_to_flow() to help make VLAN splinters transparent to the
- * rest of the upcall processing logic.  In particular, if the extracted
- * in_port is a VLAN splinter port, it replaces flow->in_port by the "real"
- * port, sets flow->vlan_tci correctly for the VLAN of the VLAN splinter
- * port, and pushes a VLAN header onto 'packet' (if it is nonnull). The
- * caller must have called odp_flow_key_to_flow() and supply 'fitness' and
- * 'flow' from its output.  The 'flow' argument must have had the "in_port"
- * member converted to the OpenFlow number.
+/* Given a datpath, packet, and flow metadata ('backer', 'packet', and 'key'
+ * respectively), populates 'flow' with the result of odp_flow_key_to_flow().
+ * Optionally, if nonnull, populates 'ofproto' with the ofproto_dpif, and
+ * 'odp_in_port' with the datapath in_port, that 'packet' ingressed.
  *
- * Sets '*initial_tci' to the VLAN TCI with which the packet was really
- * received, that is, the actual VLAN TCI extracted by odp_flow_key_to_flow().
- * (This differs from the value returned in flow->vlan_tci only for packets
- * received on VLAN splinters.) */
+ * If 'ofproto' is nonnull, requires 'flow''s in_port to exist.  Otherwise sets
+ * 'flow''s in_port to OFPP_NONE.
+ *
+ * This function does post-processing on data returned from
+ * odp_flow_key_to_flow() to help make VLAN splinters transparent to the rest
+ * of the upcall processing logic.  In particular, if the extracted in_port is
+ * a VLAN splinter port, it replaces flow->in_port by the "real" port, sets
+ * flow->vlan_tci correctly for the VLAN of the VLAN splinter port, and pushes
+ * a VLAN header onto 'packet' (if it is nonnull).
+ *
+ * Optionally, if nonnull, sets '*initial_tci' to the VLAN TCI with which the
+ * packet was really received, that is, the actual VLAN TCI extracted by
+ * odp_flow_key_to_flow().  (This differs from the value returned in
+ * flow->vlan_tci only for packets received on VLAN splinters.) */
 static enum odp_key_fitness
-ofproto_dpif_vsp_adjust(const struct ofproto_dpif *ofproto,
-                        enum odp_key_fitness fitness,
-                        struct flow *flow, ovs_be16 *initial_tci,
-                        struct ofpbuf *packet)
+ofproto_receive(const struct dpif_backer *backer, struct ofpbuf *packet,
+                const struct nlattr *key, size_t key_len,
+                struct flow *flow, struct ofproto_dpif **ofproto,
+                uint32_t *odp_in_port, ovs_be16 *initial_tci)
+
 {
+    const struct ofport_dpif *port;
+    enum odp_key_fitness fitness;
+
+    fitness = odp_flow_key_to_flow(key, key_len, flow);
     if (fitness == ODP_FIT_ERROR) {
         return fitness;
     }
-    *initial_tci = flow->vlan_tci;
 
-    if (vsp_adjust_flow(ofproto, flow)) {
+    if (initial_tci) {
+        *initial_tci = flow->vlan_tci;
+    }
+
+    if (odp_in_port) {
+        *odp_in_port = flow->in_port;
+    }
+
+    port = odp_port_to_ofport(backer, flow->in_port);
+    if (!port) {
+        VLOG_INFO_RL(&rl, "received packet on an unassociated port %"PRIu32,
+                     flow->in_port);
+        flow->in_port = OFPP_NONE;
+        return ofproto ? ODP_FIT_ERROR : fitness;
+    }
+
+    if (ofproto) {
+        *ofproto = ofproto_dpif_cast(port->up.ofproto);
+    }
+
+    flow->in_port = (port)->up.ofp_port;
+    if (vsp_adjust_flow(ofproto_dpif_cast(port->up.ofproto), flow)) {
         if (packet) {
             /* Make the packet resemble the flow, so that it gets sent to an
              * OpenFlow controller properly, so that it looks correct for
@@ -3474,32 +3504,15 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
     for (upcall = upcalls; upcall < &upcalls[n_upcalls]; upcall++) {
         struct flow_miss *miss = &misses[n_misses];
         struct flow_miss *existing_miss;
-        enum odp_key_fitness fitness;
         struct ofproto_dpif *ofproto;
-        struct ofport_dpif *port;
         uint32_t odp_in_port;
         struct flow flow;
         uint32_t hash;
 
-        fitness = odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
-        port = odp_port_to_ofport(backer, flow.in_port);
-        if (!port) {
-            /* Received packet on port for which we couldn't associate
-             * an ofproto.  This can happen if a port is removed while
-             * traffic is being received.  Print a rate-limited message
-             * in case it happens frequently. */
-            VLOG_INFO_RL(&rl, "received packet on unassociated port %"PRIu32,
-                         flow.in_port);
-            continue;
-        }
-        ofproto = ofproto_dpif_cast(port->up.ofproto);
-        odp_in_port = flow.in_port;
-        flow.in_port = port->up.ofp_port;
-
-        /* Obtain metadata and check userspace/kernel agreement on flow match,
-         * then set 'flow''s header pointers. */
-        miss->key_fitness = ofproto_dpif_vsp_adjust(ofproto, fitness,
-                                &flow, &miss->initial_tci, upcall->packet);
+        miss->key_fitness = ofproto_receive(backer, upcall->packet,
+                                            upcall->key, upcall->key_len,
+                                            &flow, &ofproto, &odp_in_port,
+                                            &miss->initial_tci);
         if (miss->key_fitness == ODP_FIT_ERROR) {
             continue;
         }
@@ -3604,28 +3617,13 @@ handle_sflow_upcall(struct dpif_backer *backer,
     struct ofproto_dpif *ofproto;
     union user_action_cookie cookie;
     enum odp_key_fitness fitness;
-    struct ofport_dpif *port;
-    ovs_be16 initial_tci;
     struct flow flow;
     uint32_t odp_in_port;
 
-    fitness = odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
-
-    port = odp_port_to_ofport(backer, flow.in_port);
-    if (!port) {
-        return;
-    }
-
-    ofproto = ofproto_dpif_cast(port->up.ofproto);
-    if (!ofproto->sflow) {
-        return;
-    }
-
-    odp_in_port = flow.in_port;
-    flow.in_port = port->up.ofp_port;
-    fitness = ofproto_dpif_vsp_adjust(ofproto, fitness, &flow,
-                                      &initial_tci, upcall->packet);
-    if (fitness == ODP_FIT_ERROR) {
+    fitness = ofproto_receive(backer, upcall->packet, upcall->key,
+                              upcall->key_len, &flow, &ofproto, &odp_in_port,
+                              NULL);
+    if (fitness == ODP_FIT_ERROR || !ofproto->sflow) {
         return;
     }
 
@@ -7193,13 +7191,10 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
                 goto exit;
             }
 
-            fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
-            flow.in_port = odp_port_to_ofp_port(ofproto, flow.in_port);
-
-            /* Convert odp_key to flow. */
-            error = ofproto_dpif_vsp_adjust(ofproto, fitness, &flow,
-                                            &initial_tci, NULL);
-            if (error == ODP_FIT_ERROR) {
+            fitness = ofproto_receive(ofproto->backer, NULL, odp_key.data,
+                                      odp_key.size, &flow, NULL, NULL,
+                                      &initial_tci);
+            if (fitness == ODP_FIT_ERROR) {
                 unixctl_command_reply_error(conn, "Invalid flow");
                 goto exit;
             }
@@ -7214,7 +7209,6 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
             }
 
             initial_tci = flow.vlan_tci;
-            vsp_adjust_flow(ofproto, &flow);
         }
 
         /* Generate a packet, if requested. */
-- 
1.7.9.5




More information about the dev mailing list