Signed-off-by: Simon Horman <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev