[ovs-dev] [PATCH v3 10/41] ofproto: Handle monitor and delete commands in flow monitor requests
Simon Horman
horms at verge.net.au
Wed Jun 25 09:22:30 UTC 2014
On Mon, Jun 23, 2014 at 05:14:52PM -0700, Ben Pfaff wrote:
> On Mon, Jun 16, 2014 at 11:29:30AM +0900, Simon Horman wrote:
> > Handle modify and delete commands in OpenFlow1.4 flow monitor requests.
> > These commands are not yet allowed by the decoder which
> > will be updated by a subsequent patch.
> >
> > Signed-off-by: Simon Horman <horms at verge.net.au>
> >
> > ---
> > v2
> > * No change
> > ---
> > ofproto/ofproto.c | 19 +++++++++++++++----
> > 1 file changed, 15 insertions(+), 4 deletions(-)
> >
> > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> > index 3153e71..211f45e 100644
> > --- a/ofproto/ofproto.c
> > +++ b/ofproto/ofproto.c
> > @@ -4880,12 +4880,23 @@ handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh)
> > goto error;
> > }
> >
> > - error = ofmonitor_create(&request, ofconn, &m);
> > - if (error) {
> > - goto error;
> > + if (request.command == OFPFMC14_DELETE ||
> > + request.command == OFPFMC14_MODIFY) {
> > + error = flow_monitor_delete(ofconn, request.id);
> > + if (error) {
> > + goto error;
> > + }
> > }
> >
> > - list_insert(&monitor_list, &m->list_node);
> > + if (request.command == OFPFMC14_ADD ||
> > + request.command == OFPFMC14_MODIFY) {
> > + error = ofmonitor_create(&request, ofconn, &m);
> > + if (error) {
> > + goto error;
> > + }
> > +
> > + list_insert(&monitor_list, &m->list_node);
> > + }
> > }
> >
> > rule_collection_init(&rules);
>
> I think that this is correct, but this way it is written makes it look
> like a "modify" could fail in the middle with the monitor deleted and
> not re-created. That can't actually happen because ofmonitor_create()
> only fails if there's a duplicate id. I'd rather have to code written
> to be more obviously correct. (One way to do that would be to have an
> ofmonitor_modify() function, I guess, but there might be other ways
> too.)
Thanks, I understand and agree that is good to make things obvious.
I've taken a stab at implementing ofmonitor_modify() in the incremental
change below. Its a bit noisy because of shuffling some existing
infrastructure around. But would something like this address your concern?
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 8891a06..6f8eea3 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -2012,19 +2012,27 @@ static uint64_t monitor_seqno = 1;
COVERAGE_DEFINE(ofmonitor_pause);
COVERAGE_DEFINE(ofmonitor_resume);
-enum ofperr
-ofmonitor_create(const struct ofputil_flow_monitor_request *request,
- struct ofconn *ofconn, struct ofmonitor **monitorp)
+static struct ofmonitor *
+ofmonitor_lookup(struct ofconn *ofconn, uint32_t id)
OVS_REQUIRES(ofproto_mutex)
{
struct ofmonitor *m;
- *monitorp = NULL;
-
- m = ofmonitor_lookup(ofconn, request->id);
- if (m) {
- return OFPERR_OFPMOFC_MONITOR_EXISTS;
+ HMAP_FOR_EACH_IN_BUCKET (m, ofconn_node, hash_int(id, 0),
+ &ofconn->monitors) {
+ if (m->id == id) {
+ return m;
+ }
}
+ return NULL;
+}
+
+static struct ofmonitor *
+ofmonitor_create__(const struct ofputil_flow_monitor_request *request,
+ struct ofconn *ofconn)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ struct ofmonitor *m;
m = xmalloc(sizeof *m);
m->ofconn = ofconn;
@@ -2037,23 +2045,59 @@ ofmonitor_create(const struct ofputil_flow_monitor_request *request,
minimatch_init(&m->match, &request->match);
list_init(&m->list_node);
- *monitorp = m;
+ return m;
+}
+
+enum ofperr
+ofmonitor_create(const struct ofputil_flow_monitor_request *request,
+ struct ofconn *ofconn, struct ofmonitor **monitorp)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ struct ofmonitor *m;
+
+ *monitorp = NULL;
+
+ m = ofmonitor_lookup(ofconn, request->id);
+ if (m) {
+ return OFPERR_OFPMOFC_MONITOR_EXISTS;
+ }
+
+ *monitorp = ofmonitor_create__(request, ofconn);
return 0;
}
-struct ofmonitor *
-ofmonitor_lookup(struct ofconn *ofconn, uint32_t id)
+enum ofperr
+ofmonitor_modify(const struct ofputil_flow_monitor_request *request,
+ struct ofconn *ofconn, struct ofmonitor **monitorp)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ enum ofperr error;
+
+ error = ofmonitor_delete(request->id, ofconn);
+ if (error) {
+ return error;
+ }
+
+ *monitorp = ofmonitor_create__(request, ofconn);
+ return 0;
+}
+
+enum ofperr
+ofmonitor_delete(uint32_t id, struct ofconn *ofconn)
OVS_REQUIRES(ofproto_mutex)
{
struct ofmonitor *m;
+ enum ofperr error;
- HMAP_FOR_EACH_IN_BUCKET (m, ofconn_node, hash_int(id, 0),
- &ofconn->monitors) {
- if (m->id == id) {
- return m;
- }
+ m = ofmonitor_lookup(ofconn, id);
+ if (m) {
+ ofmonitor_destroy(m);
+ error = 0;
+ } else {
+ error = OFPERR_OFPMOFC_UNKNOWN_MONITOR;
}
- return NULL;
+
+ return error;
}
void
diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
index df024e6..453163b 100644
--- a/ofproto/connmgr.h
+++ b/ofproto/connmgr.h
@@ -213,10 +213,13 @@ struct ofmonitor {
struct ofputil_flow_monitor_request;
-enum ofperr ofmonitor_create(const struct ofputil_flow_monitor_request *,
+enum ofperr ofmonitor_create(const struct ofputil_flow_monitor_request *request,
struct ofconn *, struct ofmonitor **)
OVS_REQUIRES(ofproto_mutex);
-struct ofmonitor *ofmonitor_lookup(struct ofconn *, uint32_t id)
+enum ofperr ofmonitor_modify(const struct ofputil_flow_monitor_request *request,
+ struct ofconn *, struct ofmonitor **)
+ OVS_REQUIRES(ofproto_mutex);
+enum ofperr ofmonitor_delete(uint32_t id, struct ofconn *)
OVS_REQUIRES(ofproto_mutex);
void ofmonitor_destroy(struct ofmonitor *)
OVS_REQUIRES(ofproto_mutex);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index b90abb5..8121b32 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4915,24 +4915,6 @@ ofmonitor_collect_resume_rules(struct ofmonitor *m,
}
static enum ofperr
-flow_monitor_delete(struct ofconn *ofconn, uint32_t id)
- OVS_REQUIRES(ofproto_mutex)
-{
- struct ofmonitor *m;
- enum ofperr error;
-
- m = ofmonitor_lookup(ofconn, id);
- if (m) {
- ofmonitor_destroy(m);
- error = 0;
- } else {
- error = OFPERR_OFPMOFC_UNKNOWN_MONITOR;
- }
-
- return error;
-}
-
-static enum ofperr
handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh)
OVS_EXCLUDED(ofproto_mutex)
{
@@ -4966,21 +4948,29 @@ handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh)
goto error;
}
- if (request.command == OFPFMC14_DELETE ||
- request.command == OFPFMC14_MODIFY) {
- error = flow_monitor_delete(ofconn, request.id);
- if (error) {
- goto error;
- }
+ m = NULL;
+ switch (request.command) {
+ case OFPFMC14_ADD:
+ error = ofmonitor_create(&request, ofconn, &m);
+ break;
+
+ case OFPFMC14_MODIFY:
+ error = ofmonitor_modify(&request, ofconn, &m);
+ break;
+
+ case OFPFMC14_DELETE:
+ error = ofmonitor_delete(request.id, ofconn);
+ break;
+
+ default:
+ OVS_NOT_REACHED();
}
- if (request.command == OFPFMC14_ADD ||
- request.command == OFPFMC14_MODIFY) {
- error = ofmonitor_create(&request, ofconn, &m);
- if (error) {
- goto error;
- }
+ if (error) {
+ goto error;
+ }
+ if (m) {
list_push_back(&monitor_list, &m->list_node);
}
}
@@ -5022,7 +5012,7 @@ handle_flow_monitor_cancel(struct ofconn *ofconn, const struct ofp_header *oh)
id = ofputil_decode_flow_monitor_cancel(oh);
ovs_mutex_lock(&ofproto_mutex);
- error = flow_monitor_delete(ofconn, id);
+ error = ofmonitor_delete(id, ofconn);
ovs_mutex_unlock(&ofproto_mutex);
return error;
More information about the dev
mailing list