-execute_flow_miss(struct flow_miss *miss, struct dpif_op *ops, size_t *n_ops)
-{
- struct ofproto_dpif *ofproto = miss->ofproto;
- struct flow_wildcards wc;
- struct rule_dpif *rule;
- struct ofpbuf *packet;
- struct xlate_in xin;
-
- memset(&miss->stats, 0, sizeof miss->stats);
- miss->stats.used = time_msec();
- LIST_FOR_EACH (packet, list_node, &miss->packets) {
- miss->stats.tcp_flags |= packet_get_tcp_flags(packet, &miss->flow);
- miss->stats.n_bytes += packet->size;
- miss->stats.n_packets++;
- }
-
- flow_wildcards_init_catchall(&wc);
- rule_dpif_lookup(ofproto, &miss->flow, &wc, &rule);
- rule_credit_stats(rule, &miss->stats);
- xlate_in_init(&xin, ofproto, &miss->flow, rule, miss->stats.tcp_flags,
- NULL);
- xin.may_learn = true;
- xin.resubmit_stats = &miss->stats;
- xlate_actions(&xin, &miss->xout);
- flow_wildcards_or(&miss->xout.wc, &miss->xout.wc, &wc);
-
- if (rule->up.cr.priority == FAIL_OPEN_PRIORITY) {
- LIST_FOR_EACH (packet, list_node, &miss->packets) {
- struct ofputil_packet_in *pin;
-
- /* Extra-special case for fail-open mode.
- *
- * We are in fail-open mode and the packet matched the fail-open
- * rule, but we are connected to a controller too. We should send
- * the packet up to the controller in the hope that it will try to
- * set up a flow and thereby allow us to exit fail-open.
- *
- * See the top-level comment in fail-open.c for more information. */
- pin = xmalloc(sizeof(*pin));
- pin->packet = xmemdup(packet->data, packet->size);
- pin->packet_len = packet->size;
- pin->reason = OFPR_NO_MATCH;
- pin->controller_id = 0;
- pin->table_id = 0;
- pin->cookie = 0;
- pin->send_len = 0; /* Not used for flow table misses. */
- flow_get_metadata(&miss->flow, &pin->fmd);
- ofproto_dpif_send_packet_in(ofproto, pin);
- }
- }
-
- if (miss->xout.slow) {
- LIST_FOR_EACH (packet, list_node, &miss->packets) {
- struct xlate_in xin;
-
- xlate_in_init(&xin, miss->ofproto, &miss->flow, rule, 0, packet);
- xlate_actions_for_side_effects(&xin);
- }
- }
- rule_release(rule);
-
- if (miss->xout.odp_actions.size) {
- LIST_FOR_EACH (packet, list_node, &miss->packets) {
- struct dpif_op *op = &ops[*n_ops];
- struct dpif_execute *execute = &op->u.execute;
-
- if (miss->flow.in_port.ofp_port
- != vsp_realdev_to_vlandev(miss->ofproto,
- miss->flow.in_port.ofp_port,
- miss->flow.vlan_tci)) {
- /* This packet was received on a VLAN splinter port. We
- * added a VLAN to the packet to make the packet resemble
- * the flow, but the actions were composed assuming that
- * the packet contained no VLAN. So, we must remove the
- * VLAN header from the packet before trying to execute the
- * actions. */
- eth_pop_vlan(packet);
- }
-
- op->type = DPIF_OP_EXECUTE;
- execute->key = miss->key;
- execute->key_len = miss->key_len;
- execute->packet = packet;
- execute->actions = miss->xout.odp_actions.data;
- execute->actions_len = miss->xout.odp_actions.size;
-
- (*n_ops)++;
- }
- }
-}
-
-static void
-handle_miss_upcalls(struct udpif *udpif, struct list *upcalls)