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);
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 *);
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;
/* 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;
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);
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,
{
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
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);
}
}
-/* 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;
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
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)
{
&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
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
} 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));
}
}
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
}
}
-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
{
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);
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;
}
}
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;
}
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 {
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);
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;
}
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
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. */
/* 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