Implement OpenFlow 1.1+ "groups" protocol.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index d4fc8ec..70a226c 100644 (file)
@@ -1248,7 +1248,7 @@ construct(struct ofproto *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct shash_node *node, *next;
-    odp_port_t max_ports;
+    uint32_t max_ports;
     int error;
 
     error = open_dpif_backer(ofproto->up.type, &ofproto->backer);
@@ -1257,8 +1257,7 @@ construct(struct ofproto *ofproto_)
     }
 
     max_ports = dpif_get_max_ports(ofproto->backer->dpif);
-    ofproto_init_max_ports(ofproto_, u16_to_ofp(MIN(odp_to_u32(max_ports),
-                                                    ofp_to_u16(OFPP_MAX))));
+    ofproto_init_max_ports(ofproto_, MIN(max_ports, ofp_to_u16(OFPP_MAX)));
 
     ofproto->netflow = NULL;
     ofproto->sflow = NULL;
@@ -1438,10 +1437,11 @@ destruct(struct ofproto *ofproto_)
         ovs_rwlock_wrlock(&table->cls.rwlock);
         cls_cursor_init(&cursor, &table->cls, NULL);
         CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, up.cr, &cursor) {
-            ofproto_rule_destroy(&ofproto->up, &table->cls, &rule->up);
+            ofproto_rule_delete(&ofproto->up, &table->cls, &rule->up);
         }
         ovs_rwlock_unlock(&table->cls.rwlock);
     }
+    complete_operations(ofproto);
 
     ovs_mutex_lock(&ofproto->flow_mod_mutex);
     LIST_FOR_EACH_SAFE (fm, next_fm, list_node, &ofproto->flow_mods) {
@@ -1500,14 +1500,9 @@ run_fast(struct ofproto *ofproto_)
     }
 
     ovs_mutex_lock(&ofproto->flow_mod_mutex);
-    if (ofproto->n_flow_mods) {
-        flow_mods = ofproto->flow_mods;
-        list_moved(&flow_mods);
-        list_init(&ofproto->flow_mods);
-        ofproto->n_flow_mods = 0;
-    } else {
-        list_init(&flow_mods);
-    }
+    list_move(&flow_mods, &ofproto->flow_mods);
+    list_init(&ofproto->flow_mods);
+    ofproto->n_flow_mods = 0;
     ovs_mutex_unlock(&ofproto->flow_mod_mutex);
 
     LIST_FOR_EACH_SAFE (fm, next_fm, list_node, &flow_mods) {
@@ -1523,14 +1518,9 @@ run_fast(struct ofproto *ofproto_)
     }
 
     ovs_mutex_lock(&ofproto->pin_mutex);
-    if (ofproto->n_pins) {
-        pins = ofproto->pins;
-        list_moved(&pins);
-        list_init(&ofproto->pins);
-        ofproto->n_pins = 0;
-    } else {
-        list_init(&pins);
-    }
+    list_move(&pins, &ofproto->pins);
+    list_init(&ofproto->pins);
+    ofproto->n_pins = 0;
     ovs_mutex_unlock(&ofproto->pin_mutex);
 
     LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &pins) {
@@ -1585,6 +1575,9 @@ run(struct ofproto *ofproto_)
     if (ofproto->sflow) {
         dpif_sflow_run(ofproto->sflow);
     }
+    if (ofproto->ipfix) {
+        dpif_ipfix_run(ofproto->ipfix);
+    }
 
     HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
         port_run(ofport);
@@ -1644,6 +1637,9 @@ wait(struct ofproto *ofproto_)
     if (ofproto->sflow) {
         dpif_sflow_wait(ofproto->sflow);
     }
+    if (ofproto->ipfix) {
+        dpif_ipfix_wait(ofproto->ipfix);
+    }
     HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
         port_wait(ofport);
     }
@@ -1905,6 +1901,10 @@ port_modified(struct ofport *port_)
         cfm_set_netdev(port->cfm, port->up.netdev);
     }
 
+    if (port->bfd) {
+        bfd_set_netdev(port->bfd, port->up.netdev);
+    }
+
     if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
                                                 port->odp_port)) {
         ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
@@ -1969,20 +1969,25 @@ set_ipfix(
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct dpif_ipfix *di = ofproto->ipfix;
+    bool has_options = bridge_exporter_options || flow_exporters_options;
 
-    if (bridge_exporter_options || flow_exporters_options) {
-        if (!di) {
-            di = ofproto->ipfix = dpif_ipfix_create();
-        }
+    if (has_options && !di) {
+        di = ofproto->ipfix = dpif_ipfix_create();
+    }
+
+    if (di) {
+        /* Call set_options in any case to cleanly flush the flow
+         * caches in the last exporters that are to be destroyed. */
         dpif_ipfix_set_options(
             di, bridge_exporter_options, flow_exporters_options,
             n_flow_exporters_options);
-    } else {
-        if (di) {
+
+        if (!has_options) {
             dpif_ipfix_unref(di);
             ofproto->ipfix = NULL;
         }
     }
+
     return 0;
 }
 
@@ -2039,7 +2044,8 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg)
     struct bfd *old;
 
     old = ofport->bfd;
-    ofport->bfd = bfd_configure(old, netdev_get_name(ofport->up.netdev), cfg);
+    ofport->bfd = bfd_configure(old, netdev_get_name(ofport->up.netdev),
+                                cfg, ofport->up.netdev);
     if (ofport->bfd != old) {
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
@@ -2952,6 +2958,8 @@ port_run(struct ofport_dpif *ofport)
     long long int carrier_seq = netdev_get_carrier_resets(ofport->up.netdev);
     bool carrier_changed = carrier_seq != ofport->carrier_seq;
     bool enable = netdev_get_carrier(ofport->up.netdev);
+    bool cfm_enable = false;
+    bool bfd_enable = false;
 
     ofport->carrier_seq = carrier_seq;
 
@@ -2961,16 +2969,20 @@ port_run(struct ofport_dpif *ofport)
         int cfm_opup = cfm_get_opup(ofport->cfm);
 
         cfm_run(ofport->cfm);
-        enable = enable && !cfm_get_fault(ofport->cfm);
+        cfm_enable = !cfm_get_fault(ofport->cfm);
 
         if (cfm_opup >= 0) {
-            enable = enable && cfm_opup;
+            cfm_enable = cfm_enable && cfm_opup;
         }
     }
 
     if (ofport->bfd) {
         bfd_run(ofport->bfd);
-        enable = enable && bfd_forwarding(ofport->bfd);
+        bfd_enable = bfd_forwarding(ofport->bfd);
+    }
+
+    if (ofport->bfd || ofport->cfm) {
+        enable = enable && (cfm_enable || bfd_enable);
     }
 
     if (ofport->bundle) {
@@ -3318,7 +3330,6 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet,
     facet->byte_count += miss->stats.n_bytes;
     facet->prev_byte_count += miss->stats.n_bytes;
 
-    subfacet = subfacet_create(facet, miss);
     want_path = facet->xout.slow ? SF_SLOW_PATH : SF_FAST_PATH;
 
     /* Don't install the flow if it's the result of the "userspace"
@@ -3955,12 +3966,8 @@ rule_expire(struct rule_dpif *rule)
         return;
     }
 
-    if (!ovs_rwlock_trywrlock(&rule->up.evict)) {
-        COVERAGE_INC(ofproto_dpif_expired);
-
-        /* Get rid of the rule. */
-        ofproto_rule_expire(&rule->up, reason);
-    }
+    COVERAGE_INC(ofproto_dpif_expired);
+    ofproto_rule_expire(&rule->up, reason);
 }
 \f
 /* Facets. */
@@ -4770,7 +4777,7 @@ bool
 rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto,
                           const struct flow *flow, struct flow_wildcards *wc,
                           uint8_t table_id, struct rule_dpif **rule)
-    OVS_ACQ_RDLOCK((*rule)->up.evict)
+    OVS_TRY_RDLOCK(true, (*rule)->up.evict)
 {
     struct cls_rule *cls_rule;
     struct classifier *cls;
@@ -4827,6 +4834,7 @@ choose_miss_rule(enum ofputil_port_config config, struct rule_dpif *miss_rule,
 
 void
 rule_release(struct rule_dpif *rule)
+    OVS_NO_THREAD_SAFETY_ANALYSIS
 {
     if (rule) {
         ovs_rwlock_unlock(&rule->up.evict);
@@ -4871,15 +4879,27 @@ rule_construct(struct rule *rule_)
     rule->packet_count = 0;
     rule->byte_count = 0;
     ovs_mutex_unlock(&rule->stats_mutex);
-    complete_operation(rule);
     return 0;
 }
 
 static void
-rule_destruct(struct rule *rule_)
+rule_insert(struct rule *rule_)
+{
+    struct rule_dpif *rule = rule_dpif_cast(rule_);
+    complete_operation(rule);
+}
+
+static void
+rule_delete(struct rule *rule_)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
     complete_operation(rule);
+}
+
+static void
+rule_destruct(struct rule *rule_)
+{
+    struct rule_dpif *rule = rule_dpif_cast(rule_);
     ovs_mutex_destroy(&rule->stats_mutex);
 }
 
@@ -4934,10 +4954,17 @@ rule_execute(struct rule *rule, const struct flow *flow,
 }
 
 static void
-rule_modify_actions(struct rule *rule_)
+rule_modify_actions(struct rule *rule_, bool reset_counters)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
 
+    if (reset_counters) {
+        ovs_mutex_lock(&rule->stats_mutex);
+        rule->packet_count = 0;
+        rule->byte_count = 0;
+        ovs_mutex_unlock(&rule->stats_mutex);
+    }
+
     complete_operation(rule);
 }
 \f
@@ -6322,6 +6349,8 @@ const struct ofproto_class ofproto_dpif_class = {
     NULL,                       /* rule_choose_table */
     rule_alloc,
     rule_construct,
+    rule_insert,
+    rule_delete,
     rule_destruct,
     rule_dealloc,
     rule_get_stats,
@@ -6355,4 +6384,10 @@ const struct ofproto_class ofproto_dpif_class = {
     NULL,                       /* meter_set */
     NULL,                       /* meter_get */
     NULL,                       /* meter_del */
+    NULL,                       /* group_alloc */
+    NULL,                       /* group_construct */
+    NULL,                       /* group_destruct */
+    NULL,                       /* group_dealloc */
+    NULL,                       /* group_modify */
+    NULL,                       /* group_get_stats */
 };