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
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)
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>
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)
39 spin_lock_irqsave(&ppesched_lock
, flags
);
40 if (unlikely(ppesched_current
== -1)) {
41 spin_unlock_irqrestore(&ppesched_lock
, flags
);
44 ret
= ppesched_discipline_table
[ppesched_current
]->ops
->discipline_init();
45 spin_unlock_irqrestore(&ppesched_lock
, flags
);
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
)
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
);
60 EXPORT_SYMBOL_GPL(ppesched_sched
);
62 void ppesched_cleanup(void)
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
)
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))
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
)
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;
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
)
111 spin_lock(&ppesched_lock
);
112 len
+= sprintf(page
+ len
, "running: %s\n",
113 ppesched_current
!= -1 ?
114 ppesched_discipline_table
[ppesched_current
]->name
:
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
);
129 static int ppesched_procfs_write(struct file
*file
, const char __user
*buffer
,
130 unsigned long count
, void *data
)
137 discipline
= kzalloc(32, GFP_KERNEL
);
140 len
= min(sizeof(discipline
), (size_t) count
);
141 if (copy_from_user(discipline
, buffer
, len
)) {
145 discipline
[sizeof(discipline
) - 1] = 0;
146 res
= simple_strtoul(discipline
, &discipline
, 10);
147 if (res
>= MAX_SCHED
) {
151 spin_lock(&ppesched_lock
);
152 if (!ppesched_discipline_table
[res
]) {
153 spin_unlock(&ppesched_lock
);
157 ppesched_current
= res
;
158 spin_unlock(&ppesched_lock
);
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
);
174 ppesched_proc
->read_proc
= ppesched_procfs_read
;
175 ppesched_proc
->write_proc
= ppesched_procfs_write
;
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
);