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