* 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);
+static enum ofputil_table_vacancy ofputil_decode_table_vacancy(
+ ovs_be32 config, enum ofp_version);
static enum ofputil_table_eviction ofputil_decode_table_eviction(
ovs_be32 config, enum ofp_version);
static ovs_be32 ofputil_encode_table_config(enum ofputil_table_miss,
enum ofputil_table_eviction,
+ enum ofputil_table_vacancy,
enum ofp_version);
struct ofp_prop_header {
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 33);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 34);
/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
}
if (!(ofpfw & OFPFW10_DL_SRC)) {
- memset(wc->masks.dl_src, 0xff, ETH_ADDR_LEN);
+ WC_MASK_FIELD(wc, dl_src);
}
if (!(ofpfw & OFPFW10_DL_DST)) {
- memset(wc->masks.dl_dst, 0xff, ETH_ADDR_LEN);
+ WC_MASK_FIELD(wc, dl_dst);
}
if (!(ofpfw & OFPFW10_DL_TYPE)) {
wc->masks.dl_type = OVS_BE16_MAX;
match->flow.dl_type = ofputil_dl_type_from_openflow(ofmatch->dl_type);
match->flow.tp_src = ofmatch->tp_src;
match->flow.tp_dst = ofmatch->tp_dst;
- memcpy(match->flow.dl_src, ofmatch->dl_src, ETH_ADDR_LEN);
- memcpy(match->flow.dl_dst, ofmatch->dl_dst, ETH_ADDR_LEN);
+ match->flow.dl_src = ofmatch->dl_src;
+ match->flow.dl_dst = ofmatch->dl_dst;
match->flow.nw_tos = ofmatch->nw_tos & IP_DSCP_MASK;
match->flow.nw_proto = ofmatch->nw_proto;
/* Compose most of the match structure. */
ofmatch->wildcards = htonl(ofpfw);
ofmatch->in_port = htons(ofp_to_u16(match->flow.in_port.ofp_port));
- memcpy(ofmatch->dl_src, match->flow.dl_src, ETH_ADDR_LEN);
- memcpy(ofmatch->dl_dst, match->flow.dl_dst, ETH_ADDR_LEN);
+ ofmatch->dl_src = match->flow.dl_src;
+ ofmatch->dl_dst = match->flow.dl_dst;
ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
ofmatch->nw_src = match->flow.nw_src;
ofmatch->nw_dst = match->flow.nw_dst;
struct match *match)
{
uint16_t wc = ntohl(ofmatch->wildcards);
- uint8_t dl_src_mask[ETH_ADDR_LEN];
- uint8_t dl_dst_mask[ETH_ADDR_LEN];
bool ipv4, arp, rarp;
- int i;
match_init_catchall(match);
match_set_in_port(match, ofp_port);
}
- for (i = 0; i < ETH_ADDR_LEN; i++) {
- dl_src_mask[i] = ~ofmatch->dl_src_mask[i];
- }
- match_set_dl_src_masked(match, ofmatch->dl_src, dl_src_mask);
-
- for (i = 0; i < ETH_ADDR_LEN; i++) {
- dl_dst_mask[i] = ~ofmatch->dl_dst_mask[i];
- }
- match_set_dl_dst_masked(match, ofmatch->dl_dst, dl_dst_mask);
+ match_set_dl_src_masked(match, ofmatch->dl_src,
+ eth_addr_invert(ofmatch->dl_src_mask));
+ match_set_dl_dst_masked(match, ofmatch->dl_dst,
+ eth_addr_invert(ofmatch->dl_dst_mask));
if (!(wc & OFPFW11_DL_VLAN)) {
if (ofmatch->dl_vlan == htons(OFPVID11_NONE)) {
struct ofp11_match *ofmatch)
{
uint32_t wc = 0;
- int i;
memset(ofmatch, 0, sizeof *ofmatch);
ofmatch->omh.type = htons(OFPMT_STANDARD);
ofmatch->in_port = ofputil_port_to_ofp11(match->flow.in_port.ofp_port);
}
- memcpy(ofmatch->dl_src, match->flow.dl_src, ETH_ADDR_LEN);
- for (i = 0; i < ETH_ADDR_LEN; i++) {
- ofmatch->dl_src_mask[i] = ~match->wc.masks.dl_src[i];
- }
-
- memcpy(ofmatch->dl_dst, match->flow.dl_dst, ETH_ADDR_LEN);
- for (i = 0; i < ETH_ADDR_LEN; i++) {
- ofmatch->dl_dst_mask[i] = ~match->wc.masks.dl_dst[i];
- }
+ ofmatch->dl_src = match->flow.dl_src;
+ ofmatch->dl_src_mask = eth_addr_invert(match->wc.masks.dl_src);
+ ofmatch->dl_dst = match->flow.dl_dst;
+ ofmatch->dl_dst_mask = eth_addr_invert(match->wc.masks.dl_dst);
if (match->wc.masks.vlan_tci == htons(0)) {
wc |= OFPFW11_DL_VLAN | OFPFW11_DL_VLAN_PCP;
fm->out_group = (ofm->command == OFPFC_DELETE ||
ofm->command == OFPFC_DELETE_STRICT
? ntohl(ofm->out_group)
- : OFPG11_ANY);
+ : OFPG_ANY);
raw_flags = ofm->flags;
} else {
uint16_t command;
fm->importance = 0;
fm->buffer_id = ntohl(ofm->buffer_id);
fm->out_port = u16_to_ofp(ntohs(ofm->out_port));
- fm->out_group = OFPG11_ANY;
+ fm->out_group = OFPG_ANY;
raw_flags = ofm->flags;
} else if (raw == OFPRAW_NXT_FLOW_MOD) {
/* Nicira extended flow_mod. */
fm->importance = 0;
fm->buffer_id = ntohl(nfm->buffer_id);
fm->out_port = u16_to_ofp(ntohs(nfm->out_port));
- fm->out_group = OFPG11_ANY;
+ fm->out_group = OFPG_ANY;
raw_flags = nfm->flags;
} else {
OVS_NOT_REACHED();
fsr->aggregate = aggregate;
ofputil_match_from_ofp10_match(&ofsr->match, &fsr->match);
fsr->out_port = u16_to_ofp(ntohs(ofsr->out_port));
- fsr->out_group = OFPG11_ANY;
+ fsr->out_group = OFPG_ANY;
fsr->table_id = ofsr->table_id;
fsr->cookie = fsr->cookie_mask = htonll(0);
fsr->aggregate = aggregate;
fsr->out_port = u16_to_ofp(ntohs(nfsr->out_port));
- fsr->out_group = OFPG11_ANY;
+ fsr->out_group = OFPG_ANY;
fsr->table_id = nfsr->table_id;
return 0;
const struct ofp10_phy_port *opp)
{
pp->port_no = u16_to_ofp(ntohs(opp->port_no));
- memcpy(pp->hw_addr, opp->hw_addr, OFP_ETH_ALEN);
+ pp->hw_addr = opp->hw_addr;
ovs_strlcpy(pp->name, opp->name, OFP_MAX_PORT_NAME_LEN);
pp->config = ntohl(opp->config) & OFPPC10_ALL;
if (error) {
return error;
}
- memcpy(pp->hw_addr, op->hw_addr, OFP_ETH_ALEN);
+ pp->hw_addr = op->hw_addr;
ovs_strlcpy(pp->name, op->name, OFP_MAX_PORT_NAME_LEN);
pp->config = ntohl(op->config) & OFPPC11_ALL;
if (error) {
return error;
}
- memcpy(pp->hw_addr, op->hw_addr, OFP_ETH_ALEN);
+ pp->hw_addr = op->hw_addr;
ovs_strlcpy(pp->name, op->name, OFP_MAX_PORT_NAME_LEN);
pp->config = ntohl(op->config) & OFPPC11_ALL;
memset(opp, 0, sizeof *opp);
opp->port_no = htons(ofp_to_u16(pp->port_no));
- memcpy(opp->hw_addr, pp->hw_addr, ETH_ADDR_LEN);
+ opp->hw_addr = pp->hw_addr;
ovs_strlcpy(opp->name, pp->name, OFP_MAX_PORT_NAME_LEN);
opp->config = htonl(pp->config & OFPPC10_ALL);
memset(op, 0, sizeof *op);
op->port_no = ofputil_port_to_ofp11(pp->port_no);
- memcpy(op->hw_addr, pp->hw_addr, ETH_ADDR_LEN);
+ op->hw_addr = pp->hw_addr;
ovs_strlcpy(op->name, pp->name, OFP_MAX_PORT_NAME_LEN);
op->config = htonl(pp->config & OFPPC11_ALL);
op = ofpbuf_put_zeros(b, sizeof *op);
op->port_no = ofputil_port_to_ofp11(pp->port_no);
op->length = htons(sizeof *op + sizeof *eth);
- memcpy(op->hw_addr, pp->hw_addr, ETH_ADDR_LEN);
+ op->hw_addr = pp->hw_addr;
ovs_strlcpy(op->name, pp->name, sizeof op->name);
op->config = htonl(pp->config & OFPPC11_ALL);
op->state = htonl(pp->state & OFPPS11_ALL);
const struct ofp10_port_mod *opm = b.data;
pm->port_no = u16_to_ofp(ntohs(opm->port_no));
- memcpy(pm->hw_addr, opm->hw_addr, ETH_ADDR_LEN);
+ pm->hw_addr = opm->hw_addr;
pm->config = ntohl(opm->config) & OFPPC10_ALL;
pm->mask = ntohl(opm->mask) & OFPPC10_ALL;
pm->advertise = netdev_port_features_from_ofp10(opm->advertise);
return error;
}
- memcpy(pm->hw_addr, opm->hw_addr, ETH_ADDR_LEN);
+ pm->hw_addr = opm->hw_addr;
pm->config = ntohl(opm->config) & OFPPC11_ALL;
pm->mask = ntohl(opm->mask) & OFPPC11_ALL;
pm->advertise = netdev_port_features_from_ofp11(opm->advertise);
return error;
}
- memcpy(pm->hw_addr, opm->hw_addr, ETH_ADDR_LEN);
+ pm->hw_addr = opm->hw_addr;
pm->config = ntohl(opm->config) & OFPPC11_ALL;
pm->mask = ntohl(opm->mask) & OFPPC11_ALL;
b = ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD, ofp_version, 0);
opm = ofpbuf_put_zeros(b, sizeof *opm);
opm->port_no = htons(ofp_to_u16(pm->port_no));
- memcpy(opm->hw_addr, pm->hw_addr, ETH_ADDR_LEN);
+ opm->hw_addr = pm->hw_addr;
opm->config = htonl(pm->config & OFPPC10_ALL);
opm->mask = htonl(pm->mask & OFPPC10_ALL);
opm->advertise = netdev_port_features_to_ofp10(pm->advertise);
b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0);
opm = ofpbuf_put_zeros(b, sizeof *opm);
opm->port_no = ofputil_port_to_ofp11(pm->port_no);
- memcpy(opm->hw_addr, pm->hw_addr, ETH_ADDR_LEN);
+ opm->hw_addr = pm->hw_addr;
opm->config = htonl(pm->config & OFPPC11_ALL);
opm->mask = htonl(pm->mask & OFPPC11_ALL);
opm->advertise = netdev_port_features_to_ofp11(pm->advertise);
b = ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD, ofp_version, sizeof *eth);
opm = ofpbuf_put_zeros(b, sizeof *opm);
opm->port_no = ofputil_port_to_ofp11(pm->port_no);
- memcpy(opm->hw_addr, pm->hw_addr, ETH_ADDR_LEN);
+ opm->hw_addr = pm->hw_addr;
opm->config = htonl(pm->config & OFPPC11_ALL);
opm->mask = htonl(pm->mask & OFPPC11_ALL);
otd->length = htons(reply->size - start_otd);
otd->table_id = td->table_id;
otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
- td->eviction, version);
+ td->eviction, td->vacancy,
+ version);
ofpmp_postappend(replies, start_otd);
}
+/* This function parses Vacancy property, and decodes the
+ * ofp14_table_mod_prop_vacancy in ofputil_table_mod.
+ * Returns OFPERR_OFPBPC_BAD_VALUE error code when vacancy_down is
+ * greater than vacancy_up and also when current vacancy has non-zero
+ * value. Returns 0 on success. */
+static enum ofperr
+parse_table_mod_vacancy_property(struct ofpbuf *property,
+ struct ofputil_table_mod *tm)
+{
+ struct ofp14_table_mod_prop_vacancy *otv = property->data;
+
+ if (property->size != sizeof *otv) {
+ return OFPERR_OFPBPC_BAD_LEN;
+ }
+ tm->table_vacancy.vacancy_down = otv->vacancy_down;
+ tm->table_vacancy.vacancy_up = otv->vacancy_up;
+ if (tm->table_vacancy.vacancy_down > tm->table_vacancy.vacancy_up) {
+ log_property(false, "Value of vacancy_down is greater than "
+ "vacancy_up");
+ return OFPERR_OFPBPC_BAD_VALUE;
+ }
+ if (tm->table_vacancy.vacancy_down > 100 ||
+ tm->table_vacancy.vacancy_up > 100) {
+ log_property(false, "Vacancy threshold percentage should not be"
+ "greater than 100");
+ return OFPERR_OFPBPC_BAD_VALUE;
+ }
+ tm->table_vacancy.vacancy = otv->vacancy;
+ if (tm->table_vacancy.vacancy) {
+ log_property(false, "Vacancy value should be zero for table-mod "
+ "messages");
+ return OFPERR_OFPBPC_BAD_VALUE;
+ }
+ return 0;
+}
+
+/* Given 'config', taken from an OpenFlow 'version' message that specifies
+ * table configuration (a table mod, table stats, or table features message),
+ * returns the table vacancy configuration that it specifies.
+ *
+ * Only OpenFlow 1.4 and later specify table vacancy configuration this way,
+ * so for other 'version' this function always returns
+ * OFPUTIL_TABLE_VACANCY_DEFAULT. */
+static enum ofputil_table_vacancy
+ofputil_decode_table_vacancy(ovs_be32 config, enum ofp_version version)
+{
+ return (version < OFP14_VERSION ? OFPUTIL_TABLE_VACANCY_DEFAULT
+ : config & htonl(OFPTC14_VACANCY_EVENTS) ? OFPUTIL_TABLE_VACANCY_ON
+ : OFPUTIL_TABLE_VACANCY_OFF);
+}
+
static enum ofperr
parse_table_mod_eviction_property(struct ofpbuf *property,
struct ofputil_table_mod *tm)
static ovs_be32
ofputil_encode_table_config(enum ofputil_table_miss miss,
enum ofputil_table_eviction eviction,
+ enum ofputil_table_vacancy vacancy,
enum ofp_version version)
{
+ uint32_t config = 0;
/* See the section "OFPTC_* Table Configuration" in DESIGN.md for more
* information on the crazy evolution of this field. */
switch (version) {
case OFP14_VERSION:
case OFP15_VERSION:
- /* OpenFlow 1.4 introduced OFPTC14_EVICTION and OFPTC14_VACANCY_EVENTS
- * and we don't support the latter yet. */
- return htonl(eviction == OFPUTIL_TABLE_EVICTION_ON
- ? OFPTC14_EVICTION : 0);
+ /* OpenFlow 1.4 introduced OFPTC14_EVICTION and
+ * OFPTC14_VACANCY_EVENTS. */
+ if (eviction == OFPUTIL_TABLE_EVICTION_ON) {
+ config |= OFPTC14_EVICTION;
+ }
+ if (vacancy == OFPUTIL_TABLE_VACANCY_ON) {
+ config |= OFPTC14_VACANCY_EVENTS;
+ }
+ return htonl(config);
}
OVS_NOT_REACHED();
pm->miss = OFPUTIL_TABLE_MISS_DEFAULT;
pm->eviction = OFPUTIL_TABLE_EVICTION_DEFAULT;
pm->eviction_flags = UINT32_MAX;
+ pm->vacancy = OFPUTIL_TABLE_VACANCY_DEFAULT;
ofpbuf_use_const(&b, oh, ntohs(oh->length));
raw = ofpraw_pull_assert(&b);
pm->table_id = otm->table_id;
pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
pm->eviction = ofputil_decode_table_eviction(otm->config, oh->version);
+ pm->vacancy = ofputil_decode_table_vacancy(otm->config, oh->version);
while (b.size > 0) {
struct ofpbuf property;
enum ofperr error;
error = parse_table_mod_eviction_property(&property, pm);
break;
+ case OFPTMPT14_VACANCY:
+ error = parse_table_mod_vacancy_property(&property, pm);
+ break;
+
default:
error = OFPERR_OFPBRC_BAD_TYPE;
break;
otm = ofpbuf_put_zeros(b, sizeof *otm);
otm->table_id = tm->table_id;
otm->config = ofputil_encode_table_config(tm->miss, tm->eviction,
- ofp_version);
+ tm->vacancy, ofp_version);
break;
}
case OFP14_VERSION:
case OFP15_VERSION: {
struct ofp14_table_mod *otm;
struct ofp14_table_mod_prop_eviction *ote;
+ struct ofp14_table_mod_prop_vacancy *otv;
b = ofpraw_alloc(OFPRAW_OFPT14_TABLE_MOD, ofp_version, 0);
otm = ofpbuf_put_zeros(b, sizeof *otm);
otm->table_id = tm->table_id;
otm->config = ofputil_encode_table_config(tm->miss, tm->eviction,
- ofp_version);
+ tm->vacancy, ofp_version);
if (tm->eviction_flags != UINT32_MAX) {
ote = ofpbuf_put_zeros(b, sizeof *ote);
ote->length = htons(sizeof *ote);
ote->flags = htonl(tm->eviction_flags);
}
+ if (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
+ otv = ofpbuf_put_zeros(b, sizeof *otv);
+ otv->type = htons(OFPTMPT14_VACANCY);
+ otv->length = htons(sizeof *otv);
+ otv->vacancy_down = tm->table_vacancy.vacancy_down;
+ otv->vacancy_up = tm->table_vacancy.vacancy_up;
+ }
break;
}
default:
return 0;
}
+/* Encodes 'rf' according to 'protocol', and returns the encoded message.
+ * 'protocol' must be for OpenFlow 1.4 or later. */
+struct ofpbuf *
+ofputil_encode_requestforward(const struct ofputil_requestforward *rf,
+ enum ofputil_protocol protocol)
+{
+ enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
+ struct ofpbuf *inner;
+
+ switch (rf->reason) {
+ case OFPRFR_GROUP_MOD:
+ inner = ofputil_encode_group_mod(ofp_version, rf->group_mod);
+ break;
+
+ case OFPRFR_METER_MOD:
+ inner = ofputil_encode_meter_mod(ofp_version, rf->meter_mod);
+ break;
+
+ default:
+ OVS_NOT_REACHED();
+ }
+
+ struct ofp_header *inner_oh = inner->data;
+ inner_oh->xid = rf->xid;
+ inner_oh->length = htons(inner->size);
+
+ struct ofpbuf *outer = ofpraw_alloc_xid(OFPRAW_OFPT14_REQUESTFORWARD,
+ ofp_version, htonl(0),
+ inner->size);
+ ofpbuf_put(outer, inner->data, inner->size);
+ ofpbuf_delete(inner);
+
+ return outer;
+}
+
+/* Decodes OFPT_REQUESTFORWARD message 'outer'. On success, puts the decoded
+ * form into '*rf' and returns 0, and the caller is later responsible for
+ * freeing the content of 'rf', with ofputil_destroy_requestforward(rf). On
+ * failure, returns an ofperr and '*rf' is indeterminate. */
+enum ofperr
+ofputil_decode_requestforward(const struct ofp_header *outer,
+ struct ofputil_requestforward *rf)
+{
+ struct ofpbuf b;
+ enum ofperr error;
+
+ ofpbuf_use_const(&b, outer, ntohs(outer->length));
+
+ /* Skip past outer message. */
+ enum ofpraw outer_raw = ofpraw_pull_assert(&b);
+ ovs_assert(outer_raw == OFPRAW_OFPT14_REQUESTFORWARD);
+
+ /* Validate inner message. */
+ if (b.size < sizeof(struct ofp_header)) {
+ return OFPERR_OFPBFC_MSG_BAD_LEN;
+ }
+ const struct ofp_header *inner = b.data;
+ unsigned int inner_len = ntohs(inner->length);
+ if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) {
+ return OFPERR_OFPBFC_MSG_BAD_LEN;
+ }
+ if (inner->version != outer->version) {
+ return OFPERR_OFPBRC_BAD_VERSION;
+ }
+
+ /* Parse inner message. */
+ enum ofptype type;
+ error = ofptype_decode(&type, inner);
+ if (error) {
+ return error;
+ }
+
+ rf->xid = inner->xid;
+ if (type == OFPTYPE_GROUP_MOD) {
+ rf->reason = OFPRFR_GROUP_MOD;
+ rf->group_mod = xmalloc(sizeof *rf->group_mod);
+ error = ofputil_decode_group_mod(inner, rf->group_mod);
+ if (error) {
+ free(rf->group_mod);
+ return error;
+ }
+ } else if (type == OFPTYPE_METER_MOD) {
+ rf->reason = OFPRFR_METER_MOD;
+ rf->meter_mod = xmalloc(sizeof *rf->meter_mod);
+ ofpbuf_init(&rf->bands, 64);
+ error = ofputil_decode_meter_mod(inner, rf->meter_mod, &rf->bands);
+ if (error) {
+ free(rf->meter_mod);
+ ofpbuf_uninit(&rf->bands);
+ return error;
+ }
+ } else {
+ return OFPERR_OFPBFC_MSG_UNSUP;
+ }
+
+ return 0;
+}
+
+/* Frees the content of 'rf', which should have been initialized through a
+ * successful call to ofputil_decode_requestforward(). */
+void
+ofputil_destroy_requestforward(struct ofputil_requestforward *rf)
+{
+ if (!rf) {
+ return;
+ }
+
+ switch (rf->reason) {
+ case OFPRFR_GROUP_MOD:
+ ofputil_uninit_group_mod(rf->group_mod);
+ free(rf->group_mod);
+ break;
+
+ case OFPRFR_METER_MOD:
+ ofpbuf_uninit(&rf->bands);
+ free(rf->meter_mod);
+ }
+}
+
/* Table stats. */
/* OpenFlow 1.0 and 1.1 don't distinguish between a field that cannot be
features->nonmiss.instructions, OFP12_VERSION);
out->config = ofputil_encode_table_config(features->miss_config,
OFPUTIL_TABLE_EVICTION_DEFAULT,
+ OFPUTIL_TABLE_VACANCY_DEFAULT,
OFP12_VERSION);
out->max_entries = htonl(features->max_entries);
out->active_count = htonl(stats->active_count);
ofputil_group_from_string(const char *s, uint32_t *group_idp)
{
if (!strcasecmp(s, "any")) {
- *group_idp = OFPG11_ANY;
+ *group_idp = OFPG_ANY;
} else if (!strcasecmp(s, "all")) {
- *group_idp = OFPG11_ALL;
+ *group_idp = OFPG_ALL;
} else if (!str_to_uint(s, 10, group_idp)) {
VLOG_WARN("%s is not a valid group ID. (Valid group IDs are "
"32-bit nonnegative integers or the keywords ANY or "
/* Appends to 's' a string representation of the OpenFlow group ID 'group_id'.
* Most groups' string representation is just the number, but for special
- * groups, e.g. OFPG11_ALL, it is the name, e.g. "ALL". */
+ * groups, e.g. OFPG_ALL, it is the name, e.g. "ALL". */
void
ofputil_format_group(uint32_t group_id, struct ds *s)
{
/* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string
* representation of OpenFlow group ID 'group_id'. Most group are represented
- * as just their number, but special groups, e.g. OFPG11_ALL, are represented
+ * as just their number, but special groups, e.g. OFPG_ALL, are represented
* by name, e.g. "ALL". */
void
ofputil_group_to_string(uint32_t group_id,
char namebuf[MAX_GROUP_NAME_LEN + 1], size_t bufsize)
{
switch (group_id) {
- case OFPG11_ALL:
+ case OFPG_ALL:
ovs_strlcpy(namebuf, "ALL", bufsize);
break;
- case OFPG11_ANY:
+ case OFPG_ANY:
ovs_strlcpy(namebuf, "ANY", bufsize);
break;
wc.masks.nw_ttl = 0;
}
if (!(may_match & MAY_ARP_SHA)) {
- memset(wc.masks.arp_sha, 0, ETH_ADDR_LEN);
+ WC_UNMASK_FIELD(&wc, arp_sha);
}
if (!(may_match & MAY_ARP_THA)) {
- memset(wc.masks.arp_tha, 0, ETH_ADDR_LEN);
+ WC_UNMASK_FIELD(&wc, arp_tha);
}
if (!(may_match & MAY_IPV6)) {
wc.masks.ipv6_src = wc.masks.ipv6_dst = in6addr_any;
gds->type, reply, version);
}
ogds = ofpbuf_at_assert(reply, start_ogds, sizeof *ogds);
- ogds->length = htons(reply->size - start_ogds);
ogds->type = gds->type;
ogds->group_id = htonl(gds->group_id);
ogds->bucket_list_len = htons(reply->size - start_buckets);
ofputil_put_group_prop_ntr_selection_method(version, &gds->props,
reply);
}
+ ogds->length = htons(reply->size - start_ogds);
ofpmp_postappend(replies, start_ogds);
}
switch (experimenter) {
case NTR_VENDOR_ID:
+ case NTR_COMPAT_VENDOR_ID:
error = parse_group_prop_ntr(payload, exp_type, group_type,
group_cmd, gp);
break;
* claim that the group mod command is OFPGC15_ADD to
* satisfy the check in parse_group_prop_ntr_selection_method() */
return parse_ofp15_group_properties(msg, gd->type, OFPGC15_ADD, &gd->props,
- msg->size);
+ length - sizeof *ogds - bucket_list_len);
}
/* Converts a group description reply in 'msg' into an abstract
case OFPGT11_FF:
break;
default:
- OVS_NOT_REACHED();
+ return OFPERR_OFPGMFC_BAD_TYPE;
}
switch (gm->command) {
}
break;
default:
- OVS_NOT_REACHED();
+ return OFPERR_OFPGMFC_BAD_COMMAND;
}
LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_DESC_REPLY:
case OFPTYPE_ROLE_STATUS:
+ case OFPTYPE_REQUESTFORWARD:
case OFPTYPE_NXT_GENEVE_TABLE_REQUEST:
case OFPTYPE_NXT_GENEVE_TABLE_REPLY:
break;
map->option_type = nx_map->option_type;
map->option_len = nx_map->option_len;
- if (map->option_len == 0 || map->option_len % 4 ||
- map->option_len > GENEVE_MAX_OPT_SIZE) {
+ if (map->option_len % 4 || map->option_len > GENEVE_MAX_OPT_SIZE) {
VLOG_WARN_RL(&bad_ofmsg_rl,
"geneve table option length (%u) is not a valid option size",
map->option_len);