From: Ben Pfaff Date: Wed, 20 Jan 2016 17:05:15 +0000 (-0800) Subject: ofp-prop: Add generic functions for working with 16- and 32-bit properties. X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=b611d3acad951f4309ee7ac9ac802741102db6f0 ofp-prop: Add generic functions for working with 16- and 32-bit properties. These will see increasing use in upcoming commits. Signed-off-by: Ben Pfaff Acked-by: Jarno Rajahalme --- diff --git a/include/openflow/openflow-1.4.h b/include/openflow/openflow-1.4.h index daf6cf42e..b65eeb81c 100644 --- a/include/openflow/openflow-1.4.h +++ b/include/openflow/openflow-1.4.h @@ -94,15 +94,6 @@ enum ofp14_port_mod_prop_type { OFPPMPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ }; -/* Ethernet port mod property. */ -struct ofp14_port_mod_prop_ethernet { - ovs_be16 type; /* OFPPMPT14_ETHERNET. */ - ovs_be16 length; /* Length in bytes of this property. */ - ovs_be32 advertise; /* Bitmap of OFPPF_*. Zero all bits to prevent - any action taking place. */ -}; -OFP_ASSERT(sizeof(struct ofp14_port_mod_prop_ethernet) == 8); - struct ofp14_port_mod { ovs_be32 port_no; uint8_t pad[4]; @@ -137,13 +128,6 @@ enum ofp14_table_reason { OFPTR_N_REASONS /* Denotes number of reasons. */ }; -struct ofp14_table_mod_prop_eviction { - ovs_be16 type; /* OFPTMPT14_EVICTION. */ - ovs_be16 length; /* Length in bytes of this property. */ - ovs_be32 flags; /* Bitmap of OFPTMPEF14_* flags */ -}; -OFP_ASSERT(sizeof(struct ofp14_table_mod_prop_eviction) == 8); - struct ofp14_table_mod_prop_vacancy { ovs_be16 type; /* OFPTMPT14_VACANCY. */ ovs_be16 length; /* Length in bytes of this property. */ @@ -273,17 +257,6 @@ enum ofp14_async_config_prop_type { OFPTFPT_EXPERIMENTER_MASTER = 0xFFFF, /* Experimenter for master. */ }; -/* Various reason based properties */ -struct ofp14_async_config_prop_reasons { - /* 'type' is one of OFPACPT_PACKET_IN_*, OFPACPT_PORT_STATUS_*, - * OFPACPT_FLOW_REMOVED_*, OFPACPT_ROLE_STATUS_*, - * OFPACPT_TABLE_STATUS_*, OFPACPT_REQUESTFORWARD_*. */ - ovs_be16 type; - ovs_be16 length; /* Length in bytes of this property. */ - ovs_be32 mask; /* Bitmasks of reason values. */ -}; -OFP_ASSERT(sizeof(struct ofp14_async_config_prop_reasons) == 8); - /* Experimenter async config property */ struct ofp14_async_config_prop_experimenter { ovs_be16 type; /* One of OFPTFPT_EXPERIMENTER_SLAVE, diff --git a/include/openflow/openflow-1.5.h b/include/openflow/openflow-1.5.h index b3deb2d27..0c478d1f0 100644 --- a/include/openflow/openflow-1.5.h +++ b/include/openflow/openflow-1.5.h @@ -69,24 +69,6 @@ enum ofp15_group_bucket_prop_type { OFPGBPT15_EXPERIMENTER = 0xFFFF, /* Experimenter defined. */ }; -/* Group bucket weight property, for select groups only. */ -struct ofp15_group_bucket_prop_weight { - ovs_be16 type; /* OFPGBPT15_WEIGHT. */ - ovs_be16 length; /* 8. */ - ovs_be16 weight; /* Relative weight of bucket. */ - uint8_t pad[2]; /* Pad to 64 bits. */ -}; -OFP_ASSERT(sizeof(struct ofp15_group_bucket_prop_weight) == 8); - -/* Group bucket watch port or watch group property, for fast failover groups - * only. */ -struct ofp15_group_bucket_prop_watch { - ovs_be16 type; /* OFPGBPT15_WATCH_PORT or OFPGBPT15_WATCH_GROUP. */ - ovs_be16 length; /* 8. */ - ovs_be32 watch; /* The port or the group. */ -}; -OFP_ASSERT(sizeof(struct ofp15_group_bucket_prop_watch) == 8); - /* Bucket for use in groups. */ struct ofp15_bucket { ovs_be16 len; /* Length the bucket in bytes, including diff --git a/lib/ofp-prop.c b/lib/ofp-prop.c index 408e810cc..41b620350 100644 --- a/lib/ofp-prop.c +++ b/lib/ofp-prop.c @@ -24,6 +24,21 @@ #include "openvswitch/vlog.h" #include "util.h" +struct ofp_prop_be16 { + ovs_be16 type; + ovs_be16 len; + ovs_be16 value; + uint8_t pad[2]; +}; +BUILD_ASSERT_DECL(sizeof(struct ofp_prop_be16) == 8); + +struct ofp_prop_be32 { + ovs_be16 type; + ovs_be16 len; + ovs_be32 value; +}; +BUILD_ASSERT_DECL(sizeof(struct ofp_prop_be32) == 8); + static uint32_t ofpprop_type_to_exp_id(uint64_t type) { @@ -113,6 +128,68 @@ ofpprop_pull(struct ofpbuf *msg, struct ofpbuf *property, uint64_t *typep) return ofpprop_pull__(msg, property, 8, 0xffff, typep); } +/* Attempts to parse 'property' as a property containing a 16-bit value. If + * successful, stores the value into '*value' and returns 0; otherwise returns + * an OpenFlow error. */ +enum ofperr +ofpprop_parse_be16(const struct ofpbuf *property, ovs_be16 *value) +{ + /* OpenFlow uses 8-byte properties for 16-bit values, which doesn't really + * make sense. Be forgiving by allowing any size payload as long as it's + * at least big enough. */ + ovs_be16 *p = property->msg; + if (ofpbuf_msgsize(property) < sizeof *p) { + return OFPERR_OFPBPC_BAD_LEN; + } + *value = *p; + return 0; +} + +/* Attempts to parse 'property' as a property containing a 32-bit value. If + * successful, stores the value into '*value' and returns 0; otherwise returns + * an OpenFlow error. */ +enum ofperr +ofpprop_parse_be32(const struct ofpbuf *property, ovs_be32 *value) +{ + ovs_be32 *p = property->msg; + if (ofpbuf_msgsize(property) != sizeof *p) { + return OFPERR_OFPBPC_BAD_LEN; + } + *value = *p; + return 0; +} + +/* Attempts to parse 'property' as a property containing a 16-bit value. If + * successful, stores the value into '*value' and returns 0; otherwise returns + * an OpenFlow error. */ +enum ofperr +ofpprop_parse_u16(const struct ofpbuf *property, uint16_t *value) +{ + /* OpenFlow uses 8-byte properties for 16-bit values, which doesn't really + * make sense. Be forgiving by allowing any size payload as long as it's + * at least big enough. */ + ovs_be16 *p = property->msg; + if (ofpbuf_msgsize(property) < sizeof *p) { + return OFPERR_OFPBPC_BAD_LEN; + } + *value = ntohs(*p); + return 0; +} + +/* Attempts to parse 'property' as a property containing a 32-bit value. If + * successful, stores the value into '*value' and returns 0; otherwise returns + * an OpenFlow error. */ +enum ofperr +ofpprop_parse_u32(const struct ofpbuf *property, uint32_t *value) +{ + ovs_be32 *p = property->msg; + if (ofpbuf_msgsize(property) != sizeof *p) { + return OFPERR_OFPBPC_BAD_LEN; + } + *value = ntohl(*p); + return 0; +} + /* Adds a property with the given 'type' and 'len'-byte contents 'value' to * 'msg', padding the property out to a multiple of 8 bytes. */ void @@ -123,6 +200,45 @@ ofpprop_put(struct ofpbuf *msg, uint64_t type, const void *value, size_t len) ofpprop_end(msg, start_ofs); } +/* Adds a property with the given 'type' and 16-bit 'value' to 'msg'. */ +void +ofpprop_put_be16(struct ofpbuf *msg, uint64_t type, ovs_be16 value) +{ + if (!ofpprop_is_experimenter(type)) { + /* The OpenFlow specs consistently (at least they're consistent!) give + * properties with a 16-bit integer value a length of 8, not 6, so add + * two bytes of padding. */ + ovs_be16 padded_value[2] = { value, 0 }; + ofpprop_put(msg, type, padded_value, sizeof padded_value); + } else { + /* There's no precedent but let's assume that this is generally done + * sanely. */ + ofpprop_put(msg, type, &value, sizeof value); + } +} + +/* Adds a property with the given 'type' and 32-bit 'value' to 'msg'. */ +void +ofpprop_put_be32(struct ofpbuf *msg, uint64_t type, ovs_be32 value) +{ + ofpprop_put(msg, type, &value, sizeof value); +} + +/* Adds a property with the given 'type' and 16-bit 'value' to 'msg'. */ +void +ofpprop_put_u16(struct ofpbuf *msg, uint64_t type, uint16_t value) +{ + ofpprop_put_be16(msg, type, htons(value)); +} + +/* Adds a property with the given 'type' and 32-bit 'value' to 'msg'. */ +void +ofpprop_put_u32(struct ofpbuf *msg, uint64_t type, uint32_t value) +{ + ofpprop_put_be32(msg, type, htonl(value)); +} + +/* Adds a property header to 'msg' for each 1-bit in 'bitmap'. */ /* Appends a property to 'msg' whose type is 'type' and whose contents is a * series of property headers, one for each 1-bit in 'bitmap'. */ void diff --git a/lib/ofp-prop.h b/lib/ofp-prop.h index e32bd68a2..4a9f84429 100644 --- a/lib/ofp-prop.h +++ b/lib/ofp-prop.h @@ -76,9 +76,18 @@ enum ofperr ofpprop_pull__(struct ofpbuf *msg, struct ofpbuf *property, enum ofperr ofpprop_pull(struct ofpbuf *msg, struct ofpbuf *property, uint64_t *typep); +enum ofperr ofpprop_parse_be16(const struct ofpbuf *, ovs_be16 *value); +enum ofperr ofpprop_parse_be32(const struct ofpbuf *, ovs_be32 *value); +enum ofperr ofpprop_parse_u16(const struct ofpbuf *, uint16_t *value); +enum ofperr ofpprop_parse_u32(const struct ofpbuf *, uint32_t *value); + /* Serializing properties. */ void ofpprop_put(struct ofpbuf *, uint64_t type, const void *value, size_t len); +void ofpprop_put_be16(struct ofpbuf *, uint64_t type, ovs_be16 value); +void ofpprop_put_be32(struct ofpbuf *, uint64_t type, ovs_be32 value); +void ofpprop_put_u16(struct ofpbuf *, uint64_t type, uint16_t value); +void ofpprop_put_u32(struct ofpbuf *, uint64_t type, uint32_t value); void ofpprop_put_bitmap(struct ofpbuf *, uint64_t type, uint64_t bitmap); size_t ofpprop_start(struct ofpbuf *, uint64_t type); diff --git a/lib/ofp-util.c b/lib/ofp-util.c index c6e890233..c1709bd6f 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -4327,14 +4327,14 @@ static enum ofperr parse_port_mod_ethernet_property(struct ofpbuf *property, struct ofputil_port_mod *pm) { - struct ofp14_port_mod_prop_ethernet *eth = property->data; + ovs_be32 advertise; + enum ofperr error; - if (property->size != sizeof *eth) { - return OFPERR_OFPBRC_BAD_LEN; + error = ofpprop_parse_be32(property, &advertise); + if (!error) { + pm->advertise = netdev_port_features_from_ofp11(advertise); } - - pm->advertise = netdev_port_features_from_ofp11(eth->advertise); - return 0; + return error; } /* Decodes the OpenFlow "port mod" message in '*oh' into an abstract form in @@ -4457,10 +4457,9 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, } case OFP14_VERSION: case OFP15_VERSION: { - struct ofp14_port_mod_prop_ethernet *eth; struct ofp14_port_mod *opm; - b = ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD, ofp_version, sizeof *eth); + b = ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD, ofp_version, 0); opm = ofpbuf_put_zeros(b, sizeof *opm); opm->port_no = ofputil_port_to_ofp11(pm->port_no); opm->hw_addr = pm->hw_addr; @@ -4468,10 +4467,8 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, opm->mask = htonl(pm->mask & OFPPC11_ALL); if (pm->advertise) { - eth = ofpbuf_put_zeros(b, sizeof *eth); - eth->type = htons(OFPPMPT14_ETHERNET); - eth->length = htons(sizeof *eth); - eth->advertise = netdev_port_features_to_ofp11(pm->advertise); + ofpprop_put_be32(b, OFPPMPT14_ETHERNET, + netdev_port_features_to_ofp11(pm->advertise)); } break; } @@ -4492,7 +4489,7 @@ pull_table_feature_property(struct ofpbuf *msg, struct ofpbuf *payload, error = ofpprop_pull(msg, payload, typep); if (payload && !error) { - ofpbuf_pull(payload, (uint8_t *)msg->msg - (uint8_t *)msg->header); + ofpbuf_pull(payload, (char *)payload->msg - (char *)payload->header); } return error; } @@ -4888,20 +4885,6 @@ ofputil_append_table_features_reply(const struct ofputil_table_features *tf, ofpmp_postappend(replies, start_ofs); } -static enum ofperr -parse_table_desc_eviction_property(struct ofpbuf *property, - struct ofputil_table_desc *td) -{ - struct ofp14_table_mod_prop_eviction *ote = property->data; - - if (property->size != sizeof *ote) { - return OFPERR_OFPBPC_BAD_LEN; - } - - td->eviction_flags = ntohl(ote->flags); - return 0; -} - static enum ofperr parse_table_desc_vacancy_property(struct ofpbuf *property, struct ofputil_table_desc *td) @@ -4974,7 +4957,7 @@ ofputil_decode_table_desc(struct ofpbuf *msg, switch (type) { case OFPTMPT14_EVICTION: - error = parse_table_desc_eviction_property(&payload, td); + error = ofpprop_parse_u32(&payload, &td->eviction_flags); break; case OFPTMPT14_VACANCY: @@ -5025,12 +5008,7 @@ ofputil_append_table_desc_reply(const struct ofputil_table_desc *td, start_otd = reply->size; ofpbuf_put_zeros(reply, sizeof *otd); if (td->eviction_flags != UINT32_MAX) { - struct ofp14_table_mod_prop_eviction *ote; - - ote = ofpbuf_put_zeros(reply, sizeof *ote); - ote->type = htons(OFPTMPT14_EVICTION); - ote->length = htons(sizeof *ote); - ote->flags = htonl(td->eviction_flags); + ofpprop_put_u32(reply, OFPTMPT14_EVICTION, td->eviction_flags); } if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) { struct ofp14_table_mod_prop_vacancy *otv; @@ -5103,20 +5081,6 @@ ofputil_decode_table_vacancy(ovs_be32 config, enum ofp_version version) : OFPUTIL_TABLE_VACANCY_OFF); } -static enum ofperr -parse_table_mod_eviction_property(struct ofpbuf *property, - struct ofputil_table_mod *tm) -{ - struct ofp14_table_mod_prop_eviction *ote = property->data; - - if (property->size != sizeof *ote) { - return OFPERR_OFPBPC_BAD_LEN; - } - - tm->eviction_flags = ntohl(ote->flags); - 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 eviction configuration that it specifies. @@ -5261,7 +5225,7 @@ ofputil_decode_table_mod(const struct ofp_header *oh, switch (type) { case OFPTMPT14_EVICTION: - error = parse_table_mod_eviction_property(&property, pm); + error = ofpprop_parse_u32(&property, &pm->eviction); break; case OFPTMPT14_VACANCY: @@ -5315,7 +5279,6 @@ ofputil_encode_table_mod(const struct ofputil_table_mod *tm, 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); @@ -5325,10 +5288,7 @@ ofputil_encode_table_mod(const struct ofputil_table_mod *tm, tm->vacancy, ofp_version); if (tm->eviction_flags != UINT32_MAX) { - ote = ofpbuf_put_zeros(b, sizeof *ote); - ote->type = htons(OFPTMPT14_EVICTION); - ote->length = htons(sizeof *ote); - ote->flags = htonl(tm->eviction_flags); + ofpprop_put_u32(b, OFPTMPT14_EVICTION, tm->eviction_flags); } if (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON) { otv = ofpbuf_put_zeros(b, sizeof *otv); @@ -7781,34 +7741,6 @@ ofputil_put_ofp11_bucket(const struct ofputil_bucket *bucket, ob->watch_group = htonl(bucket->watch_group); } -static void -ofputil_put_ofp15_group_bucket_prop_weight(ovs_be16 weight, - struct ofpbuf *openflow) -{ - size_t start_ofs; - struct ofp15_group_bucket_prop_weight *prop; - - start_ofs = ofpprop_start(openflow, OFPGBPT15_WEIGHT); - ofpbuf_put_zeros(openflow, sizeof *prop - sizeof(struct ofp_prop_header)); - prop = ofpbuf_at_assert(openflow, start_ofs, sizeof *prop); - prop->weight = weight; - ofpprop_end(openflow, start_ofs); -} - -static void -ofputil_put_ofp15_group_bucket_prop_watch(ovs_be32 watch, uint16_t type, - struct ofpbuf *openflow) -{ - size_t start_ofs; - struct ofp15_group_bucket_prop_watch *prop; - - start_ofs = ofpprop_start(openflow, type); - ofpbuf_put_zeros(openflow, sizeof *prop - sizeof(struct ofp_prop_header)); - prop = ofpbuf_at_assert(openflow, start_ofs, sizeof *prop); - prop->watch = watch; - ofpprop_end(openflow, start_ofs); -} - static void ofputil_put_ofp15_bucket(const struct ofputil_bucket *bucket, uint32_t bucket_id, enum ofp11_group_type group_type, @@ -7826,20 +7758,14 @@ ofputil_put_ofp15_bucket(const struct ofputil_bucket *bucket, actions_len = openflow->size - actions_start; if (group_type == OFPGT11_SELECT) { - ofputil_put_ofp15_group_bucket_prop_weight(htons(bucket->weight), - openflow); + ofpprop_put_u16(openflow, OFPGBPT15_WEIGHT, bucket->weight); } if (bucket->watch_port != OFPP_ANY) { - ovs_be32 port = ofputil_port_to_ofp11(bucket->watch_port); - ofputil_put_ofp15_group_bucket_prop_watch(port, - OFPGBPT15_WATCH_PORT, - openflow); + ofpprop_put_be32(openflow, OFPGBPT15_WATCH_PORT, + ofputil_port_to_ofp11(bucket->watch_port)); } if (bucket->watch_group != OFPG_ANY) { - ovs_be32 group = htonl(bucket->watch_group); - ofputil_put_ofp15_group_bucket_prop_watch(group, - OFPGBPT15_WATCH_GROUP, - openflow); + ofpprop_put_u32(openflow, OFPGBPT15_WATCH_GROUP, bucket->watch_group); } ob = ofpbuf_at_assert(openflow, start, sizeof *ob); @@ -8018,40 +7944,6 @@ ofputil_pull_ofp11_buckets(struct ofpbuf *msg, size_t buckets_length, return 0; } -static enum ofperr -parse_ofp15_group_bucket_prop_weight(const struct ofpbuf *payload, - ovs_be16 *weight) -{ - struct ofp15_group_bucket_prop_weight *prop = payload->data; - - if (payload->size != sizeof *prop) { - OFPPROP_LOG(&bad_ofmsg_rl, false, "OpenFlow bucket weight property " - "length %u is not valid", payload->size); - return OFPERR_OFPBPC_BAD_LEN; - } - - *weight = prop->weight; - - return 0; -} - -static enum ofperr -parse_ofp15_group_bucket_prop_watch(const struct ofpbuf *payload, - ovs_be32 *watch) -{ - struct ofp15_group_bucket_prop_watch *prop = payload->data; - - if (payload->size != sizeof *prop) { - OFPPROP_LOG(&bad_ofmsg_rl, false, "OpenFlow bucket watch port or " - "group property length %u is not valid", payload->size); - return OFPERR_OFPBPC_BAD_LEN; - } - - *watch = prop->watch; - - return 0; -} - static enum ofperr ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length, enum ofp_version version, uint8_t group_type, @@ -8121,17 +8013,15 @@ ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length, switch (type) { case OFPGBPT15_WEIGHT: - err = parse_ofp15_group_bucket_prop_weight(&payload, &weight); + err = ofpprop_parse_be16(&payload, &weight); break; case OFPGBPT15_WATCH_PORT: - err = parse_ofp15_group_bucket_prop_watch(&payload, - &watch_port); + err = ofpprop_parse_be32(&payload, &watch_port); break; case OFPGBPT15_WATCH_GROUP: - err = parse_ofp15_group_bucket_prop_watch(&payload, - &watch_group); + err = ofpprop_parse_be32(&payload, &watch_group); break; default: @@ -9517,24 +9407,23 @@ ofputil_decode_set_async_config(const struct ofp_header *oh, raw == OFPRAW_OFPT14_GET_ASYNC_REPLY) { while (b.size > 0) { - struct ofp14_async_config_prop_reasons *msg; struct ofpbuf property; enum ofperr error; uint64_t type; + uint32_t mask; error = ofpprop_pull__(&b, &property, 8, 0xfffe, &type); if (error) { return error; } - msg = property.data; - - if (property.size != sizeof *msg) { - return OFPERR_OFPBRC_BAD_LEN; + error = ofpprop_parse_u32(&property, &mask); + if (error) { + return error; } if (!loose) { - error = ofputil_check_mask(type, ntohl(msg->mask)); + error = ofputil_check_mask(type, mask); if (error) { return error; } @@ -9542,51 +9431,51 @@ ofputil_decode_set_async_config(const struct ofp_header *oh, switch (type) { case OFPACPT_PACKET_IN_SLAVE: - slave[OAM_PACKET_IN] = ntohl(msg->mask); + slave[OAM_PACKET_IN] = mask; break; case OFPACPT_PACKET_IN_MASTER: - master[OAM_PACKET_IN] = ntohl(msg->mask); + master[OAM_PACKET_IN] = mask; break; case OFPACPT_PORT_STATUS_SLAVE: - slave[OAM_PORT_STATUS] = ntohl(msg->mask); + slave[OAM_PORT_STATUS] = mask; break; case OFPACPT_PORT_STATUS_MASTER: - master[OAM_PORT_STATUS] = ntohl(msg->mask); + master[OAM_PORT_STATUS] = mask; break; case OFPACPT_FLOW_REMOVED_SLAVE: - slave[OAM_FLOW_REMOVED] = ntohl(msg->mask); + slave[OAM_FLOW_REMOVED] = mask; break; case OFPACPT_FLOW_REMOVED_MASTER: - master[OAM_FLOW_REMOVED] = ntohl(msg->mask); + master[OAM_FLOW_REMOVED] = mask; break; case OFPACPT_ROLE_STATUS_SLAVE: - slave[OAM_ROLE_STATUS] = ntohl(msg->mask); + slave[OAM_ROLE_STATUS] = mask; break; case OFPACPT_ROLE_STATUS_MASTER: - master[OAM_ROLE_STATUS] = ntohl(msg->mask); + master[OAM_ROLE_STATUS] = mask; break; case OFPACPT_TABLE_STATUS_SLAVE: - slave[OAM_TABLE_STATUS] = ntohl(msg->mask); + slave[OAM_TABLE_STATUS] = mask; break; case OFPACPT_TABLE_STATUS_MASTER: - master[OAM_TABLE_STATUS] = ntohl(msg->mask); + master[OAM_TABLE_STATUS] = mask; break; case OFPACPT_REQUESTFORWARD_SLAVE: - slave[OAM_REQUESTFORWARD] = ntohl(msg->mask); + slave[OAM_REQUESTFORWARD] = mask; break; case OFPACPT_REQUESTFORWARD_MASTER: - master[OAM_REQUESTFORWARD] = ntohl(msg->mask); + master[OAM_REQUESTFORWARD] = mask; break; default: @@ -9610,46 +9499,43 @@ ofputil_get_async_reply(struct ofpbuf *buf, const uint32_t master_mask, int role; for (role = 0; role < 2; role++) { - struct ofp14_async_config_prop_reasons *msg; - - msg = ofpbuf_put_zeros(buf, sizeof *msg); + enum ofp14_async_config_prop_type prop_type; switch (type) { case OAM_PACKET_IN: - msg->type = (role ? htons(OFPACPT_PACKET_IN_SLAVE) - : htons(OFPACPT_PACKET_IN_MASTER)); + prop_type = (role ? OFPACPT_PACKET_IN_SLAVE + : OFPACPT_PACKET_IN_MASTER); break; case OAM_PORT_STATUS: - msg->type = (role ? htons(OFPACPT_PORT_STATUS_SLAVE) - : htons(OFPACPT_PORT_STATUS_MASTER)); + prop_type = (role ? OFPACPT_PORT_STATUS_SLAVE + : OFPACPT_PORT_STATUS_MASTER); break; case OAM_FLOW_REMOVED: - msg->type = (role ? htons(OFPACPT_FLOW_REMOVED_SLAVE) - : htons(OFPACPT_FLOW_REMOVED_MASTER)); + prop_type = (role ? OFPACPT_FLOW_REMOVED_SLAVE + : OFPACPT_FLOW_REMOVED_MASTER); break; case OAM_ROLE_STATUS: - msg->type = (role ? htons(OFPACPT_ROLE_STATUS_SLAVE) - : htons(OFPACPT_ROLE_STATUS_MASTER)); + prop_type = (role ? OFPACPT_ROLE_STATUS_SLAVE + : OFPACPT_ROLE_STATUS_MASTER); break; case OAM_TABLE_STATUS: - msg->type = (role ? htons(OFPACPT_TABLE_STATUS_SLAVE) - : htons(OFPACPT_TABLE_STATUS_MASTER)); + prop_type = (role ? OFPACPT_TABLE_STATUS_SLAVE + : OFPACPT_TABLE_STATUS_MASTER); break; case OAM_REQUESTFORWARD: - msg->type = (role ? htons(OFPACPT_REQUESTFORWARD_SLAVE) - : htons(OFPACPT_REQUESTFORWARD_MASTER)); + prop_type = (role ? OFPACPT_REQUESTFORWARD_SLAVE + : OFPACPT_REQUESTFORWARD_MASTER); break; default: return OFPERR_OFPBRC_BAD_TYPE; } - msg->length = htons(sizeof *msg); - msg->mask = (role ? htonl(slave_mask) : htonl(master_mask)); + ofpprop_put_u32(buf, prop_type, role ? slave_mask : master_mask); } return 0; diff --git a/lib/ofpbuf.h b/lib/ofpbuf.h index 873065e66..678b1f16d 100644 --- a/lib/ofpbuf.h +++ b/lib/ofpbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 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. @@ -120,6 +120,7 @@ void *ofpbuf_push(struct ofpbuf *b, const void *, size_t); static inline size_t ofpbuf_headroom(const struct ofpbuf *); static inline size_t ofpbuf_tailroom(const struct ofpbuf *); +static inline size_t ofpbuf_msgsize(const struct ofpbuf *); void ofpbuf_prealloc_headroom(struct ofpbuf *, size_t); void ofpbuf_prealloc_tailroom(struct ofpbuf *, size_t); void ofpbuf_trim(struct ofpbuf *); @@ -193,6 +194,14 @@ static inline size_t ofpbuf_tailroom(const struct ofpbuf *b) return (char*)ofpbuf_end(b) - (char*)ofpbuf_tail(b); } +/* Returns the number of bytes from 'b->msg' to 'b->data + b->size', that is, + * the length of the used space in 'b' starting from 'msg'. */ +static inline size_t +ofpbuf_msgsize(const struct ofpbuf *b) +{ + return (char *)ofpbuf_tail(b) - (char *)b->msg; +} + /* Clears any data from 'b'. */ static inline void ofpbuf_clear(struct ofpbuf *b) {