X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=a943b4ecaafca3ed903602c56df3b299575a92b5;hb=2e3fa633aad59f9687e2b6e3aad3b0a308aa89fc;hp=7875cbf86a41167ffd8f0aa057c2f5b60f7ced0c;hpb=982697a4d24caa0a3bdaf85db67619338b382e50;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 7875cbf8..a943b4ec 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -265,6 +265,31 @@ ofputil_cls_rule_to_ofp10_match(const struct cls_rule *rule, memset(match->pad2, '\0', sizeof match->pad2); } +enum ofperr +ofputil_pull_ofp11_match(struct ofpbuf *buf, unsigned int priority, + struct cls_rule *rule) +{ + struct ofp11_match_header *omh; + struct ofp11_match *om; + + if (buf->size < sizeof(struct ofp11_match_header)) { + return OFPERR_OFPBMC_BAD_LEN; + } + + omh = buf->data; + switch (ntohs(omh->type)) { + case OFPMT_STANDARD: + if (omh->length != htons(sizeof *om) || buf->size < sizeof *om) { + return OFPERR_OFPBMC_BAD_LEN; + } + om = ofpbuf_pull(buf, sizeof *om); + return ofputil_cls_rule_from_ofp11_match(om, priority, rule); + + default: + return OFPERR_OFPBMC_BAD_TYPE; + } +} + /* Converts the ofp11_match in 'match' into a cls_rule in 'rule', with the * given 'priority'. Returns 0 if successful, otherwise an OFPERR_* value. */ enum ofperr @@ -570,18 +595,22 @@ size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols); * 1.0, 0x02 for OpenFlow 1.1). Returns 0 if 'version' is not supported or * outside the valid range. */ enum ofputil_protocol -ofputil_protocol_from_ofp_version(int version) +ofputil_protocol_from_ofp_version(enum ofp_version version) { switch (version) { - case OFP10_VERSION: return OFPUTIL_P_OF10; - case OFP12_VERSION: return OFPUTIL_P_OF12; - default: return 0; + case OFP10_VERSION: + return OFPUTIL_P_OF10; + case OFP12_VERSION: + return OFPUTIL_P_OF12; + case OFP11_VERSION: + default: + return 0; } } /* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION, * OFP11_VERSION or OFP12_VERSION) that corresponds to 'protocol'. */ -uint8_t +enum ofp_version ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol) { switch (protocol) { @@ -1102,87 +1131,131 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, ofpbuf_use_const(&b, oh, ntohs(oh->length)); raw = ofpraw_pull_assert(&b); - if (raw == OFPRAW_OFPT10_FLOW_MOD) { + if (raw == OFPRAW_OFPT11_FLOW_MOD) { /* Standard OpenFlow 1.1 flow_mod. */ - const struct ofp_flow_mod *ofm; - uint16_t priority; + const struct ofp11_flow_mod *ofm; enum ofperr error; - /* Get the ofp_flow_mod. */ ofm = ofpbuf_pull(&b, sizeof *ofm); - /* Set priority based on original wildcards. Normally we'd allow - * ofputil_cls_rule_from_match() to do this for us, but - * ofputil_normalize_rule() can put wildcards where the original flow - * didn't have them. */ - priority = ntohs(ofm->priority); - if (!(ofm->match.wildcards & htonl(OFPFW10_ALL))) { - priority = UINT16_MAX; + error = ofputil_pull_ofp11_match(&b, ntohs(ofm->priority), &fm->cr); + if (error) { + return error; } - /* Translate the rule. */ - ofputil_cls_rule_from_ofp10_match(&ofm->match, priority, &fm->cr); - ofputil_normalize_rule(&fm->cr); - - /* Now get the actions. */ - error = ofpacts_pull_openflow10(&b, b.size, ofpacts); + error = ofpacts_pull_openflow11_instructions(&b, b.size, ofpacts); if (error) { return error; } /* Translate the message. */ - command = ntohs(ofm->command); - fm->cookie = htonll(0); - fm->cookie_mask = htonll(0); - fm->new_cookie = ofm->cookie; + if (ofm->command == OFPFC_ADD) { + fm->cookie = htonll(0); + fm->cookie_mask = htonll(0); + fm->new_cookie = ofm->cookie; + } else { + /* XXX */ + fm->cookie = ofm->cookie; + fm->cookie_mask = ofm->cookie_mask; + fm->new_cookie = htonll(UINT64_MAX); + } + fm->command = ofm->command; + fm->table_id = ofm->table_id; fm->idle_timeout = ntohs(ofm->idle_timeout); fm->hard_timeout = ntohs(ofm->hard_timeout); fm->buffer_id = ntohl(ofm->buffer_id); - fm->out_port = ntohs(ofm->out_port); - fm->flags = ntohs(ofm->flags); - } else if (raw == OFPRAW_NXT_FLOW_MOD) { - /* Nicira extended flow_mod. */ - const struct nx_flow_mod *nfm; - enum ofperr error; - - /* Dissect the message. */ - nfm = ofpbuf_pull(&b, sizeof *nfm); - error = nx_pull_match(&b, ntohs(nfm->match_len), ntohs(nfm->priority), - &fm->cr, &fm->cookie, &fm->cookie_mask); + error = ofputil_port_from_ofp11(ofm->out_port, &fm->out_port); if (error) { return error; } - error = ofpacts_pull_openflow10(&b, b.size, ofpacts); - if (error) { - return error; + if (ofm->out_group != htonl(OFPG_ANY)) { + return OFPERR_NXFMFC_GROUPS_NOT_SUPPORTED; } - - /* Translate the message. */ - command = ntohs(nfm->command); - if ((command & 0xff) == OFPFC_ADD && fm->cookie_mask) { - /* Flow additions may only set a new cookie, not match an - * existing cookie. */ - return OFPERR_NXBRC_NXM_INVALID; - } - fm->new_cookie = nfm->cookie; - fm->idle_timeout = ntohs(nfm->idle_timeout); - fm->hard_timeout = ntohs(nfm->hard_timeout); - fm->buffer_id = ntohl(nfm->buffer_id); - fm->out_port = ntohs(nfm->out_port); - fm->flags = ntohs(nfm->flags); + fm->flags = ntohs(ofm->flags); } else { - NOT_REACHED(); + if (raw == OFPRAW_OFPT10_FLOW_MOD) { + /* Standard OpenFlow 1.0 flow_mod. */ + const struct ofp10_flow_mod *ofm; + uint16_t priority; + enum ofperr error; + + /* Get the ofp10_flow_mod. */ + ofm = ofpbuf_pull(&b, sizeof *ofm); + + /* Set priority based on original wildcards. Normally we'd allow + * ofputil_cls_rule_from_match() to do this for us, but + * ofputil_normalize_rule() can put wildcards where the original + * flow didn't have them. */ + priority = ntohs(ofm->priority); + if (!(ofm->match.wildcards & htonl(OFPFW10_ALL))) { + priority = UINT16_MAX; + } + + /* Translate the rule. */ + ofputil_cls_rule_from_ofp10_match(&ofm->match, priority, &fm->cr); + ofputil_normalize_rule(&fm->cr); + + /* Now get the actions. */ + error = ofpacts_pull_openflow10(&b, b.size, ofpacts); + if (error) { + return error; + } + + /* Translate the message. */ + command = ntohs(ofm->command); + fm->cookie = htonll(0); + fm->cookie_mask = htonll(0); + fm->new_cookie = ofm->cookie; + fm->idle_timeout = ntohs(ofm->idle_timeout); + fm->hard_timeout = ntohs(ofm->hard_timeout); + fm->buffer_id = ntohl(ofm->buffer_id); + fm->out_port = ntohs(ofm->out_port); + fm->flags = ntohs(ofm->flags); + } else if (raw == OFPRAW_NXT_FLOW_MOD) { + /* Nicira extended flow_mod. */ + const struct nx_flow_mod *nfm; + enum ofperr error; + + /* Dissect the message. */ + nfm = ofpbuf_pull(&b, sizeof *nfm); + error = nx_pull_match(&b, ntohs(nfm->match_len), ntohs(nfm->priority), + &fm->cr, &fm->cookie, &fm->cookie_mask); + if (error) { + return error; + } + error = ofpacts_pull_openflow10(&b, b.size, ofpacts); + if (error) { + return error; + } + + /* Translate the message. */ + command = ntohs(nfm->command); + if ((command & 0xff) == OFPFC_ADD && fm->cookie_mask) { + /* Flow additions may only set a new cookie, not match an + * existing cookie. */ + return OFPERR_NXBRC_NXM_INVALID; + } + fm->new_cookie = nfm->cookie; + fm->idle_timeout = ntohs(nfm->idle_timeout); + fm->hard_timeout = ntohs(nfm->hard_timeout); + fm->buffer_id = ntohl(nfm->buffer_id); + fm->out_port = ntohs(nfm->out_port); + fm->flags = ntohs(nfm->flags); + } else { + NOT_REACHED(); + } + + if (protocol & OFPUTIL_P_TID) { + fm->command = command & 0xff; + fm->table_id = command >> 8; + } else { + fm->command = command; + fm->table_id = 0xff; + } } fm->ofpacts = ofpacts->data; fm->ofpacts_len = ofpacts->size; - if (protocol & OFPUTIL_P_TID) { - fm->command = command & 0xff; - fm->table_id = command >> 8; - } else { - fm->command = command; - fm->table_id = 0xff; - } return 0; } @@ -1193,7 +1266,7 @@ struct ofpbuf * ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, enum ofputil_protocol protocol) { - struct ofp_flow_mod *ofm; + struct ofp10_flow_mod *ofm; struct nx_flow_mod *nfm; struct ofpbuf *msg; uint16_t command; @@ -1284,7 +1357,7 @@ ofputil_flow_mod_usable_protocols(const struct ofputil_flow_mod *fms, static enum ofperr ofputil_decode_ofpst_flow_request(struct ofputil_flow_stats_request *fsr, - const struct ofp_flow_stats_request *ofsr, + const struct ofp10_flow_stats_request *ofsr, bool aggregate) { fsr->aggregate = aggregate; @@ -1364,7 +1437,7 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, switch (protocol) { case OFPUTIL_P_OF10: case OFPUTIL_P_OF10_TID: { - struct ofp_flow_stats_request *ofsr; + struct ofp10_flow_stats_request *ofsr; raw = (fsr->aggregate ? OFPRAW_OFPST_AGGREGATE_REQUEST @@ -1461,7 +1534,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, if (!msg->size) { return EOF; } else if (raw == OFPRAW_OFPST_FLOW_REPLY) { - const struct ofp_flow_stats *ofs; + const struct ofp10_flow_stats *ofs; size_t length; ofs = ofpbuf_try_pull(msg, sizeof *ofs); @@ -1573,7 +1646,7 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs, ofpraw_decode_partial(&raw, reply->data, reply->size); if (raw == OFPRAW_OFPST_FLOW_REPLY) { - struct ofp_flow_stats *ofs; + struct ofp10_flow_stats *ofs; ofpbuf_put_uninit(reply, sizeof *ofs); ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply); @@ -1629,38 +1702,33 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs, } /* Converts abstract ofputil_aggregate_stats 'stats' into an OFPST_AGGREGATE or - * NXST_AGGREGATE reply according to 'protocol', and returns the message. */ + * NXST_AGGREGATE reply matching 'request', and returns the message. */ struct ofpbuf * ofputil_encode_aggregate_stats_reply( const struct ofputil_aggregate_stats *stats, const struct ofp_header *request) { + struct ofp_aggregate_stats_reply *asr; + uint64_t packet_count; + uint64_t byte_count; struct ofpbuf *msg; enum ofpraw raw; ofpraw_decode(&raw, request); if (raw == OFPRAW_OFPST_AGGREGATE_REQUEST) { - struct ofp_aggregate_stats_reply *asr; - - msg = ofpraw_alloc_reply(OFPRAW_OFPST_AGGREGATE_REPLY, request, 0); - asr = ofpbuf_put_zeros(msg, sizeof *asr); - put_32aligned_be64(&asr->packet_count, - htonll(unknown_to_zero(stats->packet_count))); - put_32aligned_be64(&asr->byte_count, - htonll(unknown_to_zero(stats->byte_count))); - asr->flow_count = htonl(stats->flow_count); - } else if (raw == OFPRAW_NXST_AGGREGATE_REQUEST) { - struct nx_aggregate_stats_reply *nasr; - - msg = ofpraw_alloc_reply(OFPRAW_NXST_AGGREGATE_REPLY, request, 0); - nasr = ofpbuf_put_zeros(msg, sizeof *nasr); - nasr->packet_count = htonll(stats->packet_count); - nasr->byte_count = htonll(stats->byte_count); - nasr->flow_count = htonl(stats->flow_count); + packet_count = unknown_to_zero(stats->packet_count); + byte_count = unknown_to_zero(stats->byte_count); } else { - NOT_REACHED(); + packet_count = stats->packet_count; + byte_count = stats->byte_count; } + msg = ofpraw_alloc_stats_reply(request, 0); + asr = ofpbuf_put_zeros(msg, sizeof *asr); + put_32aligned_be64(&asr->packet_count, htonll(packet_count)); + put_32aligned_be64(&asr->byte_count, htonll(byte_count)); + asr->flow_count = htonl(stats->flow_count); + return msg; } @@ -1668,26 +1736,16 @@ enum ofperr ofputil_decode_aggregate_stats_reply(struct ofputil_aggregate_stats *stats, const struct ofp_header *reply) { + struct ofp_aggregate_stats_reply *asr; struct ofpbuf msg; - enum ofpraw raw; ofpbuf_use_const(&msg, reply, ntohs(reply->length)); - raw = ofpraw_pull_assert(&msg); - if (raw == OFPRAW_OFPST_AGGREGATE_REPLY) { - struct ofp_aggregate_stats_reply *asr = msg.l3; - - stats->packet_count = ntohll(get_32aligned_be64(&asr->packet_count)); - stats->byte_count = ntohll(get_32aligned_be64(&asr->byte_count)); - stats->flow_count = ntohl(asr->flow_count); - } else if (raw == OFPRAW_NXST_AGGREGATE_REPLY) { - struct nx_aggregate_stats_reply *nasr = msg.l3; - - stats->packet_count = ntohll(nasr->packet_count); - stats->byte_count = ntohll(nasr->byte_count); - stats->flow_count = ntohl(nasr->flow_count); - } else { - NOT_REACHED(); - } + ofpraw_pull_assert(&msg); + + asr = msg.l3; + stats->packet_count = ntohll(get_32aligned_be64(&asr->packet_count)); + stats->byte_count = ntohll(get_32aligned_be64(&asr->byte_count)); + stats->flow_count = ntohl(asr->flow_count); return 0; } @@ -2137,10 +2195,17 @@ ofputil_decode_ofp11_port(struct ofputil_phy_port *pp, } static size_t -ofputil_get_phy_port_size(uint8_t ofp_version) -{ - return ofp_version == OFP10_VERSION ? sizeof(struct ofp10_phy_port) - : sizeof(struct ofp11_port); +ofputil_get_phy_port_size(enum ofp_version ofp_version) +{ + switch (ofp_version) { + case OFP10_VERSION: + return sizeof(struct ofp10_phy_port); + case OFP11_VERSION: + case OFP12_VERSION: + return sizeof(struct ofp11_port); + default: + NOT_REACHED(); + } } static void @@ -2185,39 +2250,59 @@ ofputil_encode_ofp11_port(const struct ofputil_phy_port *pp, } static void -ofputil_put_phy_port(uint8_t ofp_version, const struct ofputil_phy_port *pp, - struct ofpbuf *b) +ofputil_put_phy_port(enum ofp_version ofp_version, + const struct ofputil_phy_port *pp, struct ofpbuf *b) { - if (ofp_version == OFP10_VERSION) { + switch (ofp_version) { + case OFP10_VERSION: { struct ofp10_phy_port *opp; if (b->size + sizeof *opp <= UINT16_MAX) { opp = ofpbuf_put_uninit(b, sizeof *opp); ofputil_encode_ofp10_phy_port(pp, opp); } - } else { + break; + } + + case OFP11_VERSION: + case OFP12_VERSION: { struct ofp11_port *op; if (b->size + sizeof *op <= UINT16_MAX) { op = ofpbuf_put_uninit(b, sizeof *op); ofputil_encode_ofp11_port(pp, op); } + break; + } + + default: + NOT_REACHED(); } } void -ofputil_append_port_desc_stats_reply(uint8_t ofp_version, +ofputil_append_port_desc_stats_reply(enum ofp_version ofp_version, const struct ofputil_phy_port *pp, struct list *replies) { - if (ofp_version == OFP10_VERSION) { + switch (ofp_version) { + case OFP10_VERSION: { struct ofp10_phy_port *opp; opp = ofpmp_append(replies, sizeof *opp); ofputil_encode_ofp10_phy_port(pp, opp); - } else { + break; + } + + case OFP11_VERSION: + case OFP12_VERSION: { struct ofp11_port *op; op = ofpmp_append(replies, sizeof *op); ofputil_encode_ofp11_port(pp, op); + break; + } + + default: + NOT_REACHED(); } } @@ -2398,29 +2483,44 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features, { struct ofp_switch_features *osf; struct ofpbuf *b; - uint8_t version; + enum ofp_version version; + enum ofpraw raw; version = ofputil_protocol_to_ofp_version(protocol); - b = ofpraw_alloc_xid(version == OFP10_VERSION - ? OFPRAW_OFPT10_FEATURES_REPLY - : OFPRAW_OFPT11_FEATURES_REPLY, - version, xid, 0); + switch (version) { + case OFP10_VERSION: + raw = OFPRAW_OFPT10_FEATURES_REPLY; + break; + case OFP11_VERSION: + case OFP12_VERSION: + raw = OFPRAW_OFPT11_FEATURES_REPLY; + break; + default: + NOT_REACHED(); + } + b = ofpraw_alloc_xid(raw, version, xid, 0); osf = ofpbuf_put_zeros(b, sizeof *osf); osf->datapath_id = htonll(features->datapath_id); osf->n_buffers = htonl(features->n_buffers); osf->n_tables = features->n_tables; osf->capabilities = htonl(features->capabilities & OFPC_COMMON); - if (version == OFP10_VERSION) { + switch (version) { + case OFP10_VERSION: if (features->capabilities & OFPUTIL_C_STP) { osf->capabilities |= htonl(OFPC10_STP); } osf->actions = encode_action_bits(features->actions, of10_action_bits); - } else { + break; + case OFP11_VERSION: + case OFP12_VERSION: if (features->capabilities & OFPUTIL_C_GROUP_STATS) { osf->capabilities |= htonl(OFPC11_GROUP_STATS); } osf->actions = encode_action_bits(features->actions, of11_action_bits); + break; + default: + NOT_REACHED(); } return b; @@ -2475,13 +2575,25 @@ ofputil_encode_port_status(const struct ofputil_port_status *ps, { struct ofp_port_status *ops; struct ofpbuf *b; - uint8_t version; + enum ofp_version version; + enum ofpraw raw; version = ofputil_protocol_to_ofp_version(protocol); - b = ofpraw_alloc_xid(version == OFP10_VERSION - ? OFPRAW_OFPT10_PORT_STATUS - : OFPRAW_OFPT11_PORT_STATUS, - version, htonl(0), 0); + switch (version) { + case OFP10_VERSION: + raw = OFPRAW_OFPT10_PORT_STATUS; + break; + + case OFP11_VERSION: + case OFP12_VERSION: + raw = OFPRAW_OFPT11_PORT_STATUS; + break; + + default: + NOT_REACHED(); + } + + b = ofpraw_alloc_xid(raw, version, htonl(0), 0); ops = ofpbuf_put_zeros(b, sizeof *ops); ops->reason = ps->reason; ofputil_put_phy_port(version, &ps->desc, b); @@ -2539,10 +2651,11 @@ struct ofpbuf * ofputil_encode_port_mod(const struct ofputil_port_mod *pm, enum ofputil_protocol protocol) { - uint8_t ofp_version = ofputil_protocol_to_ofp_version(protocol); + enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol); struct ofpbuf *b; - if (ofp_version == OFP10_VERSION) { + switch (ofp_version) { + case OFP10_VERSION: { struct ofp10_port_mod *opm; b = ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD, ofp_version, 0); @@ -2552,7 +2665,10 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, opm->config = htonl(pm->config & OFPPC10_ALL); opm->mask = htonl(pm->mask & OFPPC10_ALL); opm->advertise = netdev_port_features_to_ofp10(pm->advertise); - } else if (ofp_version == OFP11_VERSION) { + break; + } + + case OFP11_VERSION: { struct ofp11_port_mod *opm; b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0); @@ -2562,7 +2678,11 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, opm->config = htonl(pm->config & OFPPC11_ALL); opm->mask = htonl(pm->mask & OFPPC11_ALL); opm->advertise = netdev_port_features_to_ofp11(pm->advertise); - } else { + break; + } + + case OFP12_VERSION: + default: NOT_REACHED(); } @@ -3052,16 +3172,22 @@ ofputil_format_port(uint16_t port, struct ds *s) * port and returns 0. If no ports remain to be decoded, returns EOF. * On an error, returns a positive OFPERR_* value. */ int -ofputil_pull_phy_port(uint8_t ofp_version, struct ofpbuf *b, +ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b, struct ofputil_phy_port *pp) { - if (ofp_version == OFP10_VERSION) { + switch (ofp_version) { + case OFP10_VERSION: { const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp); return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF; - } else { + } + case OFP11_VERSION: + case OFP12_VERSION: { const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op); return op ? ofputil_decode_ofp11_port(pp, op) : EOF; } + default: + NOT_REACHED(); + } } /* Given a buffer 'b' that contains an array of OpenFlow ports of type