+ /* Check if we need to use "NORMAL" action. */
+ if (sw->action_normal && out_port != OFPP_FLOOD) {
+ return OFPP_NORMAL;
+ }
+
+ return out_port;
+}
+
+static void
+process_packet_in(struct lswitch *sw, struct rconn *rconn, void *opi_)
+{
+ struct ofp_packet_in *opi = opi_;
+ uint16_t in_port = ntohs(opi->in_port);
+ uint16_t out_port;
+
+ struct ofp_action_header actions[2];
+ size_t actions_len;
+
+ size_t pkt_ofs, pkt_len;
+ struct ofpbuf pkt;
+ flow_t flow;
+
+ /* Extract flow data from 'opi' into 'flow'. */
+ pkt_ofs = offsetof(struct ofp_packet_in, data);
+ pkt_len = ntohs(opi->header.length) - pkt_ofs;
+ pkt.data = opi->data;
+ pkt.size = pkt_len;
+ flow_extract(&pkt, 0, in_port, &flow);
+
+ /* Choose output port. */
+ out_port = lswitch_choose_destination(sw, &flow);
+
+ /* Make actions. */
+ memset(actions, 0, sizeof actions);
+ if (out_port == OFPP_NONE) {
+ actions_len = 0;
+ } else if (sw->queue == UINT32_MAX || out_port >= OFPP_MAX) {
+ struct ofp_action_output *oao = (struct ofp_action_output *) actions;
+ oao->type = htons(OFPAT_OUTPUT);
+ oao->len = htons(sizeof *oao);
+ oao->port = htons(out_port);
+ actions_len = sizeof *oao;
+ } else {
+ struct ofp_action_enqueue *oae = (struct ofp_action_enqueue *) actions;
+ oae->type = htons(OFPAT_ENQUEUE);
+ oae->len = htons(sizeof *oae);
+ oae->port = htons(out_port);
+ oae->queue_id = htonl(sw->queue);
+ actions_len = sizeof *oae;
+ }
+ assert(actions_len <= sizeof actions);
+
+ /* Send the packet, and possibly the whole flow, to the output port. */
+ if (sw->max_idle >= 0 && (!sw->ml || out_port != OFPP_FLOOD)) {