Currently this only gets checked for incoming OpenFlow OFPT_FLOW_MOD
messages, so it's hard to imagine it being any kind of bottleneck, but the
NXAST_LEARN action that is soon to be added will be able to create flows
more quickly than we normally expect from a controller. (On the other
hand, ofproto-dpif, outside of a special testing mode, always completes
operations immediately, so 'pending' will always have length 0. But this
change still feels right to me for some reason.)
/* Flow table operation tracking. */
int state; /* Internal state. */
struct list pending; /* List of "struct ofopgroup"s. */
/* Flow table operation tracking. */
int state; /* Internal state. */
struct list pending; /* List of "struct ofopgroup"s. */
+ unsigned int n_pending; /* list_size(&pending). */
struct hmap deletions; /* All OFOPERATION_DELETE "ofoperation"s. */
};
struct hmap deletions; /* All OFOPERATION_DELETE "ofoperation"s. */
};
ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name);
ofproto->state = S_OPENFLOW;
list_init(&ofproto->pending);
ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name);
ofproto->state = S_OPENFLOW;
list_init(&ofproto->pending);
+ ofproto->n_pending = 0;
hmap_init(&ofproto->deletions);
error = ofproto->ofproto_class->construct(ofproto, &n_tables);
hmap_init(&ofproto->deletions);
error = ofproto->ofproto_class->construct(ofproto, &n_tables);
struct classifier *table;
assert(list_is_empty(&ofproto->pending));
struct classifier *table;
assert(list_is_empty(&ofproto->pending));
+ assert(!ofproto->n_pending);
connmgr_destroy(ofproto->connmgr);
connmgr_destroy(ofproto->connmgr);
- if (list_size(&ofproto->pending) >= 50) {
+ if (ofproto->n_pending >= 50) {
+ assert(!list_is_empty(&ofproto->pending));
return OFPROTO_POSTPONE;
}
return OFPROTO_POSTPONE;
}
ofopgroup_destroy(group);
} else {
list_push_back(&group->ofproto->pending, &group->ofproto_node);
ofopgroup_destroy(group);
} else {
list_push_back(&group->ofproto->pending, &group->ofproto_node);
+ group->ofproto->n_pending++;
{
assert(list_is_empty(&group->ops));
if (!list_is_empty(&group->ofproto_node)) {
{
assert(list_is_empty(&group->ops));
if (!list_is_empty(&group->ofproto_node)) {
+ assert(group->ofproto->n_pending > 0);
+ group->ofproto->n_pending--;
list_remove(&group->ofproto_node);
}
if (!list_is_empty(&group->ofconn_node)) {
list_remove(&group->ofproto_node);
}
if (!list_is_empty(&group->ofconn_node)) {