[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