Prepare Open vSwitch 1.1.2 release.
[sliver-openvswitch.git] / datapath / datapath.c
index b25b899..d901e6b 100644 (file)
 #include "vlan.h"
 #include "vport-internal_dev.h"
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \
+    LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)
+#error Kernels before 2.6.18 or after 2.6.38 are not supported by this version of Open vSwitch.
+#endif
+
 int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
 EXPORT_SYMBOL(dp_ioctl_hook);
 
@@ -682,23 +687,26 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        struct datapath *dp;
        struct ethhdr *eth;
        bool is_frag;
+       int len;
        int err;
 
        err = -EINVAL;
        if (!a[ODP_PACKET_ATTR_PACKET] || !a[ODP_PACKET_ATTR_ACTIONS] ||
            nla_len(a[ODP_PACKET_ATTR_PACKET]) < ETH_HLEN)
-               goto exit;
+               goto err;
 
        err = validate_actions(a[ODP_PACKET_ATTR_ACTIONS]);
        if (err)
-               goto exit;
+               goto err;
 
-       packet = skb_clone(skb, GFP_KERNEL);
+       len = nla_len(a[ODP_PACKET_ATTR_PACKET]);
+       packet = __dev_alloc_skb(NET_IP_ALIGN + len, GFP_KERNEL);
        err = -ENOMEM;
        if (!packet)
-               goto exit;
-       packet->data = nla_data(a[ODP_PACKET_ATTR_PACKET]);
-       packet->len = nla_len(a[ODP_PACKET_ATTR_PACKET]);
+               goto err;
+       skb_reserve(packet, NET_IP_ALIGN);
+
+       memcpy(__skb_put(packet, len), nla_data(a[ODP_PACKET_ATTR_PACKET]), len);
 
        skb_reset_mac_header(packet);
        eth = eth_hdr(packet);
@@ -716,18 +724,24 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 
        err = flow_extract(packet, -1, &key, &is_frag);
        if (err)
-               goto exit;
+               goto err_kfree_skb;
 
        rcu_read_lock();
        dp = get_dp(odp_header->dp_ifindex);
        err = -ENODEV;
-       if (dp)
-               err = execute_actions(dp, packet, &key,
-                                     nla_data(a[ODP_PACKET_ATTR_ACTIONS]),
-                                     nla_len(a[ODP_PACKET_ATTR_ACTIONS]));
+       if (!dp)
+               goto err_unlock;
+       err = execute_actions(dp, packet, &key,
+                             nla_data(a[ODP_PACKET_ATTR_ACTIONS]),
+                             nla_len(a[ODP_PACKET_ATTR_ACTIONS]));
        rcu_read_unlock();
+       return err;
 
-exit:
+err_unlock:
+       rcu_read_unlock();
+err_kfree_skb:
+       kfree_skb(packet);
+err:
        return err;
 }
 
@@ -1304,7 +1318,7 @@ static int odp_dp_cmd_validate(struct nlattr *a[ODP_DP_ATTR_MAX + 1])
                        return -EINVAL;
        }
 
-       return VERIFY_NUL_STRING(a[ODP_DP_ATTR_NAME], IFNAMSIZ - 1);
+       return CHECK_NUL_STRING(a[ODP_DP_ATTR_NAME], IFNAMSIZ - 1);
 }
 
 /* Called with genl_mutex and optionally with RTNL lock also. */
@@ -1674,7 +1688,7 @@ static struct sk_buff *odp_vport_cmd_build_info(struct vport *vport, u32 pid,
 
 static int odp_vport_cmd_validate(struct nlattr *a[ODP_VPORT_ATTR_MAX + 1])
 {
-       return VERIFY_NUL_STRING(a[ODP_VPORT_ATTR_NAME], IFNAMSIZ - 1);
+       return CHECK_NUL_STRING(a[ODP_VPORT_ATTR_NAME], IFNAMSIZ - 1);
 }
 
 /* Called with RTNL lock or RCU read lock. */