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;
} else if (match->wc.masks.vlan_tci & htons(VLAN_CFI)
&& !(match->flow.vlan_tci & htons(VLAN_CFI))) {
ofmatch->dl_vlan = htons(OFP10_VLAN_NONE);
- ofpfw |= OFPFW10_DL_VLAN_PCP;
} else {
if (!(match->wc.masks.vlan_tci & htons(VLAN_VID_MASK))) {
ofpfw |= OFPFW10_DL_VLAN;
/* 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;
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);
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
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;
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;
switch (gm->type) {
case OFPGT11_INDIRECT:
if (!list_is_singleton(&gm->buckets)) {
- return OFPERR_OFPGMFC_OUT_OF_BUCKETS;
+ return OFPERR_OFPGMFC_INVALID_GROUP;
}
break;
case OFPGT11_ALL:
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);