X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=ffdccda43ef1f0d5f7de19dbbe0fc6641137ae34;hb=dd1ba5b3f4425c8eba008d1a93b044da63466812;hp=ef8c4706c6cb476bda04a894c7a3d2665582bacd;hpb=73f3356323a0f94ffb5b58af4e0312e715b7a3e2;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index ef8c4706..ffdccda4 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -396,6 +396,14 @@ ofputil_decode_vendor(const struct ofp_header *oh, size_t length, { OFPUTIL_NXT_FLOW_MOD_TABLE_ID, OFP10_VERSION, NXT_FLOW_MOD_TABLE_ID, "NXT_FLOW_MOD_TABLE_ID", sizeof(struct nx_flow_mod_table_id), 0 }, + + { OFPUTIL_NXT_FLOW_AGE, OFP10_VERSION, + NXT_FLOW_AGE, "NXT_FLOW_AGE", + sizeof(struct nicira_header), 0 }, + + { OFPUTIL_NXT_SET_ASYNC_CONFIG, OFP10_VERSION, + NXT_SET_ASYNC_CONFIG, "NXT_SET_ASYNC_CONFIG", + sizeof(struct nx_async_config), 0 }, }; static const struct ofputil_msg_category nxt_category = { @@ -1307,11 +1315,18 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr, * iterates through the replies. The caller must initially leave 'msg''s layer * pointers null and not modify them between calls. * + * Most switches don't send the values needed to populate fs->idle_age and + * fs->hard_age, so those members will usually be set to 0. If the switch from + * which 'msg' originated is known to implement NXT_FLOW_AGE, then pass + * 'flow_age_extension' as true so that the contents of 'msg' determine the + * 'idle_age' and 'hard_age' members in 'fs'. + * * Returns 0 if successful, EOF if no replies were left in this 'msg', * otherwise a positive errno value. */ int ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, - struct ofpbuf *msg) + struct ofpbuf *msg, + bool flow_age_extension) { const struct ofputil_msg_type *type; int code; @@ -1362,6 +1377,8 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, 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->packet_count = ntohll(get_32aligned_be64(&ofs->packet_count)); fs->byte_count = ntohll(get_32aligned_be64(&ofs->byte_count)); } else if (code == OFPUTIL_NXST_FLOW_REPLY) { @@ -1399,6 +1416,16 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs, fs->duration_nsec = ntohl(nfs->duration_nsec); fs->idle_timeout = ntohs(nfs->idle_timeout); fs->hard_timeout = ntohs(nfs->hard_timeout); + fs->idle_age = -1; + fs->hard_age = -1; + if (flow_age_extension) { + if (nfs->idle_age) { + fs->idle_age = ntohs(nfs->idle_age) - 1; + } + if (nfs->hard_age) { + fs->hard_age = ntohs(nfs->hard_age) - 1; + } + } fs->packet_count = ntohll(nfs->packet_count); fs->byte_count = ntohll(nfs->byte_count); } else { @@ -1467,8 +1494,13 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs, nfs->priority = htons(fs->rule.priority); nfs->idle_timeout = htons(fs->idle_timeout); nfs->hard_timeout = htons(fs->hard_timeout); + nfs->idle_age = htons(fs->idle_age < 0 ? 0 + : fs->idle_age < UINT16_MAX ? fs->idle_age + 1 + : UINT16_MAX); + nfs->hard_age = htons(fs->hard_age < 0 ? 0 + : fs->hard_age < UINT16_MAX ? fs->hard_age + 1 + : UINT16_MAX); nfs->match_len = htons(nx_put_match(msg, &fs->rule, 0, 0)); - memset(nfs->pad2, 0, sizeof nfs->pad2); nfs->cookie = fs->cookie; nfs->packet_count = htonll(fs->packet_count); nfs->byte_count = htonll(fs->byte_count); @@ -1752,6 +1784,70 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin, return packet; } +enum ofperr +ofputil_decode_packet_out(struct ofputil_packet_out *po, + const struct ofp_packet_out *opo) +{ + enum ofperr error; + struct ofpbuf b; + + po->buffer_id = ntohl(opo->buffer_id); + po->in_port = ntohs(opo->in_port); + if (po->in_port >= OFPP_MAX && po->in_port != OFPP_LOCAL + && po->in_port != OFPP_NONE) { + VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16, + po->in_port); + return OFPERR_NXBRC_BAD_IN_PORT; + } + + ofpbuf_use_const(&b, opo, ntohs(opo->header.length)); + ofpbuf_pull(&b, sizeof *opo); + + error = ofputil_pull_actions(&b, ntohs(opo->actions_len), + &po->actions, &po->n_actions); + if (error) { + return error; + } + + if (po->buffer_id == UINT32_MAX) { + po->packet = b.data; + po->packet_len = b.size; + } else { + po->packet = NULL; + po->packet_len = 0; + } + + return 0; +} + +struct ofpbuf * +ofputil_encode_packet_out(const struct ofputil_packet_out *po) +{ + struct ofp_packet_out *opo; + size_t actions_len; + struct ofpbuf *msg; + size_t size; + + actions_len = po->n_actions * sizeof *po->actions; + size = sizeof *opo + actions_len; + if (po->buffer_id == UINT32_MAX) { + size += po->packet_len; + } + + msg = ofpbuf_new(size); + opo = put_openflow(sizeof *opo, OFPT_PACKET_OUT, msg); + opo->buffer_id = htonl(po->buffer_id); + opo->in_port = htons(po->in_port); + opo->actions_len = htons(actions_len); + ofpbuf_put(msg, po->actions, actions_len); + if (po->buffer_id == UINT32_MAX) { + ofpbuf_put(msg, po->packet, po->packet_len); + } + update_openflow_length(msg); + + return msg; +} + /* 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", @@ -2130,59 +2226,6 @@ make_packet_in(uint32_t buffer_id, uint16_t in_port, uint8_t reason, return buf; } -struct ofpbuf * -make_packet_out(const struct ofpbuf *packet, uint32_t buffer_id, - uint16_t in_port, - const struct ofp_action_header *actions, size_t n_actions) -{ - size_t actions_len = n_actions * sizeof *actions; - struct ofp_packet_out *opo; - size_t size = sizeof *opo + actions_len + (packet ? packet->size : 0); - struct ofpbuf *out = ofpbuf_new(size); - - opo = ofpbuf_put_uninit(out, sizeof *opo); - opo->header.version = OFP_VERSION; - opo->header.type = OFPT_PACKET_OUT; - opo->header.length = htons(size); - opo->header.xid = htonl(0); - opo->buffer_id = htonl(buffer_id); - opo->in_port = htons(in_port); - opo->actions_len = htons(actions_len); - ofpbuf_put(out, actions, actions_len); - if (packet) { - ofpbuf_put(out, packet->data, packet->size); - } - return out; -} - -struct ofpbuf * -make_unbuffered_packet_out(const struct ofpbuf *packet, - uint16_t in_port, uint16_t out_port) -{ - struct ofp_action_output action; - action.type = htons(OFPAT_OUTPUT); - action.len = htons(sizeof action); - action.port = htons(out_port); - return make_packet_out(packet, UINT32_MAX, in_port, - (struct ofp_action_header *) &action, 1); -} - -struct ofpbuf * -make_buffered_packet_out(uint32_t buffer_id, - uint16_t in_port, uint16_t out_port) -{ - if (out_port != OFPP_NONE) { - struct ofp_action_output action; - action.type = htons(OFPAT_OUTPUT); - action.len = htons(sizeof action); - action.port = htons(out_port); - return make_packet_out(NULL, buffer_id, in_port, - (struct ofp_action_header *) &action, 1); - } else { - return make_packet_out(NULL, buffer_id, in_port, NULL, 0); - } -} - /* Creates and returns an OFPT_ECHO_REQUEST message with an empty payload. */ struct ofpbuf * make_echo_request(void) @@ -2209,6 +2252,15 @@ make_echo_reply(const struct ofp_header *rq) return out; } +struct ofpbuf * +ofputil_encode_barrier_request(void) +{ + struct ofpbuf *msg; + + make_openflow(sizeof(struct ofp_header), OFPT_BARRIER_REQUEST, &msg); + return msg; +} + const char * ofputil_frag_handling_to_string(enum ofp_config_flags flags) { @@ -2456,6 +2508,7 @@ validate_actions(const union ofp_action *actions, size_t n_actions, case OFPUTIL_NXAST_SET_TUNNEL64: case OFPUTIL_NXAST_EXIT: case OFPUTIL_NXAST_DEC_TTL: + case OFPUTIL_NXAST_FIN_TIMEOUT: break; }