Skip to content

Commit

Permalink
odp-util: Update ODPUTIL_FLOW_KEY_BYTES for current kernel flow format.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
blp committed May 25, 2012
1 parent 5498c01 commit 2508ac1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 7 deletions.
5 changes: 4 additions & 1 deletion lib/odp-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,10 @@ ovs_to_odp_frag(uint8_t nw_frag)
: OVS_FRAG_TYPE_LATER);
}

/* 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)
{
Expand Down
23 changes: 18 additions & 5 deletions lib/odp-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,37 @@ void format_odp_actions(struct ds *, const struct nlattr *odp_actions,
int odp_actions_from_string(const char *, const struct simap *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
* ------ --- ------ -----
* OVS_KEY_ATTR_PRIORITY 4 -- 4 8
* 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
Expand Down
6 changes: 6 additions & 0 deletions tests/odp.at
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ s/$/)/' odp-base.txt
echo '# Valid forms with tun_id and VLAN headers.'
sed 's/^/tun_id(0xfedcba9876543210),/
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
Expand Down
9 changes: 8 additions & 1 deletion tests/test-odp.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
static int
parse_keys(void)
{
int exit_code = 0;
struct ds in;

ds_init(&in);
Expand Down Expand Up @@ -71,6 +72,12 @@ parse_keys(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);
Expand All @@ -82,7 +89,7 @@ parse_keys(void)
}
ds_destroy(&in);

return 0;
return exit_code;
}

static int
Expand Down

0 comments on commit 2508ac1

Please sign in to comment.