Merge 'master' into 'next'.
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index aefaf59..93acd42 100644 (file)
@@ -43,6 +43,7 @@
 #include "ofproto-sflow.h"
 #include "poll-loop.h"
 #include "timer.h"
+#include "unaligned.h"
 #include "unixctl.h"
 #include "vlan-bitmap.h"
 #include "vlog.h"
@@ -170,11 +171,6 @@ struct action_xlate_ctx {
      * calling action_xlate_ctx_init(). */
     void (*resubmit_hook)(struct action_xlate_ctx *, struct rule_dpif *);
 
-    /* If true, the speciality of 'flow' should be checked before executing
-     * its actions.  If special_cb returns false on 'flow' rendered
-     * uninstallable and no actions will be executed. */
-    bool check_special;
-
 /* xlate_actions() initializes and uses these members.  The client might want
  * to look at them after it returns. */
 
@@ -288,6 +284,7 @@ struct ofport_dpif {
     struct list bundle_node;    /* In struct ofbundle's "ports" list. */
     struct cfm *cfm;            /* Connectivity Fault Management, if any. */
     tag_type tag;               /* Tag associated with this port. */
+    uint32_t bond_stable_id;    /* stable_id to use as bond slave, or 0. */
 };
 
 static struct ofport_dpif *
@@ -307,6 +304,9 @@ struct ofproto_dpif {
     struct dpif *dpif;
     int max_ports;
 
+    /* Statistics. */
+    uint64_t n_matches;
+
     /* Bridging. */
     struct netflow *netflow;
     struct ofproto_sflow *sflow;
@@ -417,6 +417,7 @@ construct(struct ofproto *ofproto_)
     }
 
     ofproto->max_ports = dpif_get_max_ports(ofproto->dpif);
+    ofproto->n_matches = 0;
 
     error = dpif_recv_set_mask(ofproto->dpif,
                                ((1u << DPIF_UC_MISS) |
@@ -445,6 +446,10 @@ construct(struct ofproto *ofproto_)
     ofproto->need_revalidate = false;
     tag_set_init(&ofproto->revalidate_set);
 
+    ofproto->up.tables = xmalloc(sizeof *ofproto->up.tables);
+    classifier_init(&ofproto->up.tables[0]);
+    ofproto->up.n_tables = 1;
+
     ofproto_dpif_unixctl_init();
 
     return 0;
@@ -586,6 +591,39 @@ flush(struct ofproto *ofproto_)
     dpif_flow_flush(ofproto->dpif);
 }
 
+static void
+get_features(struct ofproto *ofproto_ OVS_UNUSED,
+             bool *arp_match_ip, uint32_t *actions)
+{
+    *arp_match_ip = true;
+    *actions = ((1u << OFPAT_OUTPUT) |
+                (1u << OFPAT_SET_VLAN_VID) |
+                (1u << OFPAT_SET_VLAN_PCP) |
+                (1u << OFPAT_STRIP_VLAN) |
+                (1u << OFPAT_SET_DL_SRC) |
+                (1u << OFPAT_SET_DL_DST) |
+                (1u << OFPAT_SET_NW_SRC) |
+                (1u << OFPAT_SET_NW_DST) |
+                (1u << OFPAT_SET_NW_TOS) |
+                (1u << OFPAT_SET_TP_SRC) |
+                (1u << OFPAT_SET_TP_DST) |
+                (1u << OFPAT_ENQUEUE));
+}
+
+static void
+get_tables(struct ofproto *ofproto_, struct ofp_table_stats *ots)
+{
+    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+    struct odp_stats s;
+
+    strcpy(ots->name, "classifier");
+
+    dpif_get_dp_stats(ofproto->dpif, &s);
+    put_32aligned_be64(&ots->lookup_count, htonll(s.n_hit + s.n_missed));
+    put_32aligned_be64(&ots->matched_count,
+                       htonll(s.n_hit + ofproto->n_matches));
+}
+
 static int
 set_netflow(struct ofproto *ofproto_,
             const struct netflow_options *netflow_options)
@@ -812,7 +850,8 @@ bundle_del_port(struct ofport_dpif *port)
 
 static bool
 bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
-                struct lacp_slave_settings *lacp)
+                struct lacp_slave_settings *lacp,
+                uint32_t bond_stable_id)
 {
     struct ofport_dpif *port;
 
@@ -836,6 +875,8 @@ bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port,
         lacp_slave_register(bundle->lacp, port, lacp);
     }
 
+    port->bond_stable_id = bond_stable_id;
+
     return true;
 }
 
@@ -939,7 +980,8 @@ bundle_set(struct ofproto *ofproto_, void *aux,
     ok = true;
     for (i = 0; i < s->n_slaves; i++) {
         if (!bundle_add_port(bundle, s->slaves[i],
-                             s->lacp ? &s->lacp_slaves[i] : NULL)) {
+                             s->lacp ? &s->lacp_slaves[i] : NULL,
+                             s->bond_stable_ids ? s->bond_stable_ids[i] : 0)) {
             ok = false;
         }
     }
@@ -990,10 +1032,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
         }
 
         LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
-            uint16_t stable_id = (bundle->lacp
-                                  ? lacp_slave_get_port_id(bundle->lacp, port)
-                                  : port->odp_port);
-            bond_slave_register(bundle->bond, port, stable_id,
+            bond_slave_register(bundle->bond, port, port->bond_stable_id,
                                 port->up.netdev);
         }
     } else {
@@ -1540,6 +1579,7 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall)
     /* Handle 802.1ag and LACP. */
     if (process_special(ofproto, &flow, upcall->packet)) {
         ofpbuf_delete(upcall->packet);
+        ofproto->n_matches++;
         return;
     }
 
@@ -1594,6 +1634,7 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall)
 
     facet_execute(ofproto, facet, upcall->packet);
     facet_install(ofproto, facet, false);
+    ofproto->n_matches++;
 }
 
 static void
@@ -1655,7 +1696,7 @@ expire(struct ofproto_dpif *ofproto)
     expire_facets(ofproto, dp_max_idle);
 
     /* Expire OpenFlow flows whose idle_timeout or hard_timeout has passed. */
-    cls_cursor_init(&cursor, &ofproto->up.cls, NULL);
+    cls_cursor_init(&cursor, &ofproto->up.tables[0], NULL);
     CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, up.cr, &cursor) {
         rule_expire(rule);
     }
@@ -2427,7 +2468,9 @@ flow_push_stats(const struct rule_dpif *rule,
 static struct rule_dpif *
 rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow)
 {
-    return rule_dpif_cast(ofproto_rule_lookup(&ofproto->up, flow));
+    return rule_dpif_cast(rule_from_cls_rule(
+                              classifier_lookup(&ofproto->up.tables[0],
+                                                flow)));
 }
 
 static struct rule *
@@ -2449,7 +2492,7 @@ rule_construct(struct rule *rule_)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
-    struct cls_rule *displaced_rule;
+    struct rule_dpif *old_rule;
     int error;
 
     error = validate_actions(rule->up.actions, rule->up.n_actions,
@@ -2458,15 +2501,19 @@ rule_construct(struct rule *rule_)
         return error;
     }
 
+    old_rule = rule_dpif_cast(rule_from_cls_rule(classifier_find_rule_exactly(
+                                                     &ofproto->up.tables[0],
+                                                     &rule->up.cr)));
+    if (old_rule) {
+        ofproto_rule_destroy(&old_rule->up);
+    }
+
     rule->used = rule->up.created;
     rule->packet_count = 0;
     rule->byte_count = 0;
     list_init(&rule->facets);
+    classifier_insert(&ofproto->up.tables[0], &rule->up.cr);
 
-    displaced_rule = classifier_insert(&ofproto->up.cls, &rule->up.cr);
-    if (displaced_rule) {
-        ofproto_rule_destroy(rule_from_cls_rule(displaced_rule));
-    }
     ofproto->need_revalidate = true;
 
     return 0;
@@ -2479,20 +2526,11 @@ rule_destruct(struct rule *rule_)
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
     struct facet *facet, *next_facet;
 
-    ofproto->need_revalidate = true;
+    classifier_remove(&ofproto->up.tables[0], &rule->up.cr);
     LIST_FOR_EACH_SAFE (facet, next_facet, list_node, &rule->facets) {
         facet_revalidate(ofproto, facet);
     }
-}
-
-static void
-rule_remove(struct rule *rule_)
-{
-    struct rule_dpif *rule = rule_dpif_cast(rule_);
-    struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
-
     ofproto->need_revalidate = true;
-    classifier_remove(&ofproto->up.cls, &rule->up.cr);
 }
 
 static void
@@ -3073,7 +3111,6 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx,
     ctx->flow = *flow;
     ctx->packet = packet;
     ctx->resubmit_hook = NULL;
-    ctx->check_special = true;
 }
 
 static struct ofpbuf *
@@ -3089,8 +3126,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
     ctx->recurse = 0;
     ctx->last_pop_priority = -1;
 
-    if (ctx->check_special
-        && process_special(ctx->ofproto, &ctx->flow, ctx->packet)) {
+    if (process_special(ctx->ofproto, &ctx->flow, ctx->packet)) {
         ctx->may_set_up_flow = false;
     } else {
         do_xlate_actions(in, n_in, ctx);
@@ -3858,6 +3894,8 @@ const struct ofproto_class ofproto_dpif_class = {
     run,
     wait,
     flush,
+    get_features,
+    get_tables,
     port_alloc,
     port_construct,
     port_destruct,
@@ -3877,7 +3915,6 @@ const struct ofproto_class ofproto_dpif_class = {
     rule_construct,
     rule_destruct,
     rule_dealloc,
-    rule_remove,
     rule_get_stats,
     rule_execute,
     rule_modify_actions,