X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=lib%2Fofp-util.c;h=9dc5b2a5013b4a8ec672031fe6e482c2365504f6;hb=a23aab1fc2f66b63ba9b7e4b9c9a8f6d58c367d0;hp=933eaf430c7b45efb30c0c4419f254859a13f129;hpb=d98e60075528c3065ad453f7add4b30f22edcde3;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 933eaf43..9dc5b2a5 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -823,3 +823,93 @@ ofp_match_to_literal_string(const struct ofp_match *match) ntohs(match->tp_src), ntohs(match->tp_dst)); } + +static uint32_t +vendor_code_to_id(uint8_t code) +{ + switch (code) { +#define OFPUTIL_VENDOR(NAME, VENDOR_ID) case NAME: return VENDOR_ID; + default: + return UINT32_MAX; + } +} + +/* Creates and returns an OpenFlow message of type OFPT_ERROR with the error + * information taken from 'error', whose encoding must be as described in the + * large comment in ofp-util.h. If 'oh' is nonnull, then the error will use + * oh->xid as its transaction ID, and it will include up to the first 64 bytes + * of 'oh'. + * + * Returns NULL if 'error' is not an OpenFlow error code. */ +struct ofpbuf * +make_ofp_error_msg(int error, const struct ofp_header *oh) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + + struct ofpbuf *buf; + const void *data; + size_t len; + uint8_t vendor; + uint16_t type; + uint16_t code; + uint32_t xid; + + if (!is_ofp_error(error)) { + /* We format 'error' with strerror() here since it seems likely to be + * a system errno value. */ + VLOG_WARN_RL(&rl, "invalid OpenFlow error code %d (%s)", + error, strerror(error)); + return NULL; + } + + if (oh) { + xid = oh->xid; + data = oh; + len = ntohs(oh->length); + if (len > 64) { + len = 64; + } + } else { + xid = 0; + data = NULL; + len = 0; + } + + vendor = get_ofp_err_vendor(error); + type = get_ofp_err_type(error); + code = get_ofp_err_code(error); + if (vendor == OFPUTIL_VENDOR_OPENFLOW) { + struct ofp_error_msg *oem; + + oem = make_openflow_xid(len + sizeof *oem, OFPT_ERROR, xid, &buf); + oem->type = htons(type); + oem->code = htons(code); + } else { + struct ofp_error_msg *oem; + struct nx_vendor_error *ove; + uint32_t vendor_id; + + vendor_id = vendor_code_to_id(vendor); + if (vendor_id == UINT32_MAX) { + VLOG_WARN_RL(&rl, "error %x contains invalid vendor code %d", + error, vendor); + return NULL; + } + + oem = make_openflow_xid(len + sizeof *oem + sizeof *ove, + 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); + } + + if (len) { + ofpbuf_put(buf, data, len); + } + + return buf; +}