ovsdb: Refactor JSON-RPC database server implementation.
[openvswitch] / datapath / datapath.c
index e927b2469515938fe9f5e08f5c1bfa5debf32076..1ae1d771a31a5a3f2128ee75f474cf9e2c645f1d 100644 (file)
@@ -782,7 +782,8 @@ static int validate_actions(const struct sw_flow_actions *actions)
                        break;
 
                case ODPAT_SET_VLAN_PCP:
-                       if (a->vlan_pcp.vlan_pcp & ~VLAN_PCP_MASK)
+                       if (a->vlan_pcp.vlan_pcp
+                           & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT))
                                return -EINVAL;
                        break;
 
@@ -1371,6 +1372,16 @@ get_port_group(struct datapath *dp, struct odp_port_group *upg)
        return 0;
 }
 
+static int get_listen_mask(const struct file *f)
+{
+       return (long)f->private_data;
+}
+
+static void set_listen_mask(struct file *f, int listen_mask)
+{
+       f->private_data = (void*)(long)listen_mask;
+}
+
 static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                           unsigned long argp)
 {
@@ -1426,7 +1437,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                break;
 
        case ODP_GET_LISTEN_MASK:
-               err = put_user((int)f->private_data, (int __user *)argp);
+               err = put_user(get_listen_mask(f), (int __user *)argp);
                break;
 
        case ODP_SET_LISTEN_MASK:
@@ -1437,7 +1448,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd,
                if (listeners & ~ODPL_ALL)
                        break;
                err = 0;
-               f->private_data = (void*)listeners;
+               set_listen_mask(f, listeners);
                break;
 
        case ODP_PORT_QUERY:
@@ -1503,7 +1514,7 @@ ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes,
                      loff_t *ppos)
 {
        /* XXX is there sufficient synchronization here? */
-       int listeners = (int) f->private_data;
+       int listeners = get_listen_mask(f);
        int dp_idx = iminor(f->f_dentry->d_inode);
        struct datapath *dp = get_dp(dp_idx);
        struct sk_buff *skb;
@@ -1543,7 +1554,7 @@ ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes,
                }
        }
 success:
-       copy_bytes = min(skb->len, nbytes);
+       copy_bytes = min_t(size_t, skb->len, nbytes);
        iov.iov_base = buf;
        iov.iov_len = copy_bytes;
        retval = skb_copy_datagram_iovec(skb, 0, &iov, iov.iov_len);
@@ -1565,7 +1576,7 @@ static unsigned int openvswitch_poll(struct file *file, poll_table *wait)
        if (dp) {
                mask = 0;
                poll_wait(file, &dp->waitqueue, wait);
-               if (dp_has_packet_of_interest(dp, (int)file->private_data))
+               if (dp_has_packet_of_interest(dp, get_listen_mask(file)))
                        mask |= POLLIN | POLLRDNORM;
        } else {
                mask = POLLIN | POLLRDNORM | POLLHUP;
@@ -1582,6 +1593,8 @@ struct file_operations openvswitch_fops = {
 };
 
 static int major;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
 static struct llc_sap *dp_stp_sap;
 
 static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
@@ -1594,12 +1607,8 @@ static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
        return 0;
 }
 
-static int __init dp_init(void)
+static int dp_avoid_bridge_init(void)
 {
-       int err;
-
-       printk("Open vSwitch %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR);
-
        /* Register to receive STP packets because the bridge module also
         * attempts to do so.  Since there can only be a single listener for a
         * given protocol, this provides mutual exclusion against the bridge
@@ -1610,6 +1619,43 @@ static int __init dp_init(void)
                printk(KERN_ERR "openvswitch: can't register sap for STP (probably the bridge module is loaded)\n");
                return -EADDRINUSE;
        }
+       return 0;
+}
+
+static void dp_avoid_bridge_exit(void)
+{
+       llc_sap_put(dp_stp_sap);
+}
+#else  /* Linux 2.6.27 or later. */
+static int dp_avoid_bridge_init(void)
+{
+       /* Linux 2.6.27 introduces a way for multiple clients to register for
+        * STP packets, which interferes with what we try to do above.
+        * Instead, just check whether there's a bridge hook defined.  This is
+        * not as safe--the bridge module is willing to load over the top of
+        * us--but it provides a little bit of protection. */
+       if (br_handle_frame_hook) {
+               printk(KERN_ERR "openvswitch: bridge module is loaded, cannot load over it\n");
+               return -EADDRINUSE;
+       }
+       return 0;
+}
+
+static void dp_avoid_bridge_exit(void)
+{
+       /* Nothing to do. */
+}
+#endif /* Linux 2.6.27 or later */
+
+static int __init dp_init(void)
+{
+       int err;
+
+       printk("Open vSwitch %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR);
+
+       err = dp_avoid_bridge_init();
+       if (err)
+               return err;
 
        err = flow_init();
        if (err)
@@ -1644,7 +1690,7 @@ static void dp_cleanup(void)
        unregister_netdevice_notifier(&dp_device_notifier);
        flow_exit();
        br_handle_frame_hook = NULL;
-       llc_sap_put(dp_stp_sap);
+       dp_avoid_bridge_exit();
 }
 
 module_init(dp_init);