From: Ben Pfaff Date: Tue, 22 Mar 2011 16:13:02 +0000 (-0700) Subject: ofproto: Break packet_in encoding out of ofproto into ofp-util. X-Git-Tag: v1.1.0~52 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=ebb57021a9827b59997a00defc32bf761bc16148;p=sliver-openvswitch.git ofproto: Break packet_in encoding out of ofproto into ofp-util. This removes some code from ofproto.c. --- diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 3d64fcf1e..e42abc50f 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1453,6 +1453,49 @@ 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 + * pin->packet. 'rw_packet' is allowed to be the same ofpbuf as pin->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 c31165bb2..b4fe64238 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -192,6 +192,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 6fd883397..699985cf3 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -4955,59 +4955,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