X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=81a5dadf5a597e0367e229ce4784098b74d515d2;hb=d530fcd2425c2443c1a1c093903b6932c4c5814c;hp=c95e7c6d7f9be37f01500af3820db67dbbe8a068;hpb=3a75cda939c7155ec9e12dd747983e37dee9b3e6;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index c95e7c6d..81a5dadf 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -19,6 +19,7 @@ #include #include #include "byte-order.h" +#include "nx-match.h" #include "ofp-util.h" #include "ofpbuf.h" #include "packets.h" @@ -59,6 +60,14 @@ make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **bufferp) return put_openflow_xid(openflow_len, type, alloc_xid(), *bufferp); } +/* Similar to make_openflow() but creates a Nicira vendor extension message + * with the specific 'subtype'. 'subtype' should be in host byte order. */ +void * +make_nxmsg(size_t openflow_len, uint32_t subtype, struct ofpbuf **bufferp) +{ + return make_nxmsg_xid(openflow_len, subtype, alloc_xid(), bufferp); +} + /* Allocates and stores in '*bufferp' a new ofpbuf with a size of * 'openflow_len', starting with an OpenFlow header with the given 'type' and * transaction id 'xid'. Allocated bytes beyond the header, if any, are @@ -80,6 +89,19 @@ make_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid, return put_openflow_xid(openflow_len, type, xid, *bufferp); } +/* Similar to make_openflow_xid() but creates a Nicira vendor extension message + * with the specific 'subtype'. 'subtype' should be in host byte order. */ +void * +make_nxmsg_xid(size_t openflow_len, uint32_t subtype, uint32_t xid, + struct ofpbuf **bufferp) +{ + struct nicira_header *nxh = make_openflow_xid(openflow_len, OFPT_VENDOR, + xid, bufferp); + nxh->vendor = htonl(NX_VENDOR_ID); + nxh->subtype = htonl(subtype); + return nxh; +} + /* Appends 'openflow_len' bytes to 'buffer', starting with an OpenFlow header * with the given 'type' and an arbitrary transaction id. Allocated bytes * beyond the header, if any, are zeroed. @@ -394,50 +416,6 @@ check_ofp_message_array(const struct ofp_header *msg, uint8_t type, return 0; } -int -check_ofp_packet_out(const struct ofp_header *oh, struct ofpbuf *data, - int *n_actionsp, int max_ports) -{ - const struct ofp_packet_out *opo; - unsigned int actions_len, n_actions; - size_t extra; - int error; - - *n_actionsp = 0; - error = check_ofp_message_array(oh, OFPT_PACKET_OUT, - sizeof *opo, 1, &extra); - if (error) { - return error; - } - opo = (const struct ofp_packet_out *) oh; - - actions_len = ntohs(opo->actions_len); - if (actions_len > extra) { - VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %u bytes of actions " - "but message has room for only %zu bytes", - actions_len, extra); - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); - } - if (actions_len % sizeof(union ofp_action)) { - VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out claims %u bytes of actions, " - "which is not a multiple of %zu", - actions_len, sizeof(union ofp_action)); - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); - } - - n_actions = actions_len / sizeof(union ofp_action); - error = validate_actions((const union ofp_action *) opo->actions, - n_actions, max_ports); - if (error) { - return error; - } - - data->data = (void *) &opo->actions[n_actions]; - data->size = extra - actions_len; - *n_actionsp = n_actions; - return 0; -} - const struct ofp_flow_stats * flow_stats_first(struct flow_stats_iterator *iter, const struct ofp_stats_reply *osr) @@ -550,9 +528,11 @@ check_enqueue_action(const union ofp_action *a, unsigned int len, } static int -check_nicira_action(const union ofp_action *a, unsigned int len) +check_nicira_action(const union ofp_action *a, unsigned int len, + const struct flow *flow) { const struct nx_action_header *nah; + int error; if (len < 16) { VLOG_DBG_RL(&bad_ofmsg_rl, @@ -568,13 +548,28 @@ check_nicira_action(const union ofp_action *a, unsigned int len) case NXAST_SET_QUEUE: case NXAST_POP_QUEUE: return check_action_exact_len(a, len, 16); + case NXAST_REG_MOVE: + error = check_action_exact_len(a, len, + sizeof(struct nx_action_reg_move)); + if (error) { + return error; + } + return nxm_check_reg_move((const struct nx_action_reg_move *) a, flow); + case NXAST_REG_LOAD: + error = check_action_exact_len(a, len, + sizeof(struct nx_action_reg_load)); + if (error) { + return error; + } + return nxm_check_reg_load((const struct nx_action_reg_load *) a, flow); default: return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE); } } static int -check_action(const union ofp_action *a, unsigned int len, int max_ports) +check_action(const union ofp_action *a, unsigned int len, + const struct flow *flow, int max_ports) { int error; @@ -620,7 +615,7 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports) case OFPAT_VENDOR: return (a->vendor.vendor == htonl(NX_VENDOR_ID) - ? check_nicira_action(a, len) + ? check_nicira_action(a, len, flow) : ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR)); case OFPAT_ENQUEUE: @@ -635,7 +630,7 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports) int validate_actions(const union ofp_action *actions, size_t n_actions, - int max_ports) + const struct flow *flow, int max_ports) { size_t i; @@ -660,7 +655,7 @@ validate_actions(const union ofp_action *actions, size_t n_actions, return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } - error = check_action(a, len, max_ports); + error = check_action(a, len, flow, max_ports); if (error) { return error; } @@ -888,7 +883,7 @@ make_ofp_error_msg(int error, const struct ofp_header *oh) oem->code = htons(code); } else { struct ofp_error_msg *oem; - struct nx_vendor_error *ove; + struct nx_vendor_error *nve; uint32_t vendor_id; vendor_id = vendor_code_to_id(vendor); @@ -898,15 +893,15 @@ make_ofp_error_msg(int error, const struct ofp_header *oh) return NULL; } - oem = make_openflow_xid(len + sizeof *oem + sizeof *ove, + oem = make_openflow_xid(len + sizeof *oem + sizeof *nve, OFPT_ERROR, xid, &buf); oem->type = htons(NXET_VENDOR); oem->code = htons(NXVC_VENDOR_ERROR); - ove = ofpbuf_put_uninit(buf, sizeof *ove); - ove->vendor = htonl(vendor_id); - ove->type = htons(type); - ove->code = htons(code); + nve = ofpbuf_put_uninit(buf, sizeof *nve); + nve->vendor = htonl(vendor_id); + nve->type = htons(type); + nve->code = htons(code); } if (len) { @@ -915,3 +910,41 @@ make_ofp_error_msg(int error, const struct ofp_header *oh) return buf; } + +/* Attempts to pull 'actions_len' bytes from the front of 'b'. Returns 0 if + * successful, otherwise an OpenFlow error. + * + * If successful, the first action is stored in '*actionsp' and the number of + * "union ofp_action" size elements into '*n_actionsp'. Otherwise NULL and 0 + * are stored, respectively. + * + * This function does not check that the actions are valid (the caller should + * do so, with validate_actions()). The caller is also responsible for making + * sure that 'b->data' is initially aligned appropriately for "union + * ofp_action". */ +int +ofputil_pull_actions(struct ofpbuf *b, unsigned int actions_len, + union ofp_action **actionsp, size_t *n_actionsp) +{ + if (actions_len % ACTION_ALIGNMENT != 0) { + VLOG_DBG_RL(&bad_ofmsg_rl, "OpenFlow message actions length %u " + "is not a multiple of %d", actions_len, ACTION_ALIGNMENT); + goto error; + } + + *actionsp = ofpbuf_try_pull(b, actions_len); + if (*actionsp == NULL) { + VLOG_DBG_RL(&bad_ofmsg_rl, "OpenFlow message actions length %u " + "exceeds remaining message length (%zu)", + actions_len, b->size); + goto error; + } + + *n_actionsp = actions_len / ACTION_ALIGNMENT; + return 0; + +error: + *actionsp = NULL; + *n_actionsp = 0; + return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); +}