#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include "flow.h"
-#include "datapath.h"
-#include "mpls.h"
#include <linux/uaccess.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rculist.h>
#include <net/geneve.h>
#include <net/ip.h>
-#include <net/ip_tunnels.h>
#include <net/ipv6.h>
#include <net/ndisc.h>
+#include <net/mpls.h>
+#include "datapath.h"
+#include "flow.h"
#include "flow_netlink.h"
static void update_range(struct sw_flow_match *match,
break;
case OVS_KEY_ATTR_TUNNEL:
+ if (eth_p_mpls(eth_type))
+ return -EINVAL;
+
*set_tun = true;
err = validate_and_copy_set_tun(a, sfa, log);
if (err)
__be16 eth_type, __be16 vlan_tci, bool log)
{
const struct nlattr *a;
+ bool out_tnl_port = false;
int rem, err;
if (depth >= SAMPLE_ACTION_DEPTH)
case OVS_ACTION_ATTR_OUTPUT:
if (nla_get_u32(a) >= DP_MAX_PORTS)
return -EINVAL;
+ out_tnl_port = false;
break;
case OVS_ACTION_ATTR_HASH: {
case OVS_ACTION_ATTR_PUSH_MPLS: {
const struct ovs_action_push_mpls *mpls = nla_data(a);
+ /* Networking stack do not allow simultaneous Tunnel
+ * and MPLS GSO.
+ */
+ if (out_tnl_port)
+ return -EINVAL;
+
if (!eth_p_mpls(mpls->mpls_ethertype))
return -EINVAL;
/* Prohibit push MPLS other than to a white list
break;
case OVS_ACTION_ATTR_SET:
- err = validate_set(a, key, sfa, &skip_copy, eth_type,
- log);
+ err = validate_set(a, key, sfa,
+ &out_tnl_port, eth_type, log);
if (err)
return err;
+ skip_copy = out_tnl_port;
break;
case OVS_ACTION_ATTR_SAMPLE: