Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 lib/ofp-msgs.c    |   3 +-
 ofproto/ofproto.c |  63 +++++++++++++++++++---------
 tests/ofproto.at  | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+), 21 deletions(-)

diff --git a/lib/ofp-msgs.c b/lib/ofp-msgs.c
index 29f9770..91650b9 100644
--- a/lib/ofp-msgs.c
+++ b/lib/ofp-msgs.c
@@ -915,8 +915,7 @@ ofpmsg_is_mp_request(const struct ofp_header *oh)
 bool
 ofpmsg_may_buffer_mp_request(enum ofptype type OVS_UNUSED)
 {
-    /* Currently no types are allowed to be buffered. */
-    return false;
+    return type == OFPTYPE_FLOW_MONITOR_STATS_REQUEST;
 }
 
 static ovs_be16 *ofpmp_flags__(const struct ofp_header *);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index f8d2690..c930243 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4906,21 +4906,17 @@ flow_monitor_delete(struct ofconn *ofconn, uint32_t id)
 }
 
 static enum ofperr
-handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh)
-    OVS_EXCLUDED(ofproto_mutex)
+handle_one_flow_monitor_request(struct ofconn *ofconn,
+                                const struct ofp_header *oh,
+                                struct list *monitor_list)
+    OVS_REQUIRES(ofproto_mutex)
 {
-    struct list monitor_list = LIST_INITIALIZER(&monitor_list);
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
-    struct rule_collection rules;
-    struct list replies;
-    struct ofmonitor *m, *next;
-    enum ofperr error;
+    struct ofmonitor *m;
     struct ofpbuf b;
 
-    error = 0;
     ofpbuf_use_const(&b, oh, ntohs(oh->length));
 
-    ovs_mutex_lock(&ofproto_mutex);
     for (;;) {
         struct ofputil_flow_monitor_request request;
         int retval;
@@ -4929,32 +4925,61 @@ handle_flow_monitor_request(struct ofconn *ofconn, 
const struct ofp_header *oh)
         if (retval == EOF) {
             break;
         } else if (retval) {
-            error = retval;
-            goto error;
+            return retval;
         }
 
         if (request.table_id != 0xff
             && request.table_id >= ofproto->n_tables) {
-            error = OFPERR_OFPBRC_BAD_TABLE_ID;
-            goto error;
+            return OFPERR_OFPBRC_BAD_TABLE_ID;
         }
 
         if (request.command == OFPFMC14_DELETE ||
             request.command == OFPFMC14_MODIFY) {
-            error = flow_monitor_delete(ofconn, request.id);
+            enum ofperr error = flow_monitor_delete(ofconn, request.id);
             if (error) {
-                goto error;
+                return error;
             }
         }
 
         if (request.command == OFPFMC14_ADD ||
             request.command == OFPFMC14_MODIFY) {
-            error = ofmonitor_create(&request, ofconn, &m);
+            enum ofperr error = ofmonitor_create(&request, ofconn, &m);
             if (error) {
-                goto error;
+                return error;
             }
 
-            list_insert(&monitor_list, &m->list_node);
+            list_insert(monitor_list, &m->list_node);
+        }
+    }
+
+    return 0;
+}
+
+static enum ofperr
+handle_flow_monitor_request(struct ofconn *ofconn, const struct ofpbuf *msg)
+    OVS_EXCLUDED(ofproto_mutex)
+{
+    struct list monitor_list = LIST_INITIALIZER(&monitor_list);
+    const struct ofp_header *oh = ofpbuf_data(msg);
+    struct rule_collection rules;
+    struct list replies;
+    struct ofmonitor *m, *next;
+    enum ofperr error;
+    struct ofpbuf *b;
+
+    error = 0;
+
+    ovs_mutex_lock(&ofproto_mutex);
+
+    /* First part of multi-part request */
+    handle_one_flow_monitor_request(ofconn, oh, &monitor_list);
+
+    /* Any subsequent parts */
+    LIST_FOR_EACH (b, list_node, &msg->list_node) {
+        error = handle_one_flow_monitor_request(ofconn, ofpbuf_data(b),
+                                                &monitor_list);
+        if (error) {
+            goto error;
         }
     }
 
@@ -6025,7 +6050,7 @@ handle_openflow__(struct ofconn *ofconn, const struct 
ofpbuf *msg)
         return handle_port_desc_stats_request(ofconn, oh);
 
     case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
-        return handle_flow_monitor_request(ofconn, oh);
+        return handle_flow_monitor_request(ofconn, msg);
 
     case OFPTYPE_METER_STATS_REQUEST:
     case OFPTYPE_METER_CONFIG_STATS_REQUEST:
diff --git a/tests/ofproto.at b/tests/ofproto.at
index af48809..18fe0e7 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -3583,3 +3583,125 @@ OFPT_BARRIER_REPLY (OF1.4):
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_SETUP([ofproto - multipart flow monitor request (OpenFlow 1.3)])
+AT_KEYWORDS([monitor])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], [1], [2], [3])
+
+# Start a monitor, use the required protocol version
+ovs-ofctl -O OpenFlow13 monitor br0 --detach --no-chdir --pidfile >monitor.log 
2>&1
+AT_CAPTURE_FILE([monitor.log])
+
+# Send first part: monitor actions with dl_vlan=7
+ovs-appctl -t ovs-ofctl ofctl/send "\
+04 12 00 30 00 00 00 01 ff ff 00 01 00 00 00 00 \
+4f 4e 46 00 00 00 07 4e 00 00 00 07 00 1f 00 06 \
+ff ff ff ff 00 00 00 00 80 00 0c 02 10 07 00 00 \
+"
+
+# Send second part: monitor actions with dl_vlan=8
+ovs-appctl -t ovs-ofctl ofctl/send "\
+04 12 00 30 00 00 00 01 ff ff 00 01 00 00 00 00 \
+4f 4e 46 00 00 00 07 4e 00 00 00 08 00 1f 00 06 \
+ff ff ff ff 00 00 00 00 80 00 0c 02 10 08 00 00 \
+"
+
+# Send third part: monitor actions with dl_vlan=9
+ovs-appctl -t ovs-ofctl ofctl/send "\
+04 12 00 30 00 00 00 01 ff ff 00 00 00 00 00 00 \
+4f 4e 46 00 00 00 07 4e 00 00 00 09 00 1f 00 06 \
+ff ff ff ff 00 00 00 00 80 00 0c 02 10 09 00 00 \
+"
+
+ovs-appctl -t ovs-ofctl ofctl/barrier
+
+# Create some evnents that should be monitored
+ovs-ofctl -O OpenFlow13 add-flow br0 in_port=0,dl_vlan=7,actions=output:2
+ovs-ofctl -O OpenFlow13 add-flow br0 in_port=0,dl_vlan=8,actions=output:2
+ovs-ofctl -O OpenFlow13 add-flow br0 in_port=0,dl_vlan=9,actions=output:2
+
+# Check default setting
+read -r -d '' expected <<'EOF'
+EOF
+
+AT_CHECK([ofctl_strip < monitor.log ], [], [dnl
+send: ONFST_FLOW_MONITOR request (OF1.3):
+ id=7 flags=initial,add,delete,modify,actions table=0 dl_vlan=7
+send: ONFST_FLOW_MONITOR request (OF1.3):
+ id=8 flags=initial,add,delete,modify,actions table=0 dl_vlan=8
+send: ONFST_FLOW_MONITOR request (OF1.3):
+ id=9 flags=initial,add,delete,modify,actions table=0 dl_vlan=9
+ONFST_FLOW_MONITOR reply (OF1.3):
+OFPT_BARRIER_REPLY (OF1.3):
+ONFST_FLOW_MONITOR reply (OF1.3):
+ event=ADDED table=0 cookie=0 in_port=0,dl_vlan=7 actions=output:2
+ONFST_FLOW_MONITOR reply (OF1.3):
+ event=ADDED table=0 cookie=0 in_port=0,dl_vlan=8 actions=output:2
+ONFST_FLOW_MONITOR reply (OF1.3):
+ event=ADDED table=0 cookie=0 in_port=0,dl_vlan=9 actions=output:2
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - multipart flow monitor request (OpenFlow 1.4)])
+AT_KEYWORDS([monitor])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], [1], [2], [3])
+
+# Start a monitor, use the required protocol version
+ovs-ofctl -O OpenFlow14 monitor br0 --detach --no-chdir --pidfile >monitor.log 
2>&1
+AT_CAPTURE_FILE([monitor.log])
+
+# Send first part: monitor actions with dl_vlan=7
+ovs-appctl -t ovs-ofctl ofctl/send "\
+05 12 00 30 00 00 00 02 00 10 00 01 00 00 00 00 \
+00 00 00 01 ff ff ff ff ff ff ff ff 00 1f 00 00 \
+00 01 00 0a 80 00 0c 02 10 07 00 00 00 00 00 00 \
+"
+
+# Send second part: monitor actions with dl_vlan=8
+ovs-appctl -t ovs-ofctl ofctl/send "\
+05 12 00 30 00 00 00 02 00 10 00 01 00 00 00 00 \
+00 00 00 02 ff ff ff ff ff ff ff ff 00 1f 00 00 \
+00 01 00 0a 80 00 0c 02 10 08 00 00 00 00 00 00 \
+"
+
+# Send third part: monitor actions with dl_vlan=9
+ovs-appctl -t ovs-ofctl ofctl/send "\
+05 12 00 30 00 00 00 02 00 10 00 00 00 00 00 00 \
+00 00 00 03 ff ff ff ff ff ff ff ff 00 1f 00 00 \
+00 01 00 0a 80 00 0c 02 10 09 00 00 00 00 00 00 \
+"
+
+ovs-appctl -t ovs-ofctl ofctl/barrier
+
+# Create some evnents that should be monitored
+ovs-ofctl -O OpenFlow14 add-flow br0 in_port=0,dl_vlan=7,actions=output:2
+ovs-ofctl -O OpenFlow14 add-flow br0 in_port=0,dl_vlan=8,actions=output:2
+ovs-ofctl -O OpenFlow14 add-flow br0 in_port=0,dl_vlan=9,actions=output:2
+
+# Check default setting
+read -r -d '' expected <<'EOF'
+EOF
+
+AT_CHECK([ofctl_strip < monitor.log ], [], [dnl
+send: OFPST_FLOW_MONITOR request (OF1.4):
+ command=ADD id=1 flags=initial,add,delete,modify,instructions table=0 
dl_vlan=7
+send: OFPST_FLOW_MONITOR request (OF1.4):
+ command=ADD id=2 flags=initial,add,delete,modify,instructions table=0 
dl_vlan=8
+send: OFPST_FLOW_MONITOR request (OF1.4):
+ command=ADD id=3 flags=initial,add,delete,modify,instructions table=0 
dl_vlan=9
+OFPST_FLOW_MONITOR reply (OF1.4):
+OFPT_BARRIER_REPLY (OF1.4):
+OFPST_FLOW_MONITOR reply (OF1.4):
+ event=ADDED table=0 cookie=0 in_port=0,dl_vlan=7 actions=output:2
+OFPST_FLOW_MONITOR reply (OF1.4):
+ event=ADDED table=0 cookie=0 in_port=0,dl_vlan=8 actions=output:2
+OFPST_FLOW_MONITOR reply (OF1.4):
+ event=ADDED table=0 cookie=0 in_port=0,dl_vlan=9 actions=output:2
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
-- 
2.0.0.rc2

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to