[ovs-dev] [PATCH] odp-util: Update ODPUTIL_FLOW_KEY_BYTES for current kernel flow format.
Ethan Jackson
ethan at nicira.com
Tue May 15 20:11:09 UTC 2012
Nifty, thanks.
Ethan
On Tue, May 15, 2012 at 12:51 PM, Ben Pfaff <blp at nicira.com> wrote:
> Well, we can do better, anyway, by adjusting test-odp.c and odp.at.
> Update appended
>
> On Tue, May 15, 2012 at 11:19:04AM -0700, Ethan Jackson wrote:
>> Just out of curiosity, is there any way we can build assert, or unit
>> test these values? That seems like the most future proof way to
>> ensure they're correct, though I'm not sure what such a check would
>> look like.
>>
>> Ethan
>>
>> On Tue, May 15, 2012 at 10:42 AM, Justin Pettit <jpettit at nicira.com> wrote:
>> > On May 15, 2012, at 10:29 AM, Ben Pfaff wrote:
>> >
>> >>>>> Do you think it's worth having the total be a #define, and then do a
>> >>>>> build-time assertion that the total value is less than
>> >>>>> ODPUTIL_FLOW_KEY_BYTES?
>> >>>>
>> >>>> Can you explain how that would be different?
>> >>>
>> >>> Right now, we have a chart that maps out the total number of bytes
>> >>> needed to represent the largest flow. When updating that chart it's
>> >>> pretty obvious that the "total" field at the bottom needs to be
>> >>> updated. I feel like we've had issues in the past where "total" was
>> >>> updated, but ODPUTIL_FLOW_KEY_BYTES was not. This would serve as a
>> >>> reminder. It's pretty unlikely to occur, but I was thinking it would
>> >>> be a good sanity-check. We could also mandate a certain amount a
>> >>> slack. However, if you think it's unnecessary, I'm fine not adding
>> >>> one, too.
>> >>
>> >> Mostly I don't understand what you envision the code or comment looking
>> >> like. Can you show me?
>> >
>> >
>> > I was thinking of something like the following:
>> >
>> > -=-=-=-=-=-=-=-=-=-=-
>> > * struct pad nl hdr total
>> > * ------ --- ------ -----
>> > * OVS_KEY_ATTR_PRIORITY 4 -- 4 8
>> > ...
>> > * OVS_KEY_ATTR_ND 28 -- 4 32
>> > * -------------------------------------------------*/
>> > #define ODP_FLOW_KEY_MAX_TOTAL 156
>> >
>> > /* We include some slack space in case the calculation isn't quite right or we
>> > * add another field and forget to adjust this value.
>> > */
>> > #define ODPUTIL_FLOW_KEY_BYTES 200
>> >
>> > BUILD_ASSERT_DECL(ODP_FLOW_KEY_MAX_TOTAL < ODPUTIL_FLOW_KEY_BYTES)
>> > -=-=-=-=-=-=-=-=-=-=-
>> >
>> > However, ODPUTIL_FLOW_KEY_BYTES is defined pretty close to "total", so it's probably pointless. I'll drop this, unless you've suddenly fallen in love with the idea. :-)
>
> --8<--------------------------cut here-------------------------->8--
>
> From: Ben Pfaff <blp at nicira.com>
> Date: Tue, 15 May 2012 12:50:57 -0700
> Subject: [PATCH] odp-util: Update ODPUTIL_FLOW_KEY_BYTES for current kernel flow format.
>
> Before we submitted the kernel module upstream, we updated the flow format
> by adding two fields to the description of packets with VLAN headers, but
> we forgot to update ODPUTIL_FLOW_KEY_BYTES to reflect these changes. The
> result was that a maximum-length flow did not fit in the given space.
>
> This fixes a crash processing IPv6 neighbor discovery packets with VLAN
> headers received in a tunnel configured with key=flow or in_key=flow.
>
> This updates some comments to better describe the implications of
> ODPUTIL_FLOW_KEY_BYTES (suggested by Justin).
>
> This also updates test-odp.c so that it would have caught this problem, and
> updates odp.at to demonstrate that a full 156 bytes are necessary. (To see
> that, revert the change to ODPUTIL_FLOW_KEY_BYTES and run the test.)
>
> Reported-by: Dan Wendlandt <dan at nicira.com>
> Signed-off-by: Ben Pfaff <blp at nicira.com>
> ---
> lib/odp-util.c | 7 +++++--
> lib/odp-util.h | 25 +++++++++++++++++++------
> tests/odp.at | 6 ++++++
> tests/test-odp.c | 11 +++++++++--
> 4 files changed, 39 insertions(+), 10 deletions(-)
>
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index aae5cc7..7e5c12f 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2009, 2010, 2011 Nicira Networks.
> + * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -1155,7 +1155,10 @@ ovs_to_odp_frag(uint8_t ovs_frag)
> : OVS_FRAG_TYPE_NONE);
> }
>
> -/* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'. */
> +/* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'.
> + *
> + * 'buf' must have at least ODPUTIL_FLOW_KEY_BYTES bytes of space, or be
> + * capable of being expanded to allow for that much space. */
> void
> odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow)
> {
> diff --git a/lib/odp-util.h b/lib/odp-util.h
> index 7c9b588..45d7d3f 100644
> --- a/lib/odp-util.h
> +++ b/lib/odp-util.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2009, 2010, 2011 Nicira Networks.
> + * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -65,8 +65,16 @@ void format_odp_actions(struct ds *, const struct nlattr *odp_actions,
> int odp_actions_from_string(const char *, const struct shash *port_names,
> struct ofpbuf *odp_actions);
>
> -/* Upper bound on the length of a nlattr-formatted flow key. The longest
> - * nlattr-formatted flow key would be:
> +/* The maximum number of bytes that odp_flow_key_from_flow() appends to a
> + * buffer. This is the upper bound on the length of a nlattr-formatted flow
> + * key that ovs-vswitchd fully understands.
> + *
> + * OVS doesn't insist that ovs-vswitchd and the datapath have exactly the same
> + * idea of a flow, so therefore this value isn't necessarily an upper bound on
> + * the length of a flow key that the datapath can pass to ovs-vswitchd.
> + *
> + * The longest nlattr-formatted flow key appended by odp_flow_key_from_flow()
> + * would be:
> *
> * struct pad nl hdr total
> * ------ --- ------ -----
> @@ -74,15 +82,20 @@ int odp_actions_from_string(const char *, const struct shash *port_names,
> * OVS_KEY_ATTR_TUN_ID 8 -- 4 12
> * OVS_KEY_ATTR_IN_PORT 4 -- 4 8
> * OVS_KEY_ATTR_ETHERNET 12 -- 4 16
> + * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype)
> * OVS_KEY_ATTR_8021Q 4 -- 4 8
> - * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8
> + * OVS_KEY_ATTR_ENCAP 0 -- 4 4 (VLAN encapsulation)
> + * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (inner VLAN ethertype)
> * OVS_KEY_ATTR_IPV6 40 -- 4 44
> * OVS_KEY_ATTR_ICMPV6 2 2 4 8
> * OVS_KEY_ATTR_ND 28 -- 4 32
> * -------------------------------------------------
> - * total 144
> + * total 156
> + *
> + * We include some slack space in case the calculation isn't quite right or we
> + * add another field and forget to adjust this value.
> */
> -#define ODPUTIL_FLOW_KEY_BYTES 144
> +#define ODPUTIL_FLOW_KEY_BYTES 200
>
> /* A buffer with sufficient size and alignment to hold an nlattr-formatted flow
> * key. An array of "struct nlattr" might not, in theory, be sufficiently
> diff --git a/tests/odp.at b/tests/odp.at
> index 90a1192..3e7a8ad 100644
> --- a/tests/odp.at
> +++ b/tests/odp.at
> @@ -48,6 +48,12 @@ s/\(eth([[^)]]*)\),*/\1,eth_type(0x8100),vlan(vid=99,pcp=7),encap(/
> s/$/)/' odp-base.txt
>
> echo
> + echo '# Valid forms with QOS priority, tun_id, and VLAN headers.'
> + sed 's/^/priority(1234),tun_id(0xfedcba9876543210),/
> +s/\(eth([[^)]]*)\),*/\1,eth_type(0x8100),vlan(vid=99,pcp=7),encap(/
> +s/$/)/' odp-base.txt
> +
> + echo
> echo '# Valid forms with IP first fragment.'
> sed -n 's/,frag=no),/,frag=first),/p' odp-base.txt
>
> diff --git a/tests/test-odp.c b/tests/test-odp.c
> index 9ae897c..cbf6004 100644
> --- a/tests/test-odp.c
> +++ b/tests/test-odp.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2011 Nicira Networks.
> + * Copyright (c) 2011, 2012 Nicira Networks.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -27,6 +27,7 @@
> int
> main(void)
> {
> + int exit_code = 0;
> struct ds in;
>
> ds_init(&in);
> @@ -85,6 +86,12 @@ main(void)
> ofpbuf_init(&odp_key, 0);
> odp_flow_key_from_flow(&odp_key, &flow);
>
> + if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) {
> + printf ("too long: %zu > %d\n",
> + odp_key.size, ODPUTIL_FLOW_KEY_BYTES);
> + exit_code = 1;
> + }
> +
> /* Convert odp_key to string. */
> ds_init(&out);
> odp_flow_key_format(odp_key.data, odp_key.size, &out);
> @@ -96,5 +103,5 @@ main(void)
> }
> ds_destroy(&in);
>
> - return 0;
> + return exit_code;
> }
> --
> 1.7.2.5
>
More information about the dev
mailing list