X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-util.c;h=933eaf430c7b45efb30c0c4419f254859a13f129;hb=48c3de13bee26106d8e708600904f2b20bd08818;hp=e990f0f44bd3d78ebcc91f9e699bdd7a9521f165;hpb=c1c9c9c4b636ab2acf2f75024c282a9a497ca9a9;p=sliver-openvswitch.git diff --git a/lib/ofp-util.c b/lib/ofp-util.c index e990f0f44..933eaf430 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -18,15 +18,15 @@ #include "ofp-print.h" #include #include +#include "byte-order.h" #include "ofp-util.h" #include "ofpbuf.h" #include "packets.h" #include "random.h" -#include "xtoxll.h" - -#define THIS_MODULE VLM_ofp_util #include "vlog.h" +VLOG_DEFINE_THIS_MODULE(ofp_util); + /* Rate limit for OpenFlow message parse errors. These always indicate a bug * in the peer and so there's not much point in showing a lot of them. */ static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -125,14 +125,14 @@ put_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid, /* Updates the 'length' field of the OpenFlow message in 'buffer' to * 'buffer->size'. */ void -update_openflow_length(struct ofpbuf *buffer) +update_openflow_length(struct ofpbuf *buffer) { struct ofp_header *oh = ofpbuf_at_assert(buffer, 0, sizeof *oh); - oh->length = htons(buffer->size); + oh->length = htons(buffer->size); } struct ofpbuf * -make_flow_mod(uint16_t command, const flow_t *flow, size_t actions_len) +make_flow_mod(uint16_t command, const struct flow *flow, size_t actions_len) { struct ofp_flow_mod *ofm; size_t size = sizeof *ofm + actions_len; @@ -161,7 +161,7 @@ make_flow_mod(uint16_t command, const flow_t *flow, size_t actions_len) } struct ofpbuf * -make_add_flow(const flow_t *flow, uint32_t buffer_id, +make_add_flow(const struct flow *flow, uint32_t buffer_id, uint16_t idle_timeout, size_t actions_len) { struct ofpbuf *out = make_flow_mod(OFPFC_ADD, flow, actions_len); @@ -173,7 +173,7 @@ make_add_flow(const flow_t *flow, uint32_t buffer_id, } struct ofpbuf * -make_del_flow(const flow_t *flow) +make_del_flow(const struct flow *flow) { struct ofpbuf *out = make_flow_mod(OFPFC_DELETE_STRICT, flow, 0); struct ofp_flow_mod *ofm = out->data; @@ -182,18 +182,23 @@ make_del_flow(const flow_t *flow) } struct ofpbuf * -make_add_simple_flow(const flow_t *flow, +make_add_simple_flow(const struct flow *flow, uint32_t buffer_id, uint16_t out_port, uint16_t idle_timeout) { - struct ofp_action_output *oao; - struct ofpbuf *buffer = make_add_flow(flow, buffer_id, idle_timeout, - sizeof *oao); - oao = ofpbuf_put_zeros(buffer, sizeof *oao); - oao->type = htons(OFPAT_OUTPUT); - oao->len = htons(sizeof *oao); - oao->port = htons(out_port); - return buffer; + if (out_port != OFPP_NONE) { + struct ofp_action_output *oao; + struct ofpbuf *buffer; + + buffer = make_add_flow(flow, buffer_id, idle_timeout, sizeof *oao); + oao = ofpbuf_put_zeros(buffer, sizeof *oao); + oao->type = htons(OFPAT_OUTPUT); + oao->len = htons(sizeof *oao); + oao->port = htons(out_port); + return buffer; + } else { + return make_add_flow(flow, buffer_id, idle_timeout, 0); + } } struct ofpbuf * @@ -259,12 +264,16 @@ struct ofpbuf * make_buffered_packet_out(uint32_t buffer_id, 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(NULL, buffer_id, in_port, - (struct ofp_action_header *) &action, 1); + 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. */ @@ -294,7 +303,7 @@ make_echo_reply(const struct ofp_header *rq) } static int -check_message_type(uint8_t got_type, uint8_t want_type) +check_message_type(uint8_t got_type, uint8_t want_type) { if (got_type != want_type) { char *want_type_name = ofp_message_type_to_string(want_type); @@ -555,6 +564,9 @@ check_nicira_action(const union ofp_action *a, unsigned int len) switch (ntohs(nah->subtype)) { case NXAST_RESUBMIT: case NXAST_SET_TUNNEL: + case NXAST_DROP_SPOOFED_ARP: + case NXAST_SET_QUEUE: + case NXAST_POP_QUEUE: return check_action_exact_len(a, len, 16); default: return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR_TYPE); @@ -575,7 +587,25 @@ check_action(const union ofp_action *a, unsigned int len, int max_ports) return check_output_port(ntohs(a->output.port), max_ports); case OFPAT_SET_VLAN_VID: + error = check_action_exact_len(a, len, 8); + if (error) { + return error; + } + if (a->vlan_vid.vlan_vid & ~htons(0xfff)) { + return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); + } + return 0; + case OFPAT_SET_VLAN_PCP: + error = check_action_exact_len(a, len, 8); + if (error) { + return error; + } + if (a->vlan_vid.vlan_vid & ~7) { + return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); + } + return 0; + case OFPAT_STRIP_VLAN: case OFPAT_SET_NW_SRC: case OFPAT_SET_NW_DST: @@ -607,9 +637,10 @@ int validate_actions(const union ofp_action *actions, size_t n_actions, int max_ports) { - const union ofp_action *a; + size_t i; - for (a = actions; a < &actions[n_actions]; ) { + for (i = 0; i < n_actions; ) { + const union ofp_action *a = &actions[i]; unsigned int len = ntohs(a->header.len); unsigned int n_slots = len / ACTION_ALIGNMENT; unsigned int slots_left = &actions[n_actions] - a; @@ -633,7 +664,7 @@ validate_actions(const union ofp_action *actions, size_t n_actions, if (error) { return error; } - a += n_slots; + i += n_slots; } return 0; } @@ -667,7 +698,7 @@ actions_first(struct actions_iterator *iter, const union ofp_action * actions_next(struct actions_iterator *iter) { - if (iter->pos < iter->end) { + if (iter->pos != iter->end) { const union ofp_action *a = iter->pos; unsigned int len = ntohs(a->header.len); iter->pos += len / ACTION_ALIGNMENT; @@ -680,7 +711,8 @@ actions_next(struct actions_iterator *iter) void normalize_match(struct ofp_match *m) { - enum { OFPFW_NW = OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO }; + enum { OFPFW_NW = (OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO + | OFPFW_NW_TOS) }; enum { OFPFW_TP = OFPFW_TP_SRC | OFPFW_TP_DST }; uint32_t wc; @@ -691,7 +723,7 @@ normalize_match(struct ofp_match *m) /* Can't sensibly match on network or transport headers if the * data link type is unknown. */ wc |= OFPFW_NW | OFPFW_TP; - m->nw_src = m->nw_dst = m->nw_proto = 0; + m->nw_src = m->nw_dst = m->nw_proto = m->nw_tos = 0; m->tp_src = m->tp_dst = 0; } else if (m->dl_type == htons(ETH_TYPE_IP)) { if (wc & OFPFW_NW_PROTO) { @@ -722,6 +754,11 @@ normalize_match(struct ofp_match *m) if (wc & OFPFW_NW_DST_MASK) { m->nw_dst &= flow_nw_bits_to_mask(wc, OFPFW_NW_DST_SHIFT); } + if (wc & OFPFW_NW_TOS) { + m->nw_tos = 0; + } else { + m->nw_tos &= IP_DSCP_MASK; + } } else if (m->dl_type == htons(ETH_TYPE_ARP)) { if (wc & OFPFW_NW_PROTO) { m->nw_proto = 0; @@ -732,12 +769,12 @@ normalize_match(struct ofp_match *m) if (wc & OFPFW_NW_DST_MASK) { m->nw_dst &= flow_nw_bits_to_mask(wc, OFPFW_NW_DST_SHIFT); } - m->tp_src = m->tp_dst = 0; + m->tp_src = m->tp_dst = m->nw_tos = 0; } else { /* Network and transport layer fields will always be extracted as * zeros, so we can do an exact-match on those values. */ wc &= ~(OFPFW_NW | OFPFW_TP); - m->nw_proto = m->nw_src = m->nw_dst = 0; + m->nw_proto = m->nw_src = m->nw_dst = m->nw_tos = 0; m->tp_src = m->tp_dst = 0; } if (wc & OFPFW_DL_SRC) { @@ -749,3 +786,40 @@ normalize_match(struct ofp_match *m) m->wildcards = htonl(wc); } +/* Returns a string that describes 'match' in a very literal way, without + * interpreting its contents except in a very basic fashion. The returned + * string is intended to be fixed-length, so that it is easy to see differences + * between two such strings if one is put above another. This is useful for + * describing changes made by normalize_match(). + * + * The caller must free the returned string (with free()). */ +char * +ofp_match_to_literal_string(const struct ofp_match *match) +{ + return xasprintf("wildcards=%#10"PRIx32" " + " in_port=%5"PRId16" " + " dl_src="ETH_ADDR_FMT" " + " dl_dst="ETH_ADDR_FMT" " + " dl_vlan=%5"PRId16" " + " dl_vlan_pcp=%3"PRId8" " + " dl_type=%#6"PRIx16" " + " nw_tos=%#4"PRIx8" " + " nw_proto=%#4"PRIx16" " + " nw_src=%#10"PRIx32" " + " nw_dst=%#10"PRIx32" " + " tp_src=%5"PRId16" " + " tp_dst=%5"PRId16, + ntohl(match->wildcards), + ntohs(match->in_port), + ETH_ADDR_ARGS(match->dl_src), + ETH_ADDR_ARGS(match->dl_dst), + ntohs(match->dl_vlan), + match->dl_vlan_pcp, + ntohs(match->dl_type), + match->nw_tos, + match->nw_proto, + ntohl(match->nw_src), + ntohl(match->nw_dst), + ntohs(match->tp_src), + ntohs(match->tp_dst)); +}