Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 OPENFLOW-1.1+           |   6 ++-
 ofproto/ofproto.c       |  74 +++++++++++++++++++++-----------
 tests/ofproto-macros.at |   1 +
 tests/ofproto.at        | 109 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+), 27 deletions(-)

diff --git a/OPENFLOW-1.1+ b/OPENFLOW-1.1+
index 1789f17..979ee5c 100644
--- a/OPENFLOW-1.1+
+++ b/OPENFLOW-1.1+
@@ -82,8 +82,10 @@ following additional work.  (This is based on the change log 
at the
 end of the OF1.3 spec, reusing most of the section titles directly.  I
 didn't compare the specs carefully yet.)
 
-    * Add support for multipart requests.
-      Currently we always report OFPBRC_MULTIPART_BUFFER_OVERFLOW.
+    * Further support for multipart requests.
+      Multipart port stats desc stats requests are supported.
+      OFPBRC_MULTIPART_BUFFER_OVERFLOW is reported for other multipart
+      requests.
       [optional for OF1.3+]
 
     * Add OFPMP_TABLE_FEATURES statistics.  Alexander Wu has posted a
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index e3e1db9..f4c76bf 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -3194,51 +3194,75 @@ append_port_stat(struct ofport *port, struct list 
*replies)
 }
 
 static void
-handle_port_request__(struct ofconn *ofconn,
-                      const struct ofp_header *request, ofp_port_t port_no,
-                      void (*cb)(struct ofport *, struct list *replies))
+append_port_request(struct ofconn *ofconn, ofp_port_t port_no,
+                    struct list *replies,
+                    void (*cb)(struct ofport *, struct list *replies))
 {
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ofport *port;
-    struct list replies;
 
-    ofpmp_init(&replies, request);
     if (port_no != OFPP_ANY) {
         port = ofproto_get_port(ofproto, port_no);
         if (port) {
-            cb(port, &replies);
+            cb(port, replies);
         }
     } else {
         HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
-            cb(port, &replies);
+            cb(port, replies);
         }
     }
+}
 
-    ofconn_send_replies(ofconn, &replies);
+static enum ofperr
+handle_one_port_request(struct ofconn *ofconn,
+                        const struct ofp_header *request, struct list *replies,
+                        enum ofperr (*decode)(const struct ofp_header *,
+                                              ofp_port_t *),
+                        void (*append)(struct ofport *, struct list *replies))
+{
+    ofp_port_t port_no;
+    enum ofperr error;
+
+    error = decode(request, &port_no);
+    if (error) {
+      return error;
+    }
+
+    append_port_request(ofconn, port_no, replies, append);
+
+    return 0;
 }
 
 static enum ofperr
-handle_port_request(struct ofconn *ofconn,
-                    const struct ofp_header *request,
+handle_port_request(struct ofconn *ofconn, const struct ofpbuf *msg,
                     enum ofperr (*decode)(const struct ofp_header *,
                                           ofp_port_t *),
                     void (*append)(struct ofport *, struct list *replies))
 {
-    ofp_port_t port_no;
-    enum ofperr error;
+    const struct ofp_header *request = ofpbuf_data(msg);
+    struct list replies;
+    struct ofpbuf *b;
 
-    error = decode(request, &port_no);
-    if (!error) {
-        handle_port_request__(ofconn, request, port_no, append);
+    ofpmp_init(&replies, request);
+
+    /* First part of multi-part request */
+    handle_one_port_request(ofconn, request, &replies, decode, append);
+
+    /* Any subsequent parts */
+    LIST_FOR_EACH (b, list_node, &msg->list_node) {
+        request = ofpbuf_data(b);
+        handle_one_port_request(ofconn, request, &replies, decode, append);
     }
-    return error;
+
+    ofconn_send_replies(ofconn, &replies);
+
+    return 0;
 }
 
 static enum ofperr
-handle_port_stats_request(struct ofconn *ofconn,
-                          const struct ofp_header *request)
+handle_port_stats_request(struct ofconn *ofconn, const struct ofpbuf *msg)
 {
-    return handle_port_request(ofconn, request,
+    return handle_port_request(ofconn, msg,
                                ofputil_decode_port_stats_request,
                                append_port_stat);
 }
@@ -3250,10 +3274,9 @@ append_port_desc(struct ofport *port, struct list 
*replies)
 }
 
 static enum ofperr
-handle_port_desc_stats_request(struct ofconn *ofconn,
-                               const struct ofp_header *request)
+handle_port_desc_stats_request(struct ofconn *ofconn, const struct ofpbuf *msg)
 {
-    return handle_port_request(ofconn, request,
+    return handle_port_request(ofconn, msg,
                                ofputil_decode_port_desc_stats_request,
                                append_port_desc);
 }
@@ -5971,7 +5994,8 @@ handle_openflow__(struct ofconn *ofconn, const struct 
ofpbuf *msg)
         return error;
     }
     if (oh->version >= OFP13_VERSION && ofpmsg_is_stat_request(oh)
-        && ofpmp_more(oh)) {
+        && ofpmp_more(oh) && type != OFPTYPE_PORT_STATS_REQUEST
+        && type != OFPTYPE_PORT_DESC_STATS_REQUEST) {
         /* We have no buffer implementation for multipart requests.
          * Report overflow for requests which consists of multiple
          * messages. */
@@ -6060,13 +6084,13 @@ handle_openflow__(struct ofconn *ofconn, const struct 
ofpbuf *msg)
         return handle_table_stats_request(ofconn, oh);
 
     case OFPTYPE_PORT_STATS_REQUEST:
-        return handle_port_stats_request(ofconn, oh);
+        return handle_port_stats_request(ofconn, msg);
 
     case OFPTYPE_QUEUE_STATS_REQUEST:
         return handle_queue_stats_request(ofconn, oh);
 
     case OFPTYPE_PORT_DESC_STATS_REQUEST:
-        return handle_port_desc_stats_request(ofconn, oh);
+        return handle_port_desc_stats_request(ofconn, msg);
 
     case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
         return handle_flow_monitor_request(ofconn, oh);
diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
index 4b16907..2448576 100644
--- a/tests/ofproto-macros.at
+++ b/tests/ofproto-macros.at
@@ -35,6 +35,7 @@ m4_divert_pop([PREPARE_TESTS])
 
 m4_define([STRIP_XIDS], [[sed 's/ (xid=0x[0-9a-fA-F]*)//']])
 m4_define([STRIP_DURATION], [[sed 's/\bduration=[0-9.]*s/duration=?s/']])
+m4_define([STRIP_HW_ADDR], [[sed 
's/\baddr:[0-9a-f:]*/addr:??:??:??:??:??:??/']])
 m4_define([STRIP_USED], [[sed 's/used:[0-9]\.[0-9]*/used:0.0/']])
 m4_define([TESTABLE_LOG], [-vPATTERN:ANY:'%c|%p|%m'])
 
diff --git a/tests/ofproto.at b/tests/ofproto.at
index 2f1df2d..06ae8f5 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -2664,3 +2664,112 @@ OFPT_BARRIER_REPLY (OF1.4):
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_SETUP([ofproto - multipart port stats 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
+# An OpenFlow13 message (04), OFPT_MULTIPART_REQUEST (12), length (0018), xid 
(0000000a)
+#                             OFPMP_PORT_STATS (0004), OFPMPF_REPLY_MORE 
(0001), pad (00000000)
+#                             port_no (0001), pad (00000000)
+ovs-appctl -t ovs-ofctl ofctl/send "041200180000000a 0004000100000000 
0000000100000000"
+
+# Send second part
+# an OpenFlow13 message (04), OFPT_MULTIPART_REQUEST (12), length (0018), xid 
(0000000a)
+#                             OFPMP_PORT_STATS (0004), OFPMPF_REPLY_MORE 
(0001), pad (00000000)
+#                                  port_no (0002), pad (00000000)
+ovs-appctl -t ovs-ofctl ofctl/send "041200180000000a 0004000100000000 
0000000200000000"
+
+# Send third part
+# an OpenFlow13 message (04), OFPT_MULTIPART_REQUEST (12), length (0018), xid 
(0000000a)
+#                             OFPMP_PORT_STATS (0004), no flags (0000), pad 
(00000000)
+#                                  port_no (0003), pad (00000000)
+ovs-appctl -t ovs-ofctl ofctl/send "041200180000000a 0004000000000000 
0000000300000000"
+
+ovs-appctl -t ovs-ofctl ofctl/barrier
+
+# Check default setting
+read -r -d '' expected <<'EOF'
+EOF
+
+AT_CHECK([ofctl_strip < monitor.log | STRIP_DURATION], [], [dnl
+send: OFPST_PORT request (OF1.3): flags=[[more]] port_no=1
+send: OFPST_PORT request (OF1.3): flags=[[more]] port_no=2
+send: OFPST_PORT request (OF1.3): port_no=3
+OFPST_PORT reply (OF1.3): 3 ports
+  port  1: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
+           tx pkts=0, bytes=0, drop=0, errs=0, coll=0
+           duration=?s
+  port  2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
+           tx pkts=0, bytes=0, drop=0, errs=0, coll=0
+           duration=?s
+  port  3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
+           tx pkts=0, bytes=0, drop=0, errs=0, coll=0
+           duration=?s
+OFPT_BARRIER_REPLY (OF1.3):
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([ofproto - multipart port desc stats request (OpenFlow 1.5)])
+AT_KEYWORDS([monitor])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], [1], [2], [3])
+
+# Start a monitor, use the required protocol version
+ovs-ofctl -O OpenFlow15 monitor br0 --detach --no-chdir --pidfile >monitor.log 
2>&1
+AT_CAPTURE_FILE([monitor.log])
+
+# Send first part
+# An OpenFlow15 message (06), OFPT_MULTIPART_REQUEST (12), length (0014), xid 
(0000000a)
+#                             OFPMP_PORT_DESC (000d), OFPMPF_REPLY_MORE 
(0001), pad (00000000)
+#                             port_no (0001)
+ovs-appctl -t ovs-ofctl ofctl/send "061200140000000a 000d000100000000 00000001"
+
+# Send second part
+# an OpenFlow15 message (06), OFPT_MULTIPART_REQUEST (12), length (0014), xid 
(0000000a)
+#                             OFPMP_PORT_DESC (000d), OFPMPF_REPLY_MORE 
(0001), pad (00000000)
+#                                  port_no (0002)
+ovs-appctl -t ovs-ofctl ofctl/send "061200140000000a 000d000100000000 00000002"
+
+# Send third part
+# an OpenFlow15 message (06), OFPT_MULTIPART_REQUEST (12), length (0014), xid 
(0000000a)
+#                             OFPMP_PORT_DESC (000d), no flags (0000), pad 
(00000000)
+#                                  port_no (0003)
+ovs-appctl -t ovs-ofctl ofctl/send "061200140000000a 000d000000000000 00000003"
+
+ovs-appctl -t ovs-ofctl ofctl/barrier
+
+# Check default setting
+read -r -d '' expected <<'EOF'
+EOF
+
+AT_CHECK([ofctl_strip < monitor.log | STRIP_DURATION | STRIP_HW_ADDR], [], [dnl
+send: OFPST_PORT_DESC request (OF1.5): flags=[[more]] port=1
+send: OFPST_PORT_DESC request (OF1.5): flags=[[more]] port=2
+send: OFPST_PORT_DESC request (OF1.5): port=3
+OFPST_PORT_DESC reply (OF1.5):
+ 1(p1): addr:??:??:??:??:??:??
+     config:     PORT_DOWN
+     state:      LINK_DOWN
+     speed: 0 Mbps now, 0 Mbps max
+ 2(p2): addr:??:??:??:??:??:??
+     config:     PORT_DOWN
+     state:      LINK_DOWN
+     speed: 0 Mbps now, 0 Mbps max
+ 3(p3): addr:??:??:??:??:??:??
+     config:     PORT_DOWN
+     state:      LINK_DOWN
+     speed: 0 Mbps now, 0 Mbps max
+OFPT_BARRIER_REPLY (OF1.5):
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
-- 
1.8.5.2

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

Reply via email to