[ovs-dev] [PATCH 2/3] flow: Adds ethernet mask fields to flow_wildcards

Joe Stringer joe at wand.net.nz
Wed May 16 02:13:26 UTC 2012


Apologies on the whitespace "fixes" -- I realise I didn't go back over the
CodingStyle before mailing the patches. Please ignore those parts for the
purposes of reviewing. I was expecting to need to make other changes and
resubmit newer patches after I get some feedback, so please ignore these
for the moment, and I'll fix those up when I re-submit.

On 16 May 2012 13:16, Joe Stringer <joe at wand.net.nz> wrote:

> Arbitrary ethernet mask support is one step on the way to support for
> OpenFlow
> 1.0+. This patch set seeks to add this capability without breaking current
> protocol support.
>
> This patch also includes some whitespace fixes -- ^L replaced with empty
> lines.
>
> Signed-off-by: Joe Stringer <joe at wand.net.nz>
> ---
> Initial introduction of arbitrary ethernet masks to flow_wildcards. I've
> gone through the build asserts to increment FLOW_WC_SEQ, implementing
> arbitrary
> ethernet support in places I understand the code.
>
> Areas that I did not understand fully have /* ATTN */ markers with a
> relevant
> question. One overarching question I have is how ethernet matching should
> be
> handled, going forward. As I understand currently, FWW_DL_DST and
> FWW_ETH_MCAST
> bits are used in wildcards_t to indicate what kind of matching takes place.
> Will this continue to be the case?
>
> With OpenFlow 1.1, there is no equivalent ofp_flow_wildcards flags for
> ethernet
> masking; this is replaced by the eth_{src,dst}_mask. To support this fully,
> will we set the appropriate FWW_DL_DST/FWW_ETH_MCAST bits in the
> wildcards_t
> when translating from OF11+? Or do we change the OF10 code to set the
> appropriate masks, and migrate other code away from using these flags?
>
> Although nx-match.c code uses the cls_rule struct (which now contains eth
> mask
> fields), I haven't modified the nxm_put_match() code to serialize these
> masks.
> I noted that it uses flow_wildcards_to_dl_dst_mask(wc) for the mask, so
> left
> it alone as I wasn't sure if it is meant to follow OF10 functionality?
>
> All tests are satisfied, with no (known) changes to functionality, given
> that
> currently supported protocols lack support for arbitrary ethernet masks.
>
> As my first patch for submission, (and being new to the code!), I expect
> there may be some things I've missed, so I ask for your patience as I try
> to
> wrap my head around the code and attempt to contribute.
> ---
>  lib/classifier.c |   21 +++++++++++++++------
>  lib/flow.c       |   47 +++++++++++++++++++++++++++++++++++------------
>  lib/flow.h       |   12 +++++++-----
>  lib/learn.c      |    2 +-
>  lib/nx-match.c   |   18 +++++++++---------
>  lib/nx-match.h   |    4 ++--
>  lib/ofp-util.c   |   27 ++++++++++++++++++---------
>  7 files changed, 87 insertions(+), 44 deletions(-)
>
> diff --git a/lib/classifier.c b/lib/classifier.c
> index e11a585..6a1b040 100644
> --- a/lib/classifier.c
> +++ b/lib/classifier.c
> @@ -449,6 +449,15 @@ cls_rule_hash(const struct cls_rule *rule, uint32_t
> basis)
>  }
>
>  static void
> +format_eth_masked(struct ds *s, const char *name, const uint8_t eth[6],
> +                  const uint8_t mask[6])
> +{
> +    ds_put_format(s, "%s=", name);
> +    eth_format_masked(eth, mask, s);
> +    ds_put_char(s, ',');
> +}
> +
> +static void
>  format_ip_netmask(struct ds *s, const char *name, ovs_be32 ip,
>                   ovs_be32 netmask)
>  {
> @@ -500,7 +509,7 @@ cls_rule_format(const struct cls_rule *rule, struct ds
> *s)
>
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     if (rule->priority != OFP_DEFAULT_PRIORITY) {
>         ds_put_format(s, "priority=%d,", rule->priority);
> @@ -598,7 +607,7 @@ cls_rule_format(const struct cls_rule *rule, struct ds
> *s)
>         }
>     }
>     if (!(w & FWW_DL_SRC)) {
> -        ds_put_format(s, "dl_src="ETH_ADDR_FMT",",
> ETH_ADDR_ARGS(f->dl_src));
> +        format_eth_masked(s, "dl_src", f->dl_src, wc->dl_src_mask);
>     }
>     switch (w & (FWW_DL_DST | FWW_ETH_MCAST)) {
>     case 0:
> @@ -715,7 +724,7 @@ cls_rule_print(const struct cls_rule *rule)
>     puts(s);
>     free(s);
>  }
> -
> +
>  /* Initializes 'cls' as a classifier that initially contains no
> classification
>  * rules. */
>  void
> @@ -900,7 +909,7 @@ classifier_rule_overlaps(const struct classifier *cls,
>
>     return false;
>  }
> -
> +
>  /* Iteration. */
>
>  static bool
> @@ -1019,7 +1028,7 @@ cls_cursor_next(struct cls_cursor *cursor, struct
> cls_rule *rule)
>
>     return NULL;
>  }
> -
> +
>  static struct cls_table *
>  find_table(const struct classifier *cls, const struct flow_wildcards *wc)
>  {
> @@ -1179,7 +1188,7 @@ flow_equal_except(const struct flow *a, const struct
> flow *b,
>     const flow_wildcards_t wc = wildcards->wildcards;
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     for (i = 0; i < FLOW_N_REGS; i++) {
>         if ((a->regs[i] ^ b->regs[i]) & wildcards->reg_masks[i]) {
> diff --git a/lib/flow.c b/lib/flow.c
> index fc61610..c802467 100644
> --- a/lib/flow.c
> +++ b/lib/flow.c
> @@ -444,7 +444,7 @@ flow_zero_wildcards(struct flow *flow, const struct
> flow_wildcards *wildcards)
>     const flow_wildcards_t wc = wildcards->wildcards;
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     for (i = 0; i < FLOW_N_REGS; i++) {
>         flow->regs[i] &= wildcards->reg_masks[i];
> @@ -506,7 +506,7 @@ flow_zero_wildcards(struct flow *flow, const struct
> flow_wildcards *wildcards)
>  void
>  flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
>  {
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     fmd->tun_id = flow->tun_id;
>     fmd->tun_id_mask = htonll(UINT64_MAX);
> @@ -588,14 +588,14 @@ flow_print(FILE *stream, const struct flow *flow)
>     fputs(s, stream);
>     free(s);
>  }
> -
> +
>  /* flow_wildcards functions. */
>
>  /* Initializes 'wc' as a set of wildcards that matches every packet. */
>  void
>  flow_wildcards_init_catchall(struct flow_wildcards *wc)
>  {
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     wc->wildcards = FWW_ALL;
>     wc->tun_id_mask = htonll(0);
> @@ -609,6 +609,8 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
>     wc->nw_frag_mask = 0;
>     wc->tp_src_mask = htons(0);
>     wc->tp_dst_mask = htons(0);
> +    memset(wc->dl_src_mask, 0, ETH_ADDR_LEN);
> +    memset(wc->dl_dst_mask, 0, ETH_ADDR_LEN);
>     memset(wc->zeros, 0, sizeof wc->zeros);
>  }
>
> @@ -617,7 +619,7 @@ flow_wildcards_init_catchall(struct flow_wildcards *wc)
>  void
>  flow_wildcards_init_exact(struct flow_wildcards *wc)
>  {
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     wc->wildcards = 0;
>     wc->tun_id_mask = htonll(UINT64_MAX);
> @@ -631,6 +633,8 @@ flow_wildcards_init_exact(struct flow_wildcards *wc)
>     wc->nw_frag_mask = UINT8_MAX;
>     wc->tp_src_mask = htons(UINT16_MAX);
>     wc->tp_dst_mask = htons(UINT16_MAX);
> +    memset(wc->dl_src_mask, 0xff, ETH_ADDR_LEN);
> +    memset(wc->dl_dst_mask, 0xff, ETH_ADDR_LEN);
>     memset(wc->zeros, 0, sizeof wc->zeros);
>  }
>
> @@ -641,7 +645,7 @@ flow_wildcards_is_exact(const struct flow_wildcards
> *wc)
>  {
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     if (wc->wildcards
>         || wc->tun_id_mask != htonll(UINT64_MAX)
> @@ -650,6 +654,8 @@ flow_wildcards_is_exact(const struct flow_wildcards
> *wc)
>         || wc->tp_src_mask != htons(UINT16_MAX)
>         || wc->tp_dst_mask != htons(UINT16_MAX)
>         || wc->vlan_tci_mask != htons(UINT16_MAX)
> +        || !eth_mask_is_exact(wc->dl_src_mask)
> +        || !eth_mask_is_exact(wc->dl_dst_mask)
>         || !ipv6_mask_is_exact(&wc->ipv6_src_mask)
>         || !ipv6_mask_is_exact(&wc->ipv6_dst_mask)
>         || !ipv6_mask_is_exact(&wc->nd_target_mask)
> @@ -673,7 +679,7 @@ flow_wildcards_is_catchall(const struct flow_wildcards
> *wc)
>  {
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     if (wc->wildcards != FWW_ALL
>         || wc->tun_id_mask != htonll(0)
> @@ -682,6 +688,8 @@ flow_wildcards_is_catchall(const struct flow_wildcards
> *wc)
>         || wc->tp_src_mask != htons(0)
>         || wc->tp_dst_mask != htons(0)
>         || wc->vlan_tci_mask != htons(0)
> +        || !eth_addr_is_zero(wc->dl_src_mask)
> +        || !eth_addr_is_zero(wc->dl_dst_mask)
>         || !ipv6_mask_is_any(&wc->ipv6_src_mask)
>         || !ipv6_mask_is_any(&wc->ipv6_dst_mask)
>         || !ipv6_mask_is_any(&wc->nd_target_mask)
> @@ -708,7 +716,7 @@ flow_wildcards_combine(struct flow_wildcards *dst,
>  {
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     dst->wildcards = src1->wildcards | src2->wildcards;
>     dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask;
> @@ -726,6 +734,8 @@ flow_wildcards_combine(struct flow_wildcards *dst,
>     dst->vlan_tci_mask = src1->vlan_tci_mask & src2->vlan_tci_mask;
>     dst->tp_src_mask = src1->tp_src_mask & src2->tp_src_mask;
>     dst->tp_dst_mask = src1->tp_dst_mask & src2->tp_dst_mask;
> +    eth_addr_bitand(src1->dl_src_mask, src2->dl_src_mask,
> dst->dl_src_mask);
> +    eth_addr_bitand(src1->dl_dst_mask, src2->dl_dst_mask,
> dst->dl_dst_mask);
>  }
>
>  /* Returns a hash of the wildcards in 'wc'. */
> @@ -735,7 +745,7 @@ flow_wildcards_hash(const struct flow_wildcards *wc,
> uint32_t basis)
>     /* If you change struct flow_wildcards and thereby trigger this
>      * assertion, please check that the new struct flow_wildcards has no
> holes
>      * in it before you update the assertion. */
> -    BUILD_ASSERT_DECL(sizeof *wc == 80 + FLOW_N_REGS * 4);
> +    BUILD_ASSERT_DECL(sizeof *wc == 88 + FLOW_N_REGS * 4);
>     return hash_bytes(wc, sizeof *wc, basis);
>  }
>
> @@ -747,7 +757,7 @@ flow_wildcards_equal(const struct flow_wildcards *a,
>  {
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     if (a->wildcards != b->wildcards
>         || a->tun_id_mask != b->tun_id_mask
> @@ -758,7 +768,9 @@ flow_wildcards_equal(const struct flow_wildcards *a,
>         || !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask)
>         || !ipv6_addr_equals(&a->nd_target_mask, &b->nd_target_mask)
>         || a->tp_src_mask != b->tp_src_mask
> -        || a->tp_dst_mask != b->tp_dst_mask) {
> +        || a->tp_dst_mask != b->tp_dst_mask
> +        || !eth_addr_equals(a->dl_src_mask, b->dl_src_mask)
> +        || !eth_addr_equals(a->dl_dst_mask, b->dl_dst_mask)) {
>         return false;
>     }
>
> @@ -778,9 +790,10 @@ flow_wildcards_has_extra(const struct flow_wildcards
> *a,
>                          const struct flow_wildcards *b)
>  {
>     int i;
> +    uint8_t eth_masked[ETH_ADDR_LEN];
>     struct in6_addr ipv6_masked;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     for (i = 0; i < FLOW_N_REGS; i++) {
>         if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) {
> @@ -788,6 +801,16 @@ flow_wildcards_has_extra(const struct flow_wildcards
> *a,
>         }
>     }
>
> +    eth_addr_bitand(a->dl_src_mask, b->dl_src_mask, eth_masked);
> +    if (!eth_addr_equals(eth_masked, b->dl_src_mask)) {
> +        return true;
> +    }
> +
> +    eth_addr_bitand(a->dl_dst_mask, b->dl_dst_mask, eth_masked);
> +    if (!eth_addr_equals(eth_masked, b->dl_dst_mask)) {
> +        return true;
> +    }
> +
>     ipv6_masked = ipv6_addr_bitand(&a->ipv6_src_mask, &b->ipv6_src_mask);
>     if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_src_mask)) {
>         return true;
> diff --git a/lib/flow.h b/lib/flow.h
> index 7ee9a26..5d1f353 100644
> --- a/lib/flow.h
> +++ b/lib/flow.h
> @@ -35,7 +35,7 @@ struct ofpbuf;
>  /* This sequence number should be incremented whenever anything involving
> flows
>  * or the wildcarding of flows changes.  This will cause build assertion
>  * failures in places which likely need to be updated. */
> -#define FLOW_WC_SEQ 10
> +#define FLOW_WC_SEQ 11
>
>  #define FLOW_N_REGS 8
>  BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
> @@ -100,7 +100,7 @@ BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nw_frag)
> == 1);
>  BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE);
>
>  /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
> -BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 142 && FLOW_WC_SEQ == 10);
> +BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 142 && FLOW_WC_SEQ == 11);
>
>  void flow_extract(struct ofpbuf *, uint32_t priority, ovs_be64 tun_id,
>                   uint16_t in_port, struct flow *);
> @@ -164,7 +164,7 @@ typedef unsigned int OVS_BITWISE flow_wildcards_t;
>  #define FWW_ALL         ((OVS_FORCE flow_wildcards_t) (((1 << 12)) - 1))
>
>  /* Remember to update FLOW_WC_SEQ when adding or removing FWW_*. */
> -BUILD_ASSERT_DECL(FWW_ALL == ((1 << 12) - 1) && FLOW_WC_SEQ == 10);
> +BUILD_ASSERT_DECL(FWW_ALL == ((1 << 12) - 1) && FLOW_WC_SEQ == 11);
>
>  /* Information on wildcards for a flow, as a supplement to "struct flow".
>  *
> @@ -184,11 +184,13 @@ struct flow_wildcards {
>     ovs_be16 tp_src_mask;       /* 1-bit in each significant tp_src bit. */
>     ovs_be16 tp_dst_mask;       /* 1-bit in each significant tp_dst bit. */
>     uint8_t nw_frag_mask;       /* 1-bit in each significant nw_frag bit.
> */
> -    uint8_t zeros[5];           /* Padding field set to zero. */
> +    uint8_t zeros[1];           /* Padding field set to zero. */
> +    uint8_t dl_src_mask[6];     /* 1-bit in each significant dl_src bit.
> */
> +    uint8_t dl_dst_mask[6];     /* 1-bit in each significant dl_dst bit.
> */
>  };
>
>  /* Remember to update FLOW_WC_SEQ when updating struct flow_wildcards. */
> -BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 112 && FLOW_WC_SEQ ==
> 10);
> +BUILD_ASSERT_DECL(sizeof(struct flow_wildcards) == 120 && FLOW_WC_SEQ ==
> 11);
>
>  void flow_wildcards_init_catchall(struct flow_wildcards *);
>  void flow_wildcards_init_exact(struct flow_wildcards *);
> diff --git a/lib/learn.c b/lib/learn.c
> index e995c29..a89ed70 100644
> --- a/lib/learn.c
> +++ b/lib/learn.c
> @@ -184,7 +184,7 @@ learn_check(const struct nx_action_learn *learn, const
> struct flow *flow)
>                      * prerequisites.  No prerequisite depends on the
> value of
>                      * a field that is wider than 64 bits.  So just skip
>                      * setting it entirely. */
> -                    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +                    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>                 }
>             }
>         }
> diff --git a/lib/nx-match.c b/lib/nx-match.c
> index 34c8354..a5d6f12 100644
> --- a/lib/nx-match.c
> +++ b/lib/nx-match.c
> @@ -54,7 +54,7 @@ nxm_field_bits(uint32_t header)
>  {
>     return nxm_field_bytes(header) * 8;
>  }
> -
> +
>  /* nx_pull_match() and helpers. */
>
>  static uint32_t
> @@ -209,7 +209,7 @@ nx_pull_match_loose(struct ofpbuf *b, unsigned int
> match_len,
>     return nx_pull_match__(b, match_len, false, priority, rule, cookie,
>                            cookie_mask);
>  }
> -
> +
>  /* nx_put_match() and helpers.
>  *
>  * 'put' functions whose names end in 'w' add a wildcarded field.
> @@ -471,7 +471,7 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule
> *cr,
>     int match_len;
>     int i;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     /* Metadata. */
>     if (!(wc & FWW_IN_PORT)) {
> @@ -556,7 +556,7 @@ nx_put_match(struct ofpbuf *b, const struct cls_rule
> *cr,
>     ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len);
>     return match_len;
>  }
> -
> +
>  /* nx_match_to_string() and helpers. */
>
>  static void format_nxm_field_name(struct ds *, uint32_t header);
> @@ -676,7 +676,7 @@ parse_nxm_field_name(const char *name, int name_len)
>
>     return 0;
>  }
> -
> +
>  /* nx_match_from_string(). */
>
>  int
> @@ -740,7 +740,7 @@ nx_match_from_string(const char *s, struct ofpbuf *b)
>     ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len);
>     return match_len;
>  }
> -
> +
>  void
>  nxm_parse_reg_move(struct nx_action_reg_move *move, const char *s)
>  {
> @@ -797,7 +797,7 @@ nxm_parse_reg_load(struct nx_action_reg_load *load,
> const char *s)
>     load->dst = htonl(dst.field->nxm_header);
>     load->value = htonll(value);
>  }
> -
> +
>  /* nxm_format_reg_move(), nxm_format_reg_load(). */
>
>  void
> @@ -824,7 +824,7 @@ nxm_format_reg_load(const struct nx_action_reg_load
> *load, struct ds *s)
>     nxm_decode(&dst, load->dst, load->ofs_nbits);
>     mf_format_subfield(&dst, s);
>  }
> -
> +
>  /* nxm_check_reg_move(), nxm_check_reg_load(). */
>
>  enum ofperr
> @@ -866,7 +866,7 @@ nxm_check_reg_load(const struct nx_action_reg_load
> *action,
>
>     return 0;
>  }
> -
> +
>  /* nxm_execute_reg_move(), nxm_execute_reg_load(). */
>
>  void
> diff --git a/lib/nx-match.h b/lib/nx-match.h
> index a039225..f51bae5 100644
> --- a/lib/nx-match.h
> +++ b/lib/nx-match.h
> @@ -89,8 +89,8 @@ nxm_decode_n_bits(ovs_be16 ofs_nbits)
>  void nxm_decode(struct mf_subfield *, ovs_be32 header, ovs_be16
> ofs_nbits);
>  void nxm_decode_discrete(struct mf_subfield *, ovs_be32 header,
>                          ovs_be16 ofs, ovs_be16 n_bits);
> -
> -BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +
> +BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>  /* Upper bound on the length of an nx_match.  The longest nx_match (an
>  * IPV6 neighbor discovery message using 5 registers) would be:
>  *
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 501ccab..c9e77b5 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -101,7 +101,7 @@ static const flow_wildcards_t WC_INVARIANTS = 0
>  void
>  ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc)
>  {
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
>
>     /* Initialize most of rule->wc. */
>     flow_wildcards_init_catchall(wc);
> @@ -127,11 +127,16 @@ ofputil_wildcard_from_openflow(uint32_t ofpfw,
> struct flow_wildcards *wc)
>         wc->tp_dst_mask = htons(UINT16_MAX);
>     }
>
> +    if (!(ofpfw & OFPFW_DL_SRC)) {
> +        memset(wc->dl_src_mask, 0xff, ETH_ADDR_LEN);
> +    }
>     if (ofpfw & OFPFW_DL_DST) {
>         /* OpenFlow 1.0 OFPFW_DL_DST covers the whole Ethernet
> destination, but
>          * Open vSwitch breaks the Ethernet destination into bits as
> FWW_DL_DST
>          * and FWW_ETH_MCAST. */
>         wc->wildcards |= FWW_ETH_MCAST;
> +    } else {
> +        memset(wc->dl_dst_mask, 0xff, ETH_ADDR_LEN);
>     }
>
>     /* VLAN TCI mask. */
> @@ -279,7 +284,7 @@ alloc_xid(void)
>     static uint32_t next_xid = 1;
>     return htonl(next_xid++);
>  }
> -
> +
>  /* Basic parsing of OpenFlow messages. */
>
>  struct ofputil_msg_type {
> @@ -858,7 +863,7 @@ ofputil_msg_type_code(const struct ofputil_msg_type
> *type)
>  {
>     return type->code;
>  }
> -
> +
>  /* Protocols. */
>
>  struct proto_abbrev {
> @@ -1174,7 +1179,11 @@ ofputil_usable_protocols(const struct cls_rule
> *rule)
>  {
>     const struct flow_wildcards *wc = &rule->wc;
>
> -    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10);
> +    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
> +
> +    /* ATTN: How do we express OFP11-supported features? Do we need to add
> +     * anything here?
> +     */
>
>     /* Only NXM supports separately wildcards the Ethernet multicast bit.
> */
>     if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST))
> {
> @@ -2257,7 +2266,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out
> *po,
>
>     return 0;
>  }
> -
> +
>  /* ofputil_phy_port */
>
>  /* NETDEV_F_* to and from OFPPF_* and OFPPF10_*. */
> @@ -2455,7 +2464,7 @@ ofputil_append_port_desc_stats_reply(uint8_t
> ofp_version,
>         ofputil_encode_ofp11_port(pp, op);
>     }
>  }
> -
> +
>  /* ofputil_switch_features */
>
>  #define OFPC_COMMON (OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS
> | \
> @@ -2662,7 +2671,7 @@ ofputil_put_switch_features_port(const struct
> ofputil_phy_port *pp,
>
>     ofputil_put_phy_port(osf->header.version, pp, b);
>  }
> -
> +
>  /* ofputil_port_status */
>
>  /* Decodes the OpenFlow "port status" message in '*ops' into an abstract
> form
> @@ -2706,7 +2715,7 @@ ofputil_encode_port_status(const struct
> ofputil_port_status *ps,
>     update_openflow_length(b);
>     return b;
>  }
> -
> +
>  /* ofputil_port_mod */
>
>  /* Decodes the OpenFlow "port mod" message in '*oh' into an abstract form
> in
> @@ -2824,7 +2833,7 @@ ofputil_msg_type_name(const struct ofputil_msg_type
> *type)
>  {
>     return type->name;
>  }
> -
> +
>  /* Allocates and stores in '*bufferp' a new ofpbuf with a size of
>  * 'openflow_len', starting with an OpenFlow header with the given 'type'
> and
>  * an arbitrary transaction id.  Allocated bytes beyond the header, if
> any, are
> --
> 1.6.0.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20120516/7e35f657/attachment-0003.html>


More information about the dev mailing list