[ovs-dev] [PATCH 3/3] datapath: Reuse parse_nlattrs() for IPv4 tunnels.

Joe Stringer joestringer at nicira.com
Fri Aug 15 05:03:07 UTC 2014


Signed-off-by: Joe Stringer <joestringer at nicira.com>
---
 datapath/flow_netlink.c |   85 ++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 46 deletions(-)

diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 933b2a1..01f6e49 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -350,60 +350,58 @@ static int parse_flow_nlattrs(const struct nlattr *attr,
 static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 				struct sw_flow_match *match, bool is_mask)
 {
-	struct nlattr *a;
-	int rem;
+	static const int ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
+		[OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
+		[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
+		[OVS_TUNNEL_KEY_ATTR_IPV4_DST] = sizeof(u32),
+		[OVS_TUNNEL_KEY_ATTR_TOS] = 1,
+		[OVS_TUNNEL_KEY_ATTR_TTL] = 1,
+		[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
+		[OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
+		[OVS_TUNNEL_KEY_ATTR_OAM] = 0,
+		[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = -1,
+	};
+	const struct nlattr *a[OVS_TUNNEL_KEY_ATTR_MAX + 1];
 	bool ttl = false;
 	__be16 tun_flags = 0;
+	enum ovs_tunnel_key_attr type;
+	u64 attrs = 0;
+	int err;
 
-	nla_for_each_nested(a, attr, rem) {
-		int type = nla_type(a);
-		static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
-			[OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
-			[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
-			[OVS_TUNNEL_KEY_ATTR_IPV4_DST] = sizeof(u32),
-			[OVS_TUNNEL_KEY_ATTR_TOS] = 1,
-			[OVS_TUNNEL_KEY_ATTR_TTL] = 1,
-			[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
-			[OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
-			[OVS_TUNNEL_KEY_ATTR_OAM] = 0,
-			[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = -1,
-		};
+	err = parse_nlattrs(attr, a, ovs_tunnel_key_lens,
+			    OVS_TUNNEL_KEY_ATTR_MAX + 1, true, "IPv4 tunnel",
+			    &attrs, is_mask);
+	if (err)
+		return err;
 
-		if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
-			OVS_NLERR("Unknown IPv4 tunnel attribute (type=%d, max=%d).\n",
-			type, OVS_TUNNEL_KEY_ATTR_MAX);
-			return -EINVAL;
-		}
+	for (type = 0; type <= OVS_TUNNEL_KEY_ATTR_MAX; type++) {
+		const struct nlattr *nla;
 
-		if (ovs_tunnel_key_lens[type] != nla_len(a) &&
-		    ovs_tunnel_key_lens[type] != -1) {
-			OVS_NLERR("IPv4 tunnel attribute type has unexpected "
-				  " length (type=%d, length=%d, expected=%d).\n",
-				  type, nla_len(a), ovs_tunnel_key_lens[type]);
-			return -EINVAL;
-		}
+		if (!(attrs & (1ULL << type)))
+			continue;
 
+		nla = a[type];
 		switch (type) {
 		case OVS_TUNNEL_KEY_ATTR_ID:
 			SW_FLOW_KEY_PUT(match, tun_key.tun_id,
-					nla_get_be64(a), is_mask);
+					nla_get_be64(nla), is_mask);
 			tun_flags |= TUNNEL_KEY;
 			break;
 		case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
 			SW_FLOW_KEY_PUT(match, tun_key.ipv4_src,
-					nla_get_be32(a), is_mask);
+					nla_get_be32(nla), is_mask);
 			break;
 		case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
 			SW_FLOW_KEY_PUT(match, tun_key.ipv4_dst,
-					nla_get_be32(a), is_mask);
+					nla_get_be32(nla), is_mask);
 			break;
 		case OVS_TUNNEL_KEY_ATTR_TOS:
 			SW_FLOW_KEY_PUT(match, tun_key.ipv4_tos,
-					nla_get_u8(a), is_mask);
+					nla_get_u8(nla), is_mask);
 			break;
 		case OVS_TUNNEL_KEY_ATTR_TTL:
 			SW_FLOW_KEY_PUT(match, tun_key.ipv4_ttl,
-					nla_get_u8(a), is_mask);
+					nla_get_u8(nla), is_mask);
 			ttl = true;
 			break;
 		case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
@@ -417,18 +415,18 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 			break;
 		case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
 			tun_flags |= TUNNEL_OPTIONS_PRESENT;
-			if (nla_len(a) > sizeof(match->key->tun_opts)) {
+			if (nla_len(nla) > sizeof(match->key->tun_opts)) {
 				OVS_NLERR("Geneve option length exceeds "
 					  "maximum size (len %d, max %zu).\n",
-					  nla_len(a),
+					  nla_len(nla),
 					  sizeof(match->key->tun_opts));
 				return -EINVAL;
 			}
 
-			if (nla_len(a) % 4 != 0) {
+			if (nla_len(nla) % 4 != 0) {
 				OVS_NLERR("Geneve option length is not "
 					  "a multiple of 4 (len %d).\n",
-					  nla_len(a));
+					  nla_len(nla));
 				return -EINVAL;
 			}
 
@@ -437,7 +435,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 			 * additional options will be silently matched.
 			 */
 			if (!is_mask) {
-				SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
+				SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(nla),
 						false);
 			} else {
 				/* This is somewhat unusual because it looks at
@@ -450,10 +448,10 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 				 * variable length and we won't have the
 				 * information later.
 				 */
-				if (match->key->tun_opts_len != nla_len(a)) {
+				if (match->key->tun_opts_len != nla_len(nla)) {
 					OVS_NLERR("Geneve option key length (%d)"
 					   " is different from mask length (%d).",
-					   match->key->tun_opts_len, nla_len(a));
+					   match->key->tun_opts_len, nla_len(nla));
 					return -EINVAL;
 				}
 
@@ -463,8 +461,8 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 
 			SW_FLOW_KEY_MEMCPY_OFFSET(match,
 				(unsigned long)GENEVE_OPTS((struct sw_flow_key *)0,
-							   nla_len(a)),
-				nla_data(a), nla_len(a), is_mask);
+							   nla_len(nla)),
+				nla_data(nla), nla_len(nla), is_mask);
 			break;
 		default:
 			OVS_NLERR("Unknown IPv4 tunnel attribute (%d).\n", type);
@@ -474,11 +472,6 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 
 	SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
 
-	if (rem > 0) {
-		OVS_NLERR("IPv4 tunnel attribute has %d unknown bytes.\n", rem);
-		return -EINVAL;
-	}
-
 	if (!is_mask) {
 		if (!match->key->tun_key.ipv4_dst) {
 			OVS_NLERR("IPv4 tunnel destination address is zero.\n");
-- 
1.7.10.4




More information about the dev mailing list