enum ofp_packet_in_reason reason,
uint16_t controller_id)
{
- struct ofputil_packet_in pin;
+ struct ofputil_packet_in *pin;
struct ofpbuf *packet;
struct flow key;
odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data,
ctx->xout->odp_actions.size, NULL, NULL);
- pin.packet = packet->data;
- pin.packet_len = packet->size;
- pin.reason = reason;
- pin.controller_id = controller_id;
- pin.table_id = ctx->table_id;
- pin.cookie = ctx->rule ? ctx->rule->up.flow_cookie : 0;
+ pin = xmalloc(sizeof *pin);
+ pin->packet_len = packet->size;
+ pin->packet = ofpbuf_steal_data(packet);
+ pin->reason = reason;
+ pin->controller_id = controller_id;
+ pin->table_id = ctx->table_id;
+ pin->cookie = ctx->rule ? ctx->rule->up.flow_cookie : 0;
- pin.send_len = len;
- flow_get_metadata(&ctx->xin->flow, &pin.fmd);
+ pin->send_len = len;
+ flow_get_metadata(&ctx->xin->flow, &pin->fmd);
- ofproto_dpif_send_packet_in(ctx->xbridge->ofproto, &pin);
+ ofproto_dpif_send_packet_in(ctx->xbridge->ofproto, pin);
ofpbuf_delete(packet);
}
COVERAGE_DEFINE(facet_unexpected);
COVERAGE_DEFINE(facet_suppress);
COVERAGE_DEFINE(subfacet_install_fail);
+COVERAGE_DEFINE(packet_in_overflow);
COVERAGE_DEFINE(flow_mod_overflow);
/* Number of implemented OpenFlow tables. */
struct ovs_mutex flow_mod_mutex;
struct list flow_mods OVS_GUARDED;
size_t n_flow_mods OVS_GUARDED;
+
+ struct ovs_mutex pin_mutex;
+ struct list pins OVS_GUARDED;
+ size_t n_pins OVS_GUARDED;
};
/* Defer flow mod completion until "ovs-appctl ofproto/unclog"? (Useful only
ofproto_dpif_send_packet_in(struct ofproto_dpif *ofproto,
struct ofputil_packet_in *pin)
{
- connmgr_send_packet_in(ofproto->up.connmgr, pin);
+ ovs_mutex_lock(&ofproto->pin_mutex);
+ if (ofproto->n_pins > 1024) {
+ ovs_mutex_unlock(&ofproto->pin_mutex);
+ COVERAGE_INC(packet_in_overflow);
+ free(CONST_CAST(void *, pin->packet));
+ free(pin);
+ return;
+ }
+
+ list_push_back(&ofproto->pins, &pin->list_node);
+ ofproto->n_pins++;
+ ovs_mutex_unlock(&ofproto->pin_mutex);
}
\f
/* Factory functions. */
ofproto->n_flow_mods = 0;
ovs_mutex_unlock(&ofproto->flow_mod_mutex);
+ ovs_mutex_init(&ofproto->pin_mutex, PTHREAD_MUTEX_NORMAL);
+ ovs_mutex_lock(&ofproto->pin_mutex);
+ list_init(&ofproto->pins);
+ ofproto->n_pins = 0;
+ ovs_mutex_unlock(&ofproto->pin_mutex);
+
ofproto_dpif_unixctl_init();
hmap_init(&ofproto->vlandev_map);
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct rule_dpif *rule, *next_rule;
+ struct ofputil_flow_mod *pin, *next_pin;
struct ofputil_flow_mod *fm, *next_fm;
struct oftable *table;
ovs_mutex_unlock(&ofproto->flow_mod_mutex);
ovs_mutex_destroy(&ofproto->flow_mod_mutex);
+ ovs_mutex_lock(&ofproto->pin_mutex);
+ LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &ofproto->pins) {
+ list_remove(&pin->list_node);
+ ofproto->n_pins--;
+ free(pin->ofpacts);
+ free(pin);
+ }
+ ovs_mutex_unlock(&ofproto->pin_mutex);
+ ovs_mutex_destroy(&ofproto->pin_mutex);
+
mbridge_unref(ofproto->mbridge);
netflow_destroy(ofproto->netflow);
run_fast(struct ofproto *ofproto_)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
- struct ofputil_flow_mod *fm, *next;
+ struct ofputil_packet_in *pin, *next_pin;
+ struct ofputil_flow_mod *fm, *next_fm;
+ struct list flow_mods, pins;
struct ofport_dpif *ofport;
- struct list flow_mods;
/* Do not perform any periodic activity required by 'ofproto' while
* waiting for flow restore to complete. */
}
ovs_mutex_unlock(&ofproto->flow_mod_mutex);
- LIST_FOR_EACH_SAFE (fm, next, list_node, &flow_mods) {
+ LIST_FOR_EACH_SAFE (fm, next_fm, list_node, &flow_mods) {
int error = ofproto_flow_mod(&ofproto->up, fm);
if (error && !VLOG_DROP_WARN(&rl)) {
VLOG_WARN("learning action failed to modify flow table (%s)",
free(fm);
}
+ ovs_mutex_lock(&ofproto->pin_mutex);
+ if (ofproto->n_pins) {
+ pins = ofproto->pins;
+ list_moved(&pins);
+ list_init(&ofproto->pins);
+ ofproto->n_pins = 0;
+ } else {
+ list_init(&pins);
+ }
+ ovs_mutex_unlock(&ofproto->pin_mutex);
+
+ LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &pins) {
+ connmgr_send_packet_in(ofproto->up.connmgr, pin);
+ list_remove(&pin->list_node);
+ free(CONST_CAST(void *, pin->packet));
+ free(pin);
+ }
+
HMAP_FOR_EACH (ofport, up.hmap_node, &ofproto->up.ports) {
port_run_fast(ofport);
}