diff options
| author | wenxu <wenxu@ucloud.cn> | 2019-03-28 00:43:23 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2019-03-29 16:29:15 -0400 |
| commit | 18b6f717483a835fb98de9f0df6c724df9324e78 (patch) | |
| tree | 8efa350074253df8c892e921dd2c8d15024f9102 /net/openvswitch | |
| parent | eb70a1ae2339769156f8ecddd7f6cd59ac994888 (diff) | |
openvswitch: Make metadata_dst tunnel work in IP_TUNNEL_INFO_BRIDGE mode
There is currently no support for the multicast/broadcast aspects
of VXLAN in ovs. In the datapath flow the tun_dst must specific.
But in the IP_TUNNEL_INFO_BRIDGE mode the tun_dst can not be specific.
And the packet can forward through the fdb table of vxlan devcice. In
this mode the broadcast/multicast packet can be sent through the
following ways in ovs.
ovs-vsctl add-port br0 vxlan -- set in vxlan type=vxlan \
options:key=1000 options:remote_ip=flow
ovs-ofctl add-flow br0 in_port=LOCAL,dl_dst=ff:ff:ff:ff:ff:ff, \
action=output:vxlan
bridge fdb append ff:ff:ff:ff:ff:ff dev vxlan_sys_4789 dst 172.168.0.1 \
src_vni 1000 vni 1000 self
bridge fdb append ff:ff:ff:ff:ff:ff dev vxlan_sys_4789 dst 172.168.0.2 \
src_vni 1000 vni 1000 self
Signed-off-by: wenxu <wenxu@ucloud.cn>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/flow_netlink.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index b7543700db87..bd019058fc6f 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
| @@ -404,6 +404,7 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] | |||
| 404 | [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, | 404 | [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, |
| 405 | [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, | 405 | [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, |
| 406 | [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_VARIABLE }, | 406 | [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_VARIABLE }, |
| 407 | [OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE] = { .len = 0 }, | ||
| 407 | }; | 408 | }; |
| 408 | 409 | ||
| 409 | static const struct ovs_len_tbl | 410 | static const struct ovs_len_tbl |
| @@ -667,6 +668,7 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, | |||
| 667 | bool log) | 668 | bool log) |
| 668 | { | 669 | { |
| 669 | bool ttl = false, ipv4 = false, ipv6 = false; | 670 | bool ttl = false, ipv4 = false, ipv6 = false; |
| 671 | bool info_bridge_mode = false; | ||
| 670 | __be16 tun_flags = 0; | 672 | __be16 tun_flags = 0; |
| 671 | int opts_type = 0; | 673 | int opts_type = 0; |
| 672 | struct nlattr *a; | 674 | struct nlattr *a; |
| @@ -783,6 +785,10 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, | |||
| 783 | tun_flags |= TUNNEL_ERSPAN_OPT; | 785 | tun_flags |= TUNNEL_ERSPAN_OPT; |
| 784 | opts_type = type; | 786 | opts_type = type; |
| 785 | break; | 787 | break; |
| 788 | case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE: | ||
| 789 | info_bridge_mode = true; | ||
| 790 | ipv4 = true; | ||
| 791 | break; | ||
| 786 | default: | 792 | default: |
| 787 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", | 793 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", |
| 788 | type); | 794 | type); |
| @@ -813,16 +819,29 @@ static int ip_tun_from_nlattr(const struct nlattr *attr, | |||
| 813 | OVS_NLERR(log, "IP tunnel dst address not specified"); | 819 | OVS_NLERR(log, "IP tunnel dst address not specified"); |
| 814 | return -EINVAL; | 820 | return -EINVAL; |
| 815 | } | 821 | } |
| 816 | if (ipv4 && !match->key->tun_key.u.ipv4.dst) { | 822 | if (ipv4) { |
| 817 | OVS_NLERR(log, "IPv4 tunnel dst address is zero"); | 823 | if (info_bridge_mode) { |
| 818 | return -EINVAL; | 824 | if (match->key->tun_key.u.ipv4.src || |
| 825 | match->key->tun_key.u.ipv4.dst || | ||
| 826 | match->key->tun_key.tp_src || | ||
| 827 | match->key->tun_key.tp_dst || | ||
| 828 | match->key->tun_key.ttl || | ||
| 829 | match->key->tun_key.tos || | ||
| 830 | tun_flags & ~TUNNEL_KEY) { | ||
| 831 | OVS_NLERR(log, "IPv4 tun info is not correct"); | ||
| 832 | return -EINVAL; | ||
| 833 | } | ||
| 834 | } else if (!match->key->tun_key.u.ipv4.dst) { | ||
| 835 | OVS_NLERR(log, "IPv4 tunnel dst address is zero"); | ||
| 836 | return -EINVAL; | ||
| 837 | } | ||
| 819 | } | 838 | } |
| 820 | if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) { | 839 | if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) { |
| 821 | OVS_NLERR(log, "IPv6 tunnel dst address is zero"); | 840 | OVS_NLERR(log, "IPv6 tunnel dst address is zero"); |
| 822 | return -EINVAL; | 841 | return -EINVAL; |
| 823 | } | 842 | } |
| 824 | 843 | ||
| 825 | if (!ttl) { | 844 | if (!ttl && !info_bridge_mode) { |
| 826 | OVS_NLERR(log, "IP tunnel TTL not specified."); | 845 | OVS_NLERR(log, "IP tunnel TTL not specified."); |
| 827 | return -EINVAL; | 846 | return -EINVAL; |
| 828 | } | 847 | } |
| @@ -851,12 +870,17 @@ static int vxlan_opt_to_nlattr(struct sk_buff *skb, | |||
| 851 | static int __ip_tun_to_nlattr(struct sk_buff *skb, | 870 | static int __ip_tun_to_nlattr(struct sk_buff *skb, |
| 852 | const struct ip_tunnel_key *output, | 871 | const struct ip_tunnel_key *output, |
| 853 | const void *tun_opts, int swkey_tun_opts_len, | 872 | const void *tun_opts, int swkey_tun_opts_len, |
| 854 | unsigned short tun_proto) | 873 | unsigned short tun_proto, u8 mode) |
| 855 | { | 874 | { |
| 856 | if (output->tun_flags & TUNNEL_KEY && | 875 | if (output->tun_flags & TUNNEL_KEY && |
| 857 | nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id, | 876 | nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id, |
| 858 | OVS_TUNNEL_KEY_ATTR_PAD)) | 877 | OVS_TUNNEL_KEY_ATTR_PAD)) |
| 859 | return -EMSGSIZE; | 878 | return -EMSGSIZE; |
| 879 | |||
| 880 | if (mode & IP_TUNNEL_INFO_BRIDGE) | ||
| 881 | return nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE) | ||
| 882 | ? -EMSGSIZE : 0; | ||
| 883 | |||
| 860 | switch (tun_proto) { | 884 | switch (tun_proto) { |
| 861 | case AF_INET: | 885 | case AF_INET: |
| 862 | if (output->u.ipv4.src && | 886 | if (output->u.ipv4.src && |
| @@ -919,7 +943,7 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, | |||
| 919 | static int ip_tun_to_nlattr(struct sk_buff *skb, | 943 | static int ip_tun_to_nlattr(struct sk_buff *skb, |
| 920 | const struct ip_tunnel_key *output, | 944 | const struct ip_tunnel_key *output, |
| 921 | const void *tun_opts, int swkey_tun_opts_len, | 945 | const void *tun_opts, int swkey_tun_opts_len, |
| 922 | unsigned short tun_proto) | 946 | unsigned short tun_proto, u8 mode) |
| 923 | { | 947 | { |
| 924 | struct nlattr *nla; | 948 | struct nlattr *nla; |
| 925 | int err; | 949 | int err; |
| @@ -929,7 +953,7 @@ static int ip_tun_to_nlattr(struct sk_buff *skb, | |||
| 929 | return -EMSGSIZE; | 953 | return -EMSGSIZE; |
| 930 | 954 | ||
| 931 | err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len, | 955 | err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len, |
| 932 | tun_proto); | 956 | tun_proto, mode); |
| 933 | if (err) | 957 | if (err) |
| 934 | return err; | 958 | return err; |
| 935 | 959 | ||
| @@ -943,7 +967,7 @@ int ovs_nla_put_tunnel_info(struct sk_buff *skb, | |||
| 943 | return __ip_tun_to_nlattr(skb, &tun_info->key, | 967 | return __ip_tun_to_nlattr(skb, &tun_info->key, |
| 944 | ip_tunnel_info_opts(tun_info), | 968 | ip_tunnel_info_opts(tun_info), |
| 945 | tun_info->options_len, | 969 | tun_info->options_len, |
| 946 | ip_tunnel_info_af(tun_info)); | 970 | ip_tunnel_info_af(tun_info), tun_info->mode); |
| 947 | } | 971 | } |
| 948 | 972 | ||
| 949 | static int encode_vlan_from_nlattrs(struct sw_flow_match *match, | 973 | static int encode_vlan_from_nlattrs(struct sw_flow_match *match, |
| @@ -1981,7 +2005,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey, | |||
| 1981 | opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len); | 2005 | opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len); |
| 1982 | 2006 | ||
| 1983 | if (ip_tun_to_nlattr(skb, &output->tun_key, opts, | 2007 | if (ip_tun_to_nlattr(skb, &output->tun_key, opts, |
| 1984 | swkey->tun_opts_len, swkey->tun_proto)) | 2008 | swkey->tun_opts_len, swkey->tun_proto, 0)) |
| 1985 | goto nla_put_failure; | 2009 | goto nla_put_failure; |
| 1986 | } | 2010 | } |
| 1987 | 2011 | ||
| @@ -2606,6 +2630,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, | |||
| 2606 | tun_info->mode = IP_TUNNEL_INFO_TX; | 2630 | tun_info->mode = IP_TUNNEL_INFO_TX; |
| 2607 | if (key.tun_proto == AF_INET6) | 2631 | if (key.tun_proto == AF_INET6) |
| 2608 | tun_info->mode |= IP_TUNNEL_INFO_IPV6; | 2632 | tun_info->mode |= IP_TUNNEL_INFO_IPV6; |
| 2633 | else if (key.tun_proto == AF_INET && key.tun_key.u.ipv4.dst == 0) | ||
| 2634 | tun_info->mode |= IP_TUNNEL_INFO_BRIDGE; | ||
| 2609 | tun_info->key = key.tun_key; | 2635 | tun_info->key = key.tun_key; |
| 2610 | 2636 | ||
| 2611 | /* We need to store the options in the action itself since | 2637 | /* We need to store the options in the action itself since |
| @@ -3367,7 +3393,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) | |||
| 3367 | err = ip_tun_to_nlattr(skb, &tun_info->key, | 3393 | err = ip_tun_to_nlattr(skb, &tun_info->key, |
| 3368 | ip_tunnel_info_opts(tun_info), | 3394 | ip_tunnel_info_opts(tun_info), |
| 3369 | tun_info->options_len, | 3395 | tun_info->options_len, |
| 3370 | ip_tunnel_info_af(tun_info)); | 3396 | ip_tunnel_info_af(tun_info), tun_info->mode); |
| 3371 | if (err) | 3397 | if (err) |
| 3372 | return err; | 3398 | return err; |
| 3373 | nla_nest_end(skb, start); | 3399 | nla_nest_end(skb, start); |
