aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2015-01-14 21:53:58 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-15 01:11:41 -0500
commit81bfe3c3cf153441588e50a57f53bc9816f37d37 (patch)
tree332d23a9c698cff308c8a140a886c5df45a3614d /net/openvswitch
parentd91641d9b5047b0a0a4d223a0b87306e6dff8c02 (diff)
openvswitch: Allow for any level of nesting in flow attributes
nlattr_set() is currently hardcoded to two levels of nesting. This change introduces struct ovs_len_tbl to define minimal length requirements plus next level nesting tables to traverse the key attributes to arbitrary depth. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/flow_netlink.c106
1 files changed, 56 insertions, 50 deletions
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 2e8a9cd10802..518941c5bdf1 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -50,6 +50,13 @@
50 50
51#include "flow_netlink.h" 51#include "flow_netlink.h"
52 52
53struct ovs_len_tbl {
54 int len;
55 const struct ovs_len_tbl *next;
56};
57
58#define OVS_ATTR_NESTED -1
59
53static void update_range(struct sw_flow_match *match, 60static void update_range(struct sw_flow_match *match,
54 size_t offset, size_t size, bool is_mask) 61 size_t offset, size_t size, bool is_mask)
55{ 62{
@@ -289,29 +296,44 @@ size_t ovs_key_attr_size(void)
289 + nla_total_size(28); /* OVS_KEY_ATTR_ND */ 296 + nla_total_size(28); /* OVS_KEY_ATTR_ND */
290} 297}
291 298
299static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
300 [OVS_TUNNEL_KEY_ATTR_ID] = { .len = sizeof(u64) },
301 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = { .len = sizeof(u32) },
302 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = { .len = sizeof(u32) },
303 [OVS_TUNNEL_KEY_ATTR_TOS] = { .len = 1 },
304 [OVS_TUNNEL_KEY_ATTR_TTL] = { .len = 1 },
305 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = { .len = 0 },
306 [OVS_TUNNEL_KEY_ATTR_CSUM] = { .len = 0 },
307 [OVS_TUNNEL_KEY_ATTR_TP_SRC] = { .len = sizeof(u16) },
308 [OVS_TUNNEL_KEY_ATTR_TP_DST] = { .len = sizeof(u16) },
309 [OVS_TUNNEL_KEY_ATTR_OAM] = { .len = 0 },
310 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_NESTED },
311};
312
292/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */ 313/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
293static const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { 314static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
294 [OVS_KEY_ATTR_ENCAP] = -1, 315 [OVS_KEY_ATTR_ENCAP] = { .len = OVS_ATTR_NESTED },
295 [OVS_KEY_ATTR_PRIORITY] = sizeof(u32), 316 [OVS_KEY_ATTR_PRIORITY] = { .len = sizeof(u32) },
296 [OVS_KEY_ATTR_IN_PORT] = sizeof(u32), 317 [OVS_KEY_ATTR_IN_PORT] = { .len = sizeof(u32) },
297 [OVS_KEY_ATTR_SKB_MARK] = sizeof(u32), 318 [OVS_KEY_ATTR_SKB_MARK] = { .len = sizeof(u32) },
298 [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet), 319 [OVS_KEY_ATTR_ETHERNET] = { .len = sizeof(struct ovs_key_ethernet) },
299 [OVS_KEY_ATTR_VLAN] = sizeof(__be16), 320 [OVS_KEY_ATTR_VLAN] = { .len = sizeof(__be16) },
300 [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16), 321 [OVS_KEY_ATTR_ETHERTYPE] = { .len = sizeof(__be16) },
301 [OVS_KEY_ATTR_IPV4] = sizeof(struct ovs_key_ipv4), 322 [OVS_KEY_ATTR_IPV4] = { .len = sizeof(struct ovs_key_ipv4) },
302 [OVS_KEY_ATTR_IPV6] = sizeof(struct ovs_key_ipv6), 323 [OVS_KEY_ATTR_IPV6] = { .len = sizeof(struct ovs_key_ipv6) },
303 [OVS_KEY_ATTR_TCP] = sizeof(struct ovs_key_tcp), 324 [OVS_KEY_ATTR_TCP] = { .len = sizeof(struct ovs_key_tcp) },
304 [OVS_KEY_ATTR_TCP_FLAGS] = sizeof(__be16), 325 [OVS_KEY_ATTR_TCP_FLAGS] = { .len = sizeof(__be16) },
305 [OVS_KEY_ATTR_UDP] = sizeof(struct ovs_key_udp), 326 [OVS_KEY_ATTR_UDP] = { .len = sizeof(struct ovs_key_udp) },
306 [OVS_KEY_ATTR_SCTP] = sizeof(struct ovs_key_sctp), 327 [OVS_KEY_ATTR_SCTP] = { .len = sizeof(struct ovs_key_sctp) },
307 [OVS_KEY_ATTR_ICMP] = sizeof(struct ovs_key_icmp), 328 [OVS_KEY_ATTR_ICMP] = { .len = sizeof(struct ovs_key_icmp) },
308 [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6), 329 [OVS_KEY_ATTR_ICMPV6] = { .len = sizeof(struct ovs_key_icmpv6) },
309 [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp), 330 [OVS_KEY_ATTR_ARP] = { .len = sizeof(struct ovs_key_arp) },
310 [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd), 331 [OVS_KEY_ATTR_ND] = { .len = sizeof(struct ovs_key_nd) },
311 [OVS_KEY_ATTR_RECIRC_ID] = sizeof(u32), 332 [OVS_KEY_ATTR_RECIRC_ID] = { .len = sizeof(u32) },
312 [OVS_KEY_ATTR_DP_HASH] = sizeof(u32), 333 [OVS_KEY_ATTR_DP_HASH] = { .len = sizeof(u32) },
313 [OVS_KEY_ATTR_TUNNEL] = -1, 334 [OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED,
314 [OVS_KEY_ATTR_MPLS] = sizeof(struct ovs_key_mpls), 335 .next = ovs_tunnel_key_lens, },
336 [OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) },
315}; 337};
316 338
317static bool is_all_zero(const u8 *fp, size_t size) 339static bool is_all_zero(const u8 *fp, size_t size)
@@ -352,8 +374,8 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
352 return -EINVAL; 374 return -EINVAL;
353 } 375 }
354 376
355 expected_len = ovs_key_lens[type]; 377 expected_len = ovs_key_lens[type].len;
356 if (nla_len(nla) != expected_len && expected_len != -1) { 378 if (nla_len(nla) != expected_len && expected_len != OVS_ATTR_NESTED) {
357 OVS_NLERR(log, "Key %d has unexpected len %d expected %d", 379 OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
358 type, nla_len(nla), expected_len); 380 type, nla_len(nla), expected_len);
359 return -EINVAL; 381 return -EINVAL;
@@ -451,30 +473,16 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
451 int type = nla_type(a); 473 int type = nla_type(a);
452 int err; 474 int err;
453 475
454 static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
455 [OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
456 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
457 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = sizeof(u32),
458 [OVS_TUNNEL_KEY_ATTR_TOS] = 1,
459 [OVS_TUNNEL_KEY_ATTR_TTL] = 1,
460 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
461 [OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
462 [OVS_TUNNEL_KEY_ATTR_TP_SRC] = sizeof(u16),
463 [OVS_TUNNEL_KEY_ATTR_TP_DST] = sizeof(u16),
464 [OVS_TUNNEL_KEY_ATTR_OAM] = 0,
465 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = -1,
466 };
467
468 if (type > OVS_TUNNEL_KEY_ATTR_MAX) { 476 if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
469 OVS_NLERR(log, "Tunnel attr %d out of range max %d", 477 OVS_NLERR(log, "Tunnel attr %d out of range max %d",
470 type, OVS_TUNNEL_KEY_ATTR_MAX); 478 type, OVS_TUNNEL_KEY_ATTR_MAX);
471 return -EINVAL; 479 return -EINVAL;
472 } 480 }
473 481
474 if (ovs_tunnel_key_lens[type] != nla_len(a) && 482 if (ovs_tunnel_key_lens[type].len != nla_len(a) &&
475 ovs_tunnel_key_lens[type] != -1) { 483 ovs_tunnel_key_lens[type].len != OVS_ATTR_NESTED) {
476 OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d", 484 OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
477 type, nla_len(a), ovs_tunnel_key_lens[type]); 485 type, nla_len(a), ovs_tunnel_key_lens[type].len);
478 return -EINVAL; 486 return -EINVAL;
479 } 487 }
480 488
@@ -912,18 +920,16 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
912 return 0; 920 return 0;
913} 921}
914 922
915static void nlattr_set(struct nlattr *attr, u8 val, bool is_attr_mask_key) 923static void nlattr_set(struct nlattr *attr, u8 val,
924 const struct ovs_len_tbl *tbl)
916{ 925{
917 struct nlattr *nla; 926 struct nlattr *nla;
918 int rem; 927 int rem;
919 928
920 /* The nlattr stream should already have been validated */ 929 /* The nlattr stream should already have been validated */
921 nla_for_each_nested(nla, attr, rem) { 930 nla_for_each_nested(nla, attr, rem) {
922 /* We assume that ovs_key_lens[type] == -1 means that type is a 931 if (tbl && tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
923 * nested attribute 932 nlattr_set(nla, val, tbl[nla_type(nla)].next);
924 */
925 if (is_attr_mask_key && ovs_key_lens[nla_type(nla)] == -1)
926 nlattr_set(nla, val, false);
927 else 933 else
928 memset(nla_data(nla), val, nla_len(nla)); 934 memset(nla_data(nla), val, nla_len(nla));
929 } 935 }
@@ -931,7 +937,7 @@ static void nlattr_set(struct nlattr *attr, u8 val, bool is_attr_mask_key)
931 937
932static void mask_set_nlattr(struct nlattr *attr, u8 val) 938static void mask_set_nlattr(struct nlattr *attr, u8 val)
933{ 939{
934 nlattr_set(attr, val, true); 940 nlattr_set(attr, val, ovs_key_lens);
935} 941}
936 942
937/** 943/**
@@ -1628,8 +1634,8 @@ static int validate_set(const struct nlattr *a,
1628 return -EINVAL; 1634 return -EINVAL;
1629 1635
1630 if (key_type > OVS_KEY_ATTR_MAX || 1636 if (key_type > OVS_KEY_ATTR_MAX ||
1631 (ovs_key_lens[key_type] != nla_len(ovs_key) && 1637 (ovs_key_lens[key_type].len != nla_len(ovs_key) &&
1632 ovs_key_lens[key_type] != -1)) 1638 ovs_key_lens[key_type].len != OVS_ATTR_NESTED))
1633 return -EINVAL; 1639 return -EINVAL;
1634 1640
1635 switch (key_type) { 1641 switch (key_type) {