Initial implementation of sFlow.
[sliver-openvswitch.git] / datapath / datapath.c
index 6e97c34..f6a02f7 100644 (file)
@@ -232,7 +232,7 @@ static int create_dp(int dp_idx, const char __user *devnamep)
        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))
@@ -574,7 +574,7 @@ static int dp_frame_hook(struct net_bridge_port *p, struct sk_buff **pskb)
 #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. */
@@ -715,8 +715,7 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
        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)
@@ -1021,7 +1020,7 @@ static int del_flow(struct datapath *dp, struct odp_flow __user *ufp)
         * we get completely accurate stats, but that blows our performance,
         * badly. */
        dp->n_flows--;
-       error = answer_query(flow, uf.flags, ufp);
+       error = answer_query(flow, 0, ufp);
        flow_deferred_free(flow);
 
 error:
@@ -1046,7 +1045,7 @@ static int query_flows(struct datapath *dp, const struct odp_flowvec *flowvec)
                if (!flow)
                        error = __put_user(ENOENT, &ufp->stats.error);
                else
-                       error = answer_query(flow, 0, ufp);
+                       error = answer_query(flow, uf.flags, ufp);
                if (error)
                        return -EFAULT;
        }
@@ -1167,9 +1166,9 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep)
        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
@@ -1393,6 +1392,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
        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. */
@@ -1456,6 +1456,16 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                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;