When at least one OF1.4 bundle is open, only bundle related messages are processed by the switch. The rest are queued and processed after the bundles are done.
Signed-off-by: Alexandru Copot <alex.miha...@gmail.com> Cc: Daniel Baluta <dbal...@ixiacom.com> --- ofproto/connmgr.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index e0a097f..b9d6ea5 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -141,6 +141,9 @@ struct ofconn { /* Active bundles. Contains "struct ofp_bundle"s. */ struct hmap bundles; + + /* Queued OpenFlow messages during the creation of bundles */ + struct list queued; }; static struct ofconn *ofconn_create(struct connmgr *, struct rconn *, @@ -1218,6 +1221,7 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type, list_init(&ofconn->updates); hmap_init(&ofconn->bundles); + list_init(&ofconn->queued); ofconn_flush(ofconn); @@ -1371,6 +1375,103 @@ ofconn_may_recv(const struct ofconn *ofconn) return (!ofconn->blocked || ofconn->retry) && count < OFCONN_REPLY_MAX; } +/* Returns true for the messages that a connection can process while it + * has open bundles. */ +static bool +may_pass_with_bundles(const struct ofpbuf *ofp_msg) +{ + const struct ofp_header *oh; + enum ofptype type; + enum ofperr error; + + oh = ofpbuf_data(ofp_msg); + + error = ofptype_decode(&type, oh); + if (error) { + return true; + } + + switch (type) { + case OFPTYPE_HELLO: + case OFPTYPE_ECHO_REQUEST: + case OFPTYPE_BARRIER_REQUEST: + case OFPTYPE_BUNDLE_CONTROL: + case OFPTYPE_BUNDLE_ADD_MESSAGE: + return true; + + case OFPTYPE_FEATURES_REQUEST: + case OFPTYPE_GET_CONFIG_REQUEST: + case OFPTYPE_GET_ASYNC_REQUEST: + case OFPTYPE_DESC_STATS_REQUEST: + case OFPTYPE_FLOW_STATS_REQUEST: + case OFPTYPE_AGGREGATE_STATS_REQUEST: + case OFPTYPE_TABLE_STATS_REQUEST: + case OFPTYPE_PORT_STATS_REQUEST: + case OFPTYPE_QUEUE_STATS_REQUEST: + case OFPTYPE_PORT_DESC_STATS_REQUEST: + case OFPTYPE_FLOW_MONITOR_STATS_REQUEST: + case OFPTYPE_METER_STATS_REQUEST: + case OFPTYPE_METER_CONFIG_STATS_REQUEST: + case OFPTYPE_METER_FEATURES_STATS_REQUEST: + case OFPTYPE_GROUP_STATS_REQUEST: + case OFPTYPE_GROUP_DESC_STATS_REQUEST: + case OFPTYPE_GROUP_FEATURES_STATS_REQUEST: + case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: + + case OFPTYPE_SET_CONFIG: + case OFPTYPE_PACKET_OUT: + case OFPTYPE_PORT_MOD: + case OFPTYPE_FLOW_MOD: + case OFPTYPE_GROUP_MOD: + case OFPTYPE_TABLE_MOD: + case OFPTYPE_METER_MOD: + case OFPTYPE_ROLE_REQUEST: + case OFPTYPE_ECHO_REPLY: + case OFPTYPE_FLOW_MOD_TABLE_ID: + case OFPTYPE_SET_FLOW_FORMAT: + case OFPTYPE_SET_PACKET_IN_FORMAT: + case OFPTYPE_SET_CONTROLLER_ID: + case OFPTYPE_FLOW_AGE: + case OFPTYPE_FLOW_MONITOR_CANCEL: + case OFPTYPE_SET_ASYNC_CONFIG: + + case OFPTYPE_ERROR: + case OFPTYPE_FEATURES_REPLY: + case OFPTYPE_GET_CONFIG_REPLY: + case OFPTYPE_PACKET_IN: + case OFPTYPE_FLOW_REMOVED: + case OFPTYPE_PORT_STATUS: + case OFPTYPE_BARRIER_REPLY: + case OFPTYPE_QUEUE_GET_CONFIG_REPLY: + case OFPTYPE_DESC_STATS_REPLY: + case OFPTYPE_FLOW_STATS_REPLY: + case OFPTYPE_QUEUE_STATS_REPLY: + case OFPTYPE_PORT_STATS_REPLY: + case OFPTYPE_TABLE_STATS_REPLY: + case OFPTYPE_AGGREGATE_STATS_REPLY: + case OFPTYPE_PORT_DESC_STATS_REPLY: + case OFPTYPE_ROLE_REPLY: + case OFPTYPE_FLOW_MONITOR_PAUSED: + case OFPTYPE_FLOW_MONITOR_RESUMED: + case OFPTYPE_FLOW_MONITOR_STATS_REPLY: + case OFPTYPE_GET_ASYNC_REPLY: + case OFPTYPE_GROUP_STATS_REPLY: + case OFPTYPE_GROUP_DESC_STATS_REPLY: + case OFPTYPE_GROUP_FEATURES_STATS_REPLY: + case OFPTYPE_METER_STATS_REPLY: + case OFPTYPE_METER_CONFIG_STATS_REPLY: + case OFPTYPE_METER_FEATURES_STATS_REPLY: + case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: + case OFPTYPE_TABLE_FEATURES_STATS_REPLY: + case OFPTYPE_ROLE_STATUS: + return false; + default: + return false; + } + + return false; +} + static void ofconn_run(struct ofconn *ofconn, bool (*handle_openflow)(struct ofconn *, @@ -1389,6 +1490,24 @@ ofconn_run(struct ofconn *ofconn, rconn_run(ofconn->rconn); if (handle_openflow) { + if (!hmap_count(&ofconn->bundles) && !list_is_empty(&ofconn->queued)) { + for (i = 0; i < 50 && !list_is_empty(&ofconn->queued); i++) { + struct ofpbuf *of_msg; + + of_msg = ofpbuf_from_list(list_pop_front(&ofconn->queued)); + if (!of_msg) { + break; + } + if (handle_openflow(ofconn, of_msg)) { + ofpbuf_delete(of_msg); + ofconn->blocked = NULL; + } else { + ofconn->blocked = of_msg; + ofconn->retry = false; + } + } + } + /* Limit the number of iterations to avoid starving other tasks. */ for (i = 0; i < 50 && ofconn_may_recv(ofconn); i++) { struct ofpbuf *of_msg; @@ -1403,6 +1522,11 @@ ofconn_run(struct ofconn *ofconn, fail_open_maybe_recover(mgr->fail_open); } + if (!may_pass_with_bundles(of_msg) && hmap_count(&ofconn->bundles) > 0) { + list_push_back(&ofconn->queued, &of_msg->list_node); + continue; + } + if (handle_openflow(ofconn, of_msg)) { ofpbuf_delete(of_msg); ofconn->blocked = NULL; -- 1.9.2 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev