@@ -1094,6 +1094,9 @@ struct tc_to_netdev {
* int (*ndo_get_irq_info)(struct net_device *dev,
* struct netpolicy_dev_info *info);
* This function is used to get irq information of rx and tx queues
+ * int (*ndo_set_net_policy)(struct net_device *dev,
+ * enum netpolicy_name name);
+ * This function is used to set global net policy by name
*
*/
struct net_device_ops {
@@ -1283,6 +1286,8 @@ struct net_device_ops {
struct netpolicy_info *info);
int (*ndo_get_irq_info)(struct net_device *dev,
struct netpolicy_dev_info *info);
+ int (*ndo_set_net_policy)(struct net_device *dev,
+ enum netpolicy_name name);
#endif /* CONFIG_NETPOLICY */
};
@@ -27,6 +27,7 @@ enum netpolicy_traffic {
NETPOLICY_RXTX,
};
+#define POLICY_NAME_LEN_MAX 64
extern const char *policy_name[];
struct netpolicy_dev_info {
@@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <linux/sort.h>
+#include <linux/ctype.h>
static int netpolicy_get_dev_info(struct net_device *dev,
struct netpolicy_dev_info *d_info)
@@ -430,6 +431,69 @@ err:
return ret;
}
+static int net_policy_set_by_name(char *name, struct net_device *dev)
+{
+ int i, ret;
+
+ spin_lock(&dev->np_lock);
+ ret = 0;
+
+ if (!dev->netpolicy ||
+ !dev->netdev_ops->ndo_set_net_policy) {
+ ret = -ENOTSUPP;
+ goto unlock;
+ }
+
+ for (i = 0; i < NET_POLICY_MAX; i++) {
+ if (!strncmp(name, policy_name[i], strlen(policy_name[i])))
+ break;
+ }
+
+ if (!test_bit(i, dev->netpolicy->avail_policy)) {
+ ret = -ENOTSUPP;
+ goto unlock;
+ }
+
+ if (i == dev->netpolicy->cur_policy)
+ goto unlock;
+
+ /* If there is no policy applied yet, need to do enable first . */
+ if (dev->netpolicy->cur_policy == NET_POLICY_NONE) {
+ ret = netpolicy_enable(dev);
+ if (ret)
+ goto unlock;
+ }
+
+ netpolicy_free_obj_list(dev);
+
+ /* Generate object list according to policy name */
+ ret = netpolicy_gen_obj_list(dev, i);
+ if (ret)
+ goto err;
+
+ /* set policy */
+ ret = dev->netdev_ops->ndo_set_net_policy(dev, i);
+ if (ret)
+ goto err;
+
+ /* If removing policy, need to do disable. */
+ if (i == NET_POLICY_NONE)
+ netpolicy_disable(dev);
+
+ dev->netpolicy->cur_policy = i;
+
+ spin_unlock(&dev->np_lock);
+ return 0;
+
+err:
+ netpolicy_free_obj_list(dev);
+ if (dev->netpolicy->cur_policy == NET_POLICY_NONE)
+ netpolicy_disable(dev);
+unlock:
+ spin_unlock(&dev->np_lock);
+ return ret;
+}
+
#ifdef CONFIG_PROC_FS
static int net_policy_proc_show(struct seq_file *m, void *v)
@@ -459,11 +523,40 @@ static int net_policy_proc_open(struct inode *inode, struct file *file)
return single_open(file, net_policy_proc_show, PDE_DATA(inode));
}
+static ssize_t net_policy_proc_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct seq_file *m = file->private_data;
+ struct net_device *dev = (struct net_device *)m->private;
+ char name[POLICY_NAME_LEN_MAX];
+ int i, ret;
+
+ if (!dev->netpolicy)
+ return -ENOTSUPP;
+
+ if (count > POLICY_NAME_LEN_MAX)
+ return -EINVAL;
+
+ if (copy_from_user(name, buf, count))
+ return -EINVAL;
+
+ for (i = 0; i < count - 1; i++)
+ name[i] = toupper(name[i]);
+ name[POLICY_NAME_LEN_MAX - 1] = 0;
+
+ ret = net_policy_set_by_name(name, dev);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
static const struct file_operations proc_net_policy_operations = {
.open = net_policy_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
+ .write = net_policy_proc_write,
.owner = THIS_MODULE,
};
@@ -527,6 +620,8 @@ void uninit_netpolicy(struct net_device *dev)
{
spin_lock(&dev->np_lock);
if (dev->netpolicy) {
+ if (dev->netpolicy->cur_policy > NET_POLICY_NONE)
+ netpolicy_disable(dev);
kfree(dev->netpolicy);
dev->netpolicy = NULL;
}