#include "vlan.h"
#include "vport-internal_dev.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \
+ LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
+#error Kernels before 2.6.18 or after 3.0 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);
static LIST_HEAD(dps);
static struct vport *new_vport(const struct vport_parms *);
-static int queue_control_packets(struct datapath *, struct sk_buff *,
+static int queue_userspace_packets(struct datapath *, struct sk_buff *,
const struct dp_upcall_info *);
/* Must be called with rcu_read_lock, genl_mutex, or RTNL lock. */
}
if (is_frag && dp->drop_frags) {
- kfree_skb(skb);
+ consume_skb(skb);
stats_counter_off = offsetof(struct dp_stats_percpu, n_frags);
goto out;
}
WARN_ON_ONCE(skb_shared(skb));
- forward_ip_summed(skb);
-
- err = vswitch_skb_checksum_setup(skb);
- if (err)
- goto err_kfree_skb;
+ forward_ip_summed(skb, true);
/* Break apart GSO packets into their component pieces. Otherwise
* userspace may try to stuff a 64kB packet into a 1500-byte MTU. */
if (skb_is_gso(skb)) {
struct sk_buff *nskb = skb_gso_segment(skb, NETIF_F_SG | NETIF_F_HW_CSUM);
- kfree_skb(skb);
- skb = nskb;
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
+ if (IS_ERR(nskb)) {
+ kfree_skb(skb);
+ err = PTR_ERR(nskb);
goto err;
}
+ consume_skb(skb);
+ skb = nskb;
}
- err = queue_control_packets(dp, skb, upcall_info);
+ err = queue_userspace_packets(dp, skb, upcall_info);
if (err)
goto err;
return 0;
-err_kfree_skb:
- kfree_skb(skb);
err:
local_bh_disable();
stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
* 'upcall_info'. There will be only one packet unless we broke up a GSO
* packet.
*/
-static int queue_control_packets(struct datapath *dp, struct sk_buff *skb,
+static int queue_userspace_packets(struct datapath *dp, struct sk_buff *skb,
const struct dp_upcall_info *upcall_info)
{
u32 group = packet_mc_group(dp, upcall_info->cmd);
if (err)
goto err_kfree_skbs;
- kfree_skb(skb);
+ consume_skb(skb);
skb = nskb;
} while (skb);
return 0;
nla_for_each_nested(a, attr, rem) {
static const u32 action_lens[ODP_ACTION_ATTR_MAX + 1] = {
[ODP_ACTION_ATTR_OUTPUT] = 4,
- [ODP_ACTION_ATTR_CONTROLLER] = 8,
+ [ODP_ACTION_ATTR_USERSPACE] = 8,
[ODP_ACTION_ATTR_SET_DL_TCI] = 2,
[ODP_ACTION_ATTR_STRIP_VLAN] = 0,
[ODP_ACTION_ATTR_SET_DL_SRC] = ETH_ALEN,
[ODP_ACTION_ATTR_SET_TUNNEL] = 8,
[ODP_ACTION_ATTR_SET_PRIORITY] = 4,
[ODP_ACTION_ATTR_POP_PRIORITY] = 0,
- [ODP_ACTION_ATTR_DROP_SPOOFED_ARP] = 0,
};
int type = nla_type(a);
case ODP_ACTION_ATTR_UNSPEC:
return -EINVAL;
- case ODP_ACTION_ATTR_CONTROLLER:
+ case ODP_ACTION_ATTR_USERSPACE:
case ODP_ACTION_ATTR_STRIP_VLAN:
case ODP_ACTION_ATTR_SET_DL_SRC:
case ODP_ACTION_ATTR_SET_DL_DST:
case ODP_ACTION_ATTR_SET_TUNNEL:
case ODP_ACTION_ATTR_SET_PRIORITY:
case ODP_ACTION_ATTR_POP_PRIORITY:
- case ODP_ACTION_ATTR_DROP_SPOOFED_ARP:
/* No validation needed. */
break;
struct tbl *new_table;
new_table = tbl_expand(old_table);
- if (IS_ERR(new_table))
- return PTR_ERR(new_table);
-
- rcu_assign_pointer(dp->table, new_table);
- tbl_deferred_destroy(old_table, NULL);
+ if (IS_ERR(new_table)) {
+ if (PTR_ERR(new_table) != -ENOSPC)
+ return PTR_ERR(new_table);
+ } else {
+ rcu_assign_pointer(dp->table, new_table);
+ tbl_deferred_destroy(old_table, NULL);
+ }
return 0;
}
static void get_dp_stats(struct datapath *dp, struct odp_stats *stats)
{
int i;
+ struct tbl *table = get_table_protected(dp);
+
+ stats->n_flows = tbl_count(table);
stats->n_frags = stats->n_hit = stats->n_missed = stats->n_lost = 0;
for_each_possible_cpu(i) {