datapath: Move sysfs support from brcompat_mod into openvswitch_mod.
[sliver-openvswitch.git] / datapath / brcompat.c
index d945e4e..46e7f2b 100644 (file)
@@ -261,6 +261,64 @@ brc_get_port_list(struct net_device *dev, int __user *uindices, int num)
        return num;
 }
 
+/*
+ * Format up to a page worth of forwarding table entries
+ * userbuf -- where to copy result
+ * maxnum  -- maximum number of entries desired
+ *            (limited to a page for sanity)
+ * offset  -- number of records to skip
+ */
+static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf, 
+                              unsigned long maxnum, unsigned long offset)
+{
+       struct nlattr *attrs[BRC_GENL_A_MAX + 1];
+       struct sk_buff *request, *reply;
+       int retval;
+       int len;
+
+       /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
+       if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
+               maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
+
+       request = brc_make_request(BRC_GENL_C_FDB_QUERY, dev->name, NULL);
+       if (!request)
+               return -ENOMEM;
+       NLA_PUT_U64(request, BRC_GENL_A_FDB_COUNT, maxnum);
+       NLA_PUT_U64(request, BRC_GENL_A_FDB_SKIP, offset);
+
+       rtnl_unlock();
+       reply = brc_send_command(request, attrs);
+       retval = PTR_ERR(reply);
+       if (IS_ERR(reply))
+               goto exit;
+
+       retval = -nla_get_u32(attrs[BRC_GENL_A_ERR_CODE]);
+       if (retval < 0)
+               goto exit_free_skb;
+
+       retval = -EINVAL;
+       if (!attrs[BRC_GENL_A_FDB_DATA])
+               goto exit_free_skb;
+       len = nla_len(attrs[BRC_GENL_A_FDB_DATA]);
+       if (len % sizeof(struct __fdb_entry) ||
+           len / sizeof(struct __fdb_entry) > maxnum)
+               goto exit_free_skb;
+
+       retval = len / sizeof(struct __fdb_entry);
+       if (copy_to_user(userbuf, nla_data(attrs[BRC_GENL_A_FDB_DATA]), len))
+               retval = -EFAULT;
+
+exit_free_skb:
+       kfree_skb(reply);
+exit:
+       rtnl_lock();
+       return retval;
+
+nla_put_failure:
+       kfree_skb(request);
+       return -ENOMEM;
+}
+
 /* Legacy ioctl's through SIOCDEVPRIVATE.  Called with rtnl_lock. */
 static int
 old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -281,6 +339,10 @@ old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        case BRCTL_GET_PORT_LIST:
                return brc_get_port_list(dev, (int __user *)args[1], args[2]);
+
+       case BRCTL_GET_FDB_ENTRIES:
+               return brc_get_fdb_entries(dev, (void __user *)args[1],
+                                          args[2], args[3]);
        }
 
        return -EOPNOTSUPP;
@@ -357,9 +419,12 @@ static struct genl_ops brc_genl_ops_query_dp = {
 /* Attribute policy: what each attribute may contain.  */
 static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = {
        [BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 },
+
        [BRC_GENL_A_PROC_DIR] = { .type = NLA_NUL_STRING },
        [BRC_GENL_A_PROC_NAME] = { .type = NLA_NUL_STRING },
        [BRC_GENL_A_PROC_DATA] = { .type = NLA_NUL_STRING },
+
+       [BRC_GENL_A_FDB_DATA] = { .type = NLA_UNSPEC },
 };
 
 static int
@@ -458,27 +523,6 @@ error:
        return ERR_PTR(error);
 }
 
-int brc_add_dp(struct datapath *dp)
-{
-       if (!try_module_get(THIS_MODULE))
-               return -ENODEV;
-#ifdef SUPPORT_SYSFS
-       brc_sysfs_add_dp(dp);
-#endif
-
-       return 0;
-}
-
-int brc_del_dp(struct datapath *dp) 
-{
-#ifdef SUPPORT_SYSFS
-       brc_sysfs_del_dp(dp);
-#endif
-       module_put(THIS_MODULE);
-
-       return 0;
-}
-
 static int 
 __init brc_init(void)
 {
@@ -503,16 +547,6 @@ __init brc_init(void)
        /* Set the openvswitch_mod device ioctl handler */
        dp_ioctl_hook = brc_dev_ioctl;
 
-       /* Register hooks for datapath adds and deletes */
-       dp_add_dp_hook = brc_add_dp;
-       dp_del_dp_hook = brc_del_dp;
-
-       /* Register hooks for interface adds and deletes */
-#ifdef SUPPORT_SYSFS
-       dp_add_if_hook = brc_sysfs_add_if;
-       dp_del_if_hook = brc_sysfs_del_if;
-#endif
-
        /* Randomize the initial sequence number.  This is not a security
         * feature; it only helps avoid crossed wires between userspace and
         * the kernel when the module is unloaded and reloaded. */
@@ -553,14 +587,6 @@ error:
 static void 
 brc_cleanup(void)
 {
-       /* Unregister hooks for datapath adds and deletes */
-       dp_add_dp_hook = NULL;
-       dp_del_dp_hook = NULL;
-       
-       /* Unregister hooks for interface adds and deletes */
-       dp_add_if_hook = NULL;
-       dp_del_if_hook = NULL;
-
        /* Unregister ioctl hooks */
        dp_ioctl_hook = NULL;
        brioctl_set(NULL);