ofproto: Always set VLAN_CFI bit to 0 in ODPAT_SET_DL_TCI action.
[openvswitch] / ofproto / ofproto.c
index 0bc31a5f049ae1f3a828b29e89e58903b6ebee9a..6b071c7d934ecb0ac0f8beb089f1be0c76bcf2ee 100644 (file)
@@ -124,8 +124,7 @@ static void rule_destroy(struct ofproto *, struct rule *);
 static void rule_free(struct rule *);
 
 static struct rule *rule_lookup(struct ofproto *, const struct flow *);
-static void rule_insert(struct ofproto *, struct rule *,
-                        struct ofpbuf *packet, uint16_t in_port);
+static void rule_insert(struct ofproto *, struct rule *);
 static void rule_remove(struct ofproto *, struct rule *);
 
 static void rule_send_removed(struct ofproto *, struct rule *, uint8_t reason);
@@ -180,8 +179,8 @@ static void facet_install(struct ofproto *, struct facet *, bool zero_stats);
 static void facet_uninstall(struct ofproto *, struct facet *);
 static void facet_flush_stats(struct ofproto *, struct facet *);
 
-static bool facet_make_actions(struct ofproto *, struct facet *,
-                              const struct ofpbuf *packet);
+static void facet_make_actions(struct ofproto *, struct facet *,
+                               const struct ofpbuf *packet);
 static void facet_update_stats(struct ofproto *, struct facet *,
                                const struct odp_flow_stats *);
 
@@ -306,6 +305,7 @@ struct ofproto {
     long long int next_in_band_update;
     struct sockaddr_in *extra_in_band_remotes;
     size_t n_extra_remotes;
+    int in_band_queue;
 
     /* Flow table. */
     struct classifier cls;
@@ -406,11 +406,14 @@ ofproto_create(const char *datapath, const char *datapath_type,
 
     /* Initialize submodules. */
     p->switch_status = switch_status_create(p);
-    p->in_band = NULL;
     p->fail_open = NULL;
     p->netflow = NULL;
     p->sflow = NULL;
 
+    /* Initialize in-band control. */
+    p->in_band = NULL;
+    p->in_band_queue = -1;
+
     /* Initialize flow table. */
     classifier_init(&p->cls);
     p->next_expiration = time_msec() + 1000;
@@ -601,6 +604,7 @@ update_in_band_remotes(struct ofproto *ofproto)
         if (ofproto->in_band) {
             in_band_set_remotes(ofproto->in_band, addrs, n_addrs);
         }
+        in_band_set_queue(ofproto->in_band, ofproto->in_band_queue);
         ofproto->next_in_band_update = time_msec() + 1000;
     } else {
         in_band_destroy(ofproto->in_band);
@@ -777,6 +781,18 @@ ofproto_set_extra_in_band_remotes(struct ofproto *ofproto,
     update_in_band_remotes(ofproto);
 }
 
+/* Sets the OpenFlow queue used by flows set up by in-band control on
+ * 'ofproto' to 'queue_id'.  If 'queue_id' is negative, then in-band control
+ * flows will use the default queue. */
+void
+ofproto_set_in_band_queue(struct ofproto *ofproto, int queue_id)
+{
+    if (queue_id != ofproto->in_band_queue) {
+        ofproto->in_band_queue = queue_id;
+        update_in_band_remotes(ofproto);
+    }
+}
+
 void
 ofproto_set_desc(struct ofproto *p,
                  const char *mfr_desc, const char *hw_desc,
@@ -1338,7 +1354,7 @@ ofproto_add_flow(struct ofproto *p, const struct cls_rule *cls_rule,
 {
     struct rule *rule;
     rule = rule_create(cls_rule, actions, n_actions, 0, 0, 0, false);
-    rule_insert(p, rule, NULL, 0);
+    rule_insert(p, rule);
 }
 
 void
@@ -1377,7 +1393,7 @@ ofproto_flush_flows(struct ofproto *ofproto)
         facet->installed = false;
         facet_remove(ofproto, facet);
     }
-    classifier_for_each(&ofproto->cls, CLS_INC_ALL, destroy_rule, ofproto);
+    classifier_for_each(&ofproto->cls, destroy_rule, ofproto);
     dpif_flow_flush(ofproto->dpif);
     if (ofproto->in_band) {
         in_band_flushed(ofproto->in_band);
@@ -2067,15 +2083,9 @@ rule_execute(struct ofproto *ofproto, struct rule *rule, uint16_t in_port,
     }
 }
 
-/* Inserts 'rule' into 'p''s flow table.
- *
- * If 'packet' is nonnull, takes ownership of 'packet', executes 'rule''s
- * actions on it and credits the statistics for sending the packet to 'rule'.
- * 'packet' must have at least sizeof(struct ofp_packet_in) bytes of
- * headroom. */
+/* Inserts 'rule' into 'p''s flow table. */
 static void
-rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet,
-            uint16_t in_port)
+rule_insert(struct ofproto *p, struct rule *rule)
 {
     struct rule *displaced_rule;
 
@@ -2084,10 +2094,6 @@ rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet,
         rule_destroy(p, displaced_rule);
     }
     p->need_revalidate = true;
-
-    if (packet) {
-        rule_execute(p, rule, in_port, packet);
-    }
 }
 
 /* Creates and returns a new facet within 'ofproto' owned by 'rule', given a
@@ -2156,9 +2162,8 @@ facet_remove(struct ofproto *ofproto, struct facet *facet)
     facet_free(facet);
 }
 
-/* Composes the ODP actions for 'facet' based on its rule's actions.
- * Returns true if the actions changed, false otherwise. */
-static bool
+/* Composes the ODP actions for 'facet' based on its rule's actions. */
+static void
 facet_make_actions(struct ofproto *p, struct facet *facet,
                    const struct ofpbuf *packet)
 {
@@ -2171,15 +2176,12 @@ facet_make_actions(struct ofproto *p, struct facet *facet,
                   &facet->nf_flow.output_iface);
 
     actions_len = a.n_actions * sizeof *a.actions;
-    if (facet->n_actions == a.n_actions
-        && !memcmp(facet->actions, a.actions, actions_len)) {
-        return false;
+    if (facet->n_actions != a.n_actions
+        || memcmp(facet->actions, a.actions, actions_len)) {
+        free(facet->actions);
+        facet->n_actions = a.n_actions;
+        facet->actions = xmemdup(a.actions, actions_len);
     }
-
-    free(facet->actions);
-    facet->n_actions = a.n_actions;
-    facet->actions = xmemdup(a.actions, actions_len);
-    return true;
 }
 
 static int
@@ -2600,8 +2602,7 @@ add_output_action(struct action_xlate_ctx *ctx, uint16_t port)
 static struct rule *
 rule_lookup(struct ofproto *ofproto, const struct flow *flow)
 {
-    return rule_from_cls_rule(classifier_lookup(&ofproto->cls, flow,
-                                                CLS_INC_ALL));
+    return rule_from_cls_rule(classifier_lookup(&ofproto->cls, flow));
 }
 
 static void
@@ -2794,8 +2795,7 @@ xlate_set_dl_tci(struct action_xlate_ctx *ctx)
     } else {
         union odp_action *oa = odp_actions_add(ctx->out, ODPAT_SET_DL_TCI);
         oa->dl_tci.tci = htons(ntohs(dl_vlan & htons(VLAN_VID_MASK))
-                               | (dl_vlan_pcp << VLAN_PCP_SHIFT)
-                               | VLAN_CFI);
+                               | (dl_vlan_pcp << VLAN_PCP_SHIFT));
     }
 }
 
@@ -2858,6 +2858,9 @@ xlate_nicira_action(struct action_xlate_ctx *ctx,
     case NXAST_REG_LOAD:
         nxm_execute_reg_load((const struct nx_action_reg_load *) nah,
                              &ctx->flow);
+
+    case NXAST_NOTE:
+        /* Nothing to do. */
         break;
 
     /* If you add a new action here that modifies flow data, don't forget to
@@ -3433,10 +3436,10 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     }
 }
 
-static int
-table_id_to_include(uint8_t table_id)
+static bool
+is_valid_table(uint8_t table_id)
 {
-    return table_id == 0 || table_id == 0xff ? CLS_INC_ALL : 0;
+    return table_id == 0 || table_id == 0xff;
 }
 
 static int
@@ -3445,7 +3448,6 @@ handle_flow_stats_request(struct ofconn *ofconn,
 {
     struct ofp_flow_stats_request *fsr;
     struct flow_stats_cbdata cbdata;
-    struct cls_rule target;
 
     if (arg_size != sizeof *fsr) {
         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
@@ -3453,13 +3455,17 @@ handle_flow_stats_request(struct ofconn *ofconn,
     fsr = (struct ofp_flow_stats_request *) osr->body;
 
     COVERAGE_INC(ofproto_flows_req);
-    cbdata.ofconn = ofconn;
-    cbdata.out_port = fsr->out_port;
     cbdata.msg = start_ofp_stats_reply(osr, 1024);
-    cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target);
-    classifier_for_each_match(&ofconn->ofproto->cls, &target,
-                              table_id_to_include(fsr->table_id),
-                              flow_stats_cb, &cbdata);
+    if (is_valid_table(fsr->table_id)) {
+        struct cls_rule target;
+
+        cbdata.ofconn = ofconn;
+        cbdata.out_port = fsr->out_port;
+        cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, &target);
+        classifier_for_each_match(&ofconn->ofproto->cls, &target,
+                                  flow_stats_cb, &cbdata);
+    }
+
     queue_tx(cbdata.msg, ofconn, ofconn->reply_counter);
     return 0;
 }
@@ -3521,12 +3527,13 @@ handle_nxst_flow(struct ofconn *ofconn, struct ofpbuf *b)
     }
 
     COVERAGE_INC(ofproto_flows_req);
-    cbdata.ofconn = ofconn;
-    cbdata.out_port = nfsr->out_port;
     cbdata.msg = start_nxstats_reply(&nfsr->nsm, 1024);
-    classifier_for_each_match(&ofconn->ofproto->cls, &target,
-                              table_id_to_include(nfsr->table_id),
-                              nx_flow_stats_cb, &cbdata);
+    if (is_valid_table(nfsr->table_id)) {
+        cbdata.ofconn = ofconn;
+        cbdata.out_port = nfsr->out_port;
+        classifier_for_each_match(&ofconn->ofproto->cls, &target,
+                                  nx_flow_stats_cb, &cbdata);
+    }
     queue_tx(cbdata.msg, ofconn, ofconn->reply_counter);
     return 0;
 }
@@ -3580,8 +3587,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results)
     cbdata.results = results;
 
     cls_rule_from_match(&match, 0, NXFF_OPENFLOW10, 0, &target);
-    classifier_for_each_match(&p->cls, &target, CLS_INC_ALL,
-                              flow_stats_ds_cb, &cbdata);
+    classifier_for_each_match(&p->cls, &target, flow_stats_ds_cb, &cbdata);
 }
 
 struct aggregate_stats_cbdata {
@@ -3618,14 +3624,16 @@ query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target,
     struct aggregate_stats_cbdata cbdata;
 
     COVERAGE_INC(ofproto_agg_request);
-    cbdata.ofproto = ofproto;
-    cbdata.out_port = out_port;
     cbdata.packet_count = 0;
     cbdata.byte_count = 0;
     cbdata.n_flows = 0;
-    classifier_for_each_match(&ofproto->cls, target,
-                              table_id_to_include(table_id),
-                              aggregate_stats_cb, &cbdata);
+    if (is_valid_table(table_id)) {
+        cbdata.ofproto = ofproto;
+        cbdata.out_port = out_port;
+
+        classifier_for_each_match(&ofproto->cls, target,
+                                  aggregate_stats_cb, &cbdata);
+    }
 
     oasr->flow_count = htonl(cbdata.n_flows);
     oasr->packet_count = htonll(cbdata.packet_count);
@@ -3943,7 +3951,10 @@ add_flow(struct ofconn *ofconn, struct flow_mod *fm)
     rule = rule_create(&fm->cr, fm->actions, fm->n_actions,
                        fm->idle_timeout, fm->hard_timeout, fm->cookie,
                        fm->flags & OFPFF_SEND_FLOW_REM);
-    rule_insert(p, rule, packet, in_port);
+    rule_insert(p, rule);
+    if (packet) {
+        rule_execute(p, rule, in_port, packet);
+    }
     return error;
 }
 
@@ -4001,7 +4012,7 @@ modify_flows_loose(struct ofconn *ofconn, struct flow_mod *fm)
     cbdata.fm = fm;
     cbdata.match = NULL;
 
-    classifier_for_each_match(&ofconn->ofproto->cls, &fm->cr, CLS_INC_ALL,
+    classifier_for_each_match(&ofconn->ofproto->cls, &fm->cr,
                               modify_flows_cb, &cbdata);
     if (cbdata.match) {
         /* This credits the packet to whichever flow happened to happened to
@@ -4092,8 +4103,7 @@ delete_flows_loose(struct ofproto *p, const struct flow_mod *fm)
     cbdata.ofproto = p;
     cbdata.out_port = htons(fm->out_port);
 
-    classifier_for_each_match(&p->cls, &fm->cr, CLS_INC_ALL,
-                              delete_flows_cb, &cbdata);
+    classifier_for_each_match(&p->cls, &fm->cr, delete_flows_cb, &cbdata);
 }
 
 /* Implements OFPFC_DELETE_STRICT. */
@@ -4627,7 +4637,7 @@ ofproto_expire(struct ofproto *ofproto)
 
     /* Expire OpenFlow flows whose idle_timeout or hard_timeout has passed. */
     cbdata.ofproto = ofproto;
-    classifier_for_each(&ofproto->cls, CLS_INC_ALL, rule_expire, &cbdata);
+    classifier_for_each(&ofproto->cls, rule_expire, &cbdata);
 
     /* Let the hook know that we're at a stable point: all outstanding data
      * in existing flows has been accounted to the account_cb.  Thus, the