[ovs-dev] [RFC PATCH v2 5/5] ofproto-dpif: Basic hooks for rewriting tunnel packets.

Jesse Gross jesse at nicira.com
Fri Sep 28 22:12:19 UTC 2012


This is a basic set of hooks into the ofproto-dpif code so that
tunneled packets can be have their flows rewritten to reflect the
outward facing view of how ports are laid out.  This is far from
being a comprehensive layer and should be replaced once a better
level of indirection is available.

Signed-off-by: Jesse Gross <jesse at nicira.com>
---
 ofproto/ofproto-dpif.c |   40 ++++++++++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index ff6df41..6fbe406 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -50,6 +50,7 @@
 #include "poll-loop.h"
 #include "simap.h"
 #include "timer.h"
+#include "tunnel.h"
 #include "unaligned.h"
 #include "unixctl.h"
 #include "vlan-bitmap.h"
@@ -803,6 +804,8 @@ construct(struct ofproto *ofproto_)
     hmap_init(&ofproto->vlandev_map);
     hmap_init(&ofproto->realdev_vid_map);
 
+    tnl_init();
+
     hmap_insert(&all_ofproto_dpifs, &ofproto->all_ofproto_dpifs_node,
                 hash_string(ofproto->up.name, 0));
     memset(&ofproto->stats, 0, sizeof ofproto->stats);
@@ -2536,6 +2539,11 @@ port_add(struct ofproto *ofproto_, struct netdev *netdev, uint16_t *ofp_portp)
 
     error = dpif_port_add(ofproto->dpif, netdev, &odp_port);
     if (!error) {
+        error = tnl_port_add(odp_port, odp_port, netdev);
+        if (error) {
+            dpif_port_del(ofproto->dpif, odp_port);
+            return error;
+        }
         *ofp_portp = odp_port_to_ofp_port(odp_port);
     }
     return error;
@@ -2545,9 +2553,12 @@ static int
 port_del(struct ofproto *ofproto_, uint16_t ofp_port)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+    uint16_t odp_port = ofp_port_to_odp_port(ofp_port);
     int error;
 
-    error = dpif_port_del(ofproto->dpif, ofp_port_to_odp_port(ofp_port));
+    tnl_port_del(odp_port);
+
+    error = dpif_port_del(ofproto->dpif, odp_port);
     if (!error) {
         struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port);
         if (ofport) {
@@ -3025,8 +3036,9 @@ handle_flow_miss(struct ofproto_dpif *ofproto, struct flow_miss *miss,
  * an ODP_FIT_* value that indicates how well 'key' fits our expectations for
  * what a flow key should contain.
  *
- * This function also includes some logic to help make VLAN splinters
- * transparent to the rest of the upcall processing logic.  In particular, if
+ * This function also includes some logic to help with ports that have special
+ * meaning to their flows such as tunnels and VLAN splinters.  Tunnels may
+ * map their source and destination addresses to a logical port whereas 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).
@@ -3043,13 +3055,21 @@ ofproto_dpif_extract_flow_key(const struct ofproto_dpif *ofproto,
                               struct ofpbuf *packet)
 {
     enum odp_key_fitness fitness;
+    bool adjusted;
+    int err;
 
     fitness = odp_flow_key_to_flow(key, key_len, flow);
     if (fitness == ODP_FIT_ERROR) {
         return fitness;
     }
-    *initial_tci = flow->vlan_tci;
 
+    err = tnl_port_receive(flow, &adjusted);
+    if (err) {
+        /* XXX: We should really install a drop flow here. */
+        return ODP_FIT_ERROR;
+    }
+
+    *initial_tci = flow->vlan_tci;
     if (vsp_adjust_flow(ofproto, flow)) {
         if (packet) {
             /* Make the packet resemble the flow, so that it gets sent to an
@@ -3069,10 +3089,12 @@ ofproto_dpif_extract_flow_key(const struct ofproto_dpif *ofproto,
             eth_push_vlan(packet, flow->vlan_tci);
         }
 
-        /* Let the caller know that we can't reproduce 'key' from 'flow'. */
-        if (fitness == ODP_FIT_PERFECT) {
-            fitness = ODP_FIT_TOO_MUCH;
-        }
+        adjusted = true;
+    }
+
+    /* Let the caller know that we can't reproduce 'key' from 'flow'. */
+    if (adjusted && fitness == ODP_FIT_PERFECT) {
+        fitness = ODP_FIT_TOO_MUCH;
     }
 
     return fitness;
@@ -4981,6 +5003,8 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
     if (out_port != odp_port) {
         ctx->flow.vlan_tci = htons(0);
     }
+    out_port = tnl_port_send(&ctx->flow, out_port);
+
     commit_odp_actions(&ctx->flow, &ctx->base_flow, ctx->odp_actions);
     nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT, out_port);
 
-- 
1.7.9.5




More information about the dev mailing list