mirror of
https://github.com/openvswitch/ovs
synced 2025-09-02 23:35:27 +00:00
ofproto: Add support for reverting flow mods and bundle commit.
Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
@@ -1795,11 +1795,19 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
|
|||||||
fm->command = command & 0xff;
|
fm->command = command & 0xff;
|
||||||
fm->table_id = command >> 8;
|
fm->table_id = command >> 8;
|
||||||
} else {
|
} else {
|
||||||
|
if (command > 0xff) {
|
||||||
|
VLOG_WARN_RL(&bad_ofmsg_rl, "flow_mod has explicit table_id "
|
||||||
|
"but flow_mod_table_id extension is not enabled");
|
||||||
|
}
|
||||||
fm->command = command;
|
fm->command = command;
|
||||||
fm->table_id = 0xff;
|
fm->table_id = 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fm->command > OFPFC_DELETE_STRICT) {
|
||||||
|
return OFPERR_OFPFMFC_BAD_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
error = ofpacts_pull_openflow_instructions(&b, b.size,
|
error = ofpacts_pull_openflow_instructions(&b, b.size,
|
||||||
oh->version, ofpacts);
|
oh->version, ofpacts);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@@ -59,11 +59,16 @@ ofp_bundle_create(uint32_t id, uint16_t flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle)
|
ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle,
|
||||||
|
bool success)
|
||||||
{
|
{
|
||||||
struct ofp_bundle_entry *msg;
|
struct ofp_bundle_entry *msg;
|
||||||
|
|
||||||
LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
|
LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
|
||||||
|
if (success && msg->type == OFPTYPE_FLOW_MOD) {
|
||||||
|
/* Tell connmgr about successful flow mods. */
|
||||||
|
ofconn_report_flow_mod(ofconn, msg->fm.command);
|
||||||
|
}
|
||||||
ofp_bundle_entry_free(msg);
|
ofp_bundle_entry_free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +86,7 @@ ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
|
|||||||
|
|
||||||
if (bundle) {
|
if (bundle) {
|
||||||
VLOG_INFO("Bundle %x already exists.", id);
|
VLOG_INFO("Bundle %x already exists.", id);
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
ofp_bundle_remove__(ofconn, bundle, false);
|
||||||
|
|
||||||
return OFPERR_OFPBFC_BAD_ID;
|
return OFPERR_OFPBFC_BAD_ID;
|
||||||
}
|
}
|
||||||
@@ -107,12 +112,12 @@ ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bundle->state == BS_CLOSED) {
|
if (bundle->state == BS_CLOSED) {
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
ofp_bundle_remove__(ofconn, bundle, false);
|
||||||
return OFPERR_OFPBFC_BUNDLE_CLOSED;
|
return OFPERR_OFPBFC_BUNDLE_CLOSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bundle->flags != flags) {
|
if (bundle->flags != flags) {
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
ofp_bundle_remove__(ofconn, bundle, false);
|
||||||
return OFPERR_OFPBFC_BAD_FLAGS;
|
return OFPERR_OFPBFC_BAD_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,31 +125,6 @@ ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ofperr
|
|
||||||
ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
|
|
||||||
{
|
|
||||||
struct ofp_bundle *bundle;
|
|
||||||
enum ofperr error = 0;
|
|
||||||
struct ofp_bundle_entry *msg;
|
|
||||||
|
|
||||||
bundle = ofconn_get_bundle(ofconn, id);
|
|
||||||
|
|
||||||
if (!bundle) {
|
|
||||||
return OFPERR_OFPBFC_BAD_ID;
|
|
||||||
}
|
|
||||||
if (bundle->flags != flags) {
|
|
||||||
error = OFPERR_OFPBFC_BAD_FLAGS;
|
|
||||||
} else {
|
|
||||||
LIST_FOR_EACH (msg, node, &bundle->msg_list) {
|
|
||||||
/* XXX: actual commit */
|
|
||||||
error = OFPERR_OFPBFC_MSG_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ofperr
|
enum ofperr
|
||||||
ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
|
ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
|
||||||
{
|
{
|
||||||
@@ -156,7 +136,7 @@ ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
|
|||||||
return OFPERR_OFPBFC_BAD_ID;
|
return OFPERR_OFPBFC_BAD_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
ofp_bundle_remove__(ofconn, bundle, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -179,10 +159,10 @@ ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
} else if (bundle->state == BS_CLOSED) {
|
} else if (bundle->state == BS_CLOSED) {
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
ofp_bundle_remove__(ofconn, bundle, false);
|
||||||
return OFPERR_OFPBFC_BUNDLE_CLOSED;
|
return OFPERR_OFPBFC_BUNDLE_CLOSED;
|
||||||
} else if (flags != bundle->flags) {
|
} else if (flags != bundle->flags) {
|
||||||
ofp_bundle_remove__(ofconn, bundle);
|
ofp_bundle_remove__(ofconn, bundle, false);
|
||||||
return OFPERR_OFPBFC_BAD_FLAGS;
|
return OFPERR_OFPBFC_BAD_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,8 @@
|
|||||||
#include "connmgr.h"
|
#include "connmgr.h"
|
||||||
#include "ofp-msgs.h"
|
#include "ofp-msgs.h"
|
||||||
#include "ofp-util.h"
|
#include "ofp-util.h"
|
||||||
|
#include "ofproto-provider.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -31,12 +33,19 @@ extern "C" {
|
|||||||
|
|
||||||
struct ofp_bundle_entry {
|
struct ofp_bundle_entry {
|
||||||
struct ovs_list node;
|
struct ovs_list node;
|
||||||
ovs_be32 xid; /* For error returns. */
|
|
||||||
enum ofptype type; /* OFPTYPE_FLOW_MOD or OFPTYPE_PORT_MOD. */
|
enum ofptype type; /* OFPTYPE_FLOW_MOD or OFPTYPE_PORT_MOD. */
|
||||||
union {
|
union {
|
||||||
struct ofputil_flow_mod fm; /* 'fm.ofpacts' must be malloced. */
|
struct ofputil_flow_mod fm; /* 'fm.ofpacts' must be malloced. */
|
||||||
struct ofputil_port_mod pm;
|
struct ofputil_port_mod pm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Used during commit. */
|
||||||
|
struct rule_collection rules; /* Affected rules. */
|
||||||
|
struct rule *rule;
|
||||||
|
bool modify;
|
||||||
|
|
||||||
|
/* OpenFlow header and some of the message contents for error reporting. */
|
||||||
|
struct ofp_header ofp_msg[DIV_ROUND_UP(64, sizeof(struct ofp_header))];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bundle_state {
|
enum bundle_state {
|
||||||
@@ -55,30 +64,32 @@ struct ofp_bundle {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static inline struct ofp_bundle_entry *ofp_bundle_entry_alloc(
|
static inline struct ofp_bundle_entry *ofp_bundle_entry_alloc(
|
||||||
enum ofptype type, ovs_be32 xid);
|
enum ofptype type, const struct ofp_header *oh);
|
||||||
static inline void ofp_bundle_entry_free(struct ofp_bundle_entry *);
|
static inline void ofp_bundle_entry_free(struct ofp_bundle_entry *);
|
||||||
|
|
||||||
enum ofperr ofp_bundle_open(struct ofconn *, uint32_t id, uint16_t flags);
|
enum ofperr ofp_bundle_open(struct ofconn *, uint32_t id, uint16_t flags);
|
||||||
enum ofperr ofp_bundle_close(struct ofconn *, uint32_t id, uint16_t flags);
|
enum ofperr ofp_bundle_close(struct ofconn *, uint32_t id, uint16_t flags);
|
||||||
enum ofperr ofp_bundle_commit(struct ofconn *, uint32_t id, uint16_t flags);
|
|
||||||
enum ofperr ofp_bundle_discard(struct ofconn *, uint32_t id);
|
enum ofperr ofp_bundle_discard(struct ofconn *, uint32_t id);
|
||||||
enum ofperr ofp_bundle_add_message(struct ofconn *, uint32_t id,
|
enum ofperr ofp_bundle_add_message(struct ofconn *, uint32_t id,
|
||||||
uint16_t flags, struct ofp_bundle_entry *);
|
uint16_t flags, struct ofp_bundle_entry *);
|
||||||
|
|
||||||
void ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle);
|
void ofp_bundle_remove__(struct ofconn *, struct ofp_bundle *, bool success);
|
||||||
|
|
||||||
static inline struct ofp_bundle_entry *
|
static inline struct ofp_bundle_entry *
|
||||||
ofp_bundle_entry_alloc(enum ofptype type, ovs_be32 xid)
|
ofp_bundle_entry_alloc(enum ofptype type, const struct ofp_header *oh)
|
||||||
{
|
{
|
||||||
struct ofp_bundle_entry *entry = xmalloc(sizeof *entry);
|
struct ofp_bundle_entry *entry = xmalloc(sizeof *entry);
|
||||||
|
|
||||||
entry->xid = xid;
|
|
||||||
entry->type = type;
|
entry->type = type;
|
||||||
|
|
||||||
|
/* Max 64 bytes for error reporting. */
|
||||||
|
memcpy(entry->ofp_msg, oh, MIN(ntohs(oh->length), sizeof entry->ofp_msg));
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ofp_bundle_entry_free(struct ofp_bundle_entry *entry)
|
static inline void
|
||||||
|
ofp_bundle_entry_free(struct ofp_bundle_entry *entry)
|
||||||
{
|
{
|
||||||
if (entry) {
|
if (entry) {
|
||||||
if (entry->type == OFPTYPE_FLOW_MOD) {
|
if (entry->type == OFPTYPE_FLOW_MOD) {
|
||||||
|
@@ -1215,7 +1215,7 @@ bundle_remove_all(struct ofconn *ofconn)
|
|||||||
struct ofp_bundle *b, *next;
|
struct ofp_bundle *b, *next;
|
||||||
|
|
||||||
HMAP_FOR_EACH_SAFE (b, next, node, &ofconn->bundles) {
|
HMAP_FOR_EACH_SAFE (b, next, node, &ofconn->bundles) {
|
||||||
ofp_bundle_remove__(ofconn, b);
|
ofp_bundle_remove__(ofconn, b, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -253,9 +253,6 @@ struct flow_mod_requester {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* OpenFlow. */
|
/* OpenFlow. */
|
||||||
static enum ofperr add_flow(struct ofproto *, struct ofputil_flow_mod *,
|
|
||||||
const struct flow_mod_requester *);
|
|
||||||
|
|
||||||
static enum ofperr modify_flow_check__(struct ofproto *,
|
static enum ofperr modify_flow_check__(struct ofproto *,
|
||||||
struct ofputil_flow_mod *,
|
struct ofputil_flow_mod *,
|
||||||
const struct rule *)
|
const struct rule *)
|
||||||
@@ -281,6 +278,15 @@ static bool ofproto_group_exists(const struct ofproto *ofproto,
|
|||||||
OVS_EXCLUDED(ofproto->groups_rwlock);
|
OVS_EXCLUDED(ofproto->groups_rwlock);
|
||||||
static enum ofperr add_group(struct ofproto *, struct ofputil_group_mod *);
|
static enum ofperr add_group(struct ofproto *, struct ofputil_group_mod *);
|
||||||
static void handle_openflow(struct ofconn *, const struct ofpbuf *);
|
static void handle_openflow(struct ofconn *, const struct ofpbuf *);
|
||||||
|
static enum ofperr do_bundle_flow_mod_begin(struct ofproto *,
|
||||||
|
struct ofputil_flow_mod *,
|
||||||
|
struct ofp_bundle_entry *)
|
||||||
|
OVS_REQUIRES(ofproto_mutex);
|
||||||
|
static void do_bundle_flow_mod_finish(struct ofproto *,
|
||||||
|
struct ofputil_flow_mod *,
|
||||||
|
const struct flow_mod_requester *,
|
||||||
|
struct ofp_bundle_entry *)
|
||||||
|
OVS_REQUIRES(ofproto_mutex);
|
||||||
static enum ofperr handle_flow_mod__(struct ofproto *,
|
static enum ofperr handle_flow_mod__(struct ofproto *,
|
||||||
struct ofputil_flow_mod *,
|
struct ofputil_flow_mod *,
|
||||||
const struct flow_mod_requester *)
|
const struct flow_mod_requester *)
|
||||||
@@ -4338,6 +4344,17 @@ set_conjunctions(struct rule *rule, const struct cls_conjunction *conjs,
|
|||||||
cls_rule_set_conjunctions(cr, conjs, n_conjs);
|
cls_rule_set_conjunctions(cr, conjs, n_conjs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implements OFPFC_ADD and the cases for OFPFC_MODIFY and OFPFC_MODIFY_STRICT
|
||||||
|
* in which no matching flow already exists in the flow table.
|
||||||
|
*
|
||||||
|
* Adds the flow specified by 'fm', to the ofproto's flow table. Returns 0 on
|
||||||
|
* success, or an OpenFlow error code on failure.
|
||||||
|
*
|
||||||
|
* On successful return the caller must complete the operation either by
|
||||||
|
* calling add_flow_finish(), or add_flow_revert() if the operation needs to
|
||||||
|
* be reverted.
|
||||||
|
*
|
||||||
|
* The caller retains ownership of 'fm->ofpacts'. */
|
||||||
static enum ofperr
|
static enum ofperr
|
||||||
add_flow_begin(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
add_flow_begin(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
||||||
struct rule **rulep, bool *modify)
|
struct rule **rulep, bool *modify)
|
||||||
@@ -4388,7 +4405,8 @@ add_flow_begin(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
|
|
||||||
cls_rule_init(&cr, &fm->match, fm->priority);
|
cls_rule_init(&cr, &fm->match, fm->priority);
|
||||||
|
|
||||||
/* Check for the existence of an identical rule. */
|
/* Check for the existence of an identical rule.
|
||||||
|
* This will not return rules earlier marked as 'to_be_removed'. */
|
||||||
rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls, &cr));
|
rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls, &cr));
|
||||||
if (rule) {
|
if (rule) {
|
||||||
/* Transform "add" into "modify" of an existing identical flow. */
|
/* Transform "add" into "modify" of an existing identical flow. */
|
||||||
@@ -4450,6 +4468,29 @@ add_flow_begin(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Revert the effects of add_flow_begin().
|
||||||
|
* 'new_rule' must be passed in as NULL, if no new rule was allocated and
|
||||||
|
* inserted to the classifier.
|
||||||
|
* Note: evictions cannot be reverted. */
|
||||||
|
static void
|
||||||
|
add_flow_revert(struct ofproto *ofproto, struct rule *new_rule)
|
||||||
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
|
{
|
||||||
|
/* Old rule was not changed yet, only need to revert a new rule. */
|
||||||
|
if (new_rule) {
|
||||||
|
struct oftable *table = &ofproto->tables[new_rule->table_id];
|
||||||
|
|
||||||
|
if (!classifier_remove(&table->cls, &new_rule->cr)) {
|
||||||
|
OVS_NOT_REACHED();
|
||||||
|
}
|
||||||
|
classifier_publish(&table->cls);
|
||||||
|
|
||||||
|
ofproto_rule_remove__(ofproto, new_rule);
|
||||||
|
ofproto->ofproto_class->rule_delete(new_rule);
|
||||||
|
ofproto_rule_unref(new_rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_flow_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
add_flow_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
||||||
const struct flow_mod_requester *req,
|
const struct flow_mod_requester *req,
|
||||||
@@ -4489,30 +4530,6 @@ add_flow_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
|
|
||||||
send_buffered_packet(req, fm->buffer_id, rule);
|
send_buffered_packet(req, fm->buffer_id, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implements OFPFC_ADD and the cases for OFPFC_MODIFY and OFPFC_MODIFY_STRICT
|
|
||||||
* in which no matching flow already exists in the flow table.
|
|
||||||
*
|
|
||||||
* Adds the flow specified by 'fm', to the ofproto's flow table. Returns 0 on
|
|
||||||
* success, or an OpenFlow error code on failure.
|
|
||||||
*
|
|
||||||
* The caller retains ownership of 'fm->ofpacts'. */
|
|
||||||
static enum ofperr
|
|
||||||
add_flow(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|
||||||
const struct flow_mod_requester *req)
|
|
||||||
OVS_REQUIRES(ofproto_mutex)
|
|
||||||
{
|
|
||||||
struct rule *rule;
|
|
||||||
bool modify;
|
|
||||||
enum ofperr error;
|
|
||||||
|
|
||||||
error = add_flow_begin(ofproto, fm, &rule, &modify);
|
|
||||||
if (!error) {
|
|
||||||
add_flow_finish(ofproto, fm, req, rule, modify);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OFPFC_MODIFY and OFPFC_MODIFY_STRICT. */
|
/* OFPFC_MODIFY and OFPFC_MODIFY_STRICT. */
|
||||||
|
|
||||||
@@ -4741,6 +4758,17 @@ modify_flows_begin_loose(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
modify_flows_revert(struct ofproto *ofproto, struct rule_collection *rules)
|
||||||
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
|
{
|
||||||
|
/* Old rules were not changed yet, only need to revert a new rule. */
|
||||||
|
if (rules->n == 0 && rules->rules[0] != NULL) {
|
||||||
|
add_flow_revert(ofproto, rules->rules[0]);
|
||||||
|
}
|
||||||
|
rule_collection_destroy(rules);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
modify_flows_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
modify_flows_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
||||||
const struct flow_mod_requester *req,
|
const struct flow_mod_requester *req,
|
||||||
@@ -4756,22 +4784,6 @@ modify_flows_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
rule_collection_destroy(rules);
|
rule_collection_destroy(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ofperr
|
|
||||||
modify_flows_loose(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|
||||||
const struct flow_mod_requester *req)
|
|
||||||
OVS_REQUIRES(ofproto_mutex)
|
|
||||||
{
|
|
||||||
struct rule_collection rules;
|
|
||||||
enum ofperr error;
|
|
||||||
|
|
||||||
error = modify_flows_begin_loose(ofproto, fm, &rules);
|
|
||||||
if (!error) {
|
|
||||||
modify_flows_finish(ofproto, fm, req, &rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements OFPFC_MODIFY_STRICT. Returns 0 on success or an OpenFlow error
|
/* Implements OFPFC_MODIFY_STRICT. Returns 0 on success or an OpenFlow error
|
||||||
* code on failure. */
|
* code on failure. */
|
||||||
static enum ofperr
|
static enum ofperr
|
||||||
@@ -4799,23 +4811,6 @@ modify_flow_begin_strict(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ofperr
|
|
||||||
modify_flow_strict(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|
||||||
const struct flow_mod_requester *req)
|
|
||||||
OVS_REQUIRES(ofproto_mutex)
|
|
||||||
{
|
|
||||||
struct rule_collection rules;
|
|
||||||
enum ofperr error;
|
|
||||||
|
|
||||||
error = modify_flow_begin_strict(ofproto, fm, &rules);
|
|
||||||
if (!error) {
|
|
||||||
modify_flows_finish(ofproto, fm, req, &rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* OFPFC_DELETE implementation. */
|
/* OFPFC_DELETE implementation. */
|
||||||
|
|
||||||
@@ -4894,6 +4889,18 @@ delete_flows_begin_loose(struct ofproto *ofproto,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
delete_flows_revert(struct rule_collection *rules)
|
||||||
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < rules->n; i++) {
|
||||||
|
struct rule *rule = rules->rules[i];
|
||||||
|
|
||||||
|
CONST_CAST(struct cls_rule *, &rule->cr)->to_be_removed = false;
|
||||||
|
}
|
||||||
|
rule_collection_destroy(rules);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
delete_flows_finish(const struct ofputil_flow_mod *fm,
|
delete_flows_finish(const struct ofputil_flow_mod *fm,
|
||||||
const struct flow_mod_requester *req,
|
const struct flow_mod_requester *req,
|
||||||
@@ -4904,23 +4911,6 @@ delete_flows_finish(const struct ofputil_flow_mod *fm,
|
|||||||
rule_collection_destroy(rules);
|
rule_collection_destroy(rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ofperr
|
|
||||||
delete_flows_loose(struct ofproto *ofproto,
|
|
||||||
const struct ofputil_flow_mod *fm,
|
|
||||||
const struct flow_mod_requester *req)
|
|
||||||
OVS_REQUIRES(ofproto_mutex)
|
|
||||||
{
|
|
||||||
struct rule_collection rules;
|
|
||||||
enum ofperr error;
|
|
||||||
|
|
||||||
error = delete_flows_begin_loose(ofproto, fm, &rules);
|
|
||||||
if (!error) {
|
|
||||||
delete_flows_finish(fm, req, &rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements OFPFC_DELETE_STRICT. */
|
/* Implements OFPFC_DELETE_STRICT. */
|
||||||
static enum ofperr
|
static enum ofperr
|
||||||
delete_flow_begin_strict(struct ofproto *ofproto,
|
delete_flow_begin_strict(struct ofproto *ofproto,
|
||||||
@@ -4950,22 +4940,6 @@ delete_flow_begin_strict(struct ofproto *ofproto,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ofperr
|
|
||||||
delete_flow_strict(struct ofproto *ofproto, const struct ofputil_flow_mod *fm,
|
|
||||||
const struct flow_mod_requester *req)
|
|
||||||
OVS_REQUIRES(ofproto_mutex)
|
|
||||||
{
|
|
||||||
struct rule_collection rules;
|
|
||||||
enum ofperr error;
|
|
||||||
|
|
||||||
error = delete_flow_begin_strict(ofproto, fm, &rules);
|
|
||||||
if (!error) {
|
|
||||||
delete_flows_finish(fm, req, &rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ofproto_rule_send_removed(struct rule *rule, uint8_t reason)
|
ofproto_rule_send_removed(struct rule *rule, uint8_t reason)
|
||||||
OVS_REQUIRES(ofproto_mutex)
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
@@ -5096,38 +5070,13 @@ handle_flow_mod__(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
|||||||
const struct flow_mod_requester *req)
|
const struct flow_mod_requester *req)
|
||||||
OVS_EXCLUDED(ofproto_mutex)
|
OVS_EXCLUDED(ofproto_mutex)
|
||||||
{
|
{
|
||||||
|
struct ofp_bundle_entry be;
|
||||||
enum ofperr error;
|
enum ofperr error;
|
||||||
|
|
||||||
ovs_mutex_lock(&ofproto_mutex);
|
ovs_mutex_lock(&ofproto_mutex);
|
||||||
switch (fm->command) {
|
error = do_bundle_flow_mod_begin(ofproto, fm, &be);
|
||||||
case OFPFC_ADD:
|
if (!error) {
|
||||||
error = add_flow(ofproto, fm, req);
|
do_bundle_flow_mod_finish(ofproto, fm, req, &be);
|
||||||
break;
|
|
||||||
|
|
||||||
case OFPFC_MODIFY:
|
|
||||||
error = modify_flows_loose(ofproto, fm, req);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OFPFC_MODIFY_STRICT:
|
|
||||||
error = modify_flow_strict(ofproto, fm, req);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OFPFC_DELETE:
|
|
||||||
error = delete_flows_loose(ofproto, fm, req);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OFPFC_DELETE_STRICT:
|
|
||||||
error = delete_flow_strict(ofproto, fm, req);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (fm->command > 0xff) {
|
|
||||||
VLOG_WARN_RL(&rl, "%s: flow_mod has explicit table_id but "
|
|
||||||
"flow_mod_table_id extension is not enabled",
|
|
||||||
ofproto->name);
|
|
||||||
}
|
|
||||||
error = OFPERR_OFPFMFC_BAD_COMMAND;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
ofmonitor_flush(ofproto->connmgr);
|
ofmonitor_flush(ofproto->connmgr);
|
||||||
ovs_mutex_unlock(&ofproto_mutex);
|
ovs_mutex_unlock(&ofproto_mutex);
|
||||||
@@ -6490,13 +6439,174 @@ handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
|
|||||||
return table_mod(ofproto, &tm);
|
return table_mod(ofproto, &tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum ofperr
|
||||||
|
do_bundle_flow_mod_begin(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
||||||
|
struct ofp_bundle_entry *be)
|
||||||
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
|
{
|
||||||
|
switch (fm->command) {
|
||||||
|
case OFPFC_ADD:
|
||||||
|
return add_flow_begin(ofproto, fm, &be->rule, &be->modify);
|
||||||
|
|
||||||
|
case OFPFC_MODIFY:
|
||||||
|
return modify_flows_begin_loose(ofproto, fm, &be->rules);
|
||||||
|
|
||||||
|
case OFPFC_MODIFY_STRICT:
|
||||||
|
return modify_flow_begin_strict(ofproto, fm, &be->rules);
|
||||||
|
|
||||||
|
case OFPFC_DELETE:
|
||||||
|
return delete_flows_begin_loose(ofproto, fm, &be->rules);
|
||||||
|
|
||||||
|
case OFPFC_DELETE_STRICT:
|
||||||
|
return delete_flow_begin_strict(ofproto, fm, &be->rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OFPERR_OFPFMFC_BAD_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_bundle_flow_mod_revert(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
||||||
|
struct ofp_bundle_entry *be)
|
||||||
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
|
{
|
||||||
|
switch (fm->command) {
|
||||||
|
case OFPFC_ADD:
|
||||||
|
add_flow_revert(ofproto, be->modify ? NULL : be->rule);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OFPFC_MODIFY:
|
||||||
|
case OFPFC_MODIFY_STRICT:
|
||||||
|
modify_flows_revert(ofproto, &be->rules);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OFPFC_DELETE:
|
||||||
|
case OFPFC_DELETE_STRICT:
|
||||||
|
delete_flows_revert(&be->rules);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_bundle_flow_mod_finish(struct ofproto *ofproto, struct ofputil_flow_mod *fm,
|
||||||
|
const struct flow_mod_requester *req,
|
||||||
|
struct ofp_bundle_entry *be)
|
||||||
|
OVS_REQUIRES(ofproto_mutex)
|
||||||
|
{
|
||||||
|
switch (fm->command) {
|
||||||
|
case OFPFC_ADD:
|
||||||
|
add_flow_finish(ofproto, fm, req, be->rule, be->modify);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OFPFC_MODIFY:
|
||||||
|
case OFPFC_MODIFY_STRICT:
|
||||||
|
modify_flows_finish(ofproto, fm, req, &be->rules);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OFPFC_DELETE:
|
||||||
|
case OFPFC_DELETE_STRICT:
|
||||||
|
delete_flows_finish(fm, req, &be->rules);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Commit phases (all while locking ofproto_mutex):
|
||||||
|
*
|
||||||
|
* 1. Gather resources - do not send any events or notifications.
|
||||||
|
*
|
||||||
|
* add: Check conflicts, check for a displaced flow. If no displaced flow
|
||||||
|
* exists, add the new flow, but mark it as "invisible".
|
||||||
|
* mod: Collect affected flows, Do not modify yet.
|
||||||
|
* del: Collect affected flows, Do not delete yet.
|
||||||
|
*
|
||||||
|
* 2a. Fail if any errors are found. After this point no errors are possible.
|
||||||
|
* No visible changes were made, so rollback is minimal (remove added invisible
|
||||||
|
* flows, revert 'to_be_removed' status of flows).
|
||||||
|
*
|
||||||
|
* 2b. Commit the changes
|
||||||
|
*
|
||||||
|
* add: if have displaced flow, modify it, otherwise mark the new flow as
|
||||||
|
* "visible".
|
||||||
|
* mod: Modify the collected flows.
|
||||||
|
* del: Delete the collected flows.
|
||||||
|
*/
|
||||||
|
static enum ofperr
|
||||||
|
do_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
|
||||||
|
{
|
||||||
|
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
|
||||||
|
struct ofp_bundle *bundle;
|
||||||
|
struct ofp_bundle_entry *be;
|
||||||
|
enum ofperr error;
|
||||||
|
|
||||||
|
bundle = ofconn_get_bundle(ofconn, id);
|
||||||
|
|
||||||
|
if (!bundle) {
|
||||||
|
return OFPERR_OFPBFC_BAD_ID;
|
||||||
|
}
|
||||||
|
if (bundle->flags != flags) {
|
||||||
|
error = OFPERR_OFPBFC_BAD_FLAGS;
|
||||||
|
} else {
|
||||||
|
error = 0;
|
||||||
|
ovs_mutex_lock(&ofproto_mutex);
|
||||||
|
LIST_FOR_EACH (be, node, &bundle->msg_list) {
|
||||||
|
if (be->type == OFPTYPE_PORT_MOD) {
|
||||||
|
/* Not supported yet. */
|
||||||
|
error = OFPERR_OFPBFC_MSG_FAILED;
|
||||||
|
} else if (be->type == OFPTYPE_FLOW_MOD) {
|
||||||
|
error = do_bundle_flow_mod_begin(ofproto, &be->fm, be);
|
||||||
|
} else {
|
||||||
|
OVS_NOT_REACHED();
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
/* Send error referring to the original message. */
|
||||||
|
if (error) {
|
||||||
|
ofconn_send_error(ofconn, be->ofp_msg, error);
|
||||||
|
error = OFPERR_OFPBFC_MSG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Revert all previous entires. */
|
||||||
|
LIST_FOR_EACH_REVERSE_CONTINUE(be, node, &bundle->msg_list) {
|
||||||
|
if (be->type == OFPTYPE_FLOW_MOD) {
|
||||||
|
do_bundle_flow_mod_revert(ofproto, &be->fm, be);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Finish the changes. */
|
||||||
|
LIST_FOR_EACH (be, node, &bundle->msg_list) {
|
||||||
|
if (be->type == OFPTYPE_FLOW_MOD) {
|
||||||
|
struct flow_mod_requester req = { ofconn, be->ofp_msg };
|
||||||
|
|
||||||
|
do_bundle_flow_mod_finish(ofproto, &be->fm, &req, be);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ofmonitor_flush(ofproto->connmgr);
|
||||||
|
ovs_mutex_unlock(&ofproto_mutex);
|
||||||
|
|
||||||
|
run_rule_executes(ofproto);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The bundle is discarded regardless the outcome. */
|
||||||
|
ofp_bundle_remove__(ofconn, bundle, !error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
static enum ofperr
|
static enum ofperr
|
||||||
handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh)
|
handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh)
|
||||||
{
|
{
|
||||||
enum ofperr error;
|
|
||||||
struct ofputil_bundle_ctrl_msg bctrl;
|
struct ofputil_bundle_ctrl_msg bctrl;
|
||||||
struct ofpbuf *buf;
|
|
||||||
struct ofputil_bundle_ctrl_msg reply;
|
struct ofputil_bundle_ctrl_msg reply;
|
||||||
|
struct ofpbuf *buf;
|
||||||
|
enum ofperr error;
|
||||||
|
|
||||||
error = reject_slave_controller(ofconn);
|
error = reject_slave_controller(ofconn);
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -6507,6 +6617,10 @@ handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh)
|
|||||||
if (error) {
|
if (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
/* Atomic updates not supported yet. */
|
||||||
|
if (bctrl.flags & OFPBF_ATOMIC) {
|
||||||
|
return OFPERR_OFPBFC_BAD_FLAGS;
|
||||||
|
}
|
||||||
reply.flags = 0;
|
reply.flags = 0;
|
||||||
reply.bundle_id = bctrl.bundle_id;
|
reply.bundle_id = bctrl.bundle_id;
|
||||||
|
|
||||||
@@ -6520,7 +6634,7 @@ handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh)
|
|||||||
reply.type = OFPBCT_CLOSE_REPLY;;
|
reply.type = OFPBCT_CLOSE_REPLY;;
|
||||||
break;
|
break;
|
||||||
case OFPBCT_COMMIT_REQUEST:
|
case OFPBCT_COMMIT_REQUEST:
|
||||||
error = ofp_bundle_commit(ofconn, bctrl.bundle_id, bctrl.flags);
|
error = do_bundle_commit(ofconn, bctrl.bundle_id, bctrl.flags);
|
||||||
reply.type = OFPBCT_COMMIT_REPLY;
|
reply.type = OFPBCT_COMMIT_REPLY;
|
||||||
break;
|
break;
|
||||||
case OFPBCT_DISCARD_REQUEST:
|
case OFPBCT_DISCARD_REQUEST:
|
||||||
@@ -6562,7 +6676,7 @@ handle_bundle_add(struct ofconn *ofconn, const struct ofp_header *oh)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bmsg = ofp_bundle_entry_alloc(type, badd.msg->xid);
|
bmsg = ofp_bundle_entry_alloc(type, badd.msg);
|
||||||
|
|
||||||
if (type == OFPTYPE_PORT_MOD) {
|
if (type == OFPTYPE_PORT_MOD) {
|
||||||
error = ofputil_decode_port_mod(badd.msg, &bmsg->pm, false);
|
error = ofputil_decode_port_mod(badd.msg, &bmsg->pm, false);
|
||||||
|
@@ -3227,13 +3227,13 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Send an OpenFlow14 message (05), OFPT_BUNDLE_CONTROL (21), length (10), xid (0a)
|
# Send an OpenFlow14 message (05), OFPT_BUNDLE_CONTROL (21), length (10), xid (0a)
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REPLY flags=0
|
bundle_id=0x1 type=OPEN_REPLY flags=0
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
@@ -3251,23 +3251,23 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Send twice an OpenFlow14 message (05), OFPT_BUNDLE_CONTROL (21), length (10), xid (0a)
|
# Send twice an OpenFlow14 message (05), OFPT_BUNDLE_CONTROL (21), length (10), xid (0a)
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REPLY flags=0
|
bundle_id=0x1 type=OPEN_REPLY flags=0
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -3282,16 +3282,16 @@ OVS_VSWITCHD_START
|
|||||||
ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2>&1
|
ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2>&1
|
||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -3307,30 +3307,30 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Open, Close, Close
|
# Open, Close, Close
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REPLY flags=0
|
bundle_id=0x1 type=OPEN_REPLY flags=0
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REPLY flags=0
|
bundle_id=0x1 type=CLOSE_REPLY flags=0
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BUNDLE_CLOSED
|
OFPT_ERROR (OF1.4): OFPBFC_BUNDLE_CLOSED
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -3346,23 +3346,23 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Open, Close, Close
|
# Open, Close, Close
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 02"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 02 00 01"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REPLY flags=0
|
bundle_id=0x1 type=OPEN_REPLY flags=0
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BAD_FLAGS
|
OFPT_ERROR (OF1.4): OFPBFC_BAD_FLAGS
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=CLOSE_REQUEST flags=ordered
|
bundle_id=0x1 type=CLOSE_REQUEST flags=atomic
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -3378,16 +3378,16 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Open, Close, Close
|
# Open, Close, Close
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 04 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 04 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=COMMIT_REQUEST flags=atomic
|
bundle_id=0x1 type=COMMIT_REQUEST flags=ordered
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=COMMIT_REQUEST flags=atomic
|
bundle_id=0x1 type=COMMIT_REQUEST flags=ordered
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -3403,23 +3403,23 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Open, Close, Close
|
# Open, Close, Close
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 00 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 04 00 02"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 04 00 01"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REQUEST flags=atomic
|
bundle_id=0x1 type=OPEN_REQUEST flags=ordered
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=OPEN_REPLY flags=0
|
bundle_id=0x1 type=OPEN_REPLY flags=0
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=COMMIT_REQUEST flags=ordered
|
bundle_id=0x1 type=COMMIT_REQUEST flags=atomic
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BAD_FLAGS
|
OFPT_ERROR (OF1.4): OFPBFC_BAD_FLAGS
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=COMMIT_REQUEST flags=ordered
|
bundle_id=0x1 type=COMMIT_REQUEST flags=atomic
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -3435,16 +3435,16 @@ ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 2
|
|||||||
AT_CAPTURE_FILE([monitor.log])
|
AT_CAPTURE_FILE([monitor.log])
|
||||||
|
|
||||||
# Open, Close, Close
|
# Open, Close, Close
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 06 00 01"
|
ovs-appctl -t ovs-ofctl ofctl/send "05 21 00 10 00 00 00 0a 00 00 00 01 00 06 00 02"
|
||||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||||
ovs-appctl -t ovs-ofctl exit
|
ovs-appctl -t ovs-ofctl exit
|
||||||
|
|
||||||
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
AT_CHECK([ofctl_strip < monitor.log], [0], [dnl
|
||||||
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
send: OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=DISCARD_REQUEST flags=atomic
|
bundle_id=0x1 type=DISCARD_REQUEST flags=ordered
|
||||||
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
OFPT_ERROR (OF1.4): OFPBFC_BAD_ID
|
||||||
OFPT_BUNDLE_CONTROL (OF1.4):
|
OFPT_BUNDLE_CONTROL (OF1.4):
|
||||||
bundle_id=0x1 type=DISCARD_REQUEST flags=atomic
|
bundle_id=0x1 type=DISCARD_REQUEST flags=ordered
|
||||||
OFPT_BARRIER_REPLY (OF1.4):
|
OFPT_BARRIER_REPLY (OF1.4):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user