X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fnx-match.c;h=3bb71e2e41d4841c5e4383752d51aa6047567dbb;hb=015ac88281952a1b43ad46e9e6300db1c6e3647b;hp=bfead6808e2781f28c61701de9447067906a3e09;hpb=7fa0f73fb284b4406bcd085ee62552891b3fa6cd;p=sliver-openvswitch.git diff --git a/lib/nx-match.c b/lib/nx-match.c index bfead6808..3bb71e2e4 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -148,7 +148,7 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict, error = OFPERR_OFPBMC_BAD_PREREQ; } else if (!mf_is_all_wild(mf, &match->wc)) { error = OFPERR_OFPBMC_DUP_FIELD; - } else if (header != OXM_OF_IN_PORT) { + } else { unsigned int width = mf->n_bytes; union mf_value value; @@ -170,17 +170,6 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict, mf_set(mf, &value, &mask, match); } } - } else { - /* Special case for 32bit ports when using OXM, - * ports are 16 bits wide otherwise. */ - ovs_be32 port_of11; - uint16_t port; - - memcpy(&port_of11, p + 4, sizeof port_of11); - error = ofputil_port_from_ofp11(port_of11, &port); - if (!error) { - match_set_in_port(match, port); - } } /* Check if the match is for a cookie rather than a classifier rule. */ @@ -291,7 +280,7 @@ oxm_pull_match__(struct ofpbuf *b, bool strict, struct match *match) strict, match, NULL, NULL); } -/* Parses the oxm formatted match description preceeded by a struct ofp11_match +/* Parses the oxm formatted match description preceded by a struct ofp11_match * in 'b' with length 'match_len'. Stores the result in 'match'. * * Fails with an error when encountering unknown OXM headers. @@ -517,8 +506,11 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match, nxm_put_frag(b, match); if (match->wc.masks.nw_tos & IP_DSCP_MASK) { - nxm_put_8(b, oxm ? OXM_OF_IP_DSCP : NXM_OF_IP_TOS, - flow->nw_tos & IP_DSCP_MASK); + if (oxm) { + nxm_put_8(b, OXM_OF_IP_DSCP, flow->nw_tos >> 2); + } else { + nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK); + } } if (match->wc.masks.nw_tos & IP_ECN_MASK) { @@ -543,6 +535,11 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match, flow->tp_src, match->wc.masks.tp_src); nxm_put_16m(b, oxm ? OXM_OF_UDP_DST : NXM_OF_UDP_DST, flow->tp_dst, match->wc.masks.tp_dst); + } else if (flow->nw_proto == IPPROTO_SCTP) { + nxm_put_16m(b, OXM_OF_SCTP_SRC, flow->tp_src, + match->wc.masks.tp_src); + nxm_put_16m(b, OXM_OF_SCTP_DST, flow->tp_dst, + match->wc.masks.tp_dst); } else if (flow->nw_proto == icmp_proto) { if (match->wc.masks.tp_src) { nxm_put_8(b, icmp_type, ntohs(flow->tp_src)); @@ -576,12 +573,12 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match, BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20); /* Metadata. */ - if (match->wc.masks.in_port) { - uint16_t in_port = flow->in_port; + if (match->wc.masks.in_port.ofp_port) { + ofp_port_t in_port = flow->in_port.ofp_port; if (oxm) { nxm_put_32(b, OXM_OF_IN_PORT, ofputil_port_to_ofp11(in_port)); } else { - nxm_put_16(b, NXM_OF_IN_PORT, htons(in_port)); + nxm_put_16(b, NXM_OF_IN_PORT, htons(ofp_to_u16(in_port))); } } @@ -687,7 +684,13 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match, /* Tunnel ID. */ nxm_put_64m(b, oxm ? OXM_OF_TUNNEL_ID : NXM_NX_TUN_ID, - flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id); + flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id); + + /* Other tunnel metadata. */ + nxm_put_32m(b, NXM_NX_TUN_IPV4_SRC, + flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src); + nxm_put_32m(b, NXM_NX_TUN_IPV4_DST, + flow->tunnel.ip_dst, match->wc.masks.tunnel.ip_dst); /* Registers. */ for (i = 0; i < FLOW_N_REGS; i++) { @@ -695,6 +698,10 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match, htonl(flow->regs[i]), htonl(match->wc.masks.regs[i])); } + /* Mark. */ + nxm_put_32m(b, NXM_NX_PKT_MARK, htonl(flow->pkt_mark), + htonl(match->wc.masks.pkt_mark)); + /* OpenFlow 1.1+ Metadata. */ nxm_put_64m(b, OXM_OF_METADATA, flow->metadata, match->wc.masks.metadata); @@ -746,7 +753,7 @@ oxm_put_match(struct ofpbuf *b, const struct match *match) match_len = nx_put_raw(b, true, match, cookie, cookie_mask) + sizeof *omh; ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len); - omh = (struct ofp11_match_header *)((char *)b->data + start_len); + omh = ofpbuf_at(b, start_len, sizeof *omh); omh->type = htons(OFPMT_OXM); omh->length = htons(match_len); @@ -809,9 +816,9 @@ nx_match_to_string(const uint8_t *p, unsigned int match_len) } char * -oxm_match_to_string(const uint8_t *p, unsigned int match_len) +oxm_match_to_string(const struct ofpbuf *p, unsigned int match_len) { - const struct ofp11_match_header *omh = (struct ofp11_match_header *)p; + const struct ofp11_match_header *omh = p->data; uint16_t match_len_; struct ds s; @@ -839,7 +846,8 @@ oxm_match_to_string(const uint8_t *p, unsigned int match_len) goto err; } - return nx_match_to_string(p + sizeof *omh, match_len - sizeof *omh); + return nx_match_to_string(ofpbuf_at(p, sizeof *omh, 0), + match_len - sizeof *omh); err: return ds_steal_cstr(&s); @@ -999,57 +1007,74 @@ oxm_match_from_string(const char *s, struct ofpbuf *b) match_len = nx_match_from_string_raw(s, b) + sizeof *omh; ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len); - omh = (struct ofp11_match_header *)((char *)b->data + start_len); + omh = ofpbuf_at(b, start_len, sizeof *omh); omh->type = htons(OFPMT_OXM); omh->length = htons(match_len); return match_len; } -void +/* Parses 's' as a "move" action, in the form described in ovs-ofctl(8), into + * '*move'. + * + * Returns NULL if successful, otherwise a malloc()'d string describing the + * error. The caller is responsible for freeing the returned string. */ +char * WARN_UNUSED_RESULT nxm_parse_reg_move(struct ofpact_reg_move *move, const char *s) { const char *full_s = s; + char *error; - s = mf_parse_subfield(&move->src, s); + error = mf_parse_subfield__(&move->src, &s); + if (error) { + return error; + } if (strncmp(s, "->", 2)) { - ovs_fatal(0, "%s: missing `->' following source", full_s); + return xasprintf("%s: missing `->' following source", full_s); } s += 2; - s = mf_parse_subfield(&move->dst, s); - if (*s != '\0') { - ovs_fatal(0, "%s: trailing garbage following destination", full_s); + error = mf_parse_subfield(&move->dst, s); + if (error) { + return error; } if (move->src.n_bits != move->dst.n_bits) { - ovs_fatal(0, "%s: source field is %d bits wide but destination is " - "%d bits wide", full_s, - move->src.n_bits, move->dst.n_bits); + return xasprintf("%s: source field is %d bits wide but destination is " + "%d bits wide", full_s, + move->src.n_bits, move->dst.n_bits); } + return NULL; } -void +/* Parses 's' as a "load" action, in the form described in ovs-ofctl(8), into + * '*load'. + * + * Returns NULL if successful, otherwise a malloc()'d string describing the + * error. The caller is responsible for freeing the returned string. */ +char * WARN_UNUSED_RESULT nxm_parse_reg_load(struct ofpact_reg_load *load, const char *s) { const char *full_s = s; uint64_t value = strtoull(s, (char **) &s, 0); + char *error; if (strncmp(s, "->", 2)) { - ovs_fatal(0, "%s: missing `->' following value", full_s); + return xasprintf("%s: missing `->' following value", full_s); } s += 2; - s = mf_parse_subfield(&load->dst, s); - if (*s != '\0') { - ovs_fatal(0, "%s: trailing garbage following destination", full_s); + error = mf_parse_subfield(&load->dst, s); + if (error) { + return error; } if (load->dst.n_bits < 64 && (value >> load->dst.n_bits) != 0) { - ovs_fatal(0, "%s: value %"PRIu64" does not fit into %d bits", - full_s, value, load->dst.n_bits); + return xasprintf("%s: value %"PRIu64" does not fit into %d bits", + full_s, value, load->dst.n_bits); } load->subvalue.be64[0] = htonll(0); load->subvalue.be64[1] = htonll(value); + return NULL; } /* nxm_format_reg_move(), nxm_format_reg_load(). */ @@ -1148,19 +1173,19 @@ nxm_reg_load_from_openflow12_set_field( /* ofp12_action_set_field is padded to 64 bits by zero */ if (oasf_len != ROUND_UP(sizeof(*oasf) + oxm_length, 8)) { - return OFPERR_OFPBAC_BAD_ARGUMENT; + return OFPERR_OFPBAC_BAD_SET_LEN; } if (!is_all_zeros((const uint8_t *)(oasf) + sizeof *oasf + oxm_length, oasf_len - oxm_length - sizeof *oasf)) { - return OFPERR_OFPBAC_BAD_ARGUMENT; + return OFPERR_OFPBAC_BAD_SET_ARGUMENT; } if (NXM_HASMASK(oxm_header)) { - return OFPERR_OFPBAC_BAD_ARGUMENT; + return OFPERR_OFPBAC_BAD_SET_TYPE; } mf = mf_from_nxm_header(oxm_header); if (!mf) { - return OFPERR_OFPBAC_BAD_ARGUMENT; + return OFPERR_OFPBAC_BAD_SET_TYPE; } load = ofpact_put_REG_LOAD(ofpacts); ofpact_set_field_init(load, mf, oasf + 1); @@ -1281,11 +1306,16 @@ nxm_reg_load_to_nxast(const struct ofpact_reg_load *load, void nxm_execute_reg_move(const struct ofpact_reg_move *move, - struct flow *flow) + struct flow *flow, struct flow_wildcards *wc) { + union mf_subvalue mask_value; union mf_value src_value; union mf_value dst_value; + memset(&mask_value, 0xff, sizeof mask_value); + mf_write_subfield_flow(&move->dst, &mask_value, &wc->masks); + mf_write_subfield_flow(&move->src, &mask_value, &wc->masks); + mf_get_value(move->dst.field, flow, &dst_value); mf_get_value(move->src.field, flow, &src_value); bitwise_copy(&src_value, move->src.field->n_bytes, move->src.ofs, @@ -1302,11 +1332,15 @@ nxm_execute_reg_load(const struct ofpact_reg_load *load, struct flow *flow) void nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data, - struct flow *flow) + struct flow *flow, struct flow_wildcards *wc) { union mf_subvalue src_subvalue; + union mf_subvalue mask_value; ovs_be64 src_data_be = htonll(src_data); + memset(&mask_value, 0xff, sizeof mask_value); + mf_write_subfield_flow(dst, &mask_value, &wc->masks); + bitwise_copy(&src_data_be, sizeof src_data_be, 0, &src_subvalue, sizeof src_subvalue, 0, sizeof src_data_be * 8); @@ -1314,13 +1348,27 @@ nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data, } /* nxm_parse_stack_action, works for both push() and pop(). */ -void + +/* Parses 's' as a "push" or "pop" action, in the form described in + * ovs-ofctl(8), into '*stack_action'. + * + * Returns NULL if successful, otherwise a malloc()'d string describing the + * error. The caller is responsible for freeing the returned string. */ +char * WARN_UNUSED_RESULT nxm_parse_stack_action(struct ofpact_stack *stack_action, const char *s) { - s = mf_parse_subfield(&stack_action->subfield, s); + char *error; + + error = mf_parse_subfield__(&stack_action->subfield, &s); + if (error) { + return error; + } + if (*s != '\0') { - ovs_fatal(0, "%s: trailing garbage following push or pop", s); + return xasprintf("%s: trailing garbage following push or pop", s); } + + return NULL; } void @@ -1430,17 +1478,23 @@ nx_stack_pop(struct ofpbuf *stack) void nxm_execute_stack_push(const struct ofpact_stack *push, - const struct flow *flow, struct ofpbuf *stack) + const struct flow *flow, struct flow_wildcards *wc, + struct ofpbuf *stack) { + union mf_subvalue mask_value; union mf_subvalue dst_value; + memset(&mask_value, 0xff, sizeof mask_value); + mf_write_subfield_flow(&push->subfield, &mask_value, &wc->masks); + mf_read_subfield(&push->subfield, flow, &dst_value); nx_stack_push(stack, &dst_value); } void nxm_execute_stack_pop(const struct ofpact_stack *pop, - struct flow *flow, struct ofpbuf *stack) + struct flow *flow, struct flow_wildcards *wc, + struct ofpbuf *stack) { union mf_subvalue *src_value; @@ -1448,6 +1502,10 @@ nxm_execute_stack_pop(const struct ofpact_stack *pop, /* Only pop if stack is not empty. Otherwise, give warning. */ if (src_value) { + union mf_subvalue mask_value; + + memset(&mask_value, 0xff, sizeof mask_value); + mf_write_subfield_flow(&pop->subfield, &mask_value, &wc->masks); mf_write_subfield_flow(&pop->subfield, src_value, flow); } else { if (!VLOG_DROP_WARN(&rl)) {