This seems a little better than a pair of bare arrays.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
-/* Copyright (c) 2008, 2011, 2012, 2013, 2014 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2011, 2012, 2013, 2014, 2016 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
OFPR_ACTION_SET, /* Output to controller in action set */
OFPR_GROUP, /* Output to controller in group bucket */
OFPR_PACKET_OUT, /* Output to controller in packet-out */
+
+#define OFPR10_BITS \
+ ((1u << OFPR_NO_MATCH) | (1u << OFPR_ACTION) | (1u << OFPR_INVALID_TTL))
+#define OFPR14_BITS \
+ (OFPR10_BITS | \
+ (1u << OFPR_ACTION_SET) | (1u << OFPR_GROUP) | (1u << OFPR_PACKET_OUT))
+
OFPR_N_REASONS
};
OFPRR_METER_DELETE, /* Meter was removed. */
OFPRR_EVICTION, /* Switch eviction to free resources. */
+#define OFPRR10_BITS \
+ ((1u << OFPRR_IDLE_TIMEOUT) | \
+ (1u << OFPRR_HARD_TIMEOUT) | \
+ (1u << OFPRR_DELETE))
+#define OFPRR14_BITS \
+ (OFPRR10_BITS | \
+ (1u << OFPRR_GROUP_DELETE) | \
+ (1u << OFPRR_METER_DELETE) | \
+ (1u << OFPRR_EVICTION))
+
OVS_OFPRR_NONE /* OVS internal_use only, keep last!. */
};
OFPPR_ADD, /* The port was added. */
OFPPR_DELETE, /* The port was removed. */
OFPPR_MODIFY, /* Some attribute of the port has changed. */
+
+#define OFPPR_BITS ((1u << OFPPR_ADD) | \
+ (1u << OFPPR_DELETE) | \
+ (1u << OFPPR_MODIFY))
+
OFPPR_N_REASONS /* Denotes number of reasons. */
};
}
} else if (raw == OFPRAW_OFPT14_SET_ASYNC ||
raw == OFPRAW_OFPT14_GET_ASYNC_REPLY) {
- enum ofperr error = 0;
- uint32_t role[2][OAM_N_TYPES] = {{0}};
- uint32_t type;
-
- if (raw == OFPRAW_OFPT14_GET_ASYNC_REPLY) {
- error = ofputil_decode_set_async_config(oh, role[0], role[1], true);
- }
- else if (raw == OFPRAW_OFPT14_SET_ASYNC) {
- error = ofputil_decode_set_async_config(oh, role[0], role[1],
- false);
- }
+ struct ofputil_async_cfg ac = OFPUTIL_ASYNC_CFG_INIT;
+ bool is_reply = raw == OFPRAW_OFPT14_GET_ASYNC_REPLY;
+ enum ofperr error = ofputil_decode_set_async_config(oh, is_reply, &ac);
if (error) {
ofp_print_error(string, error);
return;
}
for (i = 0; i < 2; i++) {
-
ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");
- for (type = 0; type < OAM_N_TYPES; type++) {
+ for (uint32_t type = 0; type < OAM_N_TYPES; type++) {
ds_put_format(string, "%16s:",
ofputil_async_msg_type_to_string(type));
+ uint32_t role = i == 0 ? ac.master[type] : ac.slave[type];
for (j = 0; j < 32; j++) {
- if (role[i][type] & (1u << j)) {
+ if (role & (1u << j)) {
char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE];
const char *reason;
ds_put_format(string, " %s", reason);
}
}
- if (!role[i][type]) {
+ if (!role) {
ds_put_cstr(string, " (off)");
}
ds_put_char(string, '\n');
}
/* Decodes the OpenFlow "set async config" request and "get async config
- * reply" message in '*oh' into an abstract form in 'master' and 'slave'.
+ * reply" message in '*oh' into an abstract form in 'ac'.
*
* If 'loose' is true, this function ignores properties and values that it does
* not understand, as a controller would want to do when interpreting
* Returns error code OFPERR_OFPACFC_UNSUPPORTED if the configuration is not
* supported.*/
enum ofperr
-ofputil_decode_set_async_config(const struct ofp_header *oh,
- uint32_t master[OAM_N_TYPES],
- uint32_t slave[OAM_N_TYPES],
- bool loose)
+ofputil_decode_set_async_config(const struct ofp_header *oh, bool loose,
+ struct ofputil_async_cfg *ac)
{
enum ofpraw raw;
struct ofpbuf b;
raw == OFPRAW_OFPT13_GET_ASYNC_REPLY) {
const struct nx_async_config *msg = ofpmsg_body(oh);
- master[OAM_PACKET_IN] = ntohl(msg->packet_in_mask[0]);
- master[OAM_PORT_STATUS] = ntohl(msg->port_status_mask[0]);
- master[OAM_FLOW_REMOVED] = ntohl(msg->flow_removed_mask[0]);
-
- slave[OAM_PACKET_IN] = ntohl(msg->packet_in_mask[1]);
- slave[OAM_PORT_STATUS] = ntohl(msg->port_status_mask[1]);
- slave[OAM_FLOW_REMOVED] = ntohl(msg->flow_removed_mask[1]);
+ ac->master[OAM_PACKET_IN] = ntohl(msg->packet_in_mask[0]);
+ ac->master[OAM_PORT_STATUS] = ntohl(msg->port_status_mask[0]);
+ ac->master[OAM_FLOW_REMOVED] = ntohl(msg->flow_removed_mask[0]);
+ ac->slave[OAM_PACKET_IN] = ntohl(msg->packet_in_mask[1]);
+ ac->slave[OAM_PORT_STATUS] = ntohl(msg->port_status_mask[1]);
+ ac->slave[OAM_FLOW_REMOVED] = ntohl(msg->flow_removed_mask[1]);
} else if (raw == OFPRAW_OFPT14_SET_ASYNC ||
raw == OFPRAW_OFPT14_GET_ASYNC_REPLY) {
switch (type) {
case OFPACPT_PACKET_IN_SLAVE:
- slave[OAM_PACKET_IN] = mask;
+ ac->slave[OAM_PACKET_IN] = mask;
break;
case OFPACPT_PACKET_IN_MASTER:
- master[OAM_PACKET_IN] = mask;
+ ac->master[OAM_PACKET_IN] = mask;
break;
case OFPACPT_PORT_STATUS_SLAVE:
- slave[OAM_PORT_STATUS] = mask;
+ ac->slave[OAM_PORT_STATUS] = mask;
break;
case OFPACPT_PORT_STATUS_MASTER:
- master[OAM_PORT_STATUS] = mask;
+ ac->master[OAM_PORT_STATUS] = mask;
break;
case OFPACPT_FLOW_REMOVED_SLAVE:
- slave[OAM_FLOW_REMOVED] = mask;
+ ac->slave[OAM_FLOW_REMOVED] = mask;
break;
case OFPACPT_FLOW_REMOVED_MASTER:
- master[OAM_FLOW_REMOVED] = mask;
+ ac->master[OAM_FLOW_REMOVED] = mask;
break;
case OFPACPT_ROLE_STATUS_SLAVE:
- slave[OAM_ROLE_STATUS] = mask;
+ ac->slave[OAM_ROLE_STATUS] = mask;
break;
case OFPACPT_ROLE_STATUS_MASTER:
- master[OAM_ROLE_STATUS] = mask;
+ ac->master[OAM_ROLE_STATUS] = mask;
break;
case OFPACPT_TABLE_STATUS_SLAVE:
- slave[OAM_TABLE_STATUS] = mask;
+ ac->slave[OAM_TABLE_STATUS] = mask;
break;
case OFPACPT_TABLE_STATUS_MASTER:
- master[OAM_TABLE_STATUS] = mask;
+ ac->master[OAM_TABLE_STATUS] = mask;
break;
case OFPACPT_REQUESTFORWARD_SLAVE:
- slave[OAM_REQUESTFORWARD] = mask;
+ ac->slave[OAM_REQUESTFORWARD] = mask;
break;
case OFPACPT_REQUESTFORWARD_MASTER:
- master[OAM_REQUESTFORWARD] = mask;
+ ac->master[OAM_REQUESTFORWARD] = mask;
break;
default:
* as a reply to get async config request. */
struct ofpbuf *
ofputil_encode_get_async_config(const struct ofp_header *oh,
- uint32_t master[OAM_N_TYPES],
- uint32_t slave[OAM_N_TYPES])
+ const struct ofputil_async_cfg *ac)
{
struct ofpbuf *buf;
uint32_t type;
struct nx_async_config *msg;
msg = ofpbuf_put_zeros(buf, sizeof *msg);
- msg->packet_in_mask[0] = htonl(master[OAM_PACKET_IN]);
- msg->port_status_mask[0] = htonl(master[OAM_PORT_STATUS]);
- msg->flow_removed_mask[0] = htonl(master[OAM_FLOW_REMOVED]);
+ msg->packet_in_mask[0] = htonl(ac->master[OAM_PACKET_IN]);
+ msg->port_status_mask[0] = htonl(ac->master[OAM_PORT_STATUS]);
+ msg->flow_removed_mask[0] = htonl(ac->master[OAM_FLOW_REMOVED]);
- msg->packet_in_mask[1] = htonl(slave[OAM_PACKET_IN]);
- msg->port_status_mask[1] = htonl(slave[OAM_PORT_STATUS]);
- msg->flow_removed_mask[1] = htonl(slave[OAM_FLOW_REMOVED]);
+ msg->packet_in_mask[1] = htonl(ac->slave[OAM_PACKET_IN]);
+ msg->port_status_mask[1] = htonl(ac->slave[OAM_PORT_STATUS]);
+ msg->flow_removed_mask[1] = htonl(ac->slave[OAM_FLOW_REMOVED]);
} else if (oh->version == OFP14_VERSION) {
for (type = 0; type < OAM_N_TYPES; type++) {
- ofputil_get_async_reply(buf, master[type], slave[type], type);
+ ofputil_get_async_reply(buf, ac->master[type], ac->slave[type],
+ type);
}
}
return buf;
}
+
+struct ofputil_async_cfg
+ofputil_async_cfg_default(enum ofp_version version)
+{
+ return (struct ofputil_async_cfg) {
+ .master[OAM_PACKET_IN]
+ = ((version >= OFP14_VERSION ? OFPR14_BITS : OFPR10_BITS)
+ & ~(1u << OFPR_INVALID_TTL)),
+
+ .master[OAM_FLOW_REMOVED]
+ = (version >= OFP14_VERSION ? OFPRR14_BITS : OFPRR10_BITS),
+
+ .master[OAM_PORT_STATUS] = OFPPR_BITS,
+ .slave[OAM_PORT_STATUS] = OFPPR_BITS,
+ };
+}
/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
};
const char *ofputil_async_msg_type_to_string(enum ofputil_async_msg_type);
+struct ofputil_async_cfg {
+ uint32_t master[OAM_N_TYPES];
+ uint32_t slave[OAM_N_TYPES];
+};
+#define OFPUTIL_ASYNC_CFG_INIT (struct ofputil_async_cfg) { .master[0] = 0 }
+
enum ofperr ofputil_decode_set_async_config(const struct ofp_header *,
- uint32_t master[OAM_N_TYPES],
- uint32_t slave[OAM_N_TYPES],
- bool loose);
+ bool loose,
+ struct ofputil_async_cfg *);
+
+struct ofpbuf *ofputil_encode_get_async_config(
+ const struct ofp_header *, const struct ofputil_async_cfg *);
-struct ofpbuf *ofputil_encode_get_async_config(const struct ofp_header *,
- uint32_t master[OAM_N_TYPES],
- uint32_t slave[OAM_N_TYPES]);
+struct ofputil_async_cfg ofputil_async_cfg_default(enum ofp_version);
struct ofputil_requestforward {
ovs_be32 xid;
/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define OFCONN_REPLY_MAX 100
struct rconn_packet_counter *reply_counter;
- /* Asynchronous message configuration in each possible roles.
+ /* Asynchronous message configuration in each possible role.
*
* A 1-bit enables sending an asynchronous message for one possible reason
* that the message might be generated, a 0-bit disables it. */
- uint32_t master_async_config[OAM_N_TYPES]; /* master, other */
- uint32_t slave_async_config[OAM_N_TYPES]; /* slave */
+ struct ofputil_async_cfg *async_cfg;
/* Flow table operation logging. */
int n_add, n_delete, n_modify; /* Number of unreported ops of each kind. */
void
ofconn_set_invalid_ttl_to_controller(struct ofconn *ofconn, bool enable)
{
+ struct ofputil_async_cfg ac = ofconn_get_async_config(ofconn);
uint32_t bit = 1u << OFPR_INVALID_TTL;
if (enable) {
- ofconn->master_async_config[OAM_PACKET_IN] |= bit;
+ ac.master[OAM_PACKET_IN] |= bit;
} else {
- ofconn->master_async_config[OAM_PACKET_IN] &= ~bit;
+ ac.master[OAM_PACKET_IN] &= ~bit;
}
+ ofconn_set_async_config(ofconn, &ac);
}
bool
ofconn_get_invalid_ttl_to_controller(struct ofconn *ofconn)
{
+ struct ofputil_async_cfg ac = ofconn_get_async_config(ofconn);
uint32_t bit = 1u << OFPR_INVALID_TTL;
- return (ofconn->master_async_config[OAM_PACKET_IN] & bit) != 0;
+ return (ac.master[OAM_PACKET_IN] & bit) != 0;
}
/* Returns the currently configured protocol for 'ofconn', one of OFPUTIL_P_*.
ofconn_set_protocol(struct ofconn *ofconn, enum ofputil_protocol protocol)
{
ofconn->protocol = protocol;
- if (!(protocol & OFPUTIL_P_OF14_UP)) {
- uint32_t *master = ofconn->master_async_config;
- uint32_t *slave = ofconn->slave_async_config;
-
- /* OFPR_ACTION_SET is not supported before OF1.4 */
- master[OAM_PACKET_IN] &= ~(1u << OFPR_ACTION_SET);
- slave [OAM_PACKET_IN] &= ~(1u << OFPR_ACTION_SET);
-
- /* OFPR_GROUP is not supported before OF1.4 */
- master[OAM_PACKET_IN] &= ~(1u << OFPR_GROUP);
- slave [OAM_PACKET_IN] &= ~(1u << OFPR_GROUP);
-
- /* OFPR_PACKET_OUT is not supported before OF1.4 */
- master[OAM_PACKET_IN] &= ~(1u << OFPR_PACKET_OUT);
- slave [OAM_PACKET_IN] &= ~(1u << OFPR_PACKET_OUT);
-
- /* OFPRR_GROUP_DELETE is not supported before OF1.4 */
- master[OAM_FLOW_REMOVED] &= ~(1u << OFPRR_GROUP_DELETE);
- slave [OAM_FLOW_REMOVED] &= ~(1u << OFPRR_GROUP_DELETE);
-
- /* OFPRR_METER_DELETE is not supported before OF1.4 */
- master[OAM_FLOW_REMOVED] &= ~(1u << OFPRR_METER_DELETE);
- slave [OAM_FLOW_REMOVED] &= ~(1u << OFPRR_METER_DELETE);
-
- /* OFPRR_EVICTION is not supported before OF1.4 */
- master[OAM_FLOW_REMOVED] &= ~(1u << OFPRR_EVICTION);
- slave [OAM_FLOW_REMOVED] &= ~(1u << OFPRR_EVICTION);
- }
}
/* Returns the currently configured packet in format for 'ofconn', one of
void
ofconn_set_async_config(struct ofconn *ofconn,
- const uint32_t master_masks[OAM_N_TYPES],
- const uint32_t slave_masks[OAM_N_TYPES])
+ const struct ofputil_async_cfg *ac)
{
- size_t size = sizeof ofconn->master_async_config;
- memcpy(ofconn->master_async_config, master_masks, size);
- memcpy(ofconn->slave_async_config, slave_masks, size);
+ if (!ofconn->async_cfg) {
+ ofconn->async_cfg = xmalloc(sizeof *ofconn->async_cfg);
+ }
+ *ofconn->async_cfg = *ac;
}
-void
-ofconn_get_async_config(struct ofconn *ofconn,
- uint32_t *master_masks, uint32_t *slave_masks)
+struct ofputil_async_cfg
+ofconn_get_async_config(const struct ofconn *ofconn)
{
- size_t size = sizeof ofconn->master_async_config;
-
- /* Make sure we know the protocol version and the async_config
- * masks are properly updated by calling ofconn_get_protocol() */
- if (OFPUTIL_P_NONE == ofconn_get_protocol(ofconn)){
- OVS_NOT_REACHED();
+ if (ofconn->async_cfg) {
+ return *ofconn->async_cfg;
}
- memcpy(master_masks, ofconn->master_async_config, size);
- memcpy(slave_masks, ofconn->slave_async_config, size);
+ int version = rconn_get_version(ofconn->rconn);
+ return (version < 0 || !ofconn->enable_async_msgs
+ ? OFPUTIL_ASYNC_CFG_INIT
+ : ofputil_async_cfg_default(version));
}
/* Sends 'msg' on 'ofconn', accounting it as a reply. (If there is a
rconn_packet_counter_destroy(ofconn->reply_counter);
ofconn->reply_counter = rconn_packet_counter_create();
- if (ofconn->enable_async_msgs) {
- uint32_t *master = ofconn->master_async_config;
- uint32_t *slave = ofconn->slave_async_config;
-
- /* "master" and "other" roles get all asynchronous messages by default,
- * except that the controller needs to enable nonstandard "packet-in"
- * reasons itself. */
- master[OAM_PACKET_IN] = ((1u << OFPR_NO_MATCH)
- | (1u << OFPR_ACTION)
- | (1u << OFPR_ACTION_SET)
- | (1u << OFPR_GROUP)
- | (1u << OFPR_PACKET_OUT));
- master[OAM_PORT_STATUS] = ((1u << OFPPR_ADD)
- | (1u << OFPPR_DELETE)
- | (1u << OFPPR_MODIFY));
- master[OAM_FLOW_REMOVED] = ((1u << OFPRR_IDLE_TIMEOUT)
- | (1u << OFPRR_HARD_TIMEOUT)
- | (1u << OFPRR_DELETE)
- | (1u << OFPRR_GROUP_DELETE)
- | (1u << OFPRR_METER_DELETE)
- | (1u << OFPRR_EVICTION));
- master[OAM_ROLE_STATUS] = 0;
- master[OAM_TABLE_STATUS] = 0;
- master[OAM_REQUESTFORWARD] = 0;
- /* "slave" role gets port status updates by default. */
- slave[OAM_PACKET_IN] = 0;
- slave[OAM_PORT_STATUS] = ((1u << OFPPR_ADD)
- | (1u << OFPPR_DELETE)
- | (1u << OFPPR_MODIFY));
- slave[OAM_FLOW_REMOVED] = 0;
- slave[OAM_ROLE_STATUS] = 0;
- slave[OAM_TABLE_STATUS] = 0;
- slave[OAM_REQUESTFORWARD] = 0;
- } else {
- memset(ofconn->master_async_config, 0,
- sizeof ofconn->master_async_config);
- memset(ofconn->slave_async_config, 0,
- sizeof ofconn->slave_async_config);
- }
+ free(ofconn->async_cfg);
+ ofconn->async_cfg = NULL;
ofconn->n_add = ofconn->n_delete = ofconn->n_modify = 0;
ofconn->first_op = ofconn->last_op = LLONG_MIN;
enum ofputil_async_msg_type type,
unsigned int reason)
{
- const uint32_t *async_config;
-
ovs_assert(reason < 32);
ovs_assert((unsigned int) type < OAM_N_TYPES);
- if (ofconn_get_protocol(ofconn) == OFPUTIL_P_NONE
- || !rconn_is_connected(ofconn->rconn)) {
- return false;
- }
-
/* Keep the following code in sync with the documentation in the
* "Asynchronous Messages" section in DESIGN. */
return false;
}
- async_config = (ofconn->role == OFPCR12_ROLE_SLAVE
- ? ofconn->slave_async_config
- : ofconn->master_async_config);
- if (!(async_config[type] & (1u << reason))) {
- return false;
- }
-
- return true;
+ struct ofputil_async_cfg ac = ofconn_get_async_config(ofconn);
+ uint32_t *masks = (ofconn->role == OFPCR12_ROLE_SLAVE
+ ? ac.slave
+ : ac.master);
+ return (masks[type] & (1u << reason)) != 0;
}
/* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the
/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len);
void ofconn_set_async_config(struct ofconn *,
- const uint32_t master_masks[OAM_N_TYPES],
- const uint32_t slave_masks[OAM_N_TYPES]);
-void ofconn_get_async_config(struct ofconn *,
- uint32_t *master_masks,
- uint32_t *slave_masks);
+ const struct ofputil_async_cfg *);
+struct ofputil_async_cfg ofconn_get_async_config(const struct ofconn *);
void ofconn_send_reply(const struct ofconn *, struct ofpbuf *);
void ofconn_send_replies(const struct ofconn *, struct ovs_list *);
static enum ofperr
handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh)
{
+ struct ofputil_async_cfg ac = OFPUTIL_ASYNC_CFG_INIT;
enum ofperr error;
- uint32_t master[OAM_N_TYPES] = {0};
- uint32_t slave[OAM_N_TYPES] = {0};
- error = ofputil_decode_set_async_config(oh, master, slave, false);
+ error = ofputil_decode_set_async_config(oh, false, &ac);
if (error) {
return error;
}
- ofconn_set_async_config(ofconn, master, slave);
+ ofconn_set_async_config(ofconn, &ac);
if (ofconn_get_type(ofconn) == OFCONN_SERVICE &&
!ofconn_get_miss_send_len(ofconn)) {
ofconn_set_miss_send_len(ofconn, OFP_DEFAULT_MISS_SEND_LEN);
static enum ofperr
handle_nxt_get_async_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
- struct ofpbuf *buf;
- uint32_t master[OAM_N_TYPES];
- uint32_t slave[OAM_N_TYPES];
-
- ofconn_get_async_config(ofconn, master, slave);
-
- buf = ofputil_encode_get_async_config(oh, master, slave);
- ofconn_send_reply(ofconn, buf);
+ struct ofputil_async_cfg ac = ofconn_get_async_config(ofconn);
+ ofconn_send_reply(ofconn, ofputil_encode_get_async_config(oh, &ac));
return 0;
}