|
49 | 49 | #include <net/mpls.h>
|
50 | 50 | #include <net/vxlan.h>
|
51 | 51 | #include <net/tun_proto.h>
|
| 52 | +#include <net/erspan.h> |
52 | 53 |
|
53 | 54 | #include "flow_netlink.h"
|
54 | 55 |
|
@@ -329,7 +330,8 @@ size_t ovs_tun_key_attr_size(void)
|
329 | 330 | + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
|
330 | 331 | + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
|
331 | 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 | 335 | * OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS and covered by it.
|
334 | 336 | */
|
335 | 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 | 402 | .next = ovs_vxlan_ext_key_lens },
|
401 | 403 | [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
|
402 | 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 | 408 | static const struct ovs_len_tbl
|
@@ -631,6 +634,33 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
|
631 | 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 | 664 | static int ip_tun_from_nlattr(const struct nlattr *attr,
|
635 | 665 | struct sw_flow_match *match, bool is_mask,
|
636 | 666 | bool log)
|
@@ -738,6 +768,20 @@ static int ip_tun_from_nlattr(const struct nlattr *attr,
|
738 | 768 | break;
|
739 | 769 | case OVS_TUNNEL_KEY_ATTR_PAD:
|
740 | 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 | 785 | default:
|
742 | 786 | OVS_NLERR(log, "Unknown IP tunnel attribute %d",
|
743 | 787 | type);
|
@@ -862,6 +906,10 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb,
|
862 | 906 | else if (output->tun_flags & TUNNEL_VXLAN_OPT &&
|
863 | 907 | vxlan_opt_to_nlattr(skb, tun_opts, swkey_tun_opts_len))
|
864 | 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 | 915 | return 0;
|
@@ -2486,6 +2534,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
|
2486 | 2534 | break;
|
2487 | 2535 | case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS:
|
2488 | 2536 | break;
|
| 2537 | + case OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS: |
| 2538 | + break; |
2489 | 2539 | }
|
2490 | 2540 | }
|
2491 | 2541 |
|
|
0 commit comments