.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2007-2017 Nicira, Inc. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of version 2 of the GNU General Public |
---|
6 | | - * License as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, but |
---|
9 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
11 | | - * General Public License for more details. |
---|
12 | | - * |
---|
13 | | - * You should have received a copy of the GNU General Public License |
---|
14 | | - * along with this program; if not, write to the Free Software |
---|
15 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
---|
16 | | - * 02110-1301, USA |
---|
17 | 4 | */ |
---|
18 | 5 | |
---|
19 | 6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
91 | 78 | case OVS_ACTION_ATTR_SET: |
---|
92 | 79 | case OVS_ACTION_ATTR_SET_MASKED: |
---|
93 | 80 | case OVS_ACTION_ATTR_METER: |
---|
| 81 | + case OVS_ACTION_ATTR_CHECK_PKT_LEN: |
---|
| 82 | + case OVS_ACTION_ATTR_ADD_MPLS: |
---|
| 83 | + case OVS_ACTION_ATTR_DEC_TTL: |
---|
94 | 84 | default: |
---|
95 | 85 | return true; |
---|
96 | 86 | } |
---|
.. | .. |
---|
403 | 393 | [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) }, |
---|
404 | 394 | [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) }, |
---|
405 | 395 | [OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS] = { .len = OVS_ATTR_VARIABLE }, |
---|
| 396 | + [OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE] = { .len = 0 }, |
---|
406 | 397 | }; |
---|
407 | 398 | |
---|
408 | 399 | static const struct ovs_len_tbl |
---|
.. | .. |
---|
435 | 426 | [OVS_KEY_ATTR_DP_HASH] = { .len = sizeof(u32) }, |
---|
436 | 427 | [OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED, |
---|
437 | 428 | .next = ovs_tunnel_key_lens, }, |
---|
438 | | - [OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) }, |
---|
| 429 | + [OVS_KEY_ATTR_MPLS] = { .len = OVS_ATTR_VARIABLE }, |
---|
439 | 430 | [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u32) }, |
---|
440 | 431 | [OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) }, |
---|
441 | 432 | [OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) }, |
---|
.. | .. |
---|
666 | 657 | bool log) |
---|
667 | 658 | { |
---|
668 | 659 | bool ttl = false, ipv4 = false, ipv6 = false; |
---|
| 660 | + bool info_bridge_mode = false; |
---|
669 | 661 | __be16 tun_flags = 0; |
---|
670 | 662 | int opts_type = 0; |
---|
671 | 663 | struct nlattr *a; |
---|
.. | .. |
---|
782 | 774 | tun_flags |= TUNNEL_ERSPAN_OPT; |
---|
783 | 775 | opts_type = type; |
---|
784 | 776 | break; |
---|
| 777 | + case OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE: |
---|
| 778 | + info_bridge_mode = true; |
---|
| 779 | + ipv4 = true; |
---|
| 780 | + break; |
---|
785 | 781 | default: |
---|
786 | 782 | OVS_NLERR(log, "Unknown IP tunnel attribute %d", |
---|
787 | 783 | type); |
---|
.. | .. |
---|
812 | 808 | OVS_NLERR(log, "IP tunnel dst address not specified"); |
---|
813 | 809 | return -EINVAL; |
---|
814 | 810 | } |
---|
815 | | - if (ipv4 && !match->key->tun_key.u.ipv4.dst) { |
---|
816 | | - OVS_NLERR(log, "IPv4 tunnel dst address is zero"); |
---|
817 | | - return -EINVAL; |
---|
| 811 | + if (ipv4) { |
---|
| 812 | + if (info_bridge_mode) { |
---|
| 813 | + if (match->key->tun_key.u.ipv4.src || |
---|
| 814 | + match->key->tun_key.u.ipv4.dst || |
---|
| 815 | + match->key->tun_key.tp_src || |
---|
| 816 | + match->key->tun_key.tp_dst || |
---|
| 817 | + match->key->tun_key.ttl || |
---|
| 818 | + match->key->tun_key.tos || |
---|
| 819 | + tun_flags & ~TUNNEL_KEY) { |
---|
| 820 | + OVS_NLERR(log, "IPv4 tun info is not correct"); |
---|
| 821 | + return -EINVAL; |
---|
| 822 | + } |
---|
| 823 | + } else if (!match->key->tun_key.u.ipv4.dst) { |
---|
| 824 | + OVS_NLERR(log, "IPv4 tunnel dst address is zero"); |
---|
| 825 | + return -EINVAL; |
---|
| 826 | + } |
---|
818 | 827 | } |
---|
819 | 828 | if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) { |
---|
820 | 829 | OVS_NLERR(log, "IPv6 tunnel dst address is zero"); |
---|
821 | 830 | return -EINVAL; |
---|
822 | 831 | } |
---|
823 | 832 | |
---|
824 | | - if (!ttl) { |
---|
| 833 | + if (!ttl && !info_bridge_mode) { |
---|
825 | 834 | OVS_NLERR(log, "IP tunnel TTL not specified."); |
---|
826 | 835 | return -EINVAL; |
---|
827 | 836 | } |
---|
.. | .. |
---|
836 | 845 | const struct vxlan_metadata *opts = tun_opts; |
---|
837 | 846 | struct nlattr *nla; |
---|
838 | 847 | |
---|
839 | | - nla = nla_nest_start(skb, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS); |
---|
| 848 | + nla = nla_nest_start_noflag(skb, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS); |
---|
840 | 849 | if (!nla) |
---|
841 | 850 | return -EMSGSIZE; |
---|
842 | 851 | |
---|
.. | .. |
---|
850 | 859 | static int __ip_tun_to_nlattr(struct sk_buff *skb, |
---|
851 | 860 | const struct ip_tunnel_key *output, |
---|
852 | 861 | const void *tun_opts, int swkey_tun_opts_len, |
---|
853 | | - unsigned short tun_proto) |
---|
| 862 | + unsigned short tun_proto, u8 mode) |
---|
854 | 863 | { |
---|
855 | 864 | if (output->tun_flags & TUNNEL_KEY && |
---|
856 | 865 | nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id, |
---|
857 | 866 | OVS_TUNNEL_KEY_ATTR_PAD)) |
---|
858 | 867 | return -EMSGSIZE; |
---|
| 868 | + |
---|
| 869 | + if (mode & IP_TUNNEL_INFO_BRIDGE) |
---|
| 870 | + return nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE) |
---|
| 871 | + ? -EMSGSIZE : 0; |
---|
| 872 | + |
---|
859 | 873 | switch (tun_proto) { |
---|
860 | 874 | case AF_INET: |
---|
861 | 875 | if (output->u.ipv4.src && |
---|
.. | .. |
---|
918 | 932 | static int ip_tun_to_nlattr(struct sk_buff *skb, |
---|
919 | 933 | const struct ip_tunnel_key *output, |
---|
920 | 934 | const void *tun_opts, int swkey_tun_opts_len, |
---|
921 | | - unsigned short tun_proto) |
---|
| 935 | + unsigned short tun_proto, u8 mode) |
---|
922 | 936 | { |
---|
923 | 937 | struct nlattr *nla; |
---|
924 | 938 | int err; |
---|
925 | 939 | |
---|
926 | | - nla = nla_nest_start(skb, OVS_KEY_ATTR_TUNNEL); |
---|
| 940 | + nla = nla_nest_start_noflag(skb, OVS_KEY_ATTR_TUNNEL); |
---|
927 | 941 | if (!nla) |
---|
928 | 942 | return -EMSGSIZE; |
---|
929 | 943 | |
---|
930 | 944 | err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len, |
---|
931 | | - tun_proto); |
---|
| 945 | + tun_proto, mode); |
---|
932 | 946 | if (err) |
---|
933 | 947 | return err; |
---|
934 | 948 | |
---|
.. | .. |
---|
942 | 956 | return __ip_tun_to_nlattr(skb, &tun_info->key, |
---|
943 | 957 | ip_tunnel_info_opts(tun_info), |
---|
944 | 958 | tun_info->options_len, |
---|
945 | | - ip_tunnel_info_af(tun_info)); |
---|
| 959 | + ip_tunnel_info_af(tun_info), tun_info->mode); |
---|
946 | 960 | } |
---|
947 | 961 | |
---|
948 | 962 | static int encode_vlan_from_nlattrs(struct sw_flow_match *match, |
---|
.. | .. |
---|
990 | 1004 | if (a[OVS_KEY_ATTR_VLAN]) |
---|
991 | 1005 | tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]); |
---|
992 | 1006 | |
---|
993 | | - if (!(tci & htons(VLAN_TAG_PRESENT))) { |
---|
| 1007 | + if (!(tci & htons(VLAN_CFI_MASK))) { |
---|
994 | 1008 | if (tci) { |
---|
995 | | - OVS_NLERR(log, "%s TCI does not have VLAN_TAG_PRESENT bit set.", |
---|
| 1009 | + OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit set.", |
---|
996 | 1010 | (inner) ? "C-VLAN" : "VLAN"); |
---|
997 | 1011 | return -EINVAL; |
---|
998 | 1012 | } else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) { |
---|
.. | .. |
---|
1013 | 1027 | __be16 tci = 0; |
---|
1014 | 1028 | __be16 tpid = 0; |
---|
1015 | 1029 | bool encap_valid = !!(match->key->eth.vlan.tci & |
---|
1016 | | - htons(VLAN_TAG_PRESENT)); |
---|
| 1030 | + htons(VLAN_CFI_MASK)); |
---|
1017 | 1031 | bool i_encap_valid = !!(match->key->eth.cvlan.tci & |
---|
1018 | | - htons(VLAN_TAG_PRESENT)); |
---|
| 1032 | + htons(VLAN_CFI_MASK)); |
---|
1019 | 1033 | |
---|
1020 | 1034 | if (!(key_attrs & (1 << OVS_KEY_ATTR_ENCAP))) { |
---|
1021 | 1035 | /* Not a VLAN. */ |
---|
.. | .. |
---|
1039 | 1053 | (inner) ? "C-VLAN" : "VLAN", ntohs(tpid)); |
---|
1040 | 1054 | return -EINVAL; |
---|
1041 | 1055 | } |
---|
1042 | | - if (!(tci & htons(VLAN_TAG_PRESENT))) { |
---|
1043 | | - OVS_NLERR(log, "%s TCI mask does not have exact match for VLAN_TAG_PRESENT bit.", |
---|
| 1056 | + if (!(tci & htons(VLAN_CFI_MASK))) { |
---|
| 1057 | + OVS_NLERR(log, "%s TCI mask does not have exact match for VLAN_CFI_MASK bit.", |
---|
1044 | 1058 | (inner) ? "C-VLAN" : "VLAN"); |
---|
1045 | 1059 | return -EINVAL; |
---|
1046 | 1060 | } |
---|
.. | .. |
---|
1095 | 1109 | if (err) |
---|
1096 | 1110 | return err; |
---|
1097 | 1111 | |
---|
1098 | | - encap_valid = !!(match->key->eth.vlan.tci & htons(VLAN_TAG_PRESENT)); |
---|
| 1112 | + encap_valid = !!(match->key->eth.vlan.tci & htons(VLAN_CFI_MASK)); |
---|
1099 | 1113 | if (encap_valid) { |
---|
1100 | 1114 | err = __parse_vlan_from_nlattrs(match, key_attrs, true, a, |
---|
1101 | 1115 | is_mask, log); |
---|
.. | .. |
---|
1616 | 1630 | |
---|
1617 | 1631 | if (attrs & (1 << OVS_KEY_ATTR_MPLS)) { |
---|
1618 | 1632 | const struct ovs_key_mpls *mpls_key; |
---|
| 1633 | + u32 hdr_len; |
---|
| 1634 | + u32 label_count, label_count_mask, i; |
---|
1619 | 1635 | |
---|
1620 | 1636 | mpls_key = nla_data(a[OVS_KEY_ATTR_MPLS]); |
---|
1621 | | - SW_FLOW_KEY_PUT(match, mpls.top_lse, |
---|
1622 | | - mpls_key->mpls_lse, is_mask); |
---|
| 1637 | + hdr_len = nla_len(a[OVS_KEY_ATTR_MPLS]); |
---|
| 1638 | + label_count = hdr_len / sizeof(struct ovs_key_mpls); |
---|
| 1639 | + |
---|
| 1640 | + if (label_count == 0 || label_count > MPLS_LABEL_DEPTH || |
---|
| 1641 | + hdr_len % sizeof(struct ovs_key_mpls)) |
---|
| 1642 | + return -EINVAL; |
---|
| 1643 | + |
---|
| 1644 | + label_count_mask = GENMASK(label_count - 1, 0); |
---|
| 1645 | + |
---|
| 1646 | + for (i = 0 ; i < label_count; i++) |
---|
| 1647 | + SW_FLOW_KEY_PUT(match, mpls.lse[i], |
---|
| 1648 | + mpls_key[i].mpls_lse, is_mask); |
---|
| 1649 | + |
---|
| 1650 | + SW_FLOW_KEY_PUT(match, mpls.num_labels_mask, |
---|
| 1651 | + label_count_mask, is_mask); |
---|
1623 | 1652 | |
---|
1624 | 1653 | attrs &= ~(1 << OVS_KEY_ATTR_MPLS); |
---|
1625 | 1654 | } |
---|
.. | .. |
---|
1734 | 1763 | * does not include any don't care bit. |
---|
1735 | 1764 | * @net: Used to determine per-namespace field support. |
---|
1736 | 1765 | * @match: receives the extracted flow match information. |
---|
1737 | | - * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute |
---|
| 1766 | + * @nla_key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute |
---|
1738 | 1767 | * sequence. The fields should of the packet that triggered the creation |
---|
1739 | 1768 | * of this flow. |
---|
1740 | | - * @mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink |
---|
1741 | | - * attribute specifies the mask field of the wildcarded flow. |
---|
| 1769 | + * @nla_mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_* |
---|
| 1770 | + * Netlink attribute specifies the mask field of the wildcarded flow. |
---|
1742 | 1771 | * @log: Boolean to allow kernel error logging. Normally true, but when |
---|
1743 | 1772 | * probing for feature compatibility this should be passed in as false to |
---|
1744 | 1773 | * suppress unnecessary error logging. |
---|
.. | .. |
---|
1932 | 1961 | { |
---|
1933 | 1962 | struct nlattr *start; |
---|
1934 | 1963 | |
---|
1935 | | - start = nla_nest_start(skb, OVS_KEY_ATTR_NSH); |
---|
| 1964 | + start = nla_nest_start_noflag(skb, OVS_KEY_ATTR_NSH); |
---|
1936 | 1965 | if (!start) |
---|
1937 | 1966 | return -EMSGSIZE; |
---|
1938 | 1967 | |
---|
.. | .. |
---|
1980 | 2009 | opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len); |
---|
1981 | 2010 | |
---|
1982 | 2011 | if (ip_tun_to_nlattr(skb, &output->tun_key, opts, |
---|
1983 | | - swkey->tun_opts_len, swkey->tun_proto)) |
---|
| 2012 | + swkey->tun_opts_len, swkey->tun_proto, 0)) |
---|
1984 | 2013 | goto nla_put_failure; |
---|
1985 | 2014 | } |
---|
1986 | 2015 | |
---|
.. | .. |
---|
2015 | 2044 | if (swkey->eth.vlan.tci || eth_type_vlan(swkey->eth.type)) { |
---|
2016 | 2045 | if (ovs_nla_put_vlan(skb, &output->eth.vlan, is_mask)) |
---|
2017 | 2046 | goto nla_put_failure; |
---|
2018 | | - encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP); |
---|
| 2047 | + encap = nla_nest_start_noflag(skb, OVS_KEY_ATTR_ENCAP); |
---|
2019 | 2048 | if (!swkey->eth.vlan.tci) |
---|
2020 | 2049 | goto unencap; |
---|
2021 | 2050 | |
---|
2022 | 2051 | if (swkey->eth.cvlan.tci || eth_type_vlan(swkey->eth.type)) { |
---|
2023 | 2052 | if (ovs_nla_put_vlan(skb, &output->eth.cvlan, is_mask)) |
---|
2024 | 2053 | goto nla_put_failure; |
---|
2025 | | - in_encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP); |
---|
| 2054 | + in_encap = nla_nest_start_noflag(skb, |
---|
| 2055 | + OVS_KEY_ATTR_ENCAP); |
---|
2026 | 2056 | if (!swkey->eth.cvlan.tci) |
---|
2027 | 2057 | goto unencap; |
---|
2028 | 2058 | } |
---|
.. | .. |
---|
2101 | 2131 | ether_addr_copy(arp_key->arp_sha, output->ipv4.arp.sha); |
---|
2102 | 2132 | ether_addr_copy(arp_key->arp_tha, output->ipv4.arp.tha); |
---|
2103 | 2133 | } else if (eth_p_mpls(swkey->eth.type)) { |
---|
| 2134 | + u8 i, num_labels; |
---|
2104 | 2135 | struct ovs_key_mpls *mpls_key; |
---|
2105 | 2136 | |
---|
2106 | | - nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS, sizeof(*mpls_key)); |
---|
| 2137 | + num_labels = hweight_long(output->mpls.num_labels_mask); |
---|
| 2138 | + nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS, |
---|
| 2139 | + num_labels * sizeof(*mpls_key)); |
---|
2107 | 2140 | if (!nla) |
---|
2108 | 2141 | goto nla_put_failure; |
---|
| 2142 | + |
---|
2109 | 2143 | mpls_key = nla_data(nla); |
---|
2110 | | - mpls_key->mpls_lse = output->mpls.top_lse; |
---|
| 2144 | + for (i = 0; i < num_labels; i++) |
---|
| 2145 | + mpls_key[i].mpls_lse = output->mpls.lse[i]; |
---|
2111 | 2146 | } |
---|
2112 | 2147 | |
---|
2113 | 2148 | if ((swkey->eth.type == htons(ETH_P_IP) || |
---|
.. | .. |
---|
2166 | 2201 | icmpv6_key->icmpv6_type = ntohs(output->tp.src); |
---|
2167 | 2202 | icmpv6_key->icmpv6_code = ntohs(output->tp.dst); |
---|
2168 | 2203 | |
---|
2169 | | - if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION || |
---|
2170 | | - icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { |
---|
| 2204 | + if (swkey->tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) || |
---|
| 2205 | + swkey->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) { |
---|
2171 | 2206 | struct ovs_key_nd *nd_key; |
---|
2172 | 2207 | |
---|
2173 | 2208 | nla = nla_reserve(skb, OVS_KEY_ATTR_ND, sizeof(*nd_key)); |
---|
.. | .. |
---|
2201 | 2236 | int err; |
---|
2202 | 2237 | struct nlattr *nla; |
---|
2203 | 2238 | |
---|
2204 | | - nla = nla_nest_start(skb, attr); |
---|
| 2239 | + nla = nla_nest_start_noflag(skb, attr); |
---|
2205 | 2240 | if (!nla) |
---|
2206 | 2241 | return -EMSGSIZE; |
---|
2207 | 2242 | err = __ovs_nla_put_key(swkey, output, is_mask, skb); |
---|
.. | .. |
---|
2253 | 2288 | return sfa; |
---|
2254 | 2289 | } |
---|
2255 | 2290 | |
---|
| 2291 | +static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len); |
---|
| 2292 | + |
---|
| 2293 | +static void ovs_nla_free_check_pkt_len_action(const struct nlattr *action) |
---|
| 2294 | +{ |
---|
| 2295 | + const struct nlattr *a; |
---|
| 2296 | + int rem; |
---|
| 2297 | + |
---|
| 2298 | + nla_for_each_nested(a, action, rem) { |
---|
| 2299 | + switch (nla_type(a)) { |
---|
| 2300 | + case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL: |
---|
| 2301 | + case OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER: |
---|
| 2302 | + ovs_nla_free_nested_actions(nla_data(a), nla_len(a)); |
---|
| 2303 | + break; |
---|
| 2304 | + } |
---|
| 2305 | + } |
---|
| 2306 | +} |
---|
| 2307 | + |
---|
| 2308 | +static void ovs_nla_free_clone_action(const struct nlattr *action) |
---|
| 2309 | +{ |
---|
| 2310 | + const struct nlattr *a = nla_data(action); |
---|
| 2311 | + int rem = nla_len(action); |
---|
| 2312 | + |
---|
| 2313 | + switch (nla_type(a)) { |
---|
| 2314 | + case OVS_CLONE_ATTR_EXEC: |
---|
| 2315 | + /* The real list of actions follows this attribute. */ |
---|
| 2316 | + a = nla_next(a, &rem); |
---|
| 2317 | + ovs_nla_free_nested_actions(a, rem); |
---|
| 2318 | + break; |
---|
| 2319 | + } |
---|
| 2320 | +} |
---|
| 2321 | + |
---|
| 2322 | +static void ovs_nla_free_dec_ttl_action(const struct nlattr *action) |
---|
| 2323 | +{ |
---|
| 2324 | + const struct nlattr *a = nla_data(action); |
---|
| 2325 | + |
---|
| 2326 | + switch (nla_type(a)) { |
---|
| 2327 | + case OVS_DEC_TTL_ATTR_ACTION: |
---|
| 2328 | + ovs_nla_free_nested_actions(nla_data(a), nla_len(a)); |
---|
| 2329 | + break; |
---|
| 2330 | + } |
---|
| 2331 | +} |
---|
| 2332 | + |
---|
| 2333 | +static void ovs_nla_free_sample_action(const struct nlattr *action) |
---|
| 2334 | +{ |
---|
| 2335 | + const struct nlattr *a = nla_data(action); |
---|
| 2336 | + int rem = nla_len(action); |
---|
| 2337 | + |
---|
| 2338 | + switch (nla_type(a)) { |
---|
| 2339 | + case OVS_SAMPLE_ATTR_ARG: |
---|
| 2340 | + /* The real list of actions follows this attribute. */ |
---|
| 2341 | + a = nla_next(a, &rem); |
---|
| 2342 | + ovs_nla_free_nested_actions(a, rem); |
---|
| 2343 | + break; |
---|
| 2344 | + } |
---|
| 2345 | +} |
---|
| 2346 | + |
---|
2256 | 2347 | static void ovs_nla_free_set_action(const struct nlattr *a) |
---|
2257 | 2348 | { |
---|
2258 | 2349 | const struct nlattr *ovs_key = nla_data(a); |
---|
.. | .. |
---|
2266 | 2357 | } |
---|
2267 | 2358 | } |
---|
2268 | 2359 | |
---|
2269 | | -void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts) |
---|
| 2360 | +static void ovs_nla_free_nested_actions(const struct nlattr *actions, int len) |
---|
2270 | 2361 | { |
---|
2271 | 2362 | const struct nlattr *a; |
---|
2272 | 2363 | int rem; |
---|
2273 | 2364 | |
---|
2274 | | - if (!sf_acts) |
---|
| 2365 | + /* Whenever new actions are added, the need to update this |
---|
| 2366 | + * function should be considered. |
---|
| 2367 | + */ |
---|
| 2368 | + BUILD_BUG_ON(OVS_ACTION_ATTR_MAX != 23); |
---|
| 2369 | + |
---|
| 2370 | + if (!actions) |
---|
2275 | 2371 | return; |
---|
2276 | 2372 | |
---|
2277 | | - nla_for_each_attr(a, sf_acts->actions, sf_acts->actions_len, rem) { |
---|
| 2373 | + nla_for_each_attr(a, actions, len, rem) { |
---|
2278 | 2374 | switch (nla_type(a)) { |
---|
2279 | | - case OVS_ACTION_ATTR_SET: |
---|
2280 | | - ovs_nla_free_set_action(a); |
---|
| 2375 | + case OVS_ACTION_ATTR_CHECK_PKT_LEN: |
---|
| 2376 | + ovs_nla_free_check_pkt_len_action(a); |
---|
2281 | 2377 | break; |
---|
| 2378 | + |
---|
| 2379 | + case OVS_ACTION_ATTR_CLONE: |
---|
| 2380 | + ovs_nla_free_clone_action(a); |
---|
| 2381 | + break; |
---|
| 2382 | + |
---|
2282 | 2383 | case OVS_ACTION_ATTR_CT: |
---|
2283 | 2384 | ovs_ct_free_action(a); |
---|
2284 | 2385 | break; |
---|
| 2386 | + |
---|
| 2387 | + case OVS_ACTION_ATTR_DEC_TTL: |
---|
| 2388 | + ovs_nla_free_dec_ttl_action(a); |
---|
| 2389 | + break; |
---|
| 2390 | + |
---|
| 2391 | + case OVS_ACTION_ATTR_SAMPLE: |
---|
| 2392 | + ovs_nla_free_sample_action(a); |
---|
| 2393 | + break; |
---|
| 2394 | + |
---|
| 2395 | + case OVS_ACTION_ATTR_SET: |
---|
| 2396 | + ovs_nla_free_set_action(a); |
---|
| 2397 | + break; |
---|
2285 | 2398 | } |
---|
2286 | 2399 | } |
---|
| 2400 | +} |
---|
2287 | 2401 | |
---|
| 2402 | +void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts) |
---|
| 2403 | +{ |
---|
| 2404 | + if (!sf_acts) |
---|
| 2405 | + return; |
---|
| 2406 | + |
---|
| 2407 | + ovs_nla_free_nested_actions(sf_acts->actions, sf_acts->actions_len); |
---|
2288 | 2408 | kfree(sf_acts); |
---|
2289 | 2409 | } |
---|
2290 | 2410 | |
---|
.. | .. |
---|
2316 | 2436 | new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2); |
---|
2317 | 2437 | |
---|
2318 | 2438 | if (new_acts_size > MAX_ACTIONS_BUFSIZE) { |
---|
2319 | | - if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) { |
---|
| 2439 | + if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) { |
---|
2320 | 2440 | OVS_NLERR(log, "Flow action size exceeds max %u", |
---|
2321 | 2441 | MAX_ACTIONS_BUFSIZE); |
---|
2322 | 2442 | return ERR_PTR(-EMSGSIZE); |
---|
.. | .. |
---|
2393 | 2513 | static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, |
---|
2394 | 2514 | const struct sw_flow_key *key, |
---|
2395 | 2515 | struct sw_flow_actions **sfa, |
---|
2396 | | - __be16 eth_type, __be16 vlan_tci, bool log); |
---|
| 2516 | + __be16 eth_type, __be16 vlan_tci, |
---|
| 2517 | + u32 mpls_label_count, bool log); |
---|
2397 | 2518 | |
---|
2398 | 2519 | static int validate_and_copy_sample(struct net *net, const struct nlattr *attr, |
---|
2399 | 2520 | const struct sw_flow_key *key, |
---|
2400 | 2521 | struct sw_flow_actions **sfa, |
---|
2401 | 2522 | __be16 eth_type, __be16 vlan_tci, |
---|
2402 | | - bool log, bool last) |
---|
| 2523 | + u32 mpls_label_count, bool log, bool last) |
---|
2403 | 2524 | { |
---|
2404 | 2525 | const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1]; |
---|
2405 | 2526 | const struct nlattr *probability, *actions; |
---|
.. | .. |
---|
2450 | 2571 | return err; |
---|
2451 | 2572 | |
---|
2452 | 2573 | err = __ovs_nla_copy_actions(net, actions, key, sfa, |
---|
2453 | | - eth_type, vlan_tci, log); |
---|
| 2574 | + eth_type, vlan_tci, mpls_label_count, log); |
---|
2454 | 2575 | |
---|
2455 | 2576 | if (err) |
---|
2456 | 2577 | return err; |
---|
.. | .. |
---|
2460 | 2581 | return 0; |
---|
2461 | 2582 | } |
---|
2462 | 2583 | |
---|
| 2584 | +static int validate_and_copy_dec_ttl(struct net *net, |
---|
| 2585 | + const struct nlattr *attr, |
---|
| 2586 | + const struct sw_flow_key *key, |
---|
| 2587 | + struct sw_flow_actions **sfa, |
---|
| 2588 | + __be16 eth_type, __be16 vlan_tci, |
---|
| 2589 | + u32 mpls_label_count, bool log) |
---|
| 2590 | +{ |
---|
| 2591 | + const struct nlattr *attrs[OVS_DEC_TTL_ATTR_MAX + 1]; |
---|
| 2592 | + int start, action_start, err, rem; |
---|
| 2593 | + const struct nlattr *a, *actions; |
---|
| 2594 | + |
---|
| 2595 | + memset(attrs, 0, sizeof(attrs)); |
---|
| 2596 | + nla_for_each_nested(a, attr, rem) { |
---|
| 2597 | + int type = nla_type(a); |
---|
| 2598 | + |
---|
| 2599 | + /* Ignore unknown attributes to be future proof. */ |
---|
| 2600 | + if (type > OVS_DEC_TTL_ATTR_MAX) |
---|
| 2601 | + continue; |
---|
| 2602 | + |
---|
| 2603 | + if (!type || attrs[type]) |
---|
| 2604 | + return -EINVAL; |
---|
| 2605 | + |
---|
| 2606 | + attrs[type] = a; |
---|
| 2607 | + } |
---|
| 2608 | + |
---|
| 2609 | + actions = attrs[OVS_DEC_TTL_ATTR_ACTION]; |
---|
| 2610 | + if (rem || !actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN)) |
---|
| 2611 | + return -EINVAL; |
---|
| 2612 | + |
---|
| 2613 | + start = add_nested_action_start(sfa, OVS_ACTION_ATTR_DEC_TTL, log); |
---|
| 2614 | + if (start < 0) |
---|
| 2615 | + return start; |
---|
| 2616 | + |
---|
| 2617 | + action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log); |
---|
| 2618 | + if (action_start < 0) |
---|
| 2619 | + return action_start; |
---|
| 2620 | + |
---|
| 2621 | + err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type, |
---|
| 2622 | + vlan_tci, mpls_label_count, log); |
---|
| 2623 | + if (err) |
---|
| 2624 | + return err; |
---|
| 2625 | + |
---|
| 2626 | + add_nested_action_end(*sfa, action_start); |
---|
| 2627 | + add_nested_action_end(*sfa, start); |
---|
| 2628 | + return 0; |
---|
| 2629 | +} |
---|
| 2630 | + |
---|
2463 | 2631 | static int validate_and_copy_clone(struct net *net, |
---|
2464 | 2632 | const struct nlattr *attr, |
---|
2465 | 2633 | const struct sw_flow_key *key, |
---|
2466 | 2634 | struct sw_flow_actions **sfa, |
---|
2467 | 2635 | __be16 eth_type, __be16 vlan_tci, |
---|
2468 | | - bool log, bool last) |
---|
| 2636 | + u32 mpls_label_count, bool log, bool last) |
---|
2469 | 2637 | { |
---|
2470 | 2638 | int start, err; |
---|
2471 | 2639 | u32 exec; |
---|
.. | .. |
---|
2485 | 2653 | return err; |
---|
2486 | 2654 | |
---|
2487 | 2655 | err = __ovs_nla_copy_actions(net, attr, key, sfa, |
---|
2488 | | - eth_type, vlan_tci, log); |
---|
| 2656 | + eth_type, vlan_tci, mpls_label_count, log); |
---|
2489 | 2657 | if (err) |
---|
2490 | 2658 | return err; |
---|
2491 | 2659 | |
---|
.. | .. |
---|
2605 | 2773 | tun_info->mode = IP_TUNNEL_INFO_TX; |
---|
2606 | 2774 | if (key.tun_proto == AF_INET6) |
---|
2607 | 2775 | tun_info->mode |= IP_TUNNEL_INFO_IPV6; |
---|
| 2776 | + else if (key.tun_proto == AF_INET && key.tun_key.u.ipv4.dst == 0) |
---|
| 2777 | + tun_info->mode |= IP_TUNNEL_INFO_BRIDGE; |
---|
2608 | 2778 | tun_info->key = key.tun_key; |
---|
2609 | 2779 | |
---|
2610 | 2780 | /* We need to store the options in the action itself since |
---|
.. | .. |
---|
2671 | 2841 | return -EINVAL; |
---|
2672 | 2842 | |
---|
2673 | 2843 | switch (key_type) { |
---|
2674 | | - const struct ovs_key_ipv4 *ipv4_key; |
---|
2675 | | - const struct ovs_key_ipv6 *ipv6_key; |
---|
2676 | | - int err; |
---|
2677 | | - |
---|
2678 | 2844 | case OVS_KEY_ATTR_PRIORITY: |
---|
2679 | 2845 | case OVS_KEY_ATTR_SKB_MARK: |
---|
2680 | 2846 | case OVS_KEY_ATTR_CT_MARK: |
---|
.. | .. |
---|
2686 | 2852 | return -EINVAL; |
---|
2687 | 2853 | break; |
---|
2688 | 2854 | |
---|
2689 | | - case OVS_KEY_ATTR_TUNNEL: |
---|
| 2855 | + case OVS_KEY_ATTR_TUNNEL: { |
---|
| 2856 | + int err; |
---|
| 2857 | + |
---|
2690 | 2858 | if (masked) |
---|
2691 | 2859 | return -EINVAL; /* Masked tunnel set not supported. */ |
---|
2692 | 2860 | |
---|
.. | .. |
---|
2695 | 2863 | if (err) |
---|
2696 | 2864 | return err; |
---|
2697 | 2865 | break; |
---|
| 2866 | + } |
---|
| 2867 | + case OVS_KEY_ATTR_IPV4: { |
---|
| 2868 | + const struct ovs_key_ipv4 *ipv4_key; |
---|
2698 | 2869 | |
---|
2699 | | - case OVS_KEY_ATTR_IPV4: |
---|
2700 | 2870 | if (eth_type != htons(ETH_P_IP)) |
---|
2701 | 2871 | return -EINVAL; |
---|
2702 | 2872 | |
---|
.. | .. |
---|
2716 | 2886 | return -EINVAL; |
---|
2717 | 2887 | } |
---|
2718 | 2888 | break; |
---|
| 2889 | + } |
---|
| 2890 | + case OVS_KEY_ATTR_IPV6: { |
---|
| 2891 | + const struct ovs_key_ipv6 *ipv6_key; |
---|
2719 | 2892 | |
---|
2720 | | - case OVS_KEY_ATTR_IPV6: |
---|
2721 | 2893 | if (eth_type != htons(ETH_P_IPV6)) |
---|
2722 | 2894 | return -EINVAL; |
---|
2723 | 2895 | |
---|
.. | .. |
---|
2744 | 2916 | return -EINVAL; |
---|
2745 | 2917 | |
---|
2746 | 2918 | break; |
---|
2747 | | - |
---|
| 2919 | + } |
---|
2748 | 2920 | case OVS_KEY_ATTR_TCP: |
---|
2749 | 2921 | if ((eth_type != htons(ETH_P_IP) && |
---|
2750 | 2922 | eth_type != htons(ETH_P_IPV6)) || |
---|
.. | .. |
---|
2826 | 2998 | struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1]; |
---|
2827 | 2999 | int error; |
---|
2828 | 3000 | |
---|
2829 | | - error = nla_parse_nested(a, OVS_USERSPACE_ATTR_MAX, attr, |
---|
2830 | | - userspace_policy, NULL); |
---|
| 3001 | + error = nla_parse_nested_deprecated(a, OVS_USERSPACE_ATTR_MAX, attr, |
---|
| 3002 | + userspace_policy, NULL); |
---|
2831 | 3003 | if (error) |
---|
2832 | 3004 | return error; |
---|
2833 | 3005 | |
---|
.. | .. |
---|
2835 | 3007 | !nla_get_u32(a[OVS_USERSPACE_ATTR_PID])) |
---|
2836 | 3008 | return -EINVAL; |
---|
2837 | 3009 | |
---|
| 3010 | + return 0; |
---|
| 3011 | +} |
---|
| 3012 | + |
---|
| 3013 | +static const struct nla_policy cpl_policy[OVS_CHECK_PKT_LEN_ATTR_MAX + 1] = { |
---|
| 3014 | + [OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] = {.type = NLA_U16 }, |
---|
| 3015 | + [OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER] = {.type = NLA_NESTED }, |
---|
| 3016 | + [OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL] = {.type = NLA_NESTED }, |
---|
| 3017 | +}; |
---|
| 3018 | + |
---|
| 3019 | +static int validate_and_copy_check_pkt_len(struct net *net, |
---|
| 3020 | + const struct nlattr *attr, |
---|
| 3021 | + const struct sw_flow_key *key, |
---|
| 3022 | + struct sw_flow_actions **sfa, |
---|
| 3023 | + __be16 eth_type, __be16 vlan_tci, |
---|
| 3024 | + u32 mpls_label_count, |
---|
| 3025 | + bool log, bool last) |
---|
| 3026 | +{ |
---|
| 3027 | + const struct nlattr *acts_if_greater, *acts_if_lesser_eq; |
---|
| 3028 | + struct nlattr *a[OVS_CHECK_PKT_LEN_ATTR_MAX + 1]; |
---|
| 3029 | + struct check_pkt_len_arg arg; |
---|
| 3030 | + int nested_acts_start; |
---|
| 3031 | + int start, err; |
---|
| 3032 | + |
---|
| 3033 | + err = nla_parse_deprecated_strict(a, OVS_CHECK_PKT_LEN_ATTR_MAX, |
---|
| 3034 | + nla_data(attr), nla_len(attr), |
---|
| 3035 | + cpl_policy, NULL); |
---|
| 3036 | + if (err) |
---|
| 3037 | + return err; |
---|
| 3038 | + |
---|
| 3039 | + if (!a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN] || |
---|
| 3040 | + !nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN])) |
---|
| 3041 | + return -EINVAL; |
---|
| 3042 | + |
---|
| 3043 | + acts_if_lesser_eq = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL]; |
---|
| 3044 | + acts_if_greater = a[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER]; |
---|
| 3045 | + |
---|
| 3046 | + /* Both the nested action should be present. */ |
---|
| 3047 | + if (!acts_if_greater || !acts_if_lesser_eq) |
---|
| 3048 | + return -EINVAL; |
---|
| 3049 | + |
---|
| 3050 | + /* validation done, copy the nested actions. */ |
---|
| 3051 | + start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CHECK_PKT_LEN, |
---|
| 3052 | + log); |
---|
| 3053 | + if (start < 0) |
---|
| 3054 | + return start; |
---|
| 3055 | + |
---|
| 3056 | + arg.pkt_len = nla_get_u16(a[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN]); |
---|
| 3057 | + arg.exec_for_lesser_equal = |
---|
| 3058 | + last || !actions_may_change_flow(acts_if_lesser_eq); |
---|
| 3059 | + arg.exec_for_greater = |
---|
| 3060 | + last || !actions_may_change_flow(acts_if_greater); |
---|
| 3061 | + |
---|
| 3062 | + err = ovs_nla_add_action(sfa, OVS_CHECK_PKT_LEN_ATTR_ARG, &arg, |
---|
| 3063 | + sizeof(arg), log); |
---|
| 3064 | + if (err) |
---|
| 3065 | + return err; |
---|
| 3066 | + |
---|
| 3067 | + nested_acts_start = add_nested_action_start(sfa, |
---|
| 3068 | + OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL, log); |
---|
| 3069 | + if (nested_acts_start < 0) |
---|
| 3070 | + return nested_acts_start; |
---|
| 3071 | + |
---|
| 3072 | + err = __ovs_nla_copy_actions(net, acts_if_lesser_eq, key, sfa, |
---|
| 3073 | + eth_type, vlan_tci, mpls_label_count, log); |
---|
| 3074 | + |
---|
| 3075 | + if (err) |
---|
| 3076 | + return err; |
---|
| 3077 | + |
---|
| 3078 | + add_nested_action_end(*sfa, nested_acts_start); |
---|
| 3079 | + |
---|
| 3080 | + nested_acts_start = add_nested_action_start(sfa, |
---|
| 3081 | + OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER, log); |
---|
| 3082 | + if (nested_acts_start < 0) |
---|
| 3083 | + return nested_acts_start; |
---|
| 3084 | + |
---|
| 3085 | + err = __ovs_nla_copy_actions(net, acts_if_greater, key, sfa, |
---|
| 3086 | + eth_type, vlan_tci, mpls_label_count, log); |
---|
| 3087 | + |
---|
| 3088 | + if (err) |
---|
| 3089 | + return err; |
---|
| 3090 | + |
---|
| 3091 | + add_nested_action_end(*sfa, nested_acts_start); |
---|
| 3092 | + add_nested_action_end(*sfa, start); |
---|
2838 | 3093 | return 0; |
---|
2839 | 3094 | } |
---|
2840 | 3095 | |
---|
.. | .. |
---|
2855 | 3110 | static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, |
---|
2856 | 3111 | const struct sw_flow_key *key, |
---|
2857 | 3112 | struct sw_flow_actions **sfa, |
---|
2858 | | - __be16 eth_type, __be16 vlan_tci, bool log) |
---|
| 3113 | + __be16 eth_type, __be16 vlan_tci, |
---|
| 3114 | + u32 mpls_label_count, bool log) |
---|
2859 | 3115 | { |
---|
2860 | 3116 | u8 mac_proto = ovs_key_mac_proto(key); |
---|
2861 | 3117 | const struct nlattr *a; |
---|
.. | .. |
---|
2884 | 3140 | [OVS_ACTION_ATTR_POP_NSH] = 0, |
---|
2885 | 3141 | [OVS_ACTION_ATTR_METER] = sizeof(u32), |
---|
2886 | 3142 | [OVS_ACTION_ATTR_CLONE] = (u32)-1, |
---|
| 3143 | + [OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1, |
---|
| 3144 | + [OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls), |
---|
| 3145 | + [OVS_ACTION_ATTR_DEC_TTL] = (u32)-1, |
---|
2887 | 3146 | }; |
---|
2888 | 3147 | const struct ovs_action_push_vlan *vlan; |
---|
2889 | 3148 | int type = nla_type(a); |
---|
.. | .. |
---|
2943 | 3202 | vlan = nla_data(a); |
---|
2944 | 3203 | if (!eth_type_vlan(vlan->vlan_tpid)) |
---|
2945 | 3204 | return -EINVAL; |
---|
2946 | | - if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT))) |
---|
| 3205 | + if (!(vlan->vlan_tci & htons(VLAN_CFI_MASK))) |
---|
2947 | 3206 | return -EINVAL; |
---|
2948 | 3207 | vlan_tci = vlan->vlan_tci; |
---|
2949 | 3208 | break; |
---|
2950 | 3209 | |
---|
2951 | 3210 | case OVS_ACTION_ATTR_RECIRC: |
---|
2952 | 3211 | break; |
---|
| 3212 | + |
---|
| 3213 | + case OVS_ACTION_ATTR_ADD_MPLS: { |
---|
| 3214 | + const struct ovs_action_add_mpls *mpls = nla_data(a); |
---|
| 3215 | + |
---|
| 3216 | + if (!eth_p_mpls(mpls->mpls_ethertype)) |
---|
| 3217 | + return -EINVAL; |
---|
| 3218 | + |
---|
| 3219 | + if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK) { |
---|
| 3220 | + if (vlan_tci & htons(VLAN_CFI_MASK) || |
---|
| 3221 | + (eth_type != htons(ETH_P_IP) && |
---|
| 3222 | + eth_type != htons(ETH_P_IPV6) && |
---|
| 3223 | + eth_type != htons(ETH_P_ARP) && |
---|
| 3224 | + eth_type != htons(ETH_P_RARP) && |
---|
| 3225 | + !eth_p_mpls(eth_type))) |
---|
| 3226 | + return -EINVAL; |
---|
| 3227 | + mpls_label_count++; |
---|
| 3228 | + } else { |
---|
| 3229 | + if (mac_proto == MAC_PROTO_ETHERNET) { |
---|
| 3230 | + mpls_label_count = 1; |
---|
| 3231 | + mac_proto = MAC_PROTO_NONE; |
---|
| 3232 | + } else { |
---|
| 3233 | + mpls_label_count++; |
---|
| 3234 | + } |
---|
| 3235 | + } |
---|
| 3236 | + eth_type = mpls->mpls_ethertype; |
---|
| 3237 | + break; |
---|
| 3238 | + } |
---|
2953 | 3239 | |
---|
2954 | 3240 | case OVS_ACTION_ATTR_PUSH_MPLS: { |
---|
2955 | 3241 | const struct ovs_action_push_mpls *mpls = nla_data(a); |
---|
.. | .. |
---|
2959 | 3245 | /* Prohibit push MPLS other than to a white list |
---|
2960 | 3246 | * for packets that have a known tag order. |
---|
2961 | 3247 | */ |
---|
2962 | | - if (vlan_tci & htons(VLAN_TAG_PRESENT) || |
---|
| 3248 | + if (vlan_tci & htons(VLAN_CFI_MASK) || |
---|
2963 | 3249 | (eth_type != htons(ETH_P_IP) && |
---|
2964 | 3250 | eth_type != htons(ETH_P_IPV6) && |
---|
2965 | 3251 | eth_type != htons(ETH_P_ARP) && |
---|
.. | .. |
---|
2967 | 3253 | !eth_p_mpls(eth_type))) |
---|
2968 | 3254 | return -EINVAL; |
---|
2969 | 3255 | eth_type = mpls->mpls_ethertype; |
---|
| 3256 | + mpls_label_count++; |
---|
2970 | 3257 | break; |
---|
2971 | 3258 | } |
---|
2972 | 3259 | |
---|
2973 | | - case OVS_ACTION_ATTR_POP_MPLS: |
---|
2974 | | - if (vlan_tci & htons(VLAN_TAG_PRESENT) || |
---|
| 3260 | + case OVS_ACTION_ATTR_POP_MPLS: { |
---|
| 3261 | + __be16 proto; |
---|
| 3262 | + if (vlan_tci & htons(VLAN_CFI_MASK) || |
---|
2975 | 3263 | !eth_p_mpls(eth_type)) |
---|
2976 | 3264 | return -EINVAL; |
---|
2977 | 3265 | |
---|
2978 | | - /* Disallow subsequent L2.5+ set and mpls_pop actions |
---|
2979 | | - * as there is no check here to ensure that the new |
---|
2980 | | - * eth_type is valid and thus set actions could |
---|
2981 | | - * write off the end of the packet or otherwise |
---|
2982 | | - * corrupt it. |
---|
| 3266 | + /* Disallow subsequent L2.5+ set actions and mpls_pop |
---|
| 3267 | + * actions once the last MPLS label in the packet is |
---|
| 3268 | + * is popped as there is no check here to ensure that |
---|
| 3269 | + * the new eth type is valid and thus set actions could |
---|
| 3270 | + * write off the end of the packet or otherwise corrupt |
---|
| 3271 | + * it. |
---|
2983 | 3272 | * |
---|
2984 | 3273 | * Support for these actions is planned using packet |
---|
2985 | 3274 | * recirculation. |
---|
2986 | 3275 | */ |
---|
2987 | | - eth_type = htons(0); |
---|
| 3276 | + proto = nla_get_be16(a); |
---|
| 3277 | + |
---|
| 3278 | + if (proto == htons(ETH_P_TEB) && |
---|
| 3279 | + mac_proto != MAC_PROTO_NONE) |
---|
| 3280 | + return -EINVAL; |
---|
| 3281 | + |
---|
| 3282 | + mpls_label_count--; |
---|
| 3283 | + |
---|
| 3284 | + if (!eth_p_mpls(proto) || !mpls_label_count) |
---|
| 3285 | + eth_type = htons(0); |
---|
| 3286 | + else |
---|
| 3287 | + eth_type = proto; |
---|
| 3288 | + |
---|
2988 | 3289 | break; |
---|
| 3290 | + } |
---|
2989 | 3291 | |
---|
2990 | 3292 | case OVS_ACTION_ATTR_SET: |
---|
2991 | 3293 | err = validate_set(a, key, sfa, |
---|
.. | .. |
---|
3008 | 3310 | |
---|
3009 | 3311 | err = validate_and_copy_sample(net, a, key, sfa, |
---|
3010 | 3312 | eth_type, vlan_tci, |
---|
| 3313 | + mpls_label_count, |
---|
3011 | 3314 | log, last); |
---|
3012 | 3315 | if (err) |
---|
3013 | 3316 | return err; |
---|
.. | .. |
---|
3036 | 3339 | case OVS_ACTION_ATTR_POP_ETH: |
---|
3037 | 3340 | if (mac_proto != MAC_PROTO_ETHERNET) |
---|
3038 | 3341 | return -EINVAL; |
---|
3039 | | - if (vlan_tci & htons(VLAN_TAG_PRESENT)) |
---|
| 3342 | + if (vlan_tci & htons(VLAN_CFI_MASK)) |
---|
3040 | 3343 | return -EINVAL; |
---|
3041 | 3344 | mac_proto = MAC_PROTO_NONE; |
---|
3042 | 3345 | break; |
---|
.. | .. |
---|
3078 | 3381 | |
---|
3079 | 3382 | err = validate_and_copy_clone(net, a, key, sfa, |
---|
3080 | 3383 | eth_type, vlan_tci, |
---|
| 3384 | + mpls_label_count, |
---|
3081 | 3385 | log, last); |
---|
3082 | 3386 | if (err) |
---|
3083 | 3387 | return err; |
---|
3084 | 3388 | skip_copy = true; |
---|
3085 | 3389 | break; |
---|
3086 | 3390 | } |
---|
| 3391 | + |
---|
| 3392 | + case OVS_ACTION_ATTR_CHECK_PKT_LEN: { |
---|
| 3393 | + bool last = nla_is_last(a, rem); |
---|
| 3394 | + |
---|
| 3395 | + err = validate_and_copy_check_pkt_len(net, a, key, sfa, |
---|
| 3396 | + eth_type, |
---|
| 3397 | + vlan_tci, |
---|
| 3398 | + mpls_label_count, |
---|
| 3399 | + log, last); |
---|
| 3400 | + if (err) |
---|
| 3401 | + return err; |
---|
| 3402 | + skip_copy = true; |
---|
| 3403 | + break; |
---|
| 3404 | + } |
---|
| 3405 | + |
---|
| 3406 | + case OVS_ACTION_ATTR_DEC_TTL: |
---|
| 3407 | + err = validate_and_copy_dec_ttl(net, a, key, sfa, |
---|
| 3408 | + eth_type, vlan_tci, |
---|
| 3409 | + mpls_label_count, log); |
---|
| 3410 | + if (err) |
---|
| 3411 | + return err; |
---|
| 3412 | + skip_copy = true; |
---|
| 3413 | + break; |
---|
3087 | 3414 | |
---|
3088 | 3415 | default: |
---|
3089 | 3416 | OVS_NLERR(log, "Unknown Action type %d", type); |
---|
.. | .. |
---|
3108 | 3435 | struct sw_flow_actions **sfa, bool log) |
---|
3109 | 3436 | { |
---|
3110 | 3437 | int err; |
---|
| 3438 | + u32 mpls_label_count = 0; |
---|
3111 | 3439 | |
---|
3112 | 3440 | *sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE)); |
---|
3113 | 3441 | if (IS_ERR(*sfa)) |
---|
3114 | 3442 | return PTR_ERR(*sfa); |
---|
3115 | 3443 | |
---|
| 3444 | + if (eth_p_mpls(key->eth.type)) |
---|
| 3445 | + mpls_label_count = hweight_long(key->mpls.num_labels_mask); |
---|
| 3446 | + |
---|
3116 | 3447 | (*sfa)->orig_len = nla_len(attr); |
---|
3117 | 3448 | err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type, |
---|
3118 | | - key->eth.vlan.tci, log); |
---|
| 3449 | + key->eth.vlan.tci, mpls_label_count, log); |
---|
3119 | 3450 | if (err) |
---|
3120 | 3451 | ovs_nla_free_flow_actions(*sfa); |
---|
3121 | 3452 | |
---|
.. | .. |
---|
3130 | 3461 | const struct sample_arg *arg; |
---|
3131 | 3462 | struct nlattr *actions; |
---|
3132 | 3463 | |
---|
3133 | | - start = nla_nest_start(skb, OVS_ACTION_ATTR_SAMPLE); |
---|
| 3464 | + start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SAMPLE); |
---|
3134 | 3465 | if (!start) |
---|
3135 | 3466 | return -EMSGSIZE; |
---|
3136 | 3467 | |
---|
.. | .. |
---|
3143 | 3474 | goto out; |
---|
3144 | 3475 | } |
---|
3145 | 3476 | |
---|
3146 | | - ac_start = nla_nest_start(skb, OVS_SAMPLE_ATTR_ACTIONS); |
---|
| 3477 | + ac_start = nla_nest_start_noflag(skb, OVS_SAMPLE_ATTR_ACTIONS); |
---|
3147 | 3478 | if (!ac_start) { |
---|
3148 | 3479 | err = -EMSGSIZE; |
---|
3149 | 3480 | goto out; |
---|
.. | .. |
---|
3169 | 3500 | struct nlattr *start; |
---|
3170 | 3501 | int err = 0, rem = nla_len(attr); |
---|
3171 | 3502 | |
---|
3172 | | - start = nla_nest_start(skb, OVS_ACTION_ATTR_CLONE); |
---|
| 3503 | + start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CLONE); |
---|
3173 | 3504 | if (!start) |
---|
3174 | 3505 | return -EMSGSIZE; |
---|
3175 | 3506 | |
---|
3176 | | - err = ovs_nla_put_actions(nla_data(attr), rem, skb); |
---|
| 3507 | + /* Skipping the OVS_CLONE_ATTR_EXEC that is always the first attribute. */ |
---|
| 3508 | + attr = nla_next(nla_data(attr), &rem); |
---|
| 3509 | + err = ovs_nla_put_actions(attr, rem, skb); |
---|
3177 | 3510 | |
---|
3178 | 3511 | if (err) |
---|
3179 | 3512 | nla_nest_cancel(skb, start); |
---|
3180 | 3513 | else |
---|
3181 | 3514 | nla_nest_end(skb, start); |
---|
3182 | 3515 | |
---|
| 3516 | + return err; |
---|
| 3517 | +} |
---|
| 3518 | + |
---|
| 3519 | +static int check_pkt_len_action_to_attr(const struct nlattr *attr, |
---|
| 3520 | + struct sk_buff *skb) |
---|
| 3521 | +{ |
---|
| 3522 | + struct nlattr *start, *ac_start = NULL; |
---|
| 3523 | + const struct check_pkt_len_arg *arg; |
---|
| 3524 | + const struct nlattr *a, *cpl_arg; |
---|
| 3525 | + int err = 0, rem = nla_len(attr); |
---|
| 3526 | + |
---|
| 3527 | + start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CHECK_PKT_LEN); |
---|
| 3528 | + if (!start) |
---|
| 3529 | + return -EMSGSIZE; |
---|
| 3530 | + |
---|
| 3531 | + /* The first nested attribute in 'attr' is always |
---|
| 3532 | + * 'OVS_CHECK_PKT_LEN_ATTR_ARG'. |
---|
| 3533 | + */ |
---|
| 3534 | + cpl_arg = nla_data(attr); |
---|
| 3535 | + arg = nla_data(cpl_arg); |
---|
| 3536 | + |
---|
| 3537 | + if (nla_put_u16(skb, OVS_CHECK_PKT_LEN_ATTR_PKT_LEN, arg->pkt_len)) { |
---|
| 3538 | + err = -EMSGSIZE; |
---|
| 3539 | + goto out; |
---|
| 3540 | + } |
---|
| 3541 | + |
---|
| 3542 | + /* Second nested attribute in 'attr' is always |
---|
| 3543 | + * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL'. |
---|
| 3544 | + */ |
---|
| 3545 | + a = nla_next(cpl_arg, &rem); |
---|
| 3546 | + ac_start = nla_nest_start_noflag(skb, |
---|
| 3547 | + OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL); |
---|
| 3548 | + if (!ac_start) { |
---|
| 3549 | + err = -EMSGSIZE; |
---|
| 3550 | + goto out; |
---|
| 3551 | + } |
---|
| 3552 | + |
---|
| 3553 | + err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb); |
---|
| 3554 | + if (err) { |
---|
| 3555 | + nla_nest_cancel(skb, ac_start); |
---|
| 3556 | + goto out; |
---|
| 3557 | + } else { |
---|
| 3558 | + nla_nest_end(skb, ac_start); |
---|
| 3559 | + } |
---|
| 3560 | + |
---|
| 3561 | + /* Third nested attribute in 'attr' is always |
---|
| 3562 | + * OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER. |
---|
| 3563 | + */ |
---|
| 3564 | + a = nla_next(a, &rem); |
---|
| 3565 | + ac_start = nla_nest_start_noflag(skb, |
---|
| 3566 | + OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER); |
---|
| 3567 | + if (!ac_start) { |
---|
| 3568 | + err = -EMSGSIZE; |
---|
| 3569 | + goto out; |
---|
| 3570 | + } |
---|
| 3571 | + |
---|
| 3572 | + err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb); |
---|
| 3573 | + if (err) { |
---|
| 3574 | + nla_nest_cancel(skb, ac_start); |
---|
| 3575 | + goto out; |
---|
| 3576 | + } else { |
---|
| 3577 | + nla_nest_end(skb, ac_start); |
---|
| 3578 | + } |
---|
| 3579 | + |
---|
| 3580 | + nla_nest_end(skb, start); |
---|
| 3581 | + return 0; |
---|
| 3582 | + |
---|
| 3583 | +out: |
---|
| 3584 | + nla_nest_cancel(skb, start); |
---|
| 3585 | + return err; |
---|
| 3586 | +} |
---|
| 3587 | + |
---|
| 3588 | +static int dec_ttl_action_to_attr(const struct nlattr *attr, |
---|
| 3589 | + struct sk_buff *skb) |
---|
| 3590 | +{ |
---|
| 3591 | + struct nlattr *start, *action_start; |
---|
| 3592 | + const struct nlattr *a; |
---|
| 3593 | + int err = 0, rem; |
---|
| 3594 | + |
---|
| 3595 | + start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_DEC_TTL); |
---|
| 3596 | + if (!start) |
---|
| 3597 | + return -EMSGSIZE; |
---|
| 3598 | + |
---|
| 3599 | + nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) { |
---|
| 3600 | + switch (nla_type(a)) { |
---|
| 3601 | + case OVS_DEC_TTL_ATTR_ACTION: |
---|
| 3602 | + |
---|
| 3603 | + action_start = nla_nest_start_noflag(skb, OVS_DEC_TTL_ATTR_ACTION); |
---|
| 3604 | + if (!action_start) { |
---|
| 3605 | + err = -EMSGSIZE; |
---|
| 3606 | + goto out; |
---|
| 3607 | + } |
---|
| 3608 | + |
---|
| 3609 | + err = ovs_nla_put_actions(nla_data(a), nla_len(a), skb); |
---|
| 3610 | + if (err) |
---|
| 3611 | + goto out; |
---|
| 3612 | + |
---|
| 3613 | + nla_nest_end(skb, action_start); |
---|
| 3614 | + break; |
---|
| 3615 | + |
---|
| 3616 | + default: |
---|
| 3617 | + /* Ignore all other option to be future compatible */ |
---|
| 3618 | + break; |
---|
| 3619 | + } |
---|
| 3620 | + } |
---|
| 3621 | + |
---|
| 3622 | + nla_nest_end(skb, start); |
---|
| 3623 | + return 0; |
---|
| 3624 | + |
---|
| 3625 | +out: |
---|
| 3626 | + nla_nest_cancel(skb, start); |
---|
3183 | 3627 | return err; |
---|
3184 | 3628 | } |
---|
3185 | 3629 | |
---|
.. | .. |
---|
3195 | 3639 | struct ovs_tunnel_info *ovs_tun = nla_data(ovs_key); |
---|
3196 | 3640 | struct ip_tunnel_info *tun_info = &ovs_tun->tun_dst->u.tun_info; |
---|
3197 | 3641 | |
---|
3198 | | - start = nla_nest_start(skb, OVS_ACTION_ATTR_SET); |
---|
| 3642 | + start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET); |
---|
3199 | 3643 | if (!start) |
---|
3200 | 3644 | return -EMSGSIZE; |
---|
3201 | 3645 | |
---|
3202 | 3646 | err = ip_tun_to_nlattr(skb, &tun_info->key, |
---|
3203 | 3647 | ip_tunnel_info_opts(tun_info), |
---|
3204 | 3648 | tun_info->options_len, |
---|
3205 | | - ip_tunnel_info_af(tun_info)); |
---|
| 3649 | + ip_tunnel_info_af(tun_info), tun_info->mode); |
---|
3206 | 3650 | if (err) |
---|
3207 | 3651 | return err; |
---|
3208 | 3652 | nla_nest_end(skb, start); |
---|
.. | .. |
---|
3227 | 3671 | /* Revert the conversion we did from a non-masked set action to |
---|
3228 | 3672 | * masked set action. |
---|
3229 | 3673 | */ |
---|
3230 | | - nla = nla_nest_start(skb, OVS_ACTION_ATTR_SET); |
---|
| 3674 | + nla = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_SET); |
---|
3231 | 3675 | if (!nla) |
---|
3232 | 3676 | return -EMSGSIZE; |
---|
3233 | 3677 | |
---|
.. | .. |
---|
3277 | 3721 | return err; |
---|
3278 | 3722 | break; |
---|
3279 | 3723 | |
---|
| 3724 | + case OVS_ACTION_ATTR_CHECK_PKT_LEN: |
---|
| 3725 | + err = check_pkt_len_action_to_attr(a, skb); |
---|
| 3726 | + if (err) |
---|
| 3727 | + return err; |
---|
| 3728 | + break; |
---|
| 3729 | + |
---|
| 3730 | + case OVS_ACTION_ATTR_DEC_TTL: |
---|
| 3731 | + err = dec_ttl_action_to_attr(a, skb); |
---|
| 3732 | + if (err) |
---|
| 3733 | + return err; |
---|
| 3734 | + break; |
---|
| 3735 | + |
---|
3280 | 3736 | default: |
---|
3281 | 3737 | if (nla_put(skb, type, nla_len(a), nla_data(a))) |
---|
3282 | 3738 | return -EMSGSIZE; |
---|