#include "openvswitch/vlog.h"
#include "openflow/intel-ext.h"
#include "packets.h"
-#include "pktbuf.h"
#include "random.h"
#include "tun-metadata.h"
#include "unaligned.h"
{
ovs_be16 raw_flags;
enum ofperr error;
-
- /* Ignored for non-delete actions */
- fm->delete_reason = OFPRR_DELETE;
-
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
enum ofpraw raw = ofpraw_pull_assert(&b);
if (raw == OFPRAW_OFPT11_FLOW_MOD) {
* function omits it. The caller can add it itself if desired. */
static void
ofputil_put_packet_in(const struct ofputil_packet_in *pin,
- enum ofp_version version, uint32_t buffer_id,
- size_t include_bytes, struct ofpbuf *msg)
+ enum ofp_version version, size_t include_bytes,
+ struct ofpbuf *msg)
{
/* Add packet properties. */
ofpprop_put(msg, NXPINT_PACKET, pin->packet, include_bytes);
if (include_bytes != pin->packet_len) {
ofpprop_put_u32(msg, NXPINT_FULL_LEN, pin->packet_len);
}
- if (buffer_id != UINT32_MAX) {
- ofpprop_put_u32(msg, NXPINT_BUFFER_ID, buffer_id);
- }
/* Add flow properties. */
ofpprop_put_u8(msg, NXPINT_TABLE_ID, pin->table_id);
* function omits it. The caller can add it itself if desired. */
static void
ofputil_put_packet_in_private(const struct ofputil_packet_in_private *pin,
- enum ofp_version version, uint32_t buffer_id,
- size_t include_bytes, struct ofpbuf *msg)
+ enum ofp_version version, size_t include_bytes,
+ struct ofpbuf *msg)
{
- ofputil_put_packet_in(&pin->public, version, buffer_id,
- include_bytes, msg);
+ ofputil_put_packet_in(&pin->public, version, include_bytes, msg);
size_t continuation_ofs = ofpprop_start_nested(msg, NXPINT_CONTINUATION);
size_t inner_ofs = msg->size;
}
static struct ofpbuf *
-ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in *pin,
- uint32_t buffer_id)
+ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in *pin)
{
struct ofp10_packet_in *opi;
struct ofpbuf *msg;
opi->total_len = htons(pin->packet_len);
opi->in_port = htons(ofp_to_u16(pin->flow_metadata.flow.in_port.ofp_port));
opi->reason = encode_packet_in_reason(pin->reason, OFP10_VERSION);
- opi->buffer_id = htonl(buffer_id);
+ opi->buffer_id = htonl(UINT32_MAX);
return msg;
}
static struct ofpbuf *
ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin,
- enum ofp_version version, uint32_t buffer_id)
+ enum ofp_version version)
{
struct nx_packet_in *npi;
struct ofpbuf *msg;
ofpbuf_put_zeros(msg, 2);
npi = msg->msg;
- npi->buffer_id = htonl(buffer_id);
+ npi->buffer_id = htonl(UINT32_MAX);
npi->total_len = htons(pin->packet_len);
npi->reason = encode_packet_in_reason(pin->reason, version);
npi->table_id = pin->table_id;
static struct ofpbuf *
ofputil_encode_nx_packet_in2(const struct ofputil_packet_in_private *pin,
- enum ofp_version version, uint32_t buffer_id,
- size_t include_bytes)
+ enum ofp_version version, size_t include_bytes)
{
/* 'extra' is just an estimate of the space required. */
size_t extra = (pin->public.packet_len
struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN2, version,
htonl(0), extra);
- ofputil_put_packet_in_private(pin, version, buffer_id, include_bytes, msg);
+ ofputil_put_packet_in_private(pin, version, include_bytes, msg);
if (pin->public.userdata_len) {
ofpprop_put(msg, NXPINT_USERDATA, pin->public.userdata,
pin->public.userdata_len);
}
static struct ofpbuf *
-ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin,
- uint32_t buffer_id)
+ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin)
{
struct ofp11_packet_in *opi;
struct ofpbuf *msg;
msg = ofpraw_alloc_xid(OFPRAW_OFPT11_PACKET_IN, OFP11_VERSION,
htonl(0), pin->packet_len);
opi = ofpbuf_put_zeros(msg, sizeof *opi);
- opi->buffer_id = htonl(buffer_id);
+ opi->buffer_id = htonl(UINT32_MAX);
opi->in_port = ofputil_port_to_ofp11(
pin->flow_metadata.flow.in_port.ofp_port);
opi->in_phy_port = opi->in_port;
static struct ofpbuf *
ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin,
- enum ofp_version version,
- uint32_t buffer_id)
+ enum ofp_version version)
{
enum ofpraw raw = (version >= OFP13_VERSION
? OFPRAW_OFPT13_PACKET_IN
htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);
struct ofp12_packet_in *opi = ofpbuf_put_zeros(msg, sizeof *opi);
- opi->buffer_id = htonl(buffer_id);
+ opi->buffer_id = htonl(UINT32_MAX);
opi->total_len = htons(pin->packet_len);
opi->reason = encode_packet_in_reason(pin->reason, version);
opi->table_id = pin->table_id;
/* Converts abstract ofputil_packet_in_private 'pin' into a PACKET_IN message
* for 'protocol', using the packet-in format specified by 'packet_in_format'.
*
- * If 'pkt_buf' is nonnull and 'max_len' allows the packet to be buffered, this
- * function will attempt to obtain a buffer ID from 'pktbuf' and truncate the
- * packet to 'max_len' bytes. Otherwise, or if 'pktbuf' doesn't have a free
- * buffer, it will send the whole packet without buffering.
- *
* This function is really meant only for use by ovs-vswitchd. To any other
* code, the "continuation" data, i.e. the data that is in struct
* ofputil_packet_in_private but not in struct ofputil_packet_in, is supposed
struct ofpbuf *
ofputil_encode_packet_in_private(const struct ofputil_packet_in_private *pin,
enum ofputil_protocol protocol,
- enum nx_packet_in_format packet_in_format,
- uint16_t max_len, struct pktbuf *pktbuf)
+ enum nx_packet_in_format packet_in_format)
{
enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
- /* Get buffer ID. */
- ofp_port_t in_port = pin->public.flow_metadata.flow.in_port.ofp_port;
- uint32_t buffer_id = (max_len != OFPCML12_NO_BUFFER && pktbuf
- ? pktbuf_save(pktbuf, pin->public.packet,
- pin->public.packet_len, in_port)
- : UINT32_MAX);
-
- /* Calculate the number of bytes of the packet to include in the
- * packet-in:
- *
- * - If not buffered, the whole thing.
- *
- * - Otherwise, no more than 'max_len' bytes. */
- size_t include_bytes = (buffer_id == UINT32_MAX
- ? pin->public.packet_len
- : MIN(max_len, pin->public.packet_len));
-
struct ofpbuf *msg;
switch (packet_in_format) {
case NXPIF_STANDARD:
case OFPUTIL_P_OF10_STD_TID:
case OFPUTIL_P_OF10_NXM:
case OFPUTIL_P_OF10_NXM_TID:
- msg = ofputil_encode_ofp10_packet_in(&pin->public, buffer_id);
+ msg = ofputil_encode_ofp10_packet_in(&pin->public);
break;
case OFPUTIL_P_OF11_STD:
- msg = ofputil_encode_ofp11_packet_in(&pin->public, buffer_id);
+ msg = ofputil_encode_ofp11_packet_in(&pin->public);
break;
case OFPUTIL_P_OF12_OXM:
case OFPUTIL_P_OF14_OXM:
case OFPUTIL_P_OF15_OXM:
case OFPUTIL_P_OF16_OXM:
- msg = ofputil_encode_ofp12_packet_in(&pin->public, version, buffer_id);
+ msg = ofputil_encode_ofp12_packet_in(&pin->public, version);
break;
default:
break;
case NXPIF_NXT_PACKET_IN:
- msg = ofputil_encode_nx_packet_in(&pin->public, version, buffer_id);
+ msg = ofputil_encode_nx_packet_in(&pin->public, version);
break;
case NXPIF_NXT_PACKET_IN2:
- return ofputil_encode_nx_packet_in2(pin, version, buffer_id,
- include_bytes);
+ return ofputil_encode_nx_packet_in2(pin, version,
+ pin->public.packet_len);
default:
OVS_NOT_REACHED();
}
- ofpbuf_put(msg, pin->public.packet, include_bytes);
+ ofpbuf_put(msg, pin->public.packet, pin->public.packet_len);
ofpmsg_update_length(msg);
return msg;
}
size_t extra = pin->packet_len + NXM_TYPICAL_LEN + continuation->size;
struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_RESUME, version,
0, extra);
- ofputil_put_packet_in(pin, version, UINT32_MAX, pin->packet_len, msg);
+ ofputil_put_packet_in(pin, version, pin->packet_len, msg);
ofpprop_put_nested(msg, NXPINT_CONTINUATION, continuation);
ofpmsg_update_length(msg);
return msg;
* message's actions. The caller must initialize 'ofpacts' and retains
* ownership of it. 'po->ofpacts' will point into the 'ofpacts' buffer.
*
+ * 'po->packet' refers to the packet data in 'oh', so the buffer containing
+ * 'oh' must not be destroyed while 'po' is being used.
+ *
* Returns 0 if successful, otherwise an OFPERR_* value. */
enum ofperr
ofputil_decode_packet_out(struct ofputil_packet_out *po,
ofputil_uninit_group_desc(struct ofputil_group_desc *gd)
{
ofputil_bucket_list_destroy(&gd->buckets);
- free(&gd->props.fields);
+ ofputil_group_properties_destroy(&gd->props);
}
/* Decodes the OpenFlow group description request in 'oh', returning the group
memset(gp, 0, sizeof *gp);
}
+void
+ofputil_group_properties_copy(struct ofputil_group_props *to,
+ const struct ofputil_group_props *from)
+{
+ *to = *from;
+ to->fields.values = xmemdup(from->fields.values, from->fields.values_size);
+}
+
+void
+ofputil_group_properties_destroy(struct ofputil_group_props *gp)
+{
+ free(gp->fields.values);
+}
+
static enum ofperr
parse_group_prop_ntr_selection_method(struct ofpbuf *payload,
enum ofp11_group_type group_type,
ofputil_uninit_group_mod(struct ofputil_group_mod *gm)
{
ofputil_bucket_list_destroy(&gm->buckets);
+ ofputil_group_properties_destroy(&gm->props);
}
static struct ofpbuf *
return 0;
}
+/* Destroys 'bms'. */
+void
+ofputil_free_bundle_msgs(struct ofputil_bundle_msg *bms, size_t n_bms)
+{
+ for (size_t i = 0; i < n_bms; i++) {
+ switch ((int)bms[i].type) {
+ case OFPTYPE_FLOW_MOD:
+ free(CONST_CAST(struct ofpact *, bms[i].fm.ofpacts));
+ break;
+ case OFPTYPE_GROUP_MOD:
+ ofputil_uninit_group_mod(&bms[i].gm);
+ break;
+ case OFPTYPE_PACKET_OUT:
+ free(bms[i].po.ofpacts);
+ free(CONST_CAST(void *, bms[i].po.packet));
+ break;
+ default:
+ break;
+ }
+ }
+ free(bms);
+}
+
+void
+ofputil_encode_bundle_msgs(const struct ofputil_bundle_msg *bms,
+ size_t n_bms, struct ovs_list *requests,
+ enum ofputil_protocol protocol)
+{
+ enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
+
+ for (size_t i = 0; i < n_bms; i++) {
+ struct ofpbuf *request = NULL;
+
+ switch ((int)bms[i].type) {
+ case OFPTYPE_FLOW_MOD:
+ request = ofputil_encode_flow_mod(&bms[i].fm, protocol);
+ break;
+ case OFPTYPE_GROUP_MOD:
+ request = ofputil_encode_group_mod(version, &bms[i].gm);
+ break;
+ case OFPTYPE_PACKET_OUT:
+ request = ofputil_encode_packet_out(&bms[i].po, protocol);
+ break;
+ default:
+ break;
+ }
+ if (request) {
+ ovs_list_push_back(requests, &request->list_node);
+ }
+ }
+}
+
/* Parse a queue status request message into 'oqsr'.
* Returns 0 if successful, otherwise an OFPERR_* number. */
enum ofperr
/* Minimum required by OpenFlow 1.4. */
case OFPTYPE_PORT_MOD:
case OFPTYPE_FLOW_MOD:
+ /* Other supported types. */
+ case OFPTYPE_GROUP_MOD:
+ case OFPTYPE_PACKET_OUT:
return true;
/* Nice to have later. */
case OFPTYPE_FLOW_MOD_TABLE_ID:
- case OFPTYPE_GROUP_MOD:
case OFPTYPE_TABLE_MOD:
case OFPTYPE_METER_MOD:
- case OFPTYPE_PACKET_OUT:
case OFPTYPE_NXT_TLV_TABLE_MOD:
/* Not to be bundlable. */
request = ofpraw_alloc_xid(ofp_version == OFP13_VERSION
? OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE
: OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE, ofp_version,
- msg->msg->xid, 0);
+ msg->msg->xid, ntohs(msg->msg->length));
m = ofpbuf_put_zeros(request, sizeof *m);
m->bundle_id = htonl(msg->bundle_id);
m->flags = htons(msg->flags);
ofpbuf_put(request, msg->msg, ntohs(msg->msg->length));
+ ofpmsg_update_length(request);
return request;
}