From 18c43631587c68bcd8ce82fcdd6b27ed3d998071 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Sun, 6 Feb 2011 22:46:27 -0800 Subject: [PATCH] datapath: Better calculate max nlattr-formatted flow size. Both userspace and the kernel allocate space based on the max size of a nlattr-formatted flow. It was easy to change the max size of a flow definition and cause crashes by forgetting to update one or both of those definitions. This commit attempts to make that harder by providing a better description of how the max size is calculated and a build check to look for a common indication that it may have changed. Signed-off-by: Justin Pettit Acked-by: Jesse Gross --- datapath/flow.c | 5 +++++ datapath/flow.h | 17 +++++++++++++++-- lib/odp-util.h | 27 +++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/datapath/flow.c b/datapath/flow.c index 4b0e6cc3..fe05df32 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -819,6 +819,11 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) struct odp_key_ethernet *eth_key; struct nlattr *nla; + /* This is an imperfect sanity-check that FLOW_BUFSIZE doesn't need + * to be updated, but will at least raise awareness when new ODP key + * types are added. */ + BUILD_BUG_ON(__ODP_KEY_ATTR_MAX != 14); + if (swkey->tun_id != cpu_to_be64(0)) NLA_PUT_BE64(skb, ODP_KEY_ATTR_TUN_ID, swkey->tun_id); diff --git a/datapath/flow.h b/datapath/flow.h index 9cf5c678..a40073a0 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -107,8 +107,21 @@ u64 flow_used_time(unsigned long flow_jiffies); u32 flow_hash(const struct sw_flow_key *); int flow_cmp(const struct tbl_node *, void *target); -/* By my calculations currently the longest valid nlattr-formatted flow key is - * 132 bytes long. +/* Upper bound on the length of a nlattr-formatted flow key. The longest + * nlattr-formatted flow key would be: + * + * struct pad nl hdr total + * ------ --- ------ ----- + * ODP_KEY_ATTR_TUN_ID 8 -- 4 12 + * ODP_KEY_ATTR_IN_PORT 4 -- 4 8 + * ODP_KEY_ATTR_ETHERNET 12 -- 4 16 + * ODP_KEY_ATTR_8021Q 4 -- 4 8 + * ODP_KEY_ATTR_ETHERTYPE 2 2 4 8 + * ODP_KEY_ATTR_IPV6 34 2 4 40 + * ODP_KEY_ATTR_ICMPV6 2 2 4 8 + * ODP_KEY_ATTR_ND 28 -- 4 32 + * ------------------------------------------------- + * total 132 */ #define FLOW_BUFSIZE 132 diff --git a/lib/odp-util.h b/lib/odp-util.h index d991b19a..4020660b 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -63,14 +63,33 @@ void format_odp_action(struct ds *, const struct nlattr *); void format_odp_actions(struct ds *, const struct nlattr *odp_actions, size_t actions_len); -/* By my calculations currently the longest valid nlattr-formatted flow key is - * 132 bytes long. +/* Upper bound on the length of a nlattr-formatted flow key. The longest + * nlattr-formatted flow key would be: * - * We allocate temporary on-stack buffers for flow keys as arrays of uint32_t + * struct pad nl hdr total + * ------ --- ------ ----- + * ODP_KEY_ATTR_TUN_ID 8 -- 4 12 + * ODP_KEY_ATTR_IN_PORT 4 -- 4 8 + * ODP_KEY_ATTR_ETHERNET 12 -- 4 16 + * ODP_KEY_ATTR_8021Q 4 -- 4 8 + * ODP_KEY_ATTR_ETHERTYPE 2 2 4 8 + * ODP_KEY_ATTR_IPV6 34 2 4 40 + * ODP_KEY_ATTR_ICMPV6 2 2 4 8 + * ODP_KEY_ATTR_ND 28 -- 4 32 + * ------------------------------------------------- + * total 132 + */ +#define ODPUTIL_FLOW_KEY_BYTES 132 + +/* This is an imperfect sanity-check that ODPUTIL_FLOW_KEY_BYTES doesn't + * need to be updated, but will at least raise awareness when new ODP + * key types are added. */ +BUILD_ASSERT_DECL(__ODP_KEY_ATTR_MAX == 14); + +/* We allocate temporary on-stack buffers for flow keys as arrays of uint32_t * to ensure proper 32-bit alignment for Netlink attributes. (An array of * "struct nlattr" might not, in theory, be sufficiently aligned because it * only contains 16-bit types.) */ -#define ODPUTIL_FLOW_KEY_BYTES 132 #define ODPUTIL_FLOW_KEY_U32S DIV_ROUND_UP(ODPUTIL_FLOW_KEY_BYTES, 4) void odp_flow_key_format(const struct nlattr *, size_t, struct ds *); -- 2.30.2