#include <inttypes.h>
#include <stdlib.h>
#include "byte-order.h"
+#include "nx-match.h"
#include "ofp-util.h"
#include "ofpbuf.h"
#include "packets.h"
* in the peer and so there's not much point in showing a lot of them. */
static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5);
-/* XXX we should really use consecutive xids to avoid probabilistic
- * failures. */
-static inline uint32_t
+/* Returns a transaction ID to use for an outgoing OpenFlow message. */
+static ovs_be32
alloc_xid(void)
{
- return random_uint32();
+ static uint32_t next_xid = 1;
+ return htonl(next_xid++);
}
/* Allocates and stores in '*bufferp' a new ofpbuf with a size of
*
* Returns the header. */
void *
-make_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid,
+make_openflow_xid(size_t openflow_len, uint8_t type, ovs_be32 xid,
struct ofpbuf **bufferp)
{
*bufferp = ofpbuf_new(openflow_len);
/* Similar to make_openflow_xid() but creates a Nicira vendor extension message
* with the specific 'subtype'. 'subtype' should be in host byte order. */
void *
-make_nxmsg_xid(size_t openflow_len, uint32_t subtype, uint32_t xid,
+make_nxmsg_xid(size_t openflow_len, uint32_t subtype, ovs_be32 xid,
struct ofpbuf **bufferp)
{
struct nicira_header *nxh = make_openflow_xid(openflow_len, OFPT_VENDOR,
*
* Returns the header. */
void *
-put_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid,
+put_openflow_xid(size_t openflow_len, uint8_t type, ovs_be32 xid,
struct ofpbuf *buffer)
{
struct ofp_header *oh;
rq->version = OFP_VERSION;
rq->type = OFPT_ECHO_REQUEST;
rq->length = htons(sizeof *rq);
- rq->xid = 0;
+ rq->xid = htonl(0);
return out;
}
return fs;
}
-/* Alignment of ofp_actions. */
-#define ACTION_ALIGNMENT 8
-
static int
check_action_exact_len(const union ofp_action *a, unsigned int len,
unsigned int required_len)
}
static int
-check_nicira_action(const union ofp_action *a, unsigned int len)
+check_nicira_action(const union ofp_action *a, unsigned int len,
+ const struct flow *flow)
{
const struct nx_action_header *nah;
+ int error;
if (len < 16) {
VLOG_DBG_RL(&bad_ofmsg_rl,
case NXAST_SET_QUEUE:
case NXAST_POP_QUEUE:
return check_action_exact_len(a, len, 16);
+
+ case NXAST_REG_MOVE:
+ error = check_action_exact_len(a, len,
+ sizeof(struct nx_action_reg_move));
+ if (error) {
+ return error;
+ }
+ return nxm_check_reg_move((const struct nx_action_reg_move *) a, flow);
+
+ case NXAST_REG_LOAD:
+ error = check_action_exact_len(a, len,
+ sizeof(struct nx_action_reg_load));
+ if (error) {
+ return error;
+ }
+ return nxm_check_reg_load((const struct nx_action_reg_load *) a, flow);
+
+ case NXAST_NOTE:
+ return 0;
+
default:
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE);
}
}
static int
-check_action(const union ofp_action *a, unsigned int len, int max_ports)
+check_action(const union ofp_action *a, unsigned int len,
+ const struct flow *flow, int max_ports)
{
int error;
case OFPAT_VENDOR:
return (a->vendor.vendor == htonl(NX_VENDOR_ID)
- ? check_nicira_action(a, len)
+ ? check_nicira_action(a, len, flow)
: ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR));
case OFPAT_ENQUEUE:
int
validate_actions(const union ofp_action *actions, size_t n_actions,
- const struct flow *flow OVS_UNUSED, int max_ports)
+ const struct flow *flow, int max_ports)
{
size_t i;
for (i = 0; i < n_actions; ) {
const union ofp_action *a = &actions[i];
unsigned int len = ntohs(a->header.len);
- unsigned int n_slots = len / ACTION_ALIGNMENT;
+ unsigned int n_slots = len / OFP_ACTION_ALIGN;
unsigned int slots_left = &actions[n_actions] - a;
int error;
} else if (!len) {
VLOG_DBG_RL(&bad_ofmsg_rl, "action has invalid length 0");
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
- } else if (len % ACTION_ALIGNMENT) {
+ } else if (len % OFP_ACTION_ALIGN) {
VLOG_DBG_RL(&bad_ofmsg_rl, "action length %u is not a multiple "
- "of %d", len, ACTION_ALIGNMENT);
+ "of %d", len, OFP_ACTION_ALIGN);
return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
}
- error = check_action(a, len, max_ports);
+ error = check_action(a, len, flow, max_ports);
if (error) {
return error;
}
if (iter->pos != iter->end) {
const union ofp_action *a = iter->pos;
unsigned int len = ntohs(a->header.len);
- iter->pos += len / ACTION_ALIGNMENT;
+ iter->pos += len / OFP_ACTION_ALIGN;
return a;
} else {
return NULL;
uint8_t vendor;
uint16_t type;
uint16_t code;
- uint32_t xid;
+ ovs_be32 xid;
if (!is_ofp_error(error)) {
/* We format 'error' with strerror() here since it seems likely to be
ofputil_pull_actions(struct ofpbuf *b, unsigned int actions_len,
union ofp_action **actionsp, size_t *n_actionsp)
{
- if (actions_len % ACTION_ALIGNMENT != 0) {
+ if (actions_len % OFP_ACTION_ALIGN != 0) {
VLOG_DBG_RL(&bad_ofmsg_rl, "OpenFlow message actions length %u "
- "is not a multiple of %d", actions_len, ACTION_ALIGNMENT);
+ "is not a multiple of %d", actions_len, OFP_ACTION_ALIGN);
goto error;
}
goto error;
}
- *n_actionsp = actions_len / ACTION_ALIGNMENT;
+ *n_actionsp = actions_len / OFP_ACTION_ALIGN;
return 0;
error: