X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-util.c;h=7edae8735904416ba7c3dea3d341ce754e9f5ba0;hb=95216219538e532732df6d2f51c0d7b69addae8c;hp=33ff6ea7a3aa7cf7caaac4a1e90a66686d3928c7;hpb=78a3fff6c3b2f7943bcfd7301c666934834d2a0e;p=sliver-openvswitch.git diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 33ff6ea7a..7edae8735 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1913,7 +1913,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, fr->priority = ntohs(ofr->priority); fr->cookie = ofr->cookie; fr->reason = ofr->reason; - /* XXX: ofr->table_id is ignored */ + fr->table_id = ofr->table_id; fr->duration_sec = ntohl(ofr->duration_sec); fr->duration_nsec = ntohl(ofr->duration_nsec); fr->idle_timeout = ntohs(ofr->idle_timeout); @@ -1929,6 +1929,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, fr->priority = ntohs(ofr->priority); fr->cookie = ofr->cookie; fr->reason = ofr->reason; + fr->table_id = 255; fr->duration_sec = ntohl(ofr->duration_sec); fr->duration_nsec = ntohl(ofr->duration_nsec); fr->idle_timeout = ntohs(ofr->idle_timeout); @@ -1952,6 +1953,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr, fr->priority = ntohs(nfr->priority); fr->cookie = nfr->cookie; fr->reason = nfr->reason; + fr->table_id = 255; fr->duration_sec = ntohl(nfr->duration_sec); fr->duration_nsec = ntohl(nfr->duration_nsec); fr->idle_timeout = ntohs(nfr->idle_timeout); @@ -1985,7 +1987,7 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr, ofr->cookie = fr->cookie; ofr->priority = htons(fr->priority); ofr->reason = fr->reason; - ofr->table_id = 0; + ofr->table_id = fr->table_id; ofr->duration_sec = htonl(fr->duration_sec); ofr->duration_nsec = htonl(fr->duration_nsec); ofr->idle_timeout = htons(fr->idle_timeout); @@ -2279,7 +2281,6 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, const struct ofp_header *oh, struct ofpbuf *ofpacts) { - enum ofperr bad_in_port_err; enum ofpraw raw; struct ofpbuf b; @@ -2301,8 +2302,6 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, if (error) { return error; } - - bad_in_port_err = OFPERR_OFPBMC_BAD_VALUE; } else if (raw == OFPRAW_OFPT10_PACKET_OUT) { enum ofperr error; const struct ofp_packet_out *opo = ofpbuf_pull(&b, sizeof *opo); @@ -2314,8 +2313,6 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, if (error) { return error; } - - bad_in_port_err = OFPERR_NXBRC_BAD_IN_PORT; } else { NOT_REACHED(); } @@ -2324,7 +2321,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, && po->in_port != OFPP_NONE && po->in_port != OFPP_CONTROLLER) { VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16, po->in_port); - return bad_in_port_err; + return OFPERR_OFPBRC_BAD_PORT; } po->ofpacts = ofpacts->data; @@ -2938,6 +2935,143 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, return b; } +/* Table stats. */ + +static void +ofputil_put_ofp10_table_stats(const struct ofp12_table_stats *in, + struct ofpbuf *buf) +{ + struct wc_map { + enum ofp_flow_wildcards wc10; + enum oxm12_ofb_match_fields mf12; + }; + + static const struct wc_map wc_map[] = { + { OFPFW10_IN_PORT, OFPXMT12_OFB_IN_PORT }, + { OFPFW10_DL_VLAN, OFPXMT12_OFB_VLAN_VID }, + { OFPFW10_DL_SRC, OFPXMT12_OFB_ETH_SRC }, + { OFPFW10_DL_DST, OFPXMT12_OFB_ETH_DST}, + { OFPFW10_DL_TYPE, OFPXMT12_OFB_ETH_TYPE }, + { OFPFW10_NW_PROTO, OFPXMT12_OFB_IP_PROTO }, + { OFPFW10_TP_SRC, OFPXMT12_OFB_TCP_SRC }, + { OFPFW10_TP_DST, OFPXMT12_OFB_TCP_DST }, + { OFPFW10_NW_SRC_MASK, OFPXMT12_OFB_IPV4_SRC }, + { OFPFW10_NW_DST_MASK, OFPXMT12_OFB_IPV4_DST }, + { OFPFW10_DL_VLAN_PCP, OFPXMT12_OFB_VLAN_PCP }, + { OFPFW10_NW_TOS, OFPXMT12_OFB_IP_DSCP }, + }; + + struct ofp10_table_stats *out; + const struct wc_map *p; + + out = ofpbuf_put_uninit(buf, sizeof *out); + out->table_id = in->table_id; + strcpy(out->name, in->name); + out->wildcards = 0; + for (p = wc_map; p < &wc_map[ARRAY_SIZE(wc_map)]; p++) { + if (in->wildcards & htonll(1ULL << p->mf12)) { + out->wildcards |= htonl(p->wc10); + } + } + out->max_entries = in->max_entries; + out->active_count = in->active_count; + put_32aligned_be64(&out->lookup_count, in->lookup_count); + put_32aligned_be64(&out->matched_count, in->matched_count); +} + +static ovs_be32 +oxm12_to_ofp11_flow_match_fields(ovs_be64 oxm12) +{ + struct map { + enum ofp11_flow_match_fields fmf11; + enum oxm12_ofb_match_fields mf12; + }; + + static const struct map map[] = { + { OFPFMF11_IN_PORT, OFPXMT12_OFB_IN_PORT }, + { OFPFMF11_DL_VLAN, OFPXMT12_OFB_VLAN_VID }, + { OFPFMF11_DL_VLAN_PCP, OFPXMT12_OFB_VLAN_PCP }, + { OFPFMF11_DL_TYPE, OFPXMT12_OFB_ETH_TYPE }, + { OFPFMF11_NW_TOS, OFPXMT12_OFB_IP_DSCP }, + { OFPFMF11_NW_PROTO, OFPXMT12_OFB_IP_PROTO }, + { OFPFMF11_TP_SRC, OFPXMT12_OFB_TCP_SRC }, + { OFPFMF11_TP_DST, OFPXMT12_OFB_TCP_DST }, + { OFPFMF11_MPLS_LABEL, OFPXMT12_OFB_MPLS_LABEL }, + { OFPFMF11_MPLS_TC, OFPXMT12_OFB_MPLS_TC }, + /* I don't know what OFPFMF11_TYPE means. */ + { OFPFMF11_DL_SRC, OFPXMT12_OFB_ETH_SRC }, + { OFPFMF11_DL_DST, OFPXMT12_OFB_ETH_DST }, + { OFPFMF11_NW_SRC, OFPXMT12_OFB_IPV4_SRC }, + { OFPFMF11_NW_DST, OFPXMT12_OFB_IPV4_DST }, + { OFPFMF11_METADATA, OFPXMT12_OFB_METADATA }, + }; + + const struct map *p; + uint32_t fmf11; + + fmf11 = 0; + for (p = map; p < &map[ARRAY_SIZE(map)]; p++) { + if (oxm12 & htonll(1ULL << p->mf12)) { + fmf11 |= p->fmf11; + } + } + return htonl(fmf11); +} + +static void +ofputil_put_ofp11_table_stats(const struct ofp12_table_stats *in, + struct ofpbuf *buf) +{ + struct ofp11_table_stats *out; + + out = ofpbuf_put_uninit(buf, sizeof *out); + out->table_id = in->table_id; + strcpy(out->name, in->name); + out->wildcards = oxm12_to_ofp11_flow_match_fields(in->wildcards); + out->match = oxm12_to_ofp11_flow_match_fields(in->match); + out->instructions = in->instructions; + out->write_actions = in->write_actions; + out->apply_actions = in->apply_actions; + out->config = in->config; + out->max_entries = in->max_entries; + out->active_count = in->active_count; + out->lookup_count = in->lookup_count; + out->matched_count = in->matched_count; +} + +struct ofpbuf * +ofputil_encode_table_stats_reply(const struct ofp12_table_stats stats[], int n, + const struct ofp_header *request) +{ + struct ofpbuf *reply; + int i; + + reply = ofpraw_alloc_stats_reply(request, n * sizeof *stats); + + switch ((enum ofp_version) request->version) { + case OFP10_VERSION: + for (i = 0; i < n; i++) { + ofputil_put_ofp10_table_stats(&stats[i], reply); + } + break; + + case OFP11_VERSION: + for (i = 0; i < n; i++) { + ofputil_put_ofp11_table_stats(&stats[i], reply); + } + break; + + case OFP12_VERSION: + ofpbuf_put(reply, stats, n * sizeof *stats); + break; + + default: + NOT_REACHED(); + } + + return reply; +} + /* ofputil_flow_monitor_request */ /* Converts an NXST_FLOW_MONITOR request in 'msg' into an abstract @@ -3404,36 +3538,72 @@ ofputil_check_output_port(uint16_t port, int max_ports) OFPUTIL_NAMED_PORT(LOCAL) \ OFPUTIL_NAMED_PORT(NONE) -/* Checks whether 's' is the string representation of an OpenFlow port number, - * either as an integer or a string name (e.g. "LOCAL"). If it is, stores the - * number in '*port' and returns true. Otherwise, returns false. */ -bool -ofputil_port_from_string(const char *name, uint16_t *port) +/* Returns the port number represented by 's', which may be an integer or, for + * reserved ports, the standard OpenFlow name for the port (e.g. "LOCAL"). + * + * Returns 0 if 's' is not a valid OpenFlow port number or name. The caller + * should issue an error message in this case, because this function usually + * does not. (This gives the caller an opportunity to look up the port name + * another way, e.g. by contacting the switch and listing the names of all its + * ports). + * + * This function accepts OpenFlow 1.0 port numbers. It also accepts a subset + * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit + * range as described in include/openflow/openflow-1.1.h. */ +uint16_t +ofputil_port_from_string(const char *s) { - struct pair { - const char *name; - uint16_t value; - }; - static const struct pair pairs[] = { + unsigned int port32; + + if (str_to_uint(s, 10, &port32)) { + if (port32 == 0) { + VLOG_WARN("port 0 is not a valid OpenFlow port number"); + return 0; + } else if (port32 < OFPP_MAX) { + return port32; + } else if (port32 < OFPP_FIRST_RESV) { + VLOG_WARN("port %u is a reserved OF1.0 port number that will " + "be translated to %u when talking to an OF1.1 or " + "later controller", port32, port32 + OFPP11_OFFSET); + return port32; + } else if (port32 <= OFPP_LAST_RESV) { + struct ds s; + + ds_init(&s); + ofputil_format_port(port32, &s); + VLOG_WARN_ONCE("referring to port %s as %u is deprecated for " + "compatibility with future versions of OpenFlow", + ds_cstr(&s), port32); + ds_destroy(&s); + + return port32; + } else if (port32 < OFPP11_MAX) { + VLOG_WARN("port %u is outside the supported range 0 through " + "%"PRIx16"or 0x%x through 0x%"PRIx32, port32, + UINT16_MAX, (unsigned int) OFPP11_MAX, UINT32_MAX); + return 0; + } else { + return port32 - OFPP11_OFFSET; + } + } else { + struct pair { + const char *name; + uint16_t value; + }; + static const struct pair pairs[] = { #define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME}, - OFPUTIL_NAMED_PORTS + OFPUTIL_NAMED_PORTS #undef OFPUTIL_NAMED_PORT - }; - static const int n_pairs = ARRAY_SIZE(pairs); - int i; + }; + const struct pair *p; - if (str_to_int(name, 0, &i) && i >= 0 && i < UINT16_MAX) { - *port = i; - return true; - } - - for (i = 0; i < n_pairs; i++) { - if (!strcasecmp(name, pairs[i].name)) { - *port = pairs[i].value; - return true; + for (p = pairs; p < &pairs[ARRAY_SIZE(pairs)]; p++) { + if (!strcasecmp(s, p->name)) { + return p->value; + } } + return 0; } - return false; } /* Appends to 's' a string representation of the OpenFlow port number 'port'. @@ -3497,10 +3667,9 @@ ofputil_action_code_from_name(const char *name) { static const char *names[OFPUTIL_N_ACTIONS] = { NULL, -#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME, -#define OFPAT11_ACTION(ENUM, STRUCT, NAME) NAME, -#define OFPAT12_ACTION(ENUM, STRUCT, NAME) NAME, -#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME, +#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME, +#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME, +#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME, #include "ofp-util.def" }; @@ -3526,10 +3695,10 @@ ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf) case OFPUTIL_ACTION_INVALID: NOT_REACHED(); -#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \ +#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \ + case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf); +#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \ case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf); -#define OFPAT11_ACTION OFPAT10_ACTION -#define OFPAT12_ACTION OFPAT10_ACTION #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \ case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf); #include "ofp-util.def" @@ -3553,8 +3722,8 @@ ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf) ofputil_init_##ENUM(s); \ return s; \ } -#define OFPAT11_ACTION OFPAT10_ACTION -#define OFPAT12_ACTION OFPAT10_ACTION +#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \ + OFPAT10_ACTION(ENUM, STRUCT, NAME) #define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \ void \ ofputil_init_##ENUM(struct STRUCT *s) \