- memset(&opi, 0, sizeof opi);
- opi.header.version = OFP_VERSION;
- opi.header.type = OFPT_PACKET_IN;
- opi.total_len = htons(total_len);
- opi.in_port = htons(pin->in_port);
- opi.reason = pin->reason;
- opi.buffer_id = htonl(pin->buffer_id);
- ofpbuf_push(rw_packet, &opi, offsetof(struct ofp_packet_in, data));
- update_openflow_length(rw_packet);
+ if (packet_in_format == NXPIF_OPENFLOW10) {
+ size_t header_len = offsetof(struct ofp_packet_in, data);
+ struct ofp_packet_in *opi;
+
+ packet = ofpbuf_new(send_len + header_len);
+ opi = ofpbuf_put_zeros(packet, header_len);
+ opi->header.version = OFP_VERSION;
+ opi->header.type = OFPT_PACKET_IN;
+ opi->total_len = htons(pin->total_len);
+ opi->in_port = htons(pin->fmd.in_port);
+ opi->reason = pin->reason;
+ opi->buffer_id = htonl(pin->buffer_id);
+
+ ofpbuf_put(packet, pin->packet, send_len);
+ } else if (packet_in_format == NXPIF_NXM) {
+ struct nxt_packet_in *npi;
+ struct cls_rule rule;
+ size_t match_len;
+ size_t i;
+
+ /* Estimate of required PACKET_IN length includes the NPI header, space
+ * for the match (2 times sizeof the metadata seems like enough), 2
+ * bytes for padding, and the packet length. */
+ packet = ofpbuf_new(sizeof *npi + sizeof(struct flow_metadata) * 2
+ + 2 + send_len);
+
+ cls_rule_init_catchall(&rule, 0);
+ cls_rule_set_tun_id_masked(&rule, pin->fmd.tun_id,
+ pin->fmd.tun_id_mask);
+
+ for (i = 0; i < FLOW_N_REGS; i++) {
+ cls_rule_set_reg_masked(&rule, i, pin->fmd.regs[i],
+ pin->fmd.reg_masks[i]);
+ }
+
+ cls_rule_set_in_port(&rule, pin->fmd.in_port);
+
+ ofpbuf_put_zeros(packet, sizeof *npi);
+ match_len = nx_put_match(packet, &rule, 0, 0);
+ ofpbuf_put_zeros(packet, 2);
+ ofpbuf_put(packet, pin->packet, send_len);
+
+ npi = packet->data;
+ npi->nxh.header.version = OFP_VERSION;
+ npi->nxh.header.type = OFPT_VENDOR;
+ npi->nxh.vendor = htonl(NX_VENDOR_ID);
+ npi->nxh.subtype = htonl(NXT_PACKET_IN);
+
+ npi->buffer_id = htonl(pin->buffer_id);
+ npi->total_len = htons(pin->total_len);
+ npi->reason = pin->reason;
+ npi->table_id = pin->table_id;
+ npi->cookie = pin->cookie;
+ npi->match_len = htons(match_len);
+ } else {
+ NOT_REACHED();
+ }
+ update_openflow_length(packet);