ofproto-dpif-xlate: Do initial rule lookup for callers.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index b45a289..b8b15e3 100644 (file)
@@ -52,6 +52,7 @@
 #include "ofproto-dpif-governor.h"
 #include "ofproto-dpif-ipfix.h"
 #include "ofproto-dpif-mirror.h"
+#include "ofproto-dpif-monitor.h"
 #include "ofproto-dpif-sflow.h"
 #include "ofproto-dpif-upcall.h"
 #include "ofproto-dpif-xlate.h"
@@ -361,8 +362,6 @@ ofport_dpif_cast(const struct ofport *ofport)
 }
 
 static void port_run(struct ofport_dpif *);
-static void port_run_fast(struct ofport_dpif *);
-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_update_peer(struct ofport_dpif *);
@@ -470,8 +469,9 @@ struct ofproto_dpif {
     struct classifier facets;     /* Contains 'struct facet's. */
     long long int consistency_rl;
 
-    struct netdev_stats stats; /* To account packets generated and consumed in
-                                * userspace. */
+    struct ovs_mutex stats_mutex;
+    struct netdev_stats stats OVS_GUARDED; /* To account packets generated and
+                                            * consumed in userspace. */
 
     /* Spanning tree. */
     struct stp *stp;
@@ -1230,6 +1230,7 @@ construct(struct ofproto *ofproto_)
     ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME);
     ofproto->mbridge = mbridge_create();
     ofproto->has_bonded_bundles = false;
+    ovs_mutex_init(&ofproto->stats_mutex);
     ovs_mutex_init(&ofproto->vsp_mutex);
 
     classifier_init(&ofproto->facets);
@@ -1417,6 +1418,7 @@ destruct(struct ofproto *ofproto_)
     sset_destroy(&ofproto->ghost_ports);
     sset_destroy(&ofproto->port_poll_set);
 
+    ovs_mutex_destroy(&ofproto->stats_mutex);
     ovs_mutex_destroy(&ofproto->vsp_mutex);
 
     close_dpif_backer(ofproto->backer);
@@ -1427,7 +1429,6 @@ run_fast(struct ofproto *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct ofputil_packet_in *pin, *next_pin;
-    struct ofport_dpif *ofport;
     struct list pins;
 
     /* Do not perform any periodic activity required by 'ofproto' while
@@ -1444,10 +1445,7 @@ run_fast(struct ofproto *ofproto_)
         free(pin);
     }
 
-    HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
-        port_run_fast(ofport);
-    }
-
+    ofproto_dpif_monitor_run_fast();
     return 0;
 }
 
@@ -1489,6 +1487,9 @@ run(struct ofproto *ofproto_)
         dpif_ipfix_run(ofproto->ipfix);
     }
 
+    ofproto_dpif_monitor_run_fast();
+    ofproto_dpif_monitor_run();
+
     HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
         port_run(ofport);
     }
@@ -1533,7 +1534,6 @@ static void
 wait(struct ofproto *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
-    struct ofport_dpif *ofport;
     struct ofbundle *bundle;
 
     if (ofproto_get_flow_restore_wait()) {
@@ -1546,9 +1546,7 @@ wait(struct ofproto *ofproto_)
     if (ofproto->ipfix) {
         dpif_ipfix_wait(ofproto->ipfix);
     }
-    HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
-        port_wait(ofport);
-    }
+    ofproto_dpif_monitor_wait();
     HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) {
         bundle_wait(bundle);
     }
@@ -1811,6 +1809,9 @@ port_modified(struct ofport *port_)
         bfd_set_netdev(port->bfd, port->up.netdev);
     }
 
+    ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
+                                     port->up.pp.hw_addr);
+
     if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
                                                 port->odp_port)) {
         ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
@@ -1901,11 +1902,9 @@ static int
 set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
 {
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
-    int error;
+    int error = 0;
 
-    if (!s) {
-        error = 0;
-    } else {
+    if (s) {
         if (!ofport->cfm) {
             struct ofproto_dpif *ofproto;
 
@@ -1915,13 +1914,17 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
         }
 
         if (cfm_configure(ofport->cfm, s)) {
-            return 0;
+            error = 0;
+            goto out;
         }
 
         error = EINVAL;
     }
     cfm_unref(ofport->cfm);
     ofport->cfm = NULL;
+out:
+    ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
+                                     ofport->up.pp.hw_addr);
     return error;
 }
 
@@ -1955,7 +1958,8 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg)
     if (ofport->bfd != old) {
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
-
+    ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
+                                     ofport->up.pp.hw_addr);
     return 0;
 }
 
@@ -2840,28 +2844,6 @@ ofport_update_peer(struct ofport_dpif *ofport)
     free(peer_name);
 }
 
-static void
-port_run_fast(struct ofport_dpif *ofport)
-{
-    if (ofport->cfm && cfm_should_send_ccm(ofport->cfm)) {
-        struct ofpbuf packet;
-
-        ofpbuf_init(&packet, 0);
-        cfm_compose_ccm(ofport->cfm, &packet, ofport->up.pp.hw_addr);
-        ofproto_dpif_send_packet(ofport, &packet);
-        ofpbuf_uninit(&packet);
-    }
-
-    if (ofport->bfd && bfd_should_send_packet(ofport->bfd)) {
-        struct ofpbuf packet;
-
-        ofpbuf_init(&packet, 0);
-        bfd_put_packet(ofport->bfd, &packet, ofport->up.pp.hw_addr);
-        ofproto_dpif_send_packet(ofport, &packet);
-        ofpbuf_uninit(&packet);
-    }
-}
-
 static void
 port_run(struct ofport_dpif *ofport)
 {
@@ -2873,12 +2855,9 @@ port_run(struct ofport_dpif *ofport)
 
     ofport->carrier_seq = carrier_seq;
 
-    port_run_fast(ofport);
-
     if (ofport->cfm) {
         int cfm_opup = cfm_get_opup(ofport->cfm);
 
-        cfm_run(ofport->cfm);
         cfm_enable = !cfm_get_fault(ofport->cfm);
 
         if (cfm_opup >= 0) {
@@ -2887,7 +2866,6 @@ port_run(struct ofport_dpif *ofport)
     }
 
     if (ofport->bfd) {
-        bfd_run(ofport->bfd);
         bfd_enable = bfd_forwarding(ofport->bfd);
     }
 
@@ -2910,18 +2888,6 @@ port_run(struct ofport_dpif *ofport)
     ofport->may_enable = enable;
 }
 
-static void
-port_wait(struct ofport_dpif *ofport)
-{
-    if (ofport->cfm) {
-        cfm_wait(ofport->cfm);
-    }
-
-    if (ofport->bfd) {
-        bfd_wait(ofport->bfd);
-    }
-}
-
 static int
 port_query_by_name(const struct ofproto *ofproto_, const char *devname,
                    struct ofproto_port *ofproto_port)
@@ -3035,6 +3001,7 @@ port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
     if (!error && ofport_->ofp_port == OFPP_LOCAL) {
         struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
 
+        ovs_mutex_lock(&ofproto->stats_mutex);
         /* ofproto->stats.tx_packets represents packets that we created
          * internally and sent to some port (e.g. packets sent with
          * ofproto_dpif_send_packet()).  Account for them as if they had
@@ -3059,6 +3026,7 @@ port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
         if (stats->tx_bytes != UINT64_MAX) {
             stats->tx_bytes += ofproto->stats.rx_bytes;
         }
+        ovs_mutex_unlock(&ofproto->stats_mutex);
     }
 
     return error;
@@ -4073,15 +4041,11 @@ facet_check_consistency(struct facet *facet)
 
     struct xlate_out xout;
     struct xlate_in xin;
-
-    struct rule_dpif *rule;
     bool ok;
 
     /* Check the datapath actions for consistency. */
-    rule_dpif_lookup(facet->ofproto, &facet->flow, NULL, &rule);
-    xlate_in_init(&xin, facet->ofproto, &facet->flow, rule, 0, NULL);
+    xlate_in_init(&xin, facet->ofproto, &facet->flow, NULL, 0, NULL);
     xlate_actions(&xin, &xout);
-    rule_dpif_unref(rule);
 
     ok = ofpbuf_equal(&facet->xout.odp_actions, &xout.odp_actions)
         && facet->xout.slow == xout.slow;
@@ -4233,7 +4197,6 @@ flow_push_stats(struct ofproto_dpif *ofproto, struct flow *flow,
                 struct dpif_flow_stats *stats, bool may_learn)
 {
     struct ofport_dpif *in_port;
-    struct rule_dpif *rule;
     struct xlate_in xin;
 
     in_port = get_ofp_port(ofproto, flow->in_port.ofp_port);
@@ -4241,13 +4204,10 @@ flow_push_stats(struct ofproto_dpif *ofproto, struct flow *flow,
         netdev_vport_inc_rx(in_port->up.netdev, stats);
     }
 
-    rule_dpif_lookup(ofproto, flow, NULL, &rule);
-    rule_dpif_credit_stats(rule, stats);
-    xlate_in_init(&xin, ofproto, flow, rule, stats->tcp_flags, NULL);
+    xlate_in_init(&xin, ofproto, flow, NULL, stats->tcp_flags, NULL);
     xin.resubmit_stats = stats;
     xin.may_learn = may_learn;
     xlate_actions_for_side_effects(&xin);
-    rule_dpif_unref(rule);
 }
 
 static void
@@ -4830,8 +4790,10 @@ ofproto_dpif_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet
 
     error = xlate_send_packet(ofport, packet);
 
+    ovs_mutex_lock(&ofproto->stats_mutex);
     ofproto->stats.tx_packets++;
     ofproto->stats.tx_bytes += packet->size;
+    ovs_mutex_unlock(&ofproto->stats_mutex);
     return error;
 }