ofproto-dpif: Store patch port peer in struct ofport_dpif.
authorEthan Jackson <ethan@nicira.com>
Mon, 17 Jun 2013 21:04:36 +0000 (14:04 -0700)
committerEthan Jackson <ethan@nicira.com>
Tue, 18 Jun 2013 20:14:18 +0000 (13:14 -0700)
This removes ofproto-dpif-xlate's dependency on ofport_get_peer()
which, while cleaner in-and-of itself, will become more important
as ofproto-dpif_xlate modularizes.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/netdev-vport.c
ofproto/ofproto-dpif-xlate.c
ofproto/ofproto-dpif.c
ofproto/ofproto-dpif.h

index bdb0c4d..885bf5e 100644 (file)
@@ -607,7 +607,7 @@ set_patch_config(struct netdev *dev_, const struct smap *args)
 
     free(dev->peer);
     dev->peer = xstrdup(peer);
-
+    netdev_vport_poll_notify(dev);
     return 0;
 }
 
index f5877a4..1c234ec 100644 (file)
@@ -855,16 +855,11 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
         return;
     }
 
-    if (netdev_vport_is_patch(ofport->up.netdev)) {
-        struct ofport_dpif *peer = ofport_get_peer(ofport);
+    if (ofport->peer) {
+        struct ofport_dpif *peer = ofport->peer;
         struct flow old_flow = ctx->xin->flow;
         enum slow_path_reason special;
 
-        if (!peer) {
-            xlate_report(ctx, "Nonexistent patch port peer");
-            return;
-        }
-
         ctx->ofproto = ofproto_dpif_cast(peer->up.ofproto);
         flow->in_port = peer->up.ofp_port;
         flow->metadata = htonll(0);
@@ -944,17 +939,21 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
         }
         flow->skb_mark &= ~IPSEC_MARK;
     }
-    commit_odp_actions(flow, &ctx->base_flow, &ctx->xout->odp_actions);
-    nl_msg_put_u32(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT, out_port);
 
-    ctx->sflow_odp_port = odp_port;
-    ctx->sflow_n_outputs++;
-    ctx->xout->nf_output_iface = ofp_port;
+    if (out_port != OVSP_NONE) {
+        commit_odp_actions(flow, &ctx->base_flow, &ctx->xout->odp_actions);
+        nl_msg_put_u32(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT,
+                       out_port);
+
+        ctx->sflow_odp_port = odp_port;
+        ctx->sflow_n_outputs++;
+        ctx->xout->nf_output_iface = ofp_port;
+    }
 
+ out:
     /* Restore flow */
     flow->vlan_tci = flow_vlan_tci;
     flow->skb_mark = flow_skb_mark;
- out:
     flow->nw_tos = flow_nw_tos;
 }
 
index 5b4def0..1b3b1e3 100644 (file)
@@ -301,6 +301,7 @@ static void port_wait(struct ofport_dpif *);
 static int set_bfd(struct ofport *, const struct smap *);
 static int set_cfm(struct ofport *, const struct cfm_settings *);
 static void ofport_clear_priorities(struct ofport_dpif *);
+static void ofport_update_peer(struct ofport_dpif *);
 static void run_fast_rl(void);
 
 struct dpif_completion {
@@ -1455,6 +1456,7 @@ port_construct(struct ofport *port_)
     port->stp_port = NULL;
     port->stp_state = STP_DISABLED;
     port->tnl_port = NULL;
+    port->peer = NULL;
     hmap_init(&port->priorities);
     port->realdev_ofp_port = 0;
     port->vlandev_vid = 0;
@@ -1467,6 +1469,7 @@ port_construct(struct ofport *port_)
         * to be "internal" to the switch as a whole, and therefore not an
         * candidate for counter polling. */
         port->odp_port = OVSP_NONE;
+        ofport_update_peer(port);
         return 0;
     }
 
@@ -1526,6 +1529,11 @@ port_destruct(struct ofport *port_)
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
 
+    if (port->peer) {
+        port->peer->peer = NULL;
+        port->peer = NULL;
+    }
+
     if (port->odp_port != OVSP_NONE && !port->tnl_port) {
         hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node);
     }
@@ -1562,6 +1570,8 @@ port_modified(struct ofport *port_)
                                                &port->tnl_port)) {
         ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate = true;
     }
+
+    ofport_update_peer(port);
 }
 
 static void
@@ -2833,32 +2843,54 @@ ofproto_port_from_dpif_port(struct ofproto_dpif *ofproto,
     ofproto_port->ofp_port = odp_port_to_ofp_port(ofproto, dpif_port->port_no);
 }
 
-struct ofport_dpif *
-ofport_get_peer(const struct ofport_dpif *ofport_dpif)
+static void
+ofport_update_peer(struct ofport_dpif *ofport)
 {
     const struct ofproto_dpif *ofproto;
-    const struct dpif_backer *backer;
-    const char *peer;
+    struct dpif_backer *backer;
+    const char *peer_name;
 
-    peer = netdev_vport_patch_peer(ofport_dpif->up.netdev);
-    if (!peer) {
-        return NULL;
+    if (!netdev_vport_is_patch(ofport->up.netdev)) {
+        return;
+    }
+
+    backer = ofproto_dpif_cast(ofport->up.ofproto)->backer;
+    backer->need_revalidate = true;
+
+    if (ofport->peer) {
+        ofport->peer->peer = NULL;
+        ofport->peer = NULL;
+    }
+
+    peer_name = netdev_vport_patch_peer(ofport->up.netdev);
+    if (!peer_name) {
+        return;
     }
 
-    backer = ofproto_dpif_cast(ofport_dpif->up.ofproto)->backer;
     HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
-        struct ofport *ofport;
+        struct ofport *peer_ofport;
+        struct ofport_dpif *peer;
+        const char *peer_peer;
 
         if (ofproto->backer != backer) {
             continue;
         }
 
-        ofport = shash_find_data(&ofproto->up.port_by_name, peer);
-        if (ofport) {
-            return ofport_dpif_cast(ofport);
+        peer_ofport = shash_find_data(&ofproto->up.port_by_name, peer_name);
+        if (!peer_ofport) {
+            continue;
         }
+
+        peer = ofport_dpif_cast(peer_ofport);
+        peer_peer = netdev_vport_patch_peer(peer->up.netdev);
+        if (peer_peer && !strcmp(netdev_get_name(ofport->up.netdev),
+                                 peer_peer)) {
+            ofport->peer = peer;
+            ofport->peer->peer = ofport;
+        }
+
+        return;
     }
-    return NULL;
 }
 
 static void
index 3852fa8..12a9d7e 100644 (file)
@@ -136,6 +136,7 @@ struct ofport_dpif {
     bool may_enable;            /* May be enabled in bonds. */
     long long int carrier_seq;  /* Carrier status changes. */
     struct tnl_port *tnl_port;  /* Tunnel handle, or null. */
+    struct ofport_dpif *peer;   /* Peer if patch port. */
 
     /* Spanning tree. */
     struct stp_port *stp_port;  /* Spanning Tree Protocol, if any. */
@@ -232,8 +233,6 @@ struct ofport_dpif *get_ofp_port(const struct ofproto_dpif *,
 struct ofport_dpif *get_odp_port(const struct ofproto_dpif *,
                                         uint32_t odp_port);
 
-struct ofport_dpif *ofport_get_peer(const struct ofport_dpif *);
-
 uint32_t ofp_port_to_odp_port(const struct ofproto_dpif *, uint16_t ofp_port);
 
 struct rule_dpif *rule_dpif_lookup_in_table(struct ofproto_dpif *,