X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=c49b07988cca4903ce10b259eedd266e3ef1d5a1;hb=d4da3acc2a788d1c1b78c0bea6399660c7851f4a;hp=9c894d7882ab66e7e80d8c3f0c70383ad06944ed;hpb=9b45d7f5db91cdb41eb0a2124d92885d3b3edcc9;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 9c894d78..c49b0798 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -19,6 +19,7 @@ #include #include #include +#include "autopath.h" #include "byte-order.h" #include "classifier.h" #include "dynamic-string.h" @@ -1405,6 +1406,97 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, return 0; } +/* Converts abstract ofputil_flow_removed 'fr' into an OFPT_FLOW_REMOVED or + * NXT_FLOW_REMOVED message 'oh' according to 'flow_format', and returns the + * message. */ +struct ofpbuf * +ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, + enum nx_flow_format flow_format) +{ + struct ofpbuf *msg; + + if (flow_format == NXFF_OPENFLOW10 + || flow_format == NXFF_TUN_ID_FROM_COOKIE) { + struct ofp_flow_removed *ofr; + + ofr = make_openflow_xid(sizeof *ofr, OFPT_FLOW_REMOVED, htonl(0), + &msg); + ofputil_cls_rule_to_match(&fr->rule, flow_format, &ofr->match, + fr->cookie, &ofr->cookie); + ofr->priority = htons(fr->rule.priority); + ofr->reason = fr->reason; + ofr->duration_sec = htonl(fr->duration_sec); + ofr->duration_nsec = htonl(fr->duration_nsec); + ofr->idle_timeout = htons(fr->idle_timeout); + ofr->packet_count = htonll(fr->packet_count); + ofr->byte_count = htonll(fr->byte_count); + } else if (flow_format == NXFF_NXM) { + struct nx_flow_removed *nfr; + int match_len; + + make_nxmsg_xid(sizeof *nfr, NXT_FLOW_REMOVED, htonl(0), &msg); + match_len = nx_put_match(msg, &fr->rule); + + nfr = msg->data; + nfr->cookie = fr->cookie; + nfr->priority = htons(fr->rule.priority); + nfr->reason = fr->reason; + nfr->duration_sec = htonl(fr->duration_sec); + nfr->duration_nsec = htonl(fr->duration_nsec); + nfr->idle_timeout = htons(fr->idle_timeout); + nfr->match_len = htons(match_len); + nfr->packet_count = htonll(fr->packet_count); + nfr->byte_count = htonll(fr->byte_count); + } else { + NOT_REACHED(); + } + + return msg; +} + +/* Converts abstract ofputil_packet_in 'pin' into an OFPT_PACKET_IN message + * and returns the message. + * + * If 'rw_packet' is NULL, the caller takes ownership of the newly allocated + * returned ofpbuf. + * + * If 'rw_packet' is nonnull, then it must contain the same data as + * pin->packet. 'rw_packet' is allowed to be the same ofpbuf as pin->packet. + * It is modified in-place into an OFPT_PACKET_IN message according to 'pin', + * and then ofputil_encode_packet_in() returns 'rw_packet'. If 'rw_packet' has + * enough headroom to insert a "struct ofp_packet_in", this is more efficient + * than ofputil_encode_packet_in() because it does not copy the packet + * payload. */ +struct ofpbuf * +ofputil_encode_packet_in(const struct ofputil_packet_in *pin, + struct ofpbuf *rw_packet) +{ + int total_len = pin->packet->size; + struct ofp_packet_in *opi; + + if (rw_packet) { + if (pin->send_len < rw_packet->size) { + rw_packet->size = pin->send_len; + } + } else { + rw_packet = ofpbuf_clone_data_with_headroom( + pin->packet->data, MIN(pin->send_len, pin->packet->size), + offsetof(struct ofp_packet_in, data)); + } + + /* Add OFPT_PACKET_IN. */ + opi = ofpbuf_push_zeros(rw_packet, offsetof(struct ofp_packet_in, data)); + opi->header.version = OFP_VERSION; + opi->header.type = OFPT_PACKET_IN; + opi->total_len = htons(total_len); + opi->in_port = htons(pin->in_port); + opi->reason = pin->reason; + opi->buffer_id = htonl(pin->buffer_id); + update_openflow_length(rw_packet); + + return rw_packet; +} + /* Returns a string representing the message type of 'type'. The string is the * enumeration constant for the type, e.g. "OFPT_HELLO". For statistics * messages, the constant is followed by "request" or "reply", @@ -1772,49 +1864,17 @@ make_echo_reply(const struct ofp_header *rq) return out; } -const struct ofp_flow_stats * -flow_stats_first(struct flow_stats_iterator *iter, - const struct ofp_stats_reply *osr) +/* Converts the members of 'opp' from host to network byte order. */ +void +hton_ofp_phy_port(struct ofp_phy_port *opp) { - iter->pos = osr->body; - iter->end = osr->body + (ntohs(osr->header.length) - - offsetof(struct ofp_stats_reply, body)); - return flow_stats_next(iter); -} - -const struct ofp_flow_stats * -flow_stats_next(struct flow_stats_iterator *iter) -{ - ptrdiff_t bytes_left = iter->end - iter->pos; - const struct ofp_flow_stats *fs; - size_t length; - - if (bytes_left < sizeof *fs) { - if (bytes_left != 0) { - VLOG_WARN_RL(&bad_ofmsg_rl, - "%td leftover bytes in flow stats reply", bytes_left); - } - return NULL; - } - - fs = (const void *) iter->pos; - length = ntohs(fs->length); - if (length < sizeof *fs) { - VLOG_WARN_RL(&bad_ofmsg_rl, "flow stats length %zu is shorter than " - "min %zu", length, sizeof *fs); - return NULL; - } else if (length > bytes_left) { - VLOG_WARN_RL(&bad_ofmsg_rl, "flow stats length %zu but only %td " - "bytes left", length, bytes_left); - return NULL; - } else if ((length - sizeof *fs) % sizeof fs->actions[0]) { - VLOG_WARN_RL(&bad_ofmsg_rl, "flow stats length %zu has %zu bytes " - "left over in final action", length, - (length - sizeof *fs) % sizeof fs->actions[0]); - return NULL; - } - iter->pos += length; - return fs; + opp->port_no = htons(opp->port_no); + opp->config = htonl(opp->config); + opp->state = htonl(opp->state); + opp->curr = htonl(opp->curr); + opp->advertised = htonl(opp->advertised); + opp->supported = htonl(opp->supported); + opp->peer = htonl(opp->peer); } static int @@ -1955,6 +2015,14 @@ check_nicira_action(const union ofp_action *a, unsigned int len, } return multipath_check((const struct nx_action_multipath *) a); + case NXAST_AUTOPATH: + error = check_nx_action_exact_len( + nah, len, sizeof(struct nx_action_autopath)); + if (error) { + return error; + } + return autopath_check((const struct nx_action_autopath *) a); + case NXAST_SNAT__OBSOLETE: default: VLOG_WARN_RL(&bad_ofmsg_rl,