/*
- * Copyright (c) 2007, 2008, 2009 Nicira Networks.
+ * Copyright (c) 2007, 2008, 2009, 2010 Nicira Networks.
* Distributed under the terms of the GNU GPL version 2.
*
* Significant portions of this file may be copied from parts of the Linux
if (!dp->table)
goto err_free_dp;
- /* Setup our datapath device */
+ /* Set up our datapath device. */
dp_dev = dp_dev_create(dp, devname, ODPP_LOCAL);
err = PTR_ERR(dp_dev);
if (IS_ERR(dp_dev))
p->port_no = port_no;
p->dp = dp;
p->dev = dev;
+ atomic_set(&p->sflow_pool, 0);
if (!is_dp_dev(dev))
rcu_assign_pointer(dev->br_port, p);
else {
#error
#endif
-#if defined(CONFIG_XEN) && LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
+#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
/* This code is copied verbatim from net/dev/core.c in Xen's
* linux-2.6.18-92.1.10.el5.xs5.0.0.394.644. We can't call those functions
* directly because they aren't exported. */
out:
return -EPROTO;
}
-#else
-int vswitch_skb_checksum_setup(struct sk_buff *skb) { return 0; }
-#endif /* CONFIG_XEN && linux == 2.6.18 */
+#endif /* CONFIG_XEN && HAVE_PROTO_DATA_VALID */
/* Append each packet in 'skb' list to 'queue'. There will be only one packet
* unless we broke up a GSO packet. */
int err;
WARN_ON_ONCE(skb_shared(skb));
- BUG_ON(queue_no != _ODPL_MISS_NR && queue_no != _ODPL_ACTION_NR);
-
+ BUG_ON(queue_no != _ODPL_MISS_NR && queue_no != _ODPL_ACTION_NR && queue_no != _ODPL_SFLOW_NR);
queue = &dp->queues[queue_no];
err = -ENOBUFS;
if (skb_queue_len(queue) >= DP_MAX_QUEUE_LEN)
return 0;
}
-static int answer_query(struct sw_flow *flow, struct odp_flow __user *ufp)
+static int answer_query(struct sw_flow *flow, u32 query_flags,
+ struct odp_flow __user *ufp)
{
struct odp_flow_stats stats;
unsigned long int flags;
spin_lock_irqsave(&flow->lock, flags);
get_stats(flow, &stats);
+
+ if (query_flags & ODPFF_ZERO_TCP_FLAGS) {
+ flow->tcp_flags = 0;
+ }
spin_unlock_irqrestore(&flow->lock, flags);
if (__copy_to_user(&ufp->stats, &stats, sizeof(struct odp_flow_stats)))
* we get completely accurate stats, but that blows our performance,
* badly. */
dp->n_flows--;
- error = answer_query(flow, ufp);
+ error = answer_query(flow, 0, ufp);
flow_deferred_free(flow);
error:
if (!flow)
error = __put_user(ENOENT, &ufp->stats.error);
else
- error = answer_query(flow, ufp);
+ error = answer_query(flow, uf.flags, ufp);
if (error)
return -EFAULT;
}
if (__copy_to_user(&ufp->key, &flow->key, sizeof flow->key))
return -EFAULT;
- error = answer_query(flow, ufp);
+ error = answer_query(flow, 0, ufp);
if (error)
return error;
skb_reset_mac_header(skb);
eth = eth_hdr(skb);
- /* Normally, setting the skb 'protocol' field would be handled by a
- * call to eth_type_trans(), but it assumes there's a sending
- * device, which we may not have. */
+ /* Normally, setting the skb 'protocol' field would be handled by a
+ * call to eth_type_trans(), but it assumes there's a sending
+ * device, which we may not have. */
if (ntohs(eth->h_proto) >= 1536)
skb->protocol = eth->h_proto;
else
int dp_idx = iminor(f->f_dentry->d_inode);
struct datapath *dp;
int drop_frags, listeners, port_no;
+ unsigned int sflow_probability;
int err;
/* Handle commands with special locking requirements up front. */
set_listen_mask(f, listeners);
break;
+ case ODP_GET_SFLOW_PROBABILITY:
+ err = put_user(dp->sflow_probability, (unsigned int __user *)argp);
+ break;
+
+ case ODP_SET_SFLOW_PROBABILITY:
+ err = get_user(sflow_probability, (unsigned int __user *)argp);
+ if (!err)
+ dp->sflow_probability = sflow_probability;
+ break;
+
case ODP_PORT_QUERY:
err = query_port(dp, (struct odp_port __user *)argp);
break;