X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-util.c;h=7de82c69f322b526e6b91465d535471e3d11d0aa;hb=bdd534291ff72077390f7b1745c4443ad3833d99;hp=f0cd7516cdef72ad6ff1b82525220eb1750cc31f;hpb=0e19706066f34523854cbce50c05c367e700c451;p=sliver-openvswitch.git diff --git a/lib/ofp-util.c b/lib/ofp-util.c index f0cd7516c..7de82c69f 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -84,7 +84,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask) void ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 22); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 24); /* Initialize most of wc. */ flow_wildcards_init_catchall(wc); @@ -436,11 +436,11 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch, } if (eth_type_mpls(match->flow.dl_type)) { - enum { OFPFW11_MPLS_ALL = OFPFW11_MPLS_LABEL | OFPFW11_MPLS_TC }; - - if ((wc & OFPFW11_MPLS_ALL) != OFPFW11_MPLS_ALL) { - /* MPLS not supported. */ - return OFPERR_OFPBMC_BAD_TAG; + if (!(wc & OFPFW11_MPLS_LABEL)) { + match_set_mpls_label(match, 0, ofmatch->mpls_label); + } + if (!(wc & OFPFW11_MPLS_TC)) { + match_set_mpls_tc(match, 0, ofmatch->mpls_tc); } } @@ -533,9 +533,18 @@ ofputil_match_to_ofp11_match(const struct match *match, ofmatch->tp_dst = match->flow.tp_dst; } - /* MPLS not supported. */ - wc |= OFPFW11_MPLS_LABEL; - wc |= OFPFW11_MPLS_TC; + if (!(match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK))) { + wc |= OFPFW11_MPLS_LABEL; + } else { + ofmatch->mpls_label = htonl(mpls_lse_to_label( + match->flow.mpls_lse[0])); + } + + if (!(match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK))) { + wc |= OFPFW11_MPLS_TC; + } else { + ofmatch->mpls_tc = mpls_lse_to_tc(match->flow.mpls_lse[0]); + } ofmatch->metadata = match->flow.metadata; ofmatch->metadata_mask = ~match->wc.masks.metadata; @@ -565,7 +574,7 @@ ofputil_match_typical_len(enum ofputil_protocol protocol) return NXM_TYPICAL_LEN; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -587,7 +596,7 @@ ofputil_put_ofp11_match(struct ofpbuf *b, const struct match *match, case OFPUTIL_P_OF10_STD_TID: case OFPUTIL_P_OF10_NXM: case OFPUTIL_P_OF10_NXM_TID: - NOT_REACHED(); + OVS_NOT_REACHED(); case OFPUTIL_P_OF11_STD: { struct ofp11_match *om; @@ -605,7 +614,7 @@ ofputil_put_ofp11_match(struct ofpbuf *b, const struct match *match, return oxm_put_match(b, match); } - NOT_REACHED(); + OVS_NOT_REACHED(); } /* Given a 'dl_type' value in the format used in struct flow, returns the @@ -707,7 +716,7 @@ ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol) return OFP13_VERSION; } - NOT_REACHED(); + OVS_NOT_REACHED(); } /* Returns a bitmap of OpenFlow versions that are supported by at @@ -782,7 +791,7 @@ ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable) return OFPUTIL_P_OF13_OXM; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -822,7 +831,7 @@ ofputil_protocol_set_base(enum ofputil_protocol cur, return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid); default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -910,7 +919,7 @@ ofputil_protocols_to_string(enum ofputil_protocol protocols) goto match; } } - NOT_REACHED(); + OVS_NOT_REACHED(); match: ; } @@ -1063,7 +1072,7 @@ ofputil_version_to_string(enum ofp_version ofp_version) case OFP13_VERSION: return "OpenFlow13"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1088,7 +1097,7 @@ ofputil_packet_in_format_to_string(enum nx_packet_in_format packet_in_format) case NXPIF_NXM: return "nxm"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1297,11 +1306,11 @@ ofputil_encode_set_protocol(enum ofputil_protocol current, case OFPUTIL_P_OF13_OXM: /* There is only one variant of each OpenFlow 1.1+ protocol, and we * verified above that we're not trying to change versions. */ - NOT_REACHED(); + OVS_NOT_REACHED(); case OFPUTIL_P_OF10_STD_TID: case OFPUTIL_P_OF10_NXM_TID: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1370,7 +1379,7 @@ ofputil_nx_flow_format_to_string(enum nx_flow_format flow_format) case NXFF_NXM: return "nxm"; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1484,7 +1493,8 @@ enum ofperr ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, const struct ofp_header *oh, enum ofputil_protocol protocol, - struct ofpbuf *ofpacts) + struct ofpbuf *ofpacts, + ofp_port_t max_port, uint8_t max_table) { ovs_be16 raw_flags; enum ofperr error; @@ -1533,10 +1543,10 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, /* Get table ID. * - * OF1.1 entirely forbids table_id == 255. - * OF1.2+ allows table_id == 255 only for deletes. */ + * OF1.1 entirely forbids table_id == OFPTT_ALL. + * OF1.2+ allows table_id == OFPTT_ALL only for deletes. */ fm->table_id = ofm->table_id; - if (fm->table_id == 255 + if (fm->table_id == OFPTT_ALL && (oh->version == OFP11_VERSION || (ofm->command != OFPFC_DELETE && ofm->command != OFPFC_DELETE_STRICT))) { @@ -1550,13 +1560,11 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, if (error) { return error; } - fm->out_group = ntohl(ofm->out_group); - if ((ofm->command == OFPFC_DELETE - || ofm->command == OFPFC_DELETE_STRICT) - && ofm->out_group != htonl(OFPG_ANY)) { - return OFPERR_OFPFMFC_UNKNOWN; - } + fm->out_group = (ofm->command == OFPFC_DELETE || + ofm->command == OFPFC_DELETE_STRICT + ? ntohl(ofm->out_group) + : OFPG11_ANY); raw_flags = ofm->flags; } else { uint16_t command; @@ -1629,7 +1637,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, fm->out_group = OFPG11_ANY; raw_flags = nfm->flags; } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } fm->modify_cookie = fm->new_cookie != OVS_BE64_MAX; @@ -1663,7 +1671,9 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, : OFPERR_OFPFMFC_TABLE_FULL); } - return 0; + return ofpacts_check_consistency(fm->ofpacts, fm->ofpacts_len, + &fm->match.flow, max_port, + fm->table_id, max_table, protocol); } static enum ofperr @@ -1687,6 +1697,9 @@ ofputil_pull_bands(struct ofpbuf *msg, size_t len, uint16_t *n_bands, } mb = ofpbuf_put_uninit(bands, sizeof *mb); mb->type = ntohs(ombh->type); + if (mb->type != OFPMBT13_DROP && mb->type != OFPMBT13_DSCP_REMARK) { + return OFPERR_OFPMMFC_BAD_BAND; + } mb->rate = ntohl(ombh->rate); mb->burst_size = ntohl(ombh->burst_size); mb->prec_level = (mb->type == OFPMBT13_DSCP_REMARK) ? @@ -1717,6 +1730,11 @@ ofputil_decode_meter_mod(const struct ofp_header *oh, /* Translate the message. */ mm->command = ntohs(omm->command); + if (mm->command != OFPMC13_ADD && + mm->command != OFPMC13_MODIFY && + mm->command != OFPMC13_DELETE) { + return OFPERR_OFPMMFC_BAD_COMMAND; + } mm->meter.meter_id = ntohl(omm->meter_id); if (mm->command == OFPMC13_DELETE) { @@ -1727,6 +1745,10 @@ ofputil_decode_meter_mod(const struct ofp_header *oh, enum ofperr error; mm->meter.flags = ntohs(omm->flags); + if (mm->meter.flags & OFPMF13_KBPS && + mm->meter.flags & OFPMF13_PKTPS) { + return OFPERR_OFPMMFC_BAD_FLAGS; + } mm->meter.bands = bands->data; error = ofputil_pull_bands(&b, b.size, &mm->meter.n_bands, bands); @@ -1878,7 +1900,7 @@ ofputil_decode_meter_config(struct ofpbuf *msg, omc = ofpbuf_try_pull(msg, sizeof *omc); if (!omc) { VLOG_WARN_RL(&bad_ofmsg_rl, - "OFPMP_METER_CONFIG reply has %zu leftover bytes at end", + "OFPMP_METER_CONFIG reply has %"PRIuSIZE" leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -1954,7 +1976,7 @@ ofputil_decode_meter_stats(struct ofpbuf *msg, oms = ofpbuf_try_pull(msg, sizeof *oms); if (!oms) { VLOG_WARN_RL(&bad_ofmsg_rl, - "OFPMP_METER reply has %zu leftover bytes at end", + "OFPMP_METER reply has %"PRIuSIZE" leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -2070,7 +2092,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, ofm->cookie = fm->cookie; } ofm->cookie_mask = fm->cookie_mask; - if (fm->table_id != 255 + if (fm->table_id != OFPTT_ALL || (protocol != OFPUTIL_P_OF11_STD && (fm->command == OFPFC_DELETE || fm->command == OFPFC_DELETE_STRICT))) { @@ -2138,7 +2160,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } ofpmsg_update_length(msg); @@ -2263,7 +2285,7 @@ ofputil_decode_queue_get_config_request(const struct ofp_header *oh, return ofputil_port_from_ofp11(qgcr11->port, port); } - NOT_REACHED(); + OVS_NOT_REACHED(); } /* Constructs and returns the beginning of a reply to @@ -2302,7 +2324,7 @@ ofputil_encode_queue_get_config_reply(const struct ofp_header *oh) break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return reply; @@ -2384,7 +2406,7 @@ ofputil_decode_queue_get_config_reply(struct ofpbuf *reply, ofp_port_t *port) return ofputil_port_from_ofp11(qgcr11->port, port); } - NOT_REACHED(); + OVS_NOT_REACHED(); } static enum ofperr @@ -2520,7 +2542,7 @@ ofputil_decode_flow_stats_request(struct ofputil_flow_stats_request *fsr, default: /* Hey, the caller lied. */ - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -2591,7 +2613,7 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return msg; @@ -2645,7 +2667,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, ofs = ofpbuf_try_pull(msg, sizeof *ofs); if (!ofs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %zu leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIuSIZE" leftover " "bytes at end", msg->size); return EINVAL; } @@ -2653,7 +2675,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, length = ntohs(ofs->length); if (length < sizeof *ofs) { VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid " - "length %zu", length); + "length %"PRIuSIZE, length); return EINVAL; } @@ -2695,7 +2717,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, ofs = ofpbuf_try_pull(msg, sizeof *ofs); if (!ofs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %zu leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply has %"PRIuSIZE" leftover " "bytes at end", msg->size); return EINVAL; } @@ -2703,7 +2725,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, length = ntohs(ofs->length); if (length < sizeof *ofs) { VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply claims invalid " - "length %zu", length); + "length %"PRIuSIZE, length); return EINVAL; } @@ -2731,7 +2753,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, nfs = ofpbuf_try_pull(msg, sizeof *nfs); if (!nfs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply has %zu leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply has %"PRIuSIZE" leftover " "bytes at end", msg->size); return EINVAL; } @@ -2739,8 +2761,8 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, length = ntohs(nfs->length); match_len = ntohs(nfs->match_len); if (length < sizeof *nfs + ROUND_UP(match_len, 8)) { - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply with match_len=%zu " - "claims invalid length %zu", match_len, length); + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW reply with match_len=%"PRIuSIZE" " + "claims invalid length %"PRIuSIZE, match_len, length); return EINVAL; } if (nx_pull_match(msg, match_len, &fs->match, NULL, NULL)) { @@ -2774,7 +2796,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, fs->byte_count = ntohll(nfs->byte_count); fs->flags = 0; } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } fs->ofpacts = ofpacts->data; @@ -2882,7 +2904,7 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs, nfs->packet_count = htonll(fs->packet_count); nfs->byte_count = htonll(fs->byte_count); } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } ofpmp_postappend(replies, start_ofs); @@ -3011,7 +3033,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, fr->packet_count = ntohll(nfr->packet_count); fr->byte_count = ntohll(nfr->byte_count); } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } return 0; @@ -3095,7 +3117,7 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return msg; @@ -3173,6 +3195,23 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin, pin->reason = opi->reason; pin->buffer_id = ntohl(opi->buffer_id); pin->total_len = ntohs(opi->total_len); + } else if (raw == OFPRAW_OFPT11_PACKET_IN) { + const struct ofp11_packet_in *opi; + enum ofperr error; + + opi = ofpbuf_pull(&b, sizeof *opi); + + pin->packet = b.data; + pin->packet_len = b.size; + + pin->buffer_id = ntohl(opi->buffer_id); + error = ofputil_port_from_ofp11(opi->in_port, &pin->fmd.in_port); + if (error) { + return error; + } + pin->total_len = ntohs(opi->total_len); + pin->reason = opi->reason; + pin->table_id = opi->table_id; } else if (raw == OFPRAW_NXT_PACKET_IN) { const struct nx_packet_in *npi; struct match match; @@ -3198,7 +3237,7 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin, ofputil_decode_packet_in_finish(pin, &match, &b); } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } return 0; @@ -3237,6 +3276,120 @@ ofputil_packet_in_to_match(const struct ofputil_packet_in *pin, match_set_in_port(match, pin->fmd.in_port); } +static struct ofpbuf * +ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in *pin) +{ + struct ofp10_packet_in *opi; + struct ofpbuf *packet; + + packet = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION, + htonl(0), pin->packet_len); + opi = ofpbuf_put_zeros(packet, offsetof(struct ofp10_packet_in, data)); + opi->total_len = htons(pin->total_len); + opi->in_port = htons(ofp_to_u16(pin->fmd.in_port)); + opi->reason = pin->reason; + opi->buffer_id = htonl(pin->buffer_id); + + ofpbuf_put(packet, pin->packet, pin->packet_len); + + return packet; +} + +static struct ofpbuf * +ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin) +{ + struct nx_packet_in *npi; + struct ofpbuf *packet; + struct match match; + size_t match_len; + + ofputil_packet_in_to_match(pin, &match); + + /* The final argument is just an estimate of the space required. */ + packet = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN, OFP10_VERSION, + htonl(0), (sizeof(struct flow_metadata) * 2 + + 2 + pin->packet_len)); + ofpbuf_put_zeros(packet, sizeof *npi); + match_len = nx_put_match(packet, &match, 0, 0); + ofpbuf_put_zeros(packet, 2); + ofpbuf_put(packet, pin->packet, pin->packet_len); + + npi = packet->l3; + npi->buffer_id = htonl(pin->buffer_id); + npi->total_len = htons(pin->total_len); + npi->reason = pin->reason; + npi->table_id = pin->table_id; + npi->cookie = pin->cookie; + npi->match_len = htons(match_len); + + return packet; +} + +static struct ofpbuf * +ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin) +{ + struct ofp11_packet_in *opi; + struct ofpbuf *packet; + + packet = ofpraw_alloc_xid(OFPRAW_OFPT11_PACKET_IN, OFP11_VERSION, + htonl(0), pin->packet_len); + opi = ofpbuf_put_zeros(packet, sizeof *opi); + opi->buffer_id = htonl(pin->buffer_id); + opi->in_port = ofputil_port_to_ofp11(pin->fmd.in_port); + opi->in_phy_port = opi->in_port; + opi->total_len = htons(pin->total_len); + opi->reason = pin->reason; + opi->table_id = pin->table_id; + + ofpbuf_put(packet, pin->packet, pin->packet_len); + + return packet; +} + +static struct ofpbuf * +ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin, + enum ofputil_protocol protocol) +{ + struct ofp13_packet_in *opi; + struct match match; + enum ofpraw packet_in_raw; + enum ofp_version packet_in_version; + size_t packet_in_size; + struct ofpbuf *packet; + + if (protocol == OFPUTIL_P_OF12_OXM) { + packet_in_raw = OFPRAW_OFPT12_PACKET_IN; + packet_in_version = OFP12_VERSION; + packet_in_size = sizeof (struct ofp12_packet_in); + } else { + packet_in_raw = OFPRAW_OFPT13_PACKET_IN; + packet_in_version = OFP13_VERSION; + packet_in_size = sizeof (struct ofp13_packet_in); + } + + ofputil_packet_in_to_match(pin, &match); + + /* The final argument is just an estimate of the space required. */ + packet = ofpraw_alloc_xid(packet_in_raw, packet_in_version, + htonl(0), (sizeof(struct flow_metadata) * 2 + + 2 + pin->packet_len)); + ofpbuf_put_zeros(packet, packet_in_size); + oxm_put_match(packet, &match); + ofpbuf_put_zeros(packet, 2); + ofpbuf_put(packet, pin->packet, pin->packet_len); + + opi = packet->l3; + opi->pi.buffer_id = htonl(pin->buffer_id); + opi->pi.total_len = htons(pin->total_len); + opi->pi.reason = pin->reason; + opi->pi.table_id = pin->table_id; + if (protocol == OFPUTIL_P_OF13_OXM) { + opi->cookie = pin->cookie; + } + + return packet; +} + /* Converts abstract ofputil_packet_in 'pin' into a PACKET_IN message * in the format specified by 'packet_in_format'. */ struct ofpbuf * @@ -3246,83 +3399,30 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin, { struct ofpbuf *packet; - /* Add OFPT_PACKET_IN. */ - if (protocol == OFPUTIL_P_OF13_OXM || protocol == OFPUTIL_P_OF12_OXM) { - struct ofp13_packet_in *opi; - struct match match; - enum ofpraw packet_in_raw; - enum ofp_version packet_in_version; - size_t packet_in_size; + switch (protocol) { + case OFPUTIL_P_OF10_STD: + case OFPUTIL_P_OF10_STD_TID: + case OFPUTIL_P_OF10_NXM: + case OFPUTIL_P_OF10_NXM_TID: + packet = (packet_in_format == NXPIF_NXM + ? ofputil_encode_nx_packet_in(pin) + : ofputil_encode_ofp10_packet_in(pin)); + break; - if (protocol == OFPUTIL_P_OF12_OXM) { - packet_in_raw = OFPRAW_OFPT12_PACKET_IN; - packet_in_version = OFP12_VERSION; - packet_in_size = sizeof (struct ofp12_packet_in); - } else { - packet_in_raw = OFPRAW_OFPT13_PACKET_IN; - packet_in_version = OFP13_VERSION; - packet_in_size = sizeof (struct ofp13_packet_in); - } + case OFPUTIL_P_OF11_STD: + packet = ofputil_encode_ofp11_packet_in(pin); + break; - ofputil_packet_in_to_match(pin, &match); - - /* The final argument is just an estimate of the space required. */ - packet = ofpraw_alloc_xid(packet_in_raw, packet_in_version, - htonl(0), (sizeof(struct flow_metadata) * 2 - + 2 + pin->packet_len)); - ofpbuf_put_zeros(packet, packet_in_size); - oxm_put_match(packet, &match); - ofpbuf_put_zeros(packet, 2); - ofpbuf_put(packet, pin->packet, pin->packet_len); - - opi = packet->l3; - opi->pi.buffer_id = htonl(pin->buffer_id); - opi->pi.total_len = htons(pin->total_len); - opi->pi.reason = pin->reason; - opi->pi.table_id = pin->table_id; - if (protocol == OFPUTIL_P_OF13_OXM) { - opi->cookie = pin->cookie; - } - } else if (packet_in_format == NXPIF_OPENFLOW10) { - struct ofp10_packet_in *opi; - - packet = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION, - htonl(0), pin->packet_len); - opi = ofpbuf_put_zeros(packet, offsetof(struct ofp10_packet_in, data)); - opi->total_len = htons(pin->total_len); - opi->in_port = htons(ofp_to_u16(pin->fmd.in_port)); - opi->reason = pin->reason; - opi->buffer_id = htonl(pin->buffer_id); - - ofpbuf_put(packet, pin->packet, pin->packet_len); - } else if (packet_in_format == NXPIF_NXM) { - struct nx_packet_in *npi; - struct match match; - size_t match_len; - - ofputil_packet_in_to_match(pin, &match); - - /* The final argument is just an estimate of the space required. */ - packet = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN, OFP10_VERSION, - htonl(0), (sizeof(struct flow_metadata) * 2 - + 2 + pin->packet_len)); - ofpbuf_put_zeros(packet, sizeof *npi); - match_len = nx_put_match(packet, &match, 0, 0); - ofpbuf_put_zeros(packet, 2); - ofpbuf_put(packet, pin->packet, pin->packet_len); - - npi = packet->l3; - npi->buffer_id = htonl(pin->buffer_id); - npi->total_len = htons(pin->total_len); - npi->reason = pin->reason; - npi->table_id = pin->table_id; - npi->cookie = pin->cookie; - npi->match_len = htons(match_len); - } else { - NOT_REACHED(); + case OFPUTIL_P_OF12_OXM: + case OFPUTIL_P_OF13_OXM: + packet = ofputil_encode_ofp12_packet_in(pin, protocol); + break; + + default: + OVS_NOT_REACHED(); } - ofpmsg_update_length(packet); + ofpmsg_update_length(packet); return packet; } @@ -3415,7 +3515,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, return error; } } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } if (ofp_to_u16(po->in_port) >= ofp_to_u16(OFPP_MAX) @@ -3564,7 +3664,7 @@ ofputil_get_phy_port_size(enum ofp_version ofp_version) case OFP13_VERSION: return sizeof(struct ofp11_port); default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -3635,7 +3735,7 @@ ofputil_put_phy_port(enum ofp_version ofp_version, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -3664,7 +3764,7 @@ ofputil_append_port_desc_stats_reply(enum ofp_version ofp_version, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -3855,7 +3955,7 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features, raw = OFPRAW_OFPT13_FEATURES_REPLY; break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } b = ofpraw_alloc_xid(raw, version, xid, 0); osf = ofpbuf_put_zeros(b, sizeof *osf); @@ -3883,7 +3983,7 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features, } break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return b; @@ -3956,7 +4056,7 @@ ofputil_encode_port_status(const struct ofputil_port_status *ps, break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } b = ofpraw_alloc_xid(raw, version, htonl(0), 0); @@ -4049,7 +4149,7 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return b; @@ -4109,7 +4209,7 @@ ofputil_encode_table_mod(const struct ofputil_table_mod *pm, break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return b; @@ -4169,7 +4269,7 @@ ofputil_decode_role_message(const struct ofp_header *oh, rr->have_generation_id = false; rr->generation_id = 0; } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } return 0; @@ -4206,7 +4306,7 @@ ofputil_encode_role_reply(const struct ofp_header *request, nrr = ofpbuf_put_zeros(buf, sizeof *nrr); nrr->role = htonl(rr->role - 1); } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } return buf; @@ -4418,7 +4518,7 @@ ofputil_encode_table_stats_reply(const struct ofp12_table_stats stats[], int n, break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -4455,7 +4555,7 @@ ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq, nfmr = ofpbuf_try_pull(msg, sizeof *nfmr); if (!nfmr) { - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR request has %zu " + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR request has %"PRIuSIZE" " "leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -4609,7 +4709,7 @@ ofputil_decode_flow_update(struct ofputil_flow_update *update, } bad_len: - VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has %zu " + VLOG_WARN_RL(&bad_ofmsg_rl, "NXST_FLOW_MONITOR reply has %"PRIuSIZE" " "leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -4738,7 +4838,7 @@ ofputil_encode_packet_out(const struct ofputil_packet_out *po, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } if (po->buffer_id == UINT32_MAX) { @@ -4791,7 +4891,7 @@ ofputil_encode_barrier_request(enum ofp_version ofp_version) break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return ofpraw_alloc(type, ofp_version, 0); @@ -4807,7 +4907,7 @@ ofputil_frag_handling_to_string(enum ofp_config_flags flags) case OFPC_FRAG_NX_MATCH: return "nx-match"; } - NOT_REACHED(); + OVS_NOT_REACHED(); } bool @@ -5061,7 +5161,7 @@ ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b, return op ? ofputil_decode_ofp11_port(pp, op) : EOF; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -5116,7 +5216,7 @@ ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf) { switch (code) { case OFPUTIL_ACTION_INVALID: - NOT_REACHED(); + OVS_NOT_REACHED(); #define OFPAT10_ACTION(ENUM, STRUCT, NAME) \ case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf); @@ -5126,7 +5226,7 @@ ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf) case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf); #include "ofp-util.def" } - NOT_REACHED(); + OVS_NOT_REACHED(); } #define OFPAT10_ACTION(ENUM, STRUCT, NAME) \ @@ -5245,7 +5345,7 @@ ofputil_normalize_match__(struct match *match, bool may_log) wc.masks.nd_target = in6addr_any; } if (!(may_match & MAY_MPLS)) { - wc.masks.mpls_lse = htonl(0); + memset(wc.masks.mpls_lse, 0, sizeof wc.masks.mpls_lse); } /* Log any changes. */ @@ -5396,7 +5496,7 @@ ofputil_encode_dump_ports_request(enum ofp_version ofp_version, ofp_port_t port) break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return request; @@ -5480,7 +5580,7 @@ ofputil_append_port_stat(struct list *replies, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -5562,7 +5662,7 @@ ofputil_get_port_stats_size(enum ofp_version ofp_version) case OFP13_VERSION: return sizeof(struct ofp13_port_stats); default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -5629,11 +5729,11 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg) } return ofputil_port_stats_from_ofp10(ps, ps10); } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } bad_len: - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %zu leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %"PRIuSIZE" leftover " "bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -5660,7 +5760,7 @@ ofputil_decode_port_stats_request(const struct ofp_header *request, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -5702,7 +5802,7 @@ ofputil_encode_group_stats_request(enum ofp_version ofp_version, break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return request; @@ -5730,7 +5830,7 @@ ofputil_encode_group_desc_request(enum ofp_version ofp_version) break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return request; @@ -5800,7 +5900,7 @@ ofputil_append_group_stats(struct list *replies, case OFP10_VERSION: default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -5823,7 +5923,7 @@ ofputil_encode_group_features_request(enum ofp_version ofp_version) break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return request; @@ -5939,17 +6039,17 @@ ofputil_decode_group_stats_reply(struct ofpbuf *msg, ogs11 = NULL; } } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } if (!ogs11) { - VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %zu leftover bytes at end", + VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIuSIZE" leftover bytes at end", ofpraw_get_name(raw), msg->size); return OFPERR_OFPBRC_BAD_LEN; } length = ntohs(ogs11->length); if (length < sizeof base_len) { - VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply claims invalid length %zu", + VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply claims invalid length %"PRIuSIZE, ofpraw_get_name(raw), length); return OFPERR_OFPBRC_BAD_LEN; } @@ -5962,7 +6062,7 @@ ofputil_decode_group_stats_reply(struct ofpbuf *msg, gs->n_buckets = (length - base_len) / sizeof *obc; obc = ofpbuf_try_pull(msg, gs->n_buckets * sizeof *obc); if (!obc) { - VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %zu leftover bytes at end", + VLOG_WARN_RL(&bad_ofmsg_rl, "%s reply has %"PRIuSIZE" leftover bytes at end", ofpraw_get_name(raw), msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6031,18 +6131,18 @@ ofputil_pull_buckets(struct ofpbuf *msg, size_t buckets_length, ? ofpbuf_try_pull(msg, sizeof *ob) : NULL); if (!ob) { - VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %zu leftover bytes", + VLOG_WARN_RL(&bad_ofmsg_rl, "buckets end with %"PRIuSIZE" leftover bytes", buckets_length); } ob_len = ntohs(ob->len); if (ob_len < sizeof *ob) { VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length " - "%zu is not valid", ob_len); + "%"PRIuSIZE" is not valid", ob_len); return OFPERR_OFPGMFC_BAD_BUCKET; } else if (ob_len > buckets_length) { VLOG_WARN_RL(&bad_ofmsg_rl, "OpenFlow message bucket length " - "%zu exceeds remaining buckets data size %zu", + "%"PRIuSIZE" exceeds remaining buckets data size %"PRIuSIZE, ob_len, buckets_length); return OFPERR_OFPGMFC_BAD_BUCKET; } @@ -6101,7 +6201,7 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc *gd, ogds = ofpbuf_try_pull(msg, sizeof *ogds); if (!ogds) { - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %zu " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply has %"PRIuSIZE" " "leftover bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6111,7 +6211,7 @@ ofputil_decode_group_desc_reply(struct ofputil_group_desc *gd, length = ntohs(ogds->length); if (length < sizeof *ogds || length - sizeof *ogds > msg->size) { VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST11_GROUP_DESC reply claims invalid " - "length %zu", length); + "length %"PRIuSIZE, length); return OFPERR_OFPBRC_BAD_LEN; } @@ -6151,11 +6251,11 @@ ofputil_encode_group_mod(enum ofp_version ofp_version, case OFP13_VERSION: { b = ofpraw_alloc(OFPRAW_OFPT11_GROUP_MOD, ofp_version, 0); start_ogm = b->size; - ofpbuf_put_uninit(b, sizeof *ogm); + ofpbuf_put_zeros(b, sizeof *ogm); LIST_FOR_EACH (bucket, list_node, &gm->buckets) { start_bucket = b->size; - ofpbuf_put_uninit(b, sizeof *ob); + ofpbuf_put_zeros(b, sizeof *ob); if (bucket->ofpacts && bucket->ofpacts_len) { ofpacts_put_openflow_actions(bucket->ofpacts, bucket->ofpacts_len, b, @@ -6170,14 +6270,13 @@ ofputil_encode_group_mod(enum ofp_version ofp_version, ogm = ofpbuf_at_assert(b, start_ogm, sizeof *ogm); ogm->command = htons(gm->command); ogm->type = gm->type; - ogm->pad = 0; ogm->group_id = htonl(gm->group_id); break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return b; @@ -6191,6 +6290,8 @@ ofputil_decode_group_mod(const struct ofp_header *oh, { const struct ofp11_group_mod *ogm; struct ofpbuf msg; + struct ofputil_bucket *bucket; + enum ofperr err; ofpbuf_use_const(&msg, oh, ntohs(oh->length)); ofpraw_pull_assert(&msg); @@ -6200,7 +6301,32 @@ ofputil_decode_group_mod(const struct ofp_header *oh, gm->type = ogm->type; gm->group_id = ntohl(ogm->group_id); - return ofputil_pull_buckets(&msg, msg.size, oh->version, &gm->buckets); + err = ofputil_pull_buckets(&msg, msg.size, oh->version, &gm->buckets); + if (err) { + return err; + } + + LIST_FOR_EACH (bucket, list_node, &gm->buckets) { + switch (gm->type) { + case OFPGT11_ALL: + case OFPGT11_INDIRECT: + if (ofputil_bucket_has_liveness(bucket)) { + return OFPERR_OFPGMFC_WATCH_UNSUPPORTED; + } + break; + case OFPGT11_SELECT: + break; + case OFPGT11_FF: + if (!ofputil_bucket_has_liveness(bucket)) { + return OFPERR_OFPGMFC_INVALID_GROUP; + } + break; + default: + OVS_NOT_REACHED(); + } + } + + return 0; } /* Parse a queue status request message into 'oqsr'. @@ -6230,7 +6356,7 @@ ofputil_decode_queue_stats_request(const struct ofp_header *request, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -6265,7 +6391,7 @@ ofputil_encode_queue_stats_request(enum ofp_version ofp_version, break; } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } return request; @@ -6283,7 +6409,7 @@ ofputil_get_queue_stats_size(enum ofp_version ofp_version) case OFP13_VERSION: return sizeof(struct ofp13_queue_stats); default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -6397,11 +6523,11 @@ ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg) } return ofputil_queue_stats_from_ofp10(qs, qs10); } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } bad_len: - VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %zu leftover " + VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %"PRIuSIZE" leftover " "bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; } @@ -6472,6 +6598,6 @@ ofputil_append_queue_stat(struct list *replies, } default: - NOT_REACHED(); + OVS_NOT_REACHED(); } }