+ /* Update packet headers. */
+ opi->buffer_id = htonl(buffer_id);
+ update_openflow_length(packet);
+
+ /* Hand over to packet scheduler. It might immediately call into
+ * do_send_packet_in() or it might buffer it for a while (until a later
+ * call to pinsched_run()). */
+ pinsched_send(ofconn->schedulers[opi->reason], in_port,
+ packet, do_send_packet_in, ofconn);
+}
+
+/* Replace struct odp_msg header in 'packet' by equivalent struct
+ * ofp_packet_in. The odp_msg must have sufficient headroom to do so (e.g. as
+ * returned by dpif_recv()).
+ *
+ * The conversion is not complete: the caller still needs to trim any unneeded
+ * payload off the end of the buffer, set the length in the OpenFlow header,
+ * and set buffer_id. Those require us to know the controller settings and so
+ * must be done on a per-controller basis.
+ *
+ * Returns the maximum number of bytes of the packet that should be sent to
+ * the controller (INT_MAX if no limit). */
+static int
+do_convert_to_packet_in(struct ofpbuf *packet)
+{
+ struct odp_msg *msg = packet->data;
+ struct ofp_packet_in *opi;
+ uint8_t reason;
+ uint16_t total_len;
+ uint16_t in_port;
+ int max_len;
+
+ /* Extract relevant header fields */