/* Kernel AODV v2.1 National Institute of Standards and Technology Luke Klein-Berndt ----------------------------------------------------- Version 2.1 new features: * Much more stable! * Added locks around important areas * Multihop Internet gatewaying now works * Multicast hack added * Many bug fixes! ----------------------------------------------------- Originally based upon MadHoc code. I am not sure how much of it is left anymore, but MadHoc proved to be a great starting point. MadHoc was written by - Fredrik Lilieblad, Oskar Mattsson, Petra Nylund, Dan Ouchterlony and Anders Roxenhag Mail: mad-hoc@flyinglinux.net This software is Open Source under the GNU General Public Licence. */ /**************************************************** aodv_thread ---------------------------------------------------- This is the main thread which handles the processing of packets which are placed in its queue. After netfilter calls packet_in on an interuppt, packet_in takes the packet and if it is an AODV packet it places into the event queue. It then kicks aodv_thread. Aodv_thread processes the event and pass it along to the correct function. ****************************************************/ #include "aodv_thread.h" static int aodv_pid; static wait_queue_head_t aodv_wait; static atomic_t kill_thread; static atomic_t aodv_is_dead; /**************************************************** kick_aodv ---------------------------------------------------- Wakes up the aodv_thread. You call this after you have placed something on the event queue. ****************************************************/ void kick_aodv() { //We are trying to wake up AODV!!! //AODV thread is an interupptible sleep state.... this interupts it wake_up_interruptible(&aodv_wait); } /**************************************************** kill_aodv ---------------------------------------------------- This will kill the AODV Thread. It sets the kill flag and then wakes up AODV thread. If it does not get confirmation that AODV is dead it will try again! ****************************************************/ void kill_aodv() { wait_queue_head_t queue; int count=0; //starts a wait queue init_waitqueue_head(&queue); //sets a flag letting the thread know it should die //wait for the thread to set flag saying it is dead while ((atomic_read(&aodv_is_dead)==0) && (count<5)) { //lower semaphore for the thread atomic_set(&kill_thread,1); wake_up_interruptible(&aodv_wait); interruptible_sleep_on_timeout(&queue,HZ); //sleep for a bit and then check on the thread again count++; } if (count>4) printk(KERN_WARNING "AODV_THREAD: Tried to kill AODV Thread, but failed. It may have crashed. \n"); } /**************************************************** aodv ---------------------------------------------------- This is the main section of the thread. The main loop! The big enchilada! It is a big loop which will handle everything in the Event queue and then goto sleep. ****************************************************/ void aodv() { //The queue holding all the events to be dealt with struct event_queue_entry *working_event; //Initalize the variables init_waitqueue_head(&aodv_wait); atomic_set(&kill_thread,0); atomic_set(&aodv_is_dead,0); //Name our thread lock_kernel(); sprintf(current->comm,"kernel-aodv"); exit_mm(current); unlock_kernel(); //why would I ever want to stop ? :) for (;;) { //should the thread exit? if (atomic_read(&kill_thread)) { goto exit; } //goto sleep until we recieve an interupt interruptible_sleep_on(&aodv_wait); //should the thread exit? if (atomic_read(&kill_thread)) { goto exit; } //While the buffer is not empty while((working_event=get_next_event_queue_entry())!=NULL) { if ((getcurrtime() - working_event->time) > 1000) { printk(KERN_INFO "AODV_THREAD: AODV packet queued too long\n"); } //takes a different action depending on what type of event is recieved switch (working_event->type) { //RREQ case EVENT_RREQ: monitor.rreq++; recv_rreq(working_event); kfree(working_event->data); break; //RREP case EVENT_RREP: monitor.rrep++; recv_rrep(working_event); kfree(working_event->data); break; case EVENT_RREP_ACK: recv_rrep_ack(working_event); kfree(working_event->data); break; //RERR case EVENT_RERR: monitor.rrer++; recv_rerr(working_event); kfree(working_event->data); break; //Cleanup the Route Table and Flood ID queue case EVENT_CLEANUP: find_inactive_route_table_entries(); delete_old_flood_id_queue_entries(); break; default: break; } kfree(working_event); } } exit: //Set the flag that shows you are dead atomic_set(&aodv_is_dead,1); } /**************************************************** startup_aodv ---------------------------------------------------- Creates AODV thread and tells it to start in the function aodv() ****************************************************/ void startup_aodv() { //start the thread and have it start in the aodv function aodv_pid=kernel_thread((void *) &aodv,NULL,0); }