This removes some code from ofproto.c.
---
lib/ofp-util.c | 44 ++++++++++++++++++++++++++++++++++++++
lib/ofp-util.h | 13 +++++++++++
ofproto/ofproto.c | 61 +++++++++++++++++++---------------------------------
3 files changed, 79 insertions(+), 39 deletions(-)
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 0e785ad..b4b9ffc 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -1341,6 +1341,50 @@ ofputil_encode_flow_removed(const struct
ofputil_flow_removed *fr,
return msg;
}
+/* Converts abstract ofputil_packet_in 'pin' into an OFPT_PACKET_IN message
+ * and returns the message.
+ *
+ * If 'rw_packet' is NULL, the caller takes ownership of the newly allocated
+ * returned ofpbuf.
+ *
+ * If 'rw_packet' is nonnull, then it must contain the same data as
+ * upcall->packet. 'rw_packet' is allowed to be the same ofpbuf as
+ * upcall->packet. It is modified in-place into an OFPT_PACKET_IN message
+ * according to 'pin', and then ofputil_encode_packet_in() returns 'rw_packet'.
+ * If 'rw_packet' has enough headroom to insert a "struct ofp_packet_in", this
+ * is more efficient than ofputil_encode_packet_in() because it does not copy
+ * the packet payload. */
+struct ofpbuf *
+ofputil_encode_packet_in(const struct ofputil_packet_in *pin,
+ struct ofpbuf *rw_packet)
+{
+ int total_len = pin->packet->size;
+ struct ofp_packet_in *opi;
+
+ if (rw_packet) {
+ if (pin->send_len < rw_packet->size) {
+ rw_packet->size = pin->send_len;
+ }
+ } else {
+ rw_packet = ofpbuf_clone_data_with_headroom(
+ pin->packet->data, MIN(pin->send_len, pin->packet->size),
+ offsetof(struct ofp_packet_in, data));
+ }
+
+
+ /* Add OFPT_PACKET_IN. */
+ opi = ofpbuf_push_zeros(rw_packet, offsetof(struct ofp_packet_in, data));
+ 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);
+ update_openflow_length(rw_packet);
+
+ return rw_packet;
+}
+
/* Returns a string representing the message type of 'type'. The string is the
* enumeration constant for the type, e.g. "OFPT_HELLO". For statistics
* messages, the constant is followed by "request" or "reply",
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index bd06988..f54d809 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -173,6 +173,19 @@ int ofputil_decode_flow_removed(struct
ofputil_flow_removed *,
struct ofpbuf *ofputil_encode_flow_removed(const struct ofputil_flow_removed *,
enum nx_flow_format);
+/* Abstract packet-in message. */
+struct ofputil_packet_in {
+ struct ofpbuf *packet;
+ uint16_t in_port;
+ uint8_t reason; /* One of OFPR_*. */
+
+ uint32_t buffer_id;
+ int send_len;
+};
+
+struct ofpbuf *ofputil_encode_packet_in(const struct ofputil_packet_in *,
+ struct ofpbuf *rw_packet);
+
/* OpenFlow protocol utility functions. */
void *make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **);
void *make_nxmsg(size_t openflow_len, uint32_t subtype, struct ofpbuf **);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index b5d2b01..1786694 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4827,59 +4827,42 @@ static void
schedule_packet_in(struct ofconn *ofconn, struct dpif_upcall *upcall,
const struct flow *flow, bool clone)
{
- enum { OPI_SIZE = offsetof(struct ofp_packet_in, data) };
struct ofproto *ofproto = ofconn->ofproto;
- struct ofp_packet_in *opi;
- int total_len, send_len;
- struct ofpbuf *packet;
- uint32_t buffer_id;
- int idx;
+ struct ofputil_packet_in pin;
+ struct ofpbuf *msg;
+
+ /* Figure out the easy parts. */
+ pin.packet = upcall->packet;
+ pin.in_port = odp_port_to_ofp_port(flow->in_port);
+ pin.reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION;
/* Get OpenFlow buffer_id. */
if (upcall->type == DPIF_UC_ACTION) {
- buffer_id = UINT32_MAX;
+ pin.buffer_id = UINT32_MAX;
} else if (ofproto->fail_open && fail_open_is_active(ofproto->fail_open)) {
- buffer_id = pktbuf_get_null();
+ pin.buffer_id = pktbuf_get_null();
} else if (!ofconn->pktbuf) {
- buffer_id = UINT32_MAX;
+ pin.buffer_id = UINT32_MAX;
} else {
- buffer_id = pktbuf_save(ofconn->pktbuf, upcall->packet, flow->in_port);
+ pin.buffer_id = pktbuf_save(ofconn->pktbuf, upcall->packet,
+ flow->in_port);
}
/* Figure out how much of the packet to send. */
- total_len = send_len = upcall->packet->size;
- if (buffer_id != UINT32_MAX) {
- send_len = MIN(send_len, ofconn->miss_send_len);
+ pin.send_len = upcall->packet->size;
+ if (pin.buffer_id != UINT32_MAX) {
+ pin.send_len = MIN(pin.send_len, ofconn->miss_send_len);
}
if (upcall->type == DPIF_UC_ACTION) {
- send_len = MIN(send_len, upcall->userdata);
+ pin.send_len = MIN(pin.send_len, upcall->userdata);
}
- /* Copy or steal buffer for OFPT_PACKET_IN. */
- if (clone) {
- packet = ofpbuf_clone_data_with_headroom(upcall->packet->data,
- send_len, OPI_SIZE);
- } else {
- packet = upcall->packet;
- packet->size = send_len;
- }
-
- /* Add OFPT_PACKET_IN. */
- opi = ofpbuf_push_zeros(packet, OPI_SIZE);
- opi->header.version = OFP_VERSION;
- opi->header.type = OFPT_PACKET_IN;
- opi->total_len = htons(total_len);
- opi->in_port = htons(odp_port_to_ofp_port(flow->in_port));
- opi->reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION;
- 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()). */
- idx = upcall->type == DPIF_UC_MISS ? 0 : 1;
- pinsched_send(ofconn->schedulers[idx], flow->in_port,
- packet, do_send_packet_in, ofconn);
+ /* Make OFPT_PACKET_IN and 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()). */
+ msg = ofputil_encode_packet_in(&pin, clone ? NULL : upcall->packet);
+ pinsched_send(ofconn->schedulers[upcall->type == DPIF_UC_MISS ? 0 : 1],
+ flow->in_port, msg, do_send_packet_in, ofconn);
}
/* Given 'upcall', of type DPIF_UC_ACTION or DPIF_UC_MISS, sends an
--
1.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev