X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-util.c;h=ce9bb74d1caa2a6750c7a2ee2ee8099fcda22663;hb=1e3f34c7693bcabae8e443ac1b246680ef9b60e2;hp=64eb5ca6ae6f0064fc6e84996656eb885e49c1e6;hpb=8a6bc7cd70c142eefa06d8714aa093281441cfa2;p=sliver-openvswitch.git diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 64eb5ca6a..ce9bb74d1 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1309,10 +1309,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, ofm->out_group = htonl(OFPG11_ANY); ofm->flags = htons(fm->flags); oxm_put_match(msg, &fm->cr); - if (fm->ofpacts) { - ofpacts_put_openflow11_instructions(fm->ofpacts, fm->ofpacts_len, - msg); - } + ofpacts_put_openflow11_instructions(fm->ofpacts, fm->ofpacts_len, msg); break; } @@ -1332,9 +1329,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, ofm->buffer_id = htonl(fm->buffer_id); ofm->out_port = htons(fm->out_port); ofm->flags = htons(fm->flags); - if (fm->ofpacts) { - ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg); - } + ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg); break; } @@ -1357,9 +1352,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, nfm->out_port = htons(fm->out_port); nfm->flags = htons(fm->flags); nfm->match_len = htons(match_len); - if (fm->ofpacts) { - ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg); - } + ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg); break; } @@ -1403,9 +1396,9 @@ 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 ofp10_flow_stats_request *ofsr, - bool aggregate) +ofputil_decode_ofpst10_flow_request(struct ofputil_flow_stats_request *fsr, + const struct ofp10_flow_stats_request *ofsr, + bool aggregate) { fsr->aggregate = aggregate; ofputil_cls_rule_from_ofp10_match(&ofsr->match, 0, &fsr->match); @@ -1416,6 +1409,33 @@ ofputil_decode_ofpst_flow_request(struct ofputil_flow_stats_request *fsr, return 0; } +static enum ofperr +ofputil_decode_ofpst11_flow_request(struct ofputil_flow_stats_request *fsr, + struct ofpbuf *b, bool aggregate) +{ + const struct ofp11_flow_stats_request *ofsr; + enum ofperr error; + + ofsr = ofpbuf_pull(b, sizeof *ofsr); + fsr->aggregate = aggregate; + fsr->table_id = ofsr->table_id; + error = ofputil_port_from_ofp11(ofsr->out_port, &fsr->out_port); + if (error) { + return error; + } + if (ofsr->out_group != htonl(OFPG11_ANY)) { + return OFPERR_NXFMFC_GROUPS_NOT_SUPPORTED; + } + fsr->cookie = ofsr->cookie; + fsr->cookie_mask = ofsr->cookie_mask; + error = ofputil_pull_ofp11_match(b, 0, &fsr->match, NULL); + if (error) { + return error; + } + + return 0; +} + static enum ofperr ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr, struct ofpbuf *b, bool aggregate) @@ -1453,11 +1473,17 @@ ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *fsr, ofpbuf_use_const(&b, oh, ntohs(oh->length)); raw = ofpraw_pull_assert(&b); switch ((int) raw) { - case OFPRAW_OFPST_FLOW_REQUEST: - return ofputil_decode_ofpst_flow_request(fsr, b.data, false); + case OFPRAW_OFPST10_FLOW_REQUEST: + return ofputil_decode_ofpst10_flow_request(fsr, b.data, false); - case OFPRAW_OFPST_AGGREGATE_REQUEST: - return ofputil_decode_ofpst_flow_request(fsr, b.data, true); + case OFPRAW_OFPST10_AGGREGATE_REQUEST: + return ofputil_decode_ofpst10_flow_request(fsr, b.data, true); + + case OFPRAW_OFPST11_FLOW_REQUEST: + return ofputil_decode_ofpst11_flow_request(fsr, &b, false); + + case OFPRAW_OFPST11_AGGREGATE_REQUEST: + return ofputil_decode_ofpst11_flow_request(fsr, &b, true); case OFPRAW_NXST_FLOW_REQUEST: return ofputil_decode_nxst_flow_request(fsr, &b, false); @@ -1482,13 +1508,30 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, enum ofpraw raw; switch (protocol) { + case OFPUTIL_P_OF12: { + struct ofp11_flow_stats_request *ofsr; + + raw = (fsr->aggregate + ? OFPRAW_OFPST11_AGGREGATE_REQUEST + : OFPRAW_OFPST11_FLOW_REQUEST); + msg = ofpraw_alloc(raw, OFP12_VERSION, NXM_TYPICAL_LEN); + ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr); + ofsr->table_id = fsr->table_id; + ofsr->out_port = ofputil_port_to_ofp11(fsr->out_port); + ofsr->out_group = htonl(OFPG11_ANY); + ofsr->cookie = fsr->cookie; + ofsr->cookie_mask = fsr->cookie_mask; + oxm_put_match(msg, &fsr->match); + break; + } + case OFPUTIL_P_OF10: case OFPUTIL_P_OF10_TID: { struct ofp10_flow_stats_request *ofsr; raw = (fsr->aggregate - ? OFPRAW_OFPST_AGGREGATE_REQUEST - : OFPRAW_OFPST_FLOW_REQUEST); + ? OFPRAW_OFPST10_AGGREGATE_REQUEST + : OFPRAW_OFPST10_FLOW_REQUEST); msg = ofpraw_alloc(raw, OFP10_VERSION, 0); ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr); ofputil_cls_rule_to_ofp10_match(&fsr->match, &ofsr->match); @@ -1505,7 +1548,7 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, raw = (fsr->aggregate ? OFPRAW_NXST_AGGREGATE_REQUEST : OFPRAW_NXST_FLOW_REQUEST); - msg = ofpraw_alloc(raw, OFP10_VERSION, 0); + msg = ofpraw_alloc(raw, OFP10_VERSION, NXM_TYPICAL_LEN); ofpbuf_put_zeros(msg, sizeof *nfsr); match_len = nx_put_match(msg, &fsr->match, fsr->cookie, fsr->cookie_mask); @@ -1517,7 +1560,6 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, break; } - case OFPUTIL_P_OF12: default: NOT_REACHED(); } @@ -1580,7 +1622,48 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, if (!msg->size) { return EOF; - } else if (raw == OFPRAW_OFPST_FLOW_REPLY) { + } else if (raw == OFPRAW_OFPST11_FLOW_REPLY) { + const struct ofp11_flow_stats *ofs; + size_t length; + uint16_t padded_match_len; + + ofs = ofpbuf_try_pull(msg, sizeof *ofs); + if (!ofs) { + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %zu leftover " + "bytes at end", msg->size); + return EINVAL; + } + + length = ntohs(ofs->length); + if (length < sizeof *ofs) { + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid " + "length %zu", length); + return EINVAL; + } + + if (ofputil_pull_ofp11_match(msg, ntohs(ofs->priority), &fs->rule, + &padded_match_len)) { + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad match"); + return EINVAL; + } + + if (ofpacts_pull_openflow11_instructions(msg, length - sizeof *ofs - + padded_match_len, ofpacts)) { + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions"); + return EINVAL; + } + + fs->table_id = ofs->table_id; + fs->duration_sec = ntohl(ofs->duration_sec); + fs->duration_nsec = ntohl(ofs->duration_nsec); + fs->idle_timeout = ntohs(ofs->idle_timeout); + fs->hard_timeout = ntohs(ofs->hard_timeout); + fs->idle_age = -1; + fs->hard_age = -1; + fs->cookie = ofs->cookie; + fs->packet_count = ntohll(ofs->packet_count); + fs->byte_count = ntohll(ofs->byte_count); + } else if (raw == OFPRAW_OFPST10_FLOW_REPLY) { const struct ofp10_flow_stats *ofs; size_t length; @@ -1692,7 +1775,28 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs, enum ofpraw raw; ofpraw_decode_partial(&raw, reply->data, reply->size); - if (raw == OFPRAW_OFPST_FLOW_REPLY) { + if (raw == OFPRAW_OFPST11_FLOW_REPLY) { + struct ofp11_flow_stats *ofs; + + ofpbuf_put_uninit(reply, sizeof *ofs); + oxm_put_match(reply, &fs->rule); + ofpacts_put_openflow11_instructions(fs->ofpacts, fs->ofpacts_len, + reply); + + ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs); + ofs->length = htons(reply->size - start_ofs); + ofs->table_id = fs->table_id; + ofs->pad = 0; + ofs->duration_sec = htonl(fs->duration_sec); + ofs->duration_nsec = htonl(fs->duration_nsec); + ofs->priority = htons(fs->rule.priority); + ofs->idle_timeout = htons(fs->idle_timeout); + ofs->hard_timeout = htons(fs->hard_timeout); + memset(ofs->pad2, 0, sizeof ofs->pad2); + ofs->cookie = fs->cookie; + ofs->packet_count = htonll(unknown_to_zero(fs->packet_count)); + ofs->byte_count = htonll(unknown_to_zero(fs->byte_count)); + } else if (raw == OFPRAW_OFPST10_FLOW_REPLY) { struct ofp10_flow_stats *ofs; ofpbuf_put_uninit(reply, sizeof *ofs); @@ -1762,7 +1866,7 @@ ofputil_encode_aggregate_stats_reply( enum ofpraw raw; ofpraw_decode(&raw, request); - if (raw == OFPRAW_OFPST_AGGREGATE_REQUEST) { + if (raw == OFPRAW_OFPST10_AGGREGATE_REQUEST) { packet_count = unknown_to_zero(stats->packet_count); byte_count = unknown_to_zero(stats->byte_count); } else { @@ -1809,7 +1913,28 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, ofpbuf_use_const(&b, oh, ntohs(oh->length)); raw = ofpraw_pull_assert(&b); - if (raw == OFPRAW_OFPT10_FLOW_REMOVED) { + if (raw == OFPRAW_OFPT11_FLOW_REMOVED) { + const struct ofp12_flow_removed *ofr; + enum ofperr error; + + ofr = ofpbuf_pull(&b, sizeof *ofr); + + error = ofputil_pull_ofp11_match(&b, ntohs(ofr->priority), + &fr->rule, NULL); + if (error) { + return error; + } + + fr->cookie = ofr->cookie; + fr->reason = ofr->reason; + /* XXX: ofr->table_id is ignored */ + fr->duration_sec = ntohl(ofr->duration_sec); + fr->duration_nsec = ntohl(ofr->duration_nsec); + fr->idle_timeout = ntohs(ofr->idle_timeout); + fr->hard_timeout = ntohs(ofr->hard_timeout); + fr->packet_count = ntohll(ofr->packet_count); + fr->byte_count = ntohll(ofr->byte_count); + } else if (raw == OFPRAW_OFPT10_FLOW_REMOVED) { const struct ofp_flow_removed *ofr; ofr = ofpbuf_pull(&b, sizeof *ofr); @@ -1821,6 +1946,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, fr->duration_sec = ntohl(ofr->duration_sec); fr->duration_nsec = ntohl(ofr->duration_nsec); fr->idle_timeout = ntohs(ofr->idle_timeout); + fr->hard_timeout = 0; fr->packet_count = ntohll(ofr->packet_count); fr->byte_count = ntohll(ofr->byte_count); } else if (raw == OFPRAW_NXT_FLOW_REMOVED) { @@ -1842,6 +1968,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, fr->duration_sec = ntohl(nfr->duration_sec); fr->duration_nsec = ntohl(nfr->duration_nsec); fr->idle_timeout = ntohs(nfr->idle_timeout); + fr->hard_timeout = 0; fr->packet_count = ntohll(nfr->packet_count); fr->byte_count = ntohll(nfr->byte_count); } else { @@ -1861,6 +1988,27 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, struct ofpbuf *msg; switch (protocol) { + case OFPUTIL_P_OF12: { + struct ofp12_flow_removed *ofr; + + msg = ofpraw_alloc_xid(OFPRAW_OFPT11_FLOW_REMOVED, + ofputil_protocol_to_ofp_version(protocol), + htonl(0), NXM_TYPICAL_LEN); + ofr = ofpbuf_put_zeros(msg, sizeof *ofr); + ofr->cookie = fr->cookie; + ofr->priority = htons(fr->rule.priority); + ofr->reason = fr->reason; + ofr->table_id = 0; + ofr->duration_sec = htonl(fr->duration_sec); + ofr->duration_nsec = htonl(fr->duration_nsec); + ofr->idle_timeout = htons(fr->idle_timeout); + ofr->hard_timeout = htons(fr->hard_timeout); + ofr->packet_count = htonll(fr->packet_count); + ofr->byte_count = htonll(fr->byte_count); + oxm_put_match(msg, &fr->rule); + break; + } + case OFPUTIL_P_OF10: case OFPUTIL_P_OF10_TID: { struct ofp_flow_removed *ofr; @@ -1903,7 +2051,6 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, break; } - case OFPUTIL_P_OF12: default: NOT_REACHED(); } @@ -1920,15 +2067,9 @@ ofputil_decode_packet_in_finish(struct ofputil_packet_in *pin, pin->packet_len = b->size; pin->fmd.in_port = rule->flow.in_port; - pin->fmd.tun_id = rule->flow.tun_id; - pin->fmd.tun_id_mask = rule->wc.tun_id_mask; - pin->fmd.metadata = rule->flow.metadata; - pin->fmd.metadata_mask = rule->wc.metadata_mask; - memcpy(pin->fmd.regs, rule->flow.regs, sizeof pin->fmd.regs); - memcpy(pin->fmd.reg_masks, rule->wc.reg_masks, sizeof pin->fmd.reg_masks); } enum ofperr @@ -2014,14 +2155,17 @@ ofputil_packet_in_to_rule(const struct ofputil_packet_in *pin, int i; cls_rule_init_catchall(rule, 0); - cls_rule_set_tun_id_masked(rule, pin->fmd.tun_id, - pin->fmd.tun_id_mask); - cls_rule_set_metadata_masked(rule, pin->fmd.metadata, - pin->fmd.metadata_mask); + if (pin->fmd.tun_id != htonll(0)) { + cls_rule_set_tun_id(rule, pin->fmd.tun_id); + } + if (pin->fmd.metadata != htonll(0)) { + cls_rule_set_metadata(rule, pin->fmd.metadata); + } for (i = 0; i < FLOW_N_REGS; i++) { - cls_rule_set_reg_masked(rule, i, pin->fmd.regs[i], - pin->fmd.reg_masks[i]); + if (pin->fmd.regs[i]) { + cls_rule_set_reg(rule, i, pin->fmd.regs[i]); + } } cls_rule_set_in_port(rule, pin->fmd.in_port); @@ -2149,13 +2293,31 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, const struct ofp_header *oh, struct ofpbuf *ofpacts) { + enum ofperr bad_in_port_err; enum ofpraw raw; struct ofpbuf b; ofpbuf_use_const(&b, oh, ntohs(oh->length)); raw = ofpraw_pull_assert(&b); - if (raw == OFPRAW_OFPT10_PACKET_OUT) { + if (raw == OFPRAW_OFPT11_PACKET_OUT) { + enum ofperr error; + const struct ofp11_packet_out *opo = ofpbuf_pull(&b, sizeof *opo); + + po->buffer_id = ntohl(opo->buffer_id); + error = ofputil_port_from_ofp11(opo->in_port, &po->in_port); + if (error) { + return error; + } + + error = ofpacts_pull_openflow11_actions(&b, ntohs(opo->actions_len), + ofpacts); + if (error) { + return error; + } + + bad_in_port_err = OFPERR_OFPBMC_BAD_VALUE; + } else if (raw == OFPRAW_OFPT10_PACKET_OUT) { enum ofperr error; const struct ofp_packet_out *opo = ofpbuf_pull(&b, sizeof *opo); @@ -2166,6 +2328,8 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, if (error) { return error; } + + bad_in_port_err = OFPERR_NXBRC_BAD_IN_PORT; } else { NOT_REACHED(); } @@ -2174,7 +2338,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, && po->in_port != OFPP_NONE && po->in_port != OFPP_CONTROLLER) { VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16, po->in_port); - return OFPERR_NXBRC_BAD_IN_PORT; + return bad_in_port_err; } po->ofpacts = ofpacts->data; @@ -2767,12 +2931,13 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, break; } - case OFP11_VERSION: { + case OFP11_VERSION: + case OFP12_VERSION: { struct ofp11_port_mod *opm; b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0); opm = ofpbuf_put_zeros(b, sizeof *opm); - opm->port_no = htonl(pm->port_no); + opm->port_no = ofputil_port_to_ofp11(pm->port_no); memcpy(opm->hw_addr, pm->hw_addr, ETH_ADDR_LEN); opm->config = htonl(pm->config & OFPPC11_ALL); opm->mask = htonl(pm->mask & OFPPC11_ALL); @@ -2780,7 +2945,6 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, break; } - case OFP12_VERSION: default: NOT_REACHED(); }