fixed compile warnings, removed unused enum
[ana-net.git] / src / xt_sched.c
blob50ee16e8f1fd989de4581b6713b3ba061177c415
1 /*
2 * Lightweight Autonomic Network Architecture
4 * Ingress and egress flow ppe-scheduler. Flows that traverse the network
5 * stack, e.g. ranging from PHY to the socket handler, are kept CPU-affine
6 * for the communication. This scheduler framework offers modules to register
7 * their disciplines.
9 * Change scheduling policies with, i.e. echo "1" > /proc/net/lana/ppesched
10 * where "n" is the id of the discipline.
12 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
13 * Swiss federal institute of technology (ETH Zurich)
14 * Subject to the GPL.
17 #include <linux/kernel.h>
18 #include <linux/skbuff.h>
19 #include <linux/proc_fs.h>
20 #include <linux/skbuff.h>
21 #include <linux/spinlock.h>
22 #include <linux/module.h>
24 #include "xt_sched.h"
26 #define MAX_SCHED 32
28 static int ppesched_current = -1;
29 static spinlock_t ppesched_lock;
30 struct ppesched_discipline *ppesched_discipline_table[MAX_SCHED];
32 extern struct proc_dir_entry *lana_proc_dir;
33 static struct proc_dir_entry *ppesched_proc;
35 int ppesched_init(void)
37 int ret;
38 unsigned long flags;
39 spin_lock_irqsave(&ppesched_lock, flags);
40 if (unlikely(ppesched_current == -1)) {
41 spin_unlock_irqrestore(&ppesched_lock, flags);
42 return -ENOENT;
44 ret = ppesched_discipline_table[ppesched_current]->ops->discipline_init();
45 spin_unlock_irqrestore(&ppesched_lock, flags);
46 return ret;
48 EXPORT_SYMBOL_GPL(ppesched_init);
50 /* ppesched_current must be set previously! */
51 int ppesched_sched(struct sk_buff *skb, enum path_type dir)
53 int ret;
54 unsigned long flags;
55 spin_lock_irqsave(&ppesched_lock, flags);
56 ret = ppesched_discipline_table[ppesched_current]->ops->discipline_sched(skb, dir);
57 spin_unlock_irqrestore(&ppesched_lock, flags);
58 return ret;
60 EXPORT_SYMBOL_GPL(ppesched_sched);
62 void ppesched_cleanup(void)
64 unsigned long flags;
65 spin_lock_irqsave(&ppesched_lock, flags);
66 ppesched_discipline_table[ppesched_current]->ops->discipline_cleanup();
67 spin_unlock_irqrestore(&ppesched_lock, flags);
69 EXPORT_SYMBOL_GPL(ppesched_cleanup);
71 int ppesched_discipline_register(struct ppesched_discipline *pd)
73 int i, done = 0;
74 spin_lock(&ppesched_lock);
75 for (i = 0; i < MAX_SCHED; ++i) {
76 if (!ppesched_discipline_table[i]) {
77 ppesched_discipline_table[i] = pd;
78 if (unlikely(ppesched_current == -1))
79 ppesched_current = i;
80 done = 1;
81 break;
84 spin_unlock(&ppesched_lock);
85 return done ? 0 : -ENOMEM;
87 EXPORT_SYMBOL_GPL(ppesched_discipline_register);
89 void ppesched_discipline_unregister(struct ppesched_discipline *pd)
91 int i;
92 spin_lock(&ppesched_lock);
93 for (i = 0; i < MAX_SCHED; ++i) {
94 if (ppesched_discipline_table[i] == pd) {
95 ppesched_discipline_table[i] = NULL;
96 if (i == ppesched_current)
97 ppesched_current = -1;
98 break;
101 spin_unlock(&ppesched_lock);
103 EXPORT_SYMBOL_GPL(ppesched_discipline_unregister);
105 static int ppesched_procfs_read(char *page, char **start, off_t offset,
106 int count, int *eof, void *data)
108 int i;
109 off_t len = 0;
111 spin_lock(&ppesched_lock);
112 len += sprintf(page + len, "running: %s\n",
113 ppesched_current != -1 ?
114 ppesched_discipline_table[ppesched_current]->name :
115 "none");
116 len += sprintf(page + len, "name addr id\n");
117 for (i = 0; i < MAX_SCHED; ++i) {
118 if (ppesched_discipline_table[i])
119 len += sprintf(page + len, "%s %p %d\n",
120 ppesched_discipline_table[i]->name,
121 ppesched_discipline_table[i], i);
123 spin_unlock(&ppesched_lock);
125 *eof = 1;
126 return len;
129 static int ppesched_procfs_write(struct file *file, const char __user *buffer,
130 unsigned long count, void *data)
132 int ret;
133 unsigned long res;
134 size_t len;
135 char *discipline;
137 discipline = kzalloc(32, GFP_KERNEL);
138 if (!discipline)
139 return -ENOMEM;
140 len = min(sizeof(discipline), (size_t) count);
141 if (copy_from_user(discipline, buffer, len)) {
142 ret = -EFAULT;
143 goto out;
145 discipline[sizeof(discipline) - 1] = 0;
146 res = simple_strtoul(discipline, &discipline, 10);
147 if (res >= MAX_SCHED) {
148 ret = -EINVAL;
149 goto out;
151 spin_lock(&ppesched_lock);
152 if (!ppesched_discipline_table[res]) {
153 spin_unlock(&ppesched_lock);
154 ret = -EINVAL;
155 goto out;
157 ppesched_current = res;
158 spin_unlock(&ppesched_lock);
160 return count;
161 out:
162 kfree(discipline);
163 return ret;
166 int init_ppesched_system(void)
168 ppesched_lock = __SPIN_LOCK_UNLOCKED(ppesched_lock);
169 memset(ppesched_discipline_table, 0,
170 sizeof(ppesched_discipline_table));
171 ppesched_proc = create_proc_entry("ppesched", 0600, lana_proc_dir);
172 if (!ppesched_proc)
173 return -ENOMEM;
174 ppesched_proc->read_proc = ppesched_procfs_read;
175 ppesched_proc->write_proc = ppesched_procfs_write;
176 return 0;
178 EXPORT_SYMBOL_GPL(init_ppesched_system);
180 void cleanup_ppesched_system(void)
182 remove_proc_entry("ppesched", lana_proc_dir);
184 EXPORT_SYMBOL_GPL(cleanup_ppesched_system);