diff options
author | William Tu <u9012063@gmail.com> | 2018-01-25 16:20:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-25 21:39:43 -0500 |
commit | fc1372f89ffe1f58b589643b75f679e452350703 (patch) | |
tree | 636d313b0c2830bcf6a5dc7217dcd331a9e58c9a | |
parent | d350a823020e71e20a10d1dfa44f1d1d653b0334 (diff) |
openvswitch: add erspan version I and II support
The patch adds support for openvswitch to configure erspan
v1 and v2. The OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS attr is added
to uapi as a binary blob to support all ERSPAN v1 and v2's
fields. Note that Previous commit "openvswitch: Add erspan tunnel
support." was reverted since it does not design properly.
Signed-off-by: William Tu <u9012063@gmail.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/uapi/linux/openvswitch.h | 1 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 52 |
2 files changed, 52 insertions, 1 deletions
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index dcfab5e3b55c..713e56ce681f 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h | |||
@@ -363,6 +363,7 @@ enum ovs_tunnel_key_attr { | |||
363 | OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ | 363 | OVS_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ |
364 | OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ | 364 | OVS_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ |
365 | OVS_TUNNEL_KEY_ATTR_PAD, | 365 | OVS_TUNNEL_KEY_ATTR_PAD, |
366 | OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* struct erspan_metadata */ | ||
366 | __OVS_TUNNEL_KEY_ATTR_MAX | 367 | __OVS_TUNNEL_KEY_ATTR_MAX |
367 | }; | 368 | }; |
368 | 369 | ||
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index eb55f1b3d047..7322aa1e382e 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <net/mpls.h> | 49 | #include <net/mpls.h> |
50 | #include <net/vxlan.h> | 50 | #include <net/vxlan.h> |
51 | #include <net/tun_proto.h> | 51 | #include <net/tun_proto.h> |
52 | #include <net/erspan.h> | ||
52 | 53 | ||
53 | #include "flow_netlink.h" | 54 | #include "flow_netlink.h" |
54 | 55 | ||
@@ -329,7 +330,8 @@ size_t ovs_tun_key_attr_size(void) | |||
329 | + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ | 330 | + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ |
330 | + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */ | 331 | + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */ |
331 | + nla_total_size(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */ | 332 | + nla_total_size(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */ |
332 | /* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS is mutually exclusive with | 333 | /* OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS and |
334 | * OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS is mutually exclusive with | ||
333 | * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it. | 335 | * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it. |
334 | */ | 336 | */ |
335 | + nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */ | 337 | + nla_total_size(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */ |
@@ -400,6 +402,7 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] | |||
400 | .next = ovs_vxlan_ext_key_lens }, | 402 | .next = ovs_vxlan_ext_key_lens }, |
401 | [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, | 403 | [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, |
402 | [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, | 404 | [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, |
405 | [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_VARIABLE }, | ||
403 | }; | 406 | }; |
404 | 407 | ||
405 | static const struct ovs_len_tbl | 408 | static const struct ovs_len_tbl |
@@ -631,6 +634,33 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr, | |||
631 | return 0; | 634 | return 0; |
632 | } | 635 | } |
633 | 636 | ||
637 | static int erspan_tun_opt_from_nlattr(const struct nlattr *a, | ||
638 | struct sw_flow_match *match, bool is_mask, | ||
639 | bool log) | ||
640 | { | ||
641 | unsigned long opt_key_offset; | ||
642 | |||
643 | BUILD_BUG_ON(sizeof(struct erspan_metadata) > | ||
644 | sizeof(match->key->tun_opts)); | ||
645 | |||
646 | if (nla_len(a) > sizeof(match->key->tun_opts)) { | ||
647 | OVS_NLERR(log, "ERSPAN option length err (len %d, max %zu).", | ||
648 | nla_len(a), sizeof(match->key->tun_opts)); | ||
649 | return -EINVAL; | ||
650 | } | ||
651 | |||
652 | if (!is_mask) | ||
653 | SW_FLOW_KEY_PUT(match, tun_opts_len, | ||
654 | sizeof(struct erspan_metadata), false); | ||
655 | else | ||
656 | SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true); | ||
657 | |||
658 | opt_key_offset = TUN_METADATA_OFFSET(nla_len(a)); | ||
659 | SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a), | ||
660 | nla_len(a), is_mask); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
634 | static int ip_tun_from_nlattr(const struct nlattr *attr, | 664 | static int ip_tun_from_nlattr(const struct nlattr *attr, |
635 | struct sw_flow_match *match, bool is_mask, | 665 | struct sw_flow_match *match, bool is_mask, |
636 | bool log) | 666 | bool log) |
@@ -738,6 +768,20 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, | |||
738 | break; | 768 | break; |
739 | case OVS_TUNNEL_KEY_ATTR_PAD: | 769 | case OVS_TUNNEL_KEY_ATTR_PAD: |
740 | break; | 770 | break; |
771 | case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: | ||
772 | if (opts_type) { | ||
773 | OVS_NLERR(log, "Multiple metadata blocks provided"); | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | |||
777 | err = erspan_tun_opt_from_nlattr(a, match, is_mask, | ||
778 | log); | ||
779 | if (err) | ||
780 | return err; | ||
781 | |||
782 | tun_flags |= TUNNEL_ERSPAN_OPT; | ||
783 | opts_type = type; | ||
784 | break; | ||
741 | default: | 785 | default: |
742 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", | 786 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", |
743 | type); | 787 | type); |
@@ -862,6 +906,10 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, | |||
862 | else if (output->tun_flags & TUNNEL_VXLAN_OPT && | 906 | else if (output->tun_flags & TUNNEL_VXLAN_OPT && |
863 | vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len)) | 907 | vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len)) |
864 | return -EMSGSIZE; | 908 | return -EMSGSIZE; |
909 | else if (output->tun_flags & TUNNEL_ERSPAN_OPT && | ||
910 | nla_put(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS, | ||
911 | swkey_tun_opts_len, tun_opts)) | ||
912 | return -EMSGSIZE; | ||
865 | } | 913 | } |
866 | 914 | ||
867 | return 0; | 915 | return 0; |
@@ -2486,6 +2534,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, | |||
2486 | break; | 2534 | break; |
2487 | case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: | 2535 | case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: |
2488 | break; | 2536 | break; |
2537 | case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: | ||
2538 | break; | ||
2489 | } | 2539 | } |
2490 | } | 2540 | } |
2491 | 2541 | ||