[ovs-dev] [PATCH 2/2] datapath: Better calculate max nlattr-formatted flow size.

Justin Pettit jpettit at nicira.com
Mon Feb 7 06:54:28 UTC 2011


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
defining that size in datapath-protocol.h and have the others use it.
---
 datapath/flow.h                         |    6 +++---
 include/openvswitch/datapath-protocol.h |   27 +++++++++++++++++++++++++++
 lib/odp-util.h                          |    6 +++---
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/datapath/flow.h b/datapath/flow.h
index c003393..26bc8cd 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -107,10 +107,10 @@ 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, so this leaves some safety margin.
+/* The longest valid nlattr-formatted flow key is ODP_KEY_MAX_LEN, so
+ * this leaves some safety margin.
  */
-#define FLOW_BUFSIZE 148
+#define FLOW_BUFSIZE (ODP_KEY_MAX_LEN + 16)
 
 int flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
 int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *);
diff --git a/include/openvswitch/datapath-protocol.h b/include/openvswitch/datapath-protocol.h
index e5bbc6a..cb4337b 100644
--- a/include/openvswitch/datapath-protocol.h
+++ b/include/openvswitch/datapath-protocol.h
@@ -308,6 +308,33 @@ enum odp_key_type {
 
 #define ODP_KEY_ATTR_MAX (__ODP_KEY_ATTR_MAX - 1)
 
+/* 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       2     2     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 ODP_KEY_MAX_LEN 132
+
+/* Both the userspace and kernel make assumptions about buffer sizes
+ * based on the maximum length of a nlattr-formatted flow key.  This is
+ * an imperfect sanity-check that ODP_KEY_MAX_LEN doesn't need to
+ * change, but will at least raise awareness when new ODP key types are
+ * added. */
+#ifdef BUILD_ASSERT_DECL
+BUILD_ASSERT_DECL(__ODP_KEY_ATTR_MAX == 14);
+#endif
+
 struct odp_key_ethernet {
 	uint8_t	 eth_src[6];
 	uint8_t	 eth_dst[6];
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 452c5cf..9acf5d9 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -63,14 +63,14 @@ 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, so this leaves some safety margin.
+/* The longest valid nlattr-formatted flow key is ODP_KEY_MAX_LEN, so
+ * this leaves some safety margin.
  *
  * 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 148
+#define ODPUTIL_FLOW_KEY_BYTES (ODP_KEY_MAX_LEN + 16)
 #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 *);
-- 
1.7.1





More information about the dev mailing list