diff -Naur test-for-latech/arch/arm/config.in testqf-for-latech/arch/arm/config.in --- test-for-latech/arch/arm/config.in 2004-06-11 07:42:31.000000000 -0400 +++ testqf-for-latech/arch/arm/config.in 2004-06-11 07:49:18.000000000 -0400 @@ -654,4 +654,15 @@ dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X + +#dep_bool 'modular DWCS scheduler' CONFIG_DWCS $CONFIG_PROC_FS +#dep_bool ' DFS Support' CONFIG_DWCS_DFS $CONFIG_DWCS + +bool 'Quality of Service Support (Q-Fabric)' CONFIG_QFABRIC +if [ "$CONFIG_QFABRIC" = "y" ] + define_bool CONFIG_DWCS + define_bool CONFIG_DWCS_DFS + define_bool CONFIG_PROC_FS +fi + endmenu diff -Naur test-for-latech/arch/arm/kernel/calls.S testqf-for-latech/arch/arm/kernel/calls.S --- test-for-latech/arch/arm/kernel/calls.S 2004-06-11 07:42:31.000000000 -0400 +++ testqf-for-latech/arch/arm/kernel/calls.S 2004-06-11 07:49:18.000000000 -0400 @@ -253,6 +253,28 @@ .long SYMBOL_NAME(sys_ni_syscall) /* sys_lremovexattr */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_fremovexattr */ .long SYMBOL_NAME(sys_tkill) + .long SYMBOL_NAME(sys_load_scheduler) + .long SYMBOL_NAME(sys_unload_scheduler) + .long SYMBOL_NAME(sys_DWCS_scheduler) + .long SYMBOL_NAME(sys_update_utilization) + .long SYMBOL_NAME(sys_admission_control) + .long SYMBOL_NAME(sys_start_ecalls) + .long SYMBOL_NAME(sys_end_ecalls) + .long SYMBOL_NAME(sys_register_ecall) + .long SYMBOL_NAME(sys_do_downcall) + .long SYMBOL_NAME(sys_run_event_handler) + .long SYMBOL_NAME(sys_upcall_scheduler) + .long SYMBOL_NAME(sys_wake_up_ecalls) + .long SYMBOL_NAME(sys_download_code) + .long SYMBOL_NAME(sys_kecho_load) + .long SYMBOL_NAME(sys_KECho_syscall_echo) + .long SYMBOL_NAME(sys_KECho_syscall_cm) + .long SYMBOL_NAME(sys_KECho_syscall_cg) + .long SYMBOL_NAME(sys_KECho_syscall_atl) + .long SYMBOL_NAME(sys_KECho_sw_callback) + .long SYMBOL_NAME(sys_getsyscalls) + .long SYMBOL_NAME(sys_qos_configure) + .long SYMBOL_NAME(sys_change_clock) /* * Please check 2.5 _before_ adding calls here, * and copy changes to rmk@arm.linux.org.uk. Thanks. diff -Naur test-for-latech/arch/arm/kernel/init_task.c testqf-for-latech/arch/arm/kernel/init_task.c --- test-for-latech/arch/arm/kernel/init_task.c 2004-06-11 07:42:31.000000000 -0400 +++ testqf-for-latech/arch/arm/kernel/init_task.c 2004-06-11 07:49:18.000000000 -0400 @@ -13,6 +13,9 @@ static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); +#ifdef CONFIG_DWCS +struct dwcs_struct init_dwcs = INIT_DWCS; /* --FS-- Check linux/sched.h */ +#endif /* * Initial task structure. diff -Naur test-for-latech/arch/arm/kernel/process.c testqf-for-latech/arch/arm/kernel/process.c --- test-for-latech/arch/arm/kernel/process.c 2004-06-11 07:42:31.000000000 -0400 +++ testqf-for-latech/arch/arm/kernel/process.c 2004-06-11 07:49:18.000000000 -0400 @@ -369,6 +369,9 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { pid_t __ret; +#ifdef CONFIG_QFABRIC + struct task_struct *p; +#endif __asm__ __volatile__( "orr r0, %1, %2 @ kernel_thread sys_clone @@ -385,6 +388,12 @@ : "=r" (__ret) : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg) : "r0", "r1", "lr"); +#ifdef CONFIG_QFABRIC +#ifdef CONFIG_X86 + p = find_task_by_pid(retval); + p->kthread = 1; +#endif +#endif return __ret; } diff -Naur test-for-latech/arch/i386/config.in testqf-for-latech/arch/i386/config.in --- test-for-latech/arch/i386/config.in 2004-06-11 07:42:22.000000000 -0400 +++ testqf-for-latech/arch/i386/config.in 2004-06-11 07:49:01.000000000 -0400 @@ -425,4 +425,12 @@ bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER fi +#dep_bool 'modular DWCS scheduler' CONFIG_DWCS $CONFIG_PROC_FS + +bool 'Quality of Service Support (Q-Fabric)' CONFIG_QFABRIC +if [ "$CONFIG_QFABRIC" = "y" ]; then + define_bool CONFIG_DWCS y + define_bool CONFIG_PROC_FS y +fi + endmenu diff -Naur test-for-latech/arch/i386/kernel/entry.S testqf-for-latech/arch/i386/kernel/entry.S --- test-for-latech/arch/i386/kernel/entry.S 2004-06-11 07:42:23.000000000 -0400 +++ testqf-for-latech/arch/i386/kernel/entry.S 2004-06-11 07:49:01.000000000 -0400 @@ -202,6 +202,9 @@ call *SYMBOL_NAME(sys_call_table)(,%eax,4) movl %eax,EAX(%esp) # save the return value ENTRY(ret_from_sys_call) +#ifdef CONFIG_QFABRIC + call SYMBOL_NAME(inc_syscall_counter) +#endif cli # need_resched and signals atomic test cmpl $0,need_resched(%ebx) jne reschedule @@ -259,6 +262,85 @@ call SYMBOL_NAME(schedule) # test jmp ret_from_sys_call +#ifdef CONFIG_QFABRIC +ENTRY(fast_system_call) + pushl %eax # save orig_eax + SAVE_ALL + call *SYMBOL_NAME(fast_sys_call_table)(,%eax,4) + movl %eax,EAX(%esp) # save the return value + cmpl $0,%eax + jnz handle_return_value + RESTORE_ALL + +handle_return_value: + cmpl $-1,%eax + jz not_installed + testl $8,%eax + jnz do_slow_call + GET_CURRENT(%ebx) + testl $1,%eax + jnz do_bh +cont1: + testl $2,%eax + jnz do_reschedule +cont2: + testl $4,%eax + jnz handle_signal +cont3: + RESTORE_ALL + +not_installed: + RESTORE_ALL + +do_slow_call: + GET_CURRENT(%ebx) + testb $0x20,flags(%ebx) # PF_TRACESYS + jne tracesys + movl ORIG_EAX(%esp),%eax + call *SYMBOL_NAME(sys_call_table)(,%eax,4) + movl %eax,EAX(%esp) # save the return value + ALIGN + .globl ret_from_sys_call + .globl ret_from_intr + +do_bh: +#ifdef CONFIG_SMP + movl processor(%ebx),%eax + shll $CONFIG_X86_L1_CACHE_SHIFT,%eax + movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask +#else + movl SYMBOL_NAME(irq_stat),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask +#endif + jne do_handle_bh + jmp cont1 + +do_handle_bh: + call SYMBOL_NAME(do_softirq) + jmp cont1 + +do_reschedule: + movl EFLAGS(%esp),%eax + movb CS(%esp),%al + testl $(VM_MASK | 3),%eax + je cont2 + cmpl $0,need_resched(%ebx) + je cont2 + call SYMBOL_NAME(schedule) + jmp ret_from_sys_call + +handle_signal: + cmpl $0,sigpending(%ebx) + je cont3 + testl $(VM_MASK),EFLAGS(%esp) + movl %esp,%eax + jne v86_signal_return + xorl %edx,%edx + call SYMBOL_NAME(do_signal) + jmp cont3 +#endif + ENTRY(divide_error) pushl $0 # no error code pushl $ SYMBOL_NAME(do_divide_error) @@ -639,7 +721,300 @@ .long SYMBOL_NAME(sys_ni_syscall) /* 240 reserved for futex */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_setaffinity */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_getaffinity */ - + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_update_utilization) + .long SYMBOL_NAME(sys_admission_control) + .long SYMBOL_NAME(sys_start_ecalls) + .long SYMBOL_NAME(sys_end_ecalls) + .long SYMBOL_NAME(sys_register_ecall) + .long SYMBOL_NAME(sys_do_downcall) + .long SYMBOL_NAME(sys_run_event_handler) + .long SYMBOL_NAME(sys_upcall_scheduler) + .long SYMBOL_NAME(sys_wake_up_ecalls) + .long SYMBOL_NAME(sys_download_code) + .long SYMBOL_NAME(sys_kecho_load) + .long SYMBOL_NAME(sys_KECho_syscall_echo) + .long SYMBOL_NAME(sys_KECho_syscall_cm) + .long SYMBOL_NAME(sys_KECho_syscall_cg) + .long SYMBOL_NAME(sys_KECho_syscall_atl) + .long SYMBOL_NAME(sys_KECho_sw_callback) + .long SYMBOL_NAME(sys_getsyscalls) + .long SYMBOL_NAME(sys_qos_configure) + .long SYMBOL_NAME(sys_change_clock) +#ifdef CONFIG_NET_QSOCKET + .long SYMBOL_NAME(sys_qsocketcall) +#endif + .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) .endr + +.data +ENTRY(fast_sys_call_table) + .long SYMBOL_NAME(sys_ni_syscall) /* 0 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_fast_read) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 5 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 10 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 15 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 20 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 25 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 30 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 40 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 45 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 50 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 55 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 60 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 65 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 70 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 75 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 80 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 85 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 90 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 95 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 100 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 105 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 110 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 115 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 120 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 125 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 130 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 135 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 140 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 145 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 150 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 155 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 160 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 165 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 170 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 175 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 180 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 185 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 190 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 195 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 200 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 205 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 210 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 215 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 220 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 225 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 230 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_fast_do_downcall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_fast_KECho_syscall_echo) + .long SYMBOL_NAME(sys_fast_KECho_syscall_cm) + .long SYMBOL_NAME(sys_fast_KECho_syscall_cg) + .long SYMBOL_NAME(sys_fast_KECho_syscall_atl) + + .rept NR_syscalls-(.-fast_sys_call_table)/4 + .long SYMBOL_NAME(sys_ni_syscall) + .endr diff -Naur test-for-latech/arch/i386/kernel/i8259.c testqf-for-latech/arch/i386/kernel/i8259.c --- test-for-latech/arch/i386/kernel/i8259.c 2004-06-11 07:42:23.000000000 -0400 +++ testqf-for-latech/arch/i386/kernel/i8259.c 2004-06-11 07:49:01.000000000 -0400 @@ -456,8 +456,14 @@ */ for (i = 0; i < NR_IRQS; i++) { int vector = FIRST_EXTERNAL_VECTOR + i; +#ifdef CONFIG_QFABRIC + if ((vector != SYSCALL_VECTOR) && + (vector != FAST_SYSCALL_VECTOR)) + set_intr_gate(vector, interrupt[i]); +#else if (vector != SYSCALL_VECTOR) set_intr_gate(vector, interrupt[i]); +#endif } #ifdef CONFIG_SMP diff -Naur test-for-latech/arch/i386/kernel/init_task.c testqf-for-latech/arch/i386/kernel/init_task.c --- test-for-latech/arch/i386/kernel/init_task.c 2004-06-11 07:42:23.000000000 -0400 +++ testqf-for-latech/arch/i386/kernel/init_task.c 2004-06-11 07:49:01.000000000 -0400 @@ -10,6 +10,9 @@ static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); +#ifdef CONFIG_DWCS +struct dwcs_struct init_dwcs = INIT_DWCS; /* --RW-- Check linux/sched.h */ +#endif /* * Initial task structure. diff -Naur test-for-latech/arch/i386/kernel/process.c testqf-for-latech/arch/i386/kernel/process.c --- test-for-latech/arch/i386/kernel/process.c 2004-06-11 07:42:23.000000000 -0400 +++ testqf-for-latech/arch/i386/kernel/process.c 2004-06-11 07:49:01.000000000 -0400 @@ -488,6 +488,9 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { long retval, d0; +#ifdef CONFIG_QFABRIC + struct task_struct *p; +#endif __asm__ __volatile__( "movl %%esp,%%esi\n\t" @@ -508,6 +511,10 @@ "r" (arg), "r" (fn), "b" (flags | CLONE_VM) : "memory"); +#ifdef CONFIG_QFABRIC + p = find_task_by_pid(retval); + p->kthread = 1; +#endif return retval; } diff -Naur test-for-latech/arch/i386/kernel/ptrace.c testqf-for-latech/arch/i386/kernel/ptrace.c --- test-for-latech/arch/i386/kernel/ptrace.c 2004-06-11 07:42:23.000000000 -0400 +++ testqf-for-latech/arch/i386/kernel/ptrace.c 2004-06-11 07:49:01.000000000 -0400 @@ -452,3 +452,11 @@ current->exit_code = 0; } } + +#ifdef CONFIG_QFABRIC +asmlinkage void inc_syscall_counter() +{ + current->syscall_counter++; +} +EXPORT_SYMBOL(inc_syscall_counter); +#endif diff -Naur test-for-latech/arch/i386/kernel/traps.c testqf-for-latech/arch/i386/kernel/traps.c --- test-for-latech/arch/i386/kernel/traps.c 2004-06-11 07:42:22.000000000 -0400 +++ testqf-for-latech/arch/i386/kernel/traps.c 2004-06-11 07:49:01.000000000 -0400 @@ -51,6 +51,9 @@ #include asmlinkage int system_call(void); +#ifdef CONFIG_QFABRIC +asmlinkage int fast_system_call(void); +#endif asmlinkage void lcall7(void); asmlinkage void lcall27(void); @@ -985,6 +988,9 @@ set_trap_gate(19,&simd_coprocessor_error); set_system_gate(SYSCALL_VECTOR,&system_call); +#ifdef CONFIG_QFABRIC + set_system_gate(FAST_SYSCALL_VECTOR,&fast_system_call); +#endif /* * default LDT is a single-entry callgate to lcall7 for iBCS diff -Naur test-for-latech/arch/i386/lib/usercopy.c testqf-for-latech/arch/i386/lib/usercopy.c --- test-for-latech/arch/i386/lib/usercopy.c 2004-06-11 07:42:22.000000000 -0400 +++ testqf-for-latech/arch/i386/lib/usercopy.c 2004-06-11 07:49:01.000000000 -0400 @@ -27,6 +27,12 @@ unsigned long __generic_copy_from_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif if (access_ok(VERIFY_READ, from, n)) { if(n<512) @@ -53,6 +59,12 @@ unsigned long __generic_copy_from_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif prefetchw(to); if (access_ok(VERIFY_READ, from, n)) __copy_user_zeroing(to,from,n); diff -Naur test-for-latech/Documentation/Configure.help testqf-for-latech/Documentation/Configure.help --- test-for-latech/Documentation/Configure.help 2004-06-11 07:42:36.000000000 -0400 +++ testqf-for-latech/Documentation/Configure.help 2004-06-11 07:49:26.000000000 -0400 @@ -20527,6 +20527,36 @@ "Area6" will work for most boards. For ADX, select "Area5". +#modular DWCS process scheduler +#CONFIG_DWCS +# This option includes a kernel loadable module dwcs.o which implements +# a Dynamic Window-Constrained Scheduler instead of the regular Linux +# scheduler. Loading the module is not enough, you have to switch +# scheduling to the new scheduler. + +# To find out more about the scheduler, or to find out more about how +# to use it visit: http://www.cc.gatech.edu/~west/dwcs.html + +# This scheduler is for hacking purposes only, it seems to be stable on +# uniprocessor machines, but not on SMP boxes. You've been warned. This +# is still very experimental code, play with it _only_ if you know what +# you are doing. + +#DWCS /proc interface +#CONFIG_PROC_DWCS +# This option enables a pseudo file /proc/dwcs reading which will give +# you a snapshot of the current operating parameters of the DWCS +# scheduler. The file exists only when the scheduler is loaded. + +Quality of Service Support (Q-Fabric) +CONFIG_QFABRIC + If you say Y here, Artemis-enabled kernel extensions can be used by + applications. Artemis is a QoS infrastructure based on a distributed + event notification mechanism (called KECho). Saying Y here only adds + the necessary modifications to the kernel to support Artemis. The + actual Artemis modules are not part of the kernel, but are made + available in a software package available at http://www.cc.gatech.edu/~chris. + # # m68k-specific kernel options # Documented by Chris Lawrence et al. diff -Naur test-for-latech/fs/read_write.c testqf-for-latech/fs/read_write.c --- test-for-latech/fs/read_write.c 2004-06-11 07:39:57.000000000 -0400 +++ testqf-for-latech/fs/read_write.c 2004-06-11 07:47:19.000000000 -0400 @@ -425,3 +425,9 @@ bad_file: return ret; } + +asmlinkage int sys_fast_read(int fd, + void *buffer, int len) +{ + return 0; +} diff -Naur test-for-latech/include/asm-arm/current.h testqf-for-latech/include/asm-arm/current.h --- test-for-latech/include/asm-arm/current.h 2004-06-11 07:40:29.000000000 -0400 +++ testqf-for-latech/include/asm-arm/current.h 2004-06-11 07:47:34.000000000 -0400 @@ -1,14 +1,32 @@ #ifndef _ASMARM_CURRENT_H #define _ASMARM_CURRENT_H +#ifdef CONFIG_QFABRIC +extern int ECalls_current_flag; +extern struct task_struct *ECalls_current; +#endif + static inline struct task_struct *get_current(void) __attribute__ (( __const__ )); -static inline struct task_struct *get_current(void) +static inline struct task_struct *original_get_current(void) __attribute__ (( __const__ )); + +static inline struct task_struct *original_get_current(void) { register unsigned long sp asm ("sp"); return (struct task_struct *)(sp & ~0x1fff); } +#define original_current original_get_current() + +static inline struct task_struct *get_current(void) +{ +#ifdef CONFIG_QFABRIC + if (ECalls_current_flag == 1) + return ECalls_current; +#endif + return original_get_current(); +} + #define current (get_current()) #endif /* _ASMARM_CURRENT_H */ diff -Naur test-for-latech/include/asm-arm/errno.h testqf-for-latech/include/asm-arm/errno.h --- test-for-latech/include/asm-arm/errno.h 2004-06-11 07:40:29.000000000 -0400 +++ testqf-for-latech/include/asm-arm/errno.h 2004-06-11 07:47:34.000000000 -0400 @@ -129,4 +129,8 @@ #define ENOMEDIUM 123 /* No medium found */ #define EMEDIUMTYPE 124 /* Wrong medium type */ +#ifdef CONFIG_QFABRIC +#define EADMISSION 125 /* Task admission denied. */ +#endif + #endif diff -Naur test-for-latech/include/asm-arm/socket.h testqf-for-latech/include/asm-arm/socket.h --- test-for-latech/include/asm-arm/socket.h 2004-06-11 07:40:29.000000000 -0400 +++ testqf-for-latech/include/asm-arm/socket.h 2004-06-11 07:47:34.000000000 -0400 @@ -45,6 +45,11 @@ #define SO_ACCEPTCONN 30 +#ifdef CONFIG_QFABRIC +#define SO_QOS_PRIORITY 1000 +#define SO_QOS_DEADLINE 1001 +#endif + /* Nast libc5 fixup - bletch */ #if defined(__KERNEL__) /* Socket types. */ diff -Naur test-for-latech/include/asm-arm/uaccess.h testqf-for-latech/include/asm-arm/uaccess.h --- test-for-latech/include/asm-arm/uaccess.h 2004-06-11 07:40:29.000000000 -0400 +++ testqf-for-latech/include/asm-arm/uaccess.h 2004-06-11 07:47:34.000000000 -0400 @@ -23,6 +23,11 @@ * on our cache or tlb entries. */ +#ifdef CONFIG_QFABRIC +extern mm_segment_t kernel_get_fs(void); +extern int kernel_access_ok(int type, const void *addr, size_t size); +#endif + struct exception_table_entry { unsigned long insn, fixup; @@ -32,12 +37,28 @@ extern unsigned long search_exception_table(unsigned long); #define get_ds() (KERNEL_DS) +#ifdef CONFIG_QFABRIC +#ifdef MODULE +#define get_fs() (current->addr_limit) +#else +#define get_fs() kernel_get_fs() +#endif +#else #define get_fs() (current->addr_limit) +#endif #define segment_eq(a,b) ((a) == (b)) #include +#ifdef CONFIG_QFABRIC +#ifdef MODULE +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) +#else +#define access_ok(type,addr,size) kernel_access_ok(type,addr,size) +#endif +#else #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) +#endif static inline int verify_area(int type, const void * addr, unsigned long size) { @@ -143,6 +164,12 @@ static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif if (access_ok(VERIFY_READ, from, n)) __do_copy_from_user(to, from, n); else /* security hole - plug it */ @@ -152,12 +179,24 @@ static __inline__ unsigned long __copy_from_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif __do_copy_from_user(to, from, n); return n; } static __inline__ unsigned long copy_to_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif if (access_ok(VERIFY_WRITE, to, n)) __do_copy_to_user(to, from, n); return n; @@ -165,6 +204,12 @@ static __inline__ unsigned long __copy_to_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif __do_copy_to_user(to, from, n); return n; } diff -Naur test-for-latech/include/asm-arm/unistd.h testqf-for-latech/include/asm-arm/unistd.h --- test-for-latech/include/asm-arm/unistd.h 2004-06-11 07:40:27.000000000 -0400 +++ testqf-for-latech/include/asm-arm/unistd.h 2004-06-11 07:47:34.000000000 -0400 @@ -259,6 +259,44 @@ #define __NR_fremovexattr (__NR_SYSCALL_BASE+237) #endif #define __NR_tkill (__NR_SYSCALL_BASE+238) +/* DWCS related calls. */ +#define __NR_load_scheduler (__NR_SYSCALL_BASE+239) /* Added by Rich West --RW--. */ +#define __NR_unload_scheduler (__NR_SYSCALL_BASE+240) /* Added by Rich West --RW--. */ +#define __NR_DWCS_scheduler (__NR_SYSCALL_BASE+241) /* Added by Rich West --RW--. */ +#define __NR_update_utilization (__NR_SYSCALL_BASE+242) /* Added by C. Poellabauer --CP--. */ +#define __NR_admission_control (__NR_SYSCALL_BASE+243) /* Added by C. Poellabauer --CP--. */ + +/* Additional syscalls added for the ECalls mechanism. */ +#define __NR_start_ecalls (__NR_SYSCALL_BASE+244) /* Added by C. Poellabauer --CP--. */ +#define __NR_end_ecalls (__NR_SYSCALL_BASE+245) /* Added by C. Poellabauer --CP--. */ +#define __NR_register_ecall (__NR_SYSCALL_BASE+246) /* Added by C. Poellabauer --CP--. */ +#define __NR_do_downcall (__NR_SYSCALL_BASE+247) /* Added by C. Poellabauer --CP--. */ +#define __NR_run_event_handler (__NR_SYSCALL_BASE+248) /* Added by C. Poellabauer --CP--. */ +#define __NR_upcall_scheduler (__NR_SYSCALL_BASE+249) /* Added by C. Poellabauer --CP--. */ +#define __NR_wake_up_ecalls (__NR_SYSCALL_BASE+250) /* Added by C. Poellabauer --CP--. */ +#define __NR_download_code (__NR_SYSCALL_BASE+251) /* Added by C. Poellabauer --CP--. */ + +/* Syscalls for user-level usage of KECho. */ +#define __NR_kecho_load (__NR_SYSCALL_BASE+252) /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_echo (__NR_SYSCALL_BASE+253) /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_cm (__NR_SYSCALL_BASE+254) /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_cg (__NR_SYSCALL_BASE+255) /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_atl (__NR_SYSCALL_BASE+256) /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_sw_callback (__NR_SYSCALL_BASE+257) /* Added by C. Poellabauer --CP--. */ + +/* Syscalls for measurment purposes. */ +#define __NR_getsyscalls (__NR_SYSCALL_BASE+258) /* Added by C. Poellabauer --CP--. */ +#define __NR_qos_configure (__NR_SYSCALL_BASE+259) /* Added by C. Poellabauer --CP--. */ +#define __NR_change_clock (__NR_SYSCALL_BASE+260) /* Added by C. Poellabauer --CP--. */ + +/* Fast system call definitions. */ +#define __NR_fast_read (__NR_SYSCALL_BASE+3) /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_do_downcall (__NR_SYSCALL_BASE+247) /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_echo (__NR_SYSCALL_BASE+253) /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_cm (__NR_SYSCALL_BASE+254) /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_cg (__NR_SYSCALL_BASE+255) /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_atl (__NR_SYSCALL_BASE+256) /* Added by C. Poellabauer --CP--. */ + /* * Please check 2.5 _before_ adding calls here, * and copy changes to rmk@arm.linux.org.uk. Thanks. diff -Naur test-for-latech/include/asm-i386/current.h testqf-for-latech/include/asm-i386/current.h --- test-for-latech/include/asm-i386/current.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/current.h 2004-06-11 07:47:30.000000000 -0400 @@ -3,13 +3,35 @@ struct task_struct; +#ifdef CONFIG_QFABRIC +extern int ECalls_current_flag; +extern struct task_struct *ECalls_current; + +static inline struct task_struct * original_get_current(void) +{ + struct task_struct *current; + + __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); + return current; +} + +#define original_current original_get_current() + +static inline struct task_struct * get_current(void) +{ + if (ECalls_current_flag == 1) + return ECalls_current; + return original_get_current(); +} +#else static inline struct task_struct * get_current(void) { struct task_struct *current; __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); return current; - } - +} +#endif + #define current get_current() #endif /* !(_I386_CURRENT_H) */ diff -Naur test-for-latech/include/asm-i386/errno.h testqf-for-latech/include/asm-i386/errno.h --- test-for-latech/include/asm-i386/errno.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/errno.h 2004-06-11 07:47:30.000000000 -0400 @@ -129,4 +129,8 @@ #define ENOMEDIUM 123 /* No medium found */ #define EMEDIUMTYPE 124 /* Wrong medium type */ +#ifdef CONFIG_DWCS +#define EADMISSION 125 /* Task admission denied. */ +#endif + #endif diff -Naur test-for-latech/include/asm-i386/hw_irq.h testqf-for-latech/include/asm-i386/hw_irq.h --- test-for-latech/include/asm-i386/hw_irq.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/hw_irq.h 2004-06-11 07:47:30.000000000 -0400 @@ -23,6 +23,9 @@ #define FIRST_EXTERNAL_VECTOR 0x20 #define SYSCALL_VECTOR 0x80 +#ifdef CONFIG_QFABRIC +#define FAST_SYSCALL_VECTOR 0x60 +#endif /* * Vectors 0x20-0x2f are used for ISA interrupts. diff -Naur test-for-latech/include/asm-i386/ptrace.h testqf-for-latech/include/asm-i386/ptrace.h --- test-for-latech/include/asm-i386/ptrace.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/ptrace.h 2004-06-11 07:47:30.000000000 -0400 @@ -1,6 +1,7 @@ #ifndef _I386_PTRACE_H #define _I386_PTRACE_H +#ifndef QFABRIC_DCG #define EBX 0 #define ECX 1 #define EDX 2 @@ -19,6 +20,7 @@ #define UESP 15 #define SS 16 #define FRAME_SIZE 17 +#endif /* this struct defines the way the registers are stored on the stack during a system call. */ diff -Naur test-for-latech/include/asm-i386/socket.h testqf-for-latech/include/asm-i386/socket.h --- test-for-latech/include/asm-i386/socket.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/socket.h 2004-06-11 07:47:30.000000000 -0400 @@ -45,6 +45,11 @@ #define SO_ACCEPTCONN 30 +#ifdef CONFIG_QFABRIC +#define SO_QOS_PRIORITY 1000 +#define SO_QOS_DEADLINE 1001 +#endif + /* Nasty libc5 fixup - bletch */ #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) /* Socket types. */ diff -Naur test-for-latech/include/asm-i386/uaccess.h testqf-for-latech/include/asm-i386/uaccess.h --- test-for-latech/include/asm-i386/uaccess.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/uaccess.h 2004-06-11 07:47:30.000000000 -0400 @@ -7,10 +7,21 @@ #include #include #include +#ifdef CONFIG_QFABRIC +#include +#endif #include #define VERIFY_READ 0 #define VERIFY_WRITE 1 +#ifdef CONFIG_QFABRIC +#ifndef NR_THREADS +#define NR_THREADS 512 +#endif + +extern mm_segment_t kernel_get_fs(void); +extern int kernel_access_ok(int type, const void *addr, size_t size); +#endif /* * The fs value determines whether argument validity checking should be @@ -27,7 +38,15 @@ #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) #define get_ds() (KERNEL_DS) +#ifdef CONFIG_QFABRIC +#ifdef MODULE +#define get_fs() (current->addr_limit) +#else +#define get_fs() kernel_get_fs() +#endif +#else #define get_fs() (current->addr_limit) +#endif #define set_fs(x) (current->addr_limit = (x)) #define segment_eq(a,b) ((a).seg == (b).seg) @@ -35,7 +54,7 @@ extern int __verify_write(const void *, unsigned long); #define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg)) - + /* * Uhhuh, this needs 33-bit arithmetic. We have a carry.. */ @@ -46,6 +65,24 @@ :"1" (addr),"g" ((int)(size)),"g" (current->addr_limit.seg)); \ flag; }) +#ifdef CONFIG_QFABRIC +#ifdef MODULE +#ifdef CONFIG_X86_WP_WORKS_OK + +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) + +#else + +#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \ + ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \ + segment_eq(get_fs(),KERNEL_DS) || \ + __verify_write((void *)(addr),(size)))) + +#endif +#else +#define access_ok(type,addr,size) kernel_access_ok(type,addr,size) +#endif +#else #ifdef CONFIG_X86_WP_WORKS_OK #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) @@ -58,6 +95,7 @@ __verify_write((void *)(addr),(size)))) #endif +#endif static inline int verify_area(int type, const void * addr, unsigned long size) { @@ -149,12 +187,12 @@ #define __put_user_check(x,ptr,size) \ ({ \ - long __pu_err = -EFAULT; \ + long __pu_err = -EFAULT; \ __typeof__(*(ptr)) *__pu_addr = (ptr); \ if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ __put_user_size((x),__pu_addr,(size),__pu_err); \ __pu_err; \ -}) +}) #define __put_user_u64(x, addr, err) \ __asm__ __volatile__( \ @@ -308,6 +346,12 @@ static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif __copy_user_zeroing(to,from,n); return n; } @@ -315,6 +359,12 @@ static inline unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif __copy_user(to,from,n); return n; } @@ -546,6 +596,12 @@ static inline unsigned long __constant_copy_to_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif prefetch(from); if (access_ok(VERIFY_WRITE, to, n)) __constant_copy_user(to,from,n); @@ -555,6 +611,12 @@ static inline unsigned long __constant_copy_from_user(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif if (access_ok(VERIFY_READ, from, n)) __constant_copy_user_zeroing(to,from,n); else @@ -565,6 +627,12 @@ static inline unsigned long __constant_copy_to_user_nocheck(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif __constant_copy_user(to,from,n); return n; } @@ -572,6 +640,12 @@ static inline unsigned long __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { +#ifdef CONFIG_QFABRIC + if (current->uaccess_flag == 1) { + memcpy(to, from, n); + return 0; + } +#endif __constant_copy_user_zeroing(to,from,n); return n; } diff -Naur test-for-latech/include/asm-i386/unistd.h testqf-for-latech/include/asm-i386/unistd.h --- test-for-latech/include/asm-i386/unistd.h 2004-06-11 07:40:12.000000000 -0400 +++ testqf-for-latech/include/asm-i386/unistd.h 2004-06-11 07:47:29.000000000 -0400 @@ -1,5 +1,12 @@ #ifndef _ASM_I386_UNISTD_H_ #define _ASM_I386_UNISTD_H_ +#ifdef CONFIG_QFABRIC +#include +#endif + +#ifdef CONFIG_DWCS +#define __NR_SYSCALL_BASE 0x00 +#endif /* * This file contains the system call numbers. @@ -248,6 +255,45 @@ #define __NR_sched_setaffinity 241 #define __NR_sched_getaffinity 242 +/* Additional syscalls added for the dionisys resource manager. */ +#define __NR_load_scheduler 243 /* Added by Rich West --RW--. */ +#define __NR_unload_scheduler 244 /* Added by Rich West --RW--. */ +#define __NR_DWCS_scheduler 245 /* Added by Rich West --RW--. */ +#define __NR_update_utilization 246 /* Added by C. Poellabauer --CP--. */ +#define __NR_admission_control 247 /* Added by C. Poellabauer --CP--. */ +/* Additional syscalls added for the ECalls mechanism. */ +#define __NR_start_ecalls 248 /* Added by C. Poellabauer --CP--. */ +#define __NR_end_ecalls 249 /* Added by C. Poellabauer --CP--. */ +#define __NR_register_ecall 250 /* Added by C. Poellabauer --CP--. */ +#define __NR_do_downcall 251 /* Added by C. Poellabauer --CP--. */ +#define __NR_run_event_handler 252 /* Added by C. Poellabauer --CP--. */ +#define __NR_upcall_scheduler 253 /* Added by C. Poellabauer --CP--. */ +#define __NR_wake_up_ecalls 254 /* Added by C. Poellabauer --CP--. */ +#define __NR_download_code 255 /* Added by C. Poellabauer --CP--. */ + +/* Syscalls for user-level usage of KECho. */ +#define __NR_kecho_load 256 /* --CP-- */ +#define __NR_KECho_syscall_echo 257 /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_cm 258 /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_cg 259 /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_syscall_atl 260 /* Added by C. Poellabauer --CP--. */ +#define __NR_KECho_sw_callback 261 /* Added by C. Poellabauer --CP--. */ + +#define __NR_getsyscalls 262 /* Added by C. Poellabauer --CP--. */ +#define __NR_qos_configure 263 /* Added by C. Poellabauer --CP--. */ +#define __NR_change_clock 264 /* Added by C. Poellabauer --CP--. */ + +/* QSocket changes. */ +#define __NR_qsocketcall 265 + +/* Fast system call definitions. */ +#define __NR_fast_read 3 /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_do_downcall 251 /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_echo 257 /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_cm 258 /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_cg 259 /* Added by C. Poellabauer --CP--. */ +#define __NR_fast_KECho_syscall_atl 260 /* Added by C. Poellabauer --CP--. */ + /* user-visible error numbers are in the range -1 - -124: see */ #define __syscall_return(type, res) \ @@ -337,6 +383,71 @@ __syscall_return(type,__res); \ } +/* Fast system calls. */ +#define _fast_syscall0(type,name) \ +type name(void) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x60" \ + : "=a" (__res) \ + : "0" (__NR_##name)); \ +__syscall_return(type,__res); \ +} + +#define _fast_syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x60" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ +__syscall_return(type,__res); \ +} + +#define _fast_syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x60" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ +__syscall_return(type,__res); \ +} + +#define _fast_syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x60" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ +__syscall_return(type,__res); \ +} + +#define _fast_syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x60" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ +__syscall_return(type,__res); \ +} + +#define _fast_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x60" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +__syscall_return(type,__res); \ +} + #ifdef __KERNEL_SYSCALLS__ /* diff -Naur test-for-latech/include/linux/ecalls.h testqf-for-latech/include/linux/ecalls.h --- test-for-latech/include/linux/ecalls.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/ecalls.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,239 @@ +#ifndef __ECALLS__H__ +#define __ECALLS__H__ + +#include +#include + +/* system call: start_ecalls. */ +_syscall1(int, start_ecalls, + int, flag); + +/* system call: end_ecalls. */ +_syscall0(int, end_ecalls); + +/* system call: register_ecall. */ +_syscall4(int, register_ecall, + char *, service, + int, len, + struct ecall_down *, downcall, + struct ecall_up *, upcall); + +/* system call: download code. */ +_syscall5(int, download_code, + char *, hookname, + char *, parameter1, + int, parameter2, + int, parameter3, + char *, code); + +/* system call: do_downcall. */ +_syscall3(int, do_downcall, + struct ecall_down *, downcall, + void *, data, + int, len); + +#ifdef CONFIG_X86 +/* fast system call: fast_do_downcall. */ +_fast_syscall3(int, fast_do_downcall, + struct ecall_down *, downcall, + void *, data, + int, len); +#endif + +/* Start ECalls. */ +int ECalls_start(int flag) +{ + start_ecalls(flag); + + return 0; +} + +/* End ECalls. */ +int ECalls_cancel(struct ecall_down *downcall, struct ecall_up *upcall) +{ + end_ecalls(); + + return 0; +} + +/* Initialize downcall data structure. */ +int init_downcall(char *service_name, struct ecall_down *downcall, + void *down_ptr) +{ + if (down_ptr != NULL) { + if (downcall->size1 > 0) { + if (downcall->size2 > 0) { + downcall->flag = (unsigned long) down_ptr; + downcall->bitpattern = downcall->flag + sizeof(int); + downcall->front = 0; + downcall->back = 0; + downcall->data = (unsigned long) downcall->bitpattern + + sizeof(unsigned long)* + downcall->size2; + downcall->total_size = downcall->size1; + downcall->service_name = strdup(service_name); + downcall->string_len = strlen(service_name); + } else { + downcall->flag = (unsigned long) down_ptr; + downcall->bitpattern = 0; + downcall->front = (unsigned long) downcall->flag + sizeof(int); + downcall->back = (unsigned long) downcall->back + sizeof(int); + downcall->total_size = downcall->size1; + downcall->service_name = strdup(service_name); + downcall->string_len = strlen(service_name); + } + } else { + downcall->flag = 0; + downcall->bitpattern = 0; + downcall->front = 0; + downcall->back = 0; + downcall->data = 0; + downcall->total_size = sizeof(int); + downcall->service_name = strdup(service_name); + downcall->string_len = strlen(service_name); + } + } else { + downcall->flag = 0; + downcall->bitpattern = 0; + downcall->front = 0; + downcall->back = 0; + downcall->data = 0; + downcall->total_size = sizeof(int); + downcall->service_name = strdup(service_name); + downcall->string_len = strlen(service_name); + } + return 0; +} + +/* Initialize upcall data structure. */ +int init_upcall(char *service_name, struct ecall_up *upcall, void *up_ptr) +{ + if (up_ptr != NULL) { + if (upcall->size1 > 0) { + if (upcall->size2 > 0) { + upcall->flag = (unsigned long) up_ptr; + upcall->bitpattern = (unsigned long) upcall->flag + sizeof(int); + upcall->front = 0; + upcall->back = 0; + upcall->data = (unsigned long)upcall->bitpattern + + sizeof(unsigned long)*upcall->size2; + upcall->total_size = upcall->size1; + upcall->service_name = strdup(service_name); + upcall->string_len = strlen(service_name); + } else { + upcall->flag = (unsigned long) up_ptr; + upcall->bitpattern = 0; + upcall->front = (unsigned long) upcall->flag + sizeof(int); + upcall->back = (unsigned long) upcall->back + sizeof(int); + upcall->total_size = upcall->size1; + upcall->service_name = strdup(service_name); + upcall->string_len = strlen(service_name); + } + } else { + upcall->flag = 0; + upcall->bitpattern = 0; + upcall->front = 0; + upcall->back = 0; + upcall->data = 0; + upcall->total_size = 0; + } + } else { + upcall->flag = 0; + upcall->bitpattern = 0; + upcall->front = 0; + upcall->back = 0; + upcall->data = 0; + upcall->total_size = 0; + } + return 0; +} + +/* Initialize ECalls. */ +int ECalls_init(char *service_name, struct ecall_down *downcall, + struct ecall_up *upcall, int signal, int pid, void *u_handler, + void *k_handler) +{ + if (service_name == NULL) return -1; + + upcall->service_name = strdup(service_name); + upcall->string_len = strlen(service_name); + upcall->signal = signal; + upcall->process_id = pid; + upcall->handler_function = u_handler; + upcall->kernel_function = k_handler; + upcall->kfct_string_len = 0; + if (upcall->kernel_function != NULL) + upcall->kfct_string_len = strlen(upcall->kernel_function); + return 0; +} + +/* Unregister ECalls. */ +int ECalls_unsubscribe(char *service_name) +{ + register_ecall(service_name, + strlen(service_name),NULL, NULL); + return 0; +} + +/* Register ECalls. */ +int ECalls_subscribe(char *service_name, + struct ecall_down *downcall, void *down_ptr, + struct ecall_up *upcall, void *up_ptr) +{ + int id; + + if (service_name == NULL) return -1; + + if (downcall != NULL) + init_downcall(service_name, downcall, down_ptr); + + if (upcall != NULL) + init_upcall(service_name, upcall, up_ptr); + + if ((id = register_ecall(service_name, + strlen(service_name),downcall,upcall)) < 0) + return -1; + + if (downcall != NULL) { + if (downcall->total_size > 0) + downcall->service_id = id; + } + + if (upcall != NULL) { + if (upcall->total_size > 0) + upcall->service_id = id; + } + + return 0; +} + +/* Submit Event. */ +int ECalls_submit_event(struct ecall_down *downcall, void *event, int len, + int type) +{ + if ((type == DEFERRED) || (type == NORMAL)) { + (*(int *)downcall->flag)++; + } + else if (type == SYSCALL) { + do_downcall(downcall, event, len); + } +#ifdef CONFIG_X86 + else if (type == IMMEDIATE) { + (*(int *)downcall->flag)++; + fast_do_downcall(downcall, event, len); + } +#endif + + return 0; +} + +/* Download extension code. */ +int ECalls_download(char *hookname, char *parameter1, int parameter2, + int parameter3, char *code) +{ + download_code(hookname, parameter1, parameter2, parameter3, code); + + return 0; +} + +#endif /* __ECALLS__H__ */ diff -Naur test-for-latech/include/linux/ecalls-types.h testqf-for-latech/include/linux/ecalls-types.h --- test-for-latech/include/linux/ecalls-types.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/ecalls-types.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,70 @@ +#ifndef __ECALLS_TYPES__H__ +#define __ECALLS_TYPES__H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEF_EVENT_NUM 32 +#define DEF_EVENT_SIZE sizeof(int) +#define DEF_MEM_SIZE 512 +#define FLAG_ONLY 0 +#define GENERAL_EVENTS 1 +#define PRIORITY_EVENTS 2 +#define NORMAL 0 +#define SYSCALL 1 +#define IMMEDIATE 2 +#define DEFERRED 3 + +struct ecall_down { + int service_id; + unsigned long flag; + unsigned long bitpattern; + unsigned long front; + unsigned long back; + unsigned long data; + char *service_name; + int string_len; + int total_size; + int size1; + int size2; +}; +typedef struct ecall_down *t_downcall_data; + +struct ecall_up { + int service_id; + unsigned long flag; + unsigned long bitpattern; + unsigned long front; + unsigned long back; + unsigned long data; + char *service_name; + int string_len; + int kfct_string_len; + int total_size; + int process_id; + int signal; + void *handler_function; + char *kernel_function; + int size1; + int size2; +}; +typedef struct ecall_up *t_upcall_data; + +extern int ECalls_start(int); +extern int ECalls_end(struct ecall_down *, struct ecall_up *); +extern int init_downcall(char *, struct ecall_down *, void *); +extern int init_upcall(char *, struct ecall_up *, void *); +extern int ECalls_subscribe(char *, struct ecall_down *, void *, + struct ecall_up *, void *); +extern int ECalls_cancel(struct ecall_down *, struct ecall_up *); +extern int ECalls_submit_event(struct ecall_down *, void *, int, + int); +extern int ECalls_init(char *, struct ecall_down *, + struct ecall_up *, int, int, void *, void *); +#endif /* __ECALLS_TYPES__H__ */ diff -Naur test-for-latech/include/linux/fastcalls.h testqf-for-latech/include/linux/fastcalls.h --- test-for-latech/include/linux/fastcalls.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/fastcalls.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,13 @@ +#ifndef __FASTCALLS__H__ +#define __FASTCALLS__H__ + +#include +#include +#include + +_fast_syscall3(int, fast_read, + int, fd, + void *, buffer, + int, len); + +#endif /* __FASTCALLS__H__ */ diff -Naur test-for-latech/include/linux/libqsocket.h testqf-for-latech/include/linux/libqsocket.h --- test-for-latech/include/linux/libqsocket.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/libqsocket.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int qsocket(int, int, int, struct qos_params *); +int qclose(int); +int qchange(int, struct qos_params*); +int qsendto(int fd, void *buff, size_t len, unsigned int flags, + struct sockaddr *addr, int addr_len, + struct packet_flags *pflags); +int qsend(int fd, void *buff, size_t len, unsigned int flags, + struct packet_flags *pflags); +int qinfo(int fd, struct qsocket_info *info); +int qchannel(int fd, int server); +int qinit(struct qos_params *params); diff -Naur test-for-latech/include/linux/netdevice.h testqf-for-latech/include/linux/netdevice.h --- test-for-latech/include/linux/netdevice.h 2004-06-11 07:40:03.000000000 -0400 +++ testqf-for-latech/include/linux/netdevice.h 2004-06-11 07:47:24.000000000 -0400 @@ -431,6 +431,10 @@ /* this will get initialized at each interface type init routine */ struct divert_blk *divert; #endif /* CONFIG_NET_DIVERT */ +#ifdef CONFIG_QFABRIC + int rte_list; + int rte_list_len; +#endif }; @@ -579,6 +583,9 @@ #define HAVE_NETIF_RX 1 extern int netif_rx(struct sk_buff *skb); extern int dev_ioctl(unsigned int cmd, void *); +#ifdef CONFIG_QFABRIC +extern int dev_ioctl2(unsigned int cmd, void *, int flag); +#endif extern int dev_change_flags(struct net_device *, unsigned); extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); diff -Naur test-for-latech/include/linux/net.h testqf-for-latech/include/linux/net.h --- test-for-latech/include/linux/net.h 2004-06-11 07:40:06.000000000 -0400 +++ testqf-for-latech/include/linux/net.h 2004-06-11 07:47:24.000000000 -0400 @@ -44,7 +44,9 @@ #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ #define SYS_SENDMSG 16 /* sys_sendmsg(2) */ #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ - +#ifdef CONFIG_QFABRIC +#define SYS_RTSOCKET 18 /* sys_rtsocket */ +#endif typedef enum { SS_FREE = 0, /* not allocated */ @@ -76,6 +78,12 @@ short type; unsigned char passcred; + +#ifdef CONFIG_QFABRIC + int rt_sock; + int deadline; + int rt_flags; +#endif }; #define SOCK_INODE(S) ((S)->inode) @@ -134,8 +142,15 @@ extern int sock_unregister(int family); extern struct socket *sock_alloc(void); extern int sock_create(int family, int type, int proto, struct socket **); +#ifdef CONFIG_QFABRIC +extern int make_rt_sock(struct socket *); +#endif extern void sock_release(struct socket *); extern int sock_sendmsg(struct socket *, struct msghdr *m, int len); +#ifdef CONFIG_QFABRIC +extern int rt_sock_sendmsg(struct socket *, struct msghdr *m, int len, + int deadline, int flags); +#endif extern int sock_recvmsg(struct socket *, struct msghdr *m, int len, int flags); extern int sock_readv_writev(int type, struct inode * inode, struct file * file, const struct iovec * iov, long count, long size); diff -Naur test-for-latech/include/linux/pkt_cls.h testqf-for-latech/include/linux/pkt_cls.h --- test-for-latech/include/linux/pkt_cls.h 2004-06-11 07:40:08.000000000 -0400 +++ testqf-for-latech/include/linux/pkt_cls.h 2004-06-11 07:47:28.000000000 -0400 @@ -158,4 +158,16 @@ #define TCA_TCINDEX_MAX TCA_TCINDEX_POLICE +enum +{ + TCA_SOCKET_UNSPEC, + TCA_SOCKET_CLASSID, + TCA_SOCKET_PROCESSID, + TCA_SOCKET_FDID, + TCA_SOCKET_INODEID, + TCA_SOCKET_POLICE, +}; + +#define TCA_SOCKET_MAX TCA_SOCKET_POLICE + #endif diff -Naur test-for-latech/include/linux/pkt_sched.h testqf-for-latech/include/linux/pkt_sched.h --- test-for-latech/include/linux/pkt_sched.h 2004-06-11 07:40:08.000000000 -0400 +++ testqf-for-latech/include/linux/pkt_sched.h 2004-06-11 07:47:28.000000000 -0400 @@ -93,6 +93,26 @@ __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */ }; +/* DWCS section */ +struct tc_dwcs_qopt +{ + __u32 limit; +}; + +enum +{ + TCA_DWCS_UNSPEC, + TCA_DWCS_DEADLINE, + TCA_DWCS_OLN, + TCA_DWCS_OLD, +#define DWCS_FLAG1 0x00000002 +#define DWCS_FLAG2 0x00000004 + TCA_DWCS_FLAGS, + TCA_DWCS_POLICE, +}; + +#define TCA_DWCS_MAX TCA_DWCS_POLICE + /* PRIO section */ #define TCQ_PRIO_BANDS 16 diff -Naur test-for-latech/include/linux/qfabric.h testqf-for-latech/include/linux/qfabric.h --- test-for-latech/include/linux/qfabric.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/qfabric.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,75 @@ +#ifndef __QFABRIC__H__ +#define __QFABRIC__H__ + +#ifdef __KERNEL__ +#include + +extern struct socket *look_up_pseudofd(int fd, struct socket *fd_array[]); +extern int get_pseudofd(struct socket *sock, struct socket *fd_array[]); +extern int release_pseudofd(int fd, struct socket *fd_array[]); +extern void initialize_qfabric(void); + +#else + +#ifndef CONFIG_QFABRIC +#define CONFIG_QFABRIC +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int query_module(const char *, int, void *, size_t, size_t); +extern int qfabric_config(char *app_id, char *group_id); + +/* system call: kecho_load. */ +_syscall2(int, kecho_load, + char *, module_name, + int, argument); + +_syscall1(int, KECho_syscall_echo, + void *, echo_data); + +#ifdef CONFIG_X86 +_fast_syscall1(int, fast_KECho_syscall_echo, + void *, echo_data); +#endif + +_syscall1(int, KECho_syscall_cm, + void *, cm_data); + +#ifdef CONFIG_X86 +_fast_syscall1(int, fast_KECho_syscall_cm, + void *, cm_data); +#endif + +_syscall1(int, KECho_syscall_cg, + void *, cm_data); + +#ifdef CONFIG_X86 +_fast_syscall1(int, fast_KECho_syscall_cg, + void *, cm_data); +#endif + +_syscall1(int, KECho_syscall_atl, + void *, atl_data); + +#ifdef CONFIG_X86 +_fast_syscall1(int, fast_KECho_syscall_atl, + void *, atl_data); +#endif + +_syscall2(int, qos_configure, + char *, app_id, + char *, group_id); + +#endif /* __KERNEL__ */ +#endif /* __QFABRIC__H__ */ diff -Naur test-for-latech/include/linux/qf_api.h testqf-for-latech/include/linux/qf_api.h --- test-for-latech/include/linux/qf_api.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/qf_api.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,24 @@ +#ifndef __QFAPI__H__ +#define __QFAPI__H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +_syscall2(int, change_clock, + int, flag, + int, value); + +_syscall2(int, qos_configure, + char *, app_id, + char *, group_id); + +#endif diff -Naur test-for-latech/include/linux/qos_conf.h testqf-for-latech/include/linux/qos_conf.h --- test-for-latech/include/linux/qos_conf.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/qos_conf.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,63 @@ +/*File :qos_conf.h + *Written by :Rabin Patra & Vibha Rathi + *Date :12 July 2001 + * + *Definations for: + *1.struct qos_request + *2.struct qos_msg + *3.struct qos_syscall_msg + */ + + +#ifndef __QOS_CONF_H__ +#define __QOS_CONF_H__ 1 + +#include +#include + +#define QOS_QDISC_ADD 10 +#define QOS_QDISC_CHANGE 11 +#define QOS_QDISC_DELETE 12 + +#define QOS_CLASS_ADD 14 +#define QOS_CLASS_CHANGE 15 +#define QOS_CLASS_DELETE 16 + +#define QOS_FILTER_ADD 18 +#define QOS_FILTER_CHANGE 19 +#define QOS_FILTER_DELETE 20 + +#define QOS_MAX_MSG 16 + +#define QOS_MAX_ATTRS 128 + +struct qos_request { + struct nlmsghdr n; + struct tcmsg t; + char buff[4096]; +}; + +struct qos_msg{ + struct qos_request req; + int action; +}; + +struct qos_syscall_msg { + struct qos_msg *msglist; + int no_of_msgs; +}; + +/*qos_get_all_args: + *function to copy from user to kernel space + */ +extern int qos_get_all_args(struct qos_syscall_msg *,struct qos_syscall_msg *); + +/*qos_do_conf: + *function which does the qos_configuration for one nessage + */ +extern int qos_do_conf(struct qos_msg *); + + + + +#endif diff -Naur test-for-latech/include/linux/qsocket.h testqf-for-latech/include/linux/qsocket.h --- test-for-latech/include/linux/qsocket.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/qsocket.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,177 @@ +/*File :qsocket.c + *Written by :Rabin Patra & Vibha Rathi + *Date :12 July 2001 + * + *Definations for + *1.struct qos_param + */ + +#include +//#include +//#include +//#include + +#ifndef __QSOCKET_H__ +#define __QSOCKET_H__ + +/* + * Only SYS_QSEND is used actually + */ + +#define SYS_QSOCKET 1 /* sys_qsocket(2) */ +#define SYS_QBIND 2 /* sys_qbind(2) */ +#define SYS_QCONNECT 3 /* sys_qconnect(2) */ +#define SYS_QLISTEN 4 /* sys_qlisten(2) */ +#define SYS_QACCEPT 5 /* sys_qaccept(2) */ +#define SYS_QGETSOCKNAME 6 /* sys_qgetsockname(2) */ +#define SYS_QGETPEERNAME 7 /* sys_qgetpeername(2) */ +#define SYS_QSOCKETPAIR 8 /* sys_qsocketpair(2) */ +#define SYS_QSEND 9 /* sys_qsend(2) */ +#define SYS_QSHUTDOWN 10 +#define SYS_QCHANGE 11 +#define SYS_QSENDTO 12 +#define SYS_QINFO 16 +#define SYS_QRECVMSG 17 /* sys_qrecvmesg */ +#define SYS_QINIT 20 + +#define MAX_QOS_PARAM_SIZE 128 + +struct qos_param{ + void * data; + int len; +}; + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +#ifndef DWCS_VIOLATION +/* --RW-- */ +#define DWCS_VIOLATION 0x00000001 /* Window-constraint violation. */ +#define DWCS_WORK_CONS 0x00000002 /* Does task support work-conservation? */ +#define DWCS_NON_DROPPABLE 0x00000008 /* Set when process is non-preemptive */ +#define DWCS_NON_PREEMPTIVE 0x00000004 /* Set when process is non-preemptive */ +#endif + +#define APP_MAX 128 + +#ifdef NEW_VERSION + +struct qos_params +{ + int qos_on; + int disable; + char dev[IFNAMSIZ]; + char name[IFNAMSIZ]; + char *app_id; + void *attributes; +}; + +#else + +struct qos_params +{ + int qos_on; + int disable; + char dev[IFNAMSIZ]; + char name[IFNAMSIZ]; + char *app_id; + void *attributes; + int ipg; + int old; + int oln; + int flags; /*work conserving or non work conserving*/ + int attribute; /*is the stream droppable or not?*/ + int server; + int use_cpu; + int use_net; +}; + +#endif + +struct packet_flags +{ + int drop_flag; + int urgent_flag; + int fragments; +}; + + +struct qsocket_info +{ + unsigned int input_qlen; + unsigned int output_qlen; + unsigned int missed_deadlines; + unsigned int cpu_time; + unsigned int delay_jif; + unsigned int sent_packets; +}; + +#ifdef __KERNEL__ + +struct qops +{ + char id[IFNAMSIZ]; + int (*create)(struct net_device *dev, void *attributes); + int (*add_stream)(struct Qdisc *q, void *attributes, int sock_fd); + int (*remove_stream)(struct Qdisc *q, int sock_fd); + int (*change_stream)(struct Qdisc *q, void *attributes, int i_ino); + int (*get_stream_info)(struct Qdisc *q, int i_ino, void *info); +}; + +struct qop_list +{ + struct qops *op; + struct qop_list *next; +}; + +extern struct qop_list *qop_base; + +static inline void register_qops(struct qops *ops) +{ + /*add to list*/ + struct qop_list *temp = kmalloc(sizeof(struct qop_list), GFP_KERNEL); + + if(ops == NULL) + printk("null passed damint\n"); + + temp->op = ops; + + temp->next = qop_base; + qop_base = temp; + + + printk(KERN_INFO "Registering qops = %s\n", qop_base->op->id); + +} + + +static inline void unregister_qops(struct qops *ops) +{ + /*remove from list*/ +} + +struct socket_head +{ + struct socket_filter *ht[256]; /* a hash table for socket_filters */ +}; + + +struct socket_filter +{ + struct socket_filter *next; + u32 id; + u32 pid; /* the pid, and */ + unsigned long fd; /* the fd to monitor for; or */ + unsigned long i_ino; /* the inode to monitor for */ + struct tcf_result res; +#ifdef CONFIG_NET_CLS_POLICE + struct tcf_police *police; +#endif +}; + + +#endif + +#endif + diff -Naur test-for-latech/include/linux/sch_dwcs.h testqf-for-latech/include/linux/sch_dwcs.h --- test-for-latech/include/linux/sch_dwcs.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/linux/sch_dwcs.h 2004-06-11 07:47:29.000000000 -0400 @@ -0,0 +1,161 @@ +/* + * net/sched/sch_dwcs.h DWCS algorithm scheduler. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Gregory Losik + * Richard West + * Christian Poellabauer + * + * Changes: J.D. Hollis + * cleaned up the formatting and added some comments + * + */ + + +#define TRUE 1 +#define FALSE 0 +#define MAX_CONNS 255 // GL: Technically it should be 2^16 but lets risk it... + +#define DWCS_VIOLATION 0x00000001 /* Window-constraint violation. */ +#define DWCS_WORK_CONS 0x00000002 /* Does task support work-conservation? */ +#define DWCS_NON_DROPPABLE 0x00000008 + + + +#include + + +/* Scheduler attributes. Not all members are necessary for all scheduling policies. */ +typedef struct dwcs_class_attr { + // int cd; /* Class descriptor. */ + // unsigned cnt; /* Number pkts queued for this class. */ + + /* JDH: w, s, and f might not be needed as we've got a DWCS qdisc now */ + double w; /* Weight. (For SFQ) */ + double s; /* Start tag. (For SFQ) */ + double f; /* Finish tag. (For SFQ) */ + + /* these are the actual, user-definable attributes */ + long deadline; + long readytime;/* ok this requires a little explanation + this is to maintain a specific throughput from the class + thus a stream with packets to send, on an idle network + won't send packets until the ready time has elasped for the + stream + */ + + unsigned long ipg; /* Inter-packet/msg gap. */ + unsigned oln; /* Original loss numerator. */ + unsigned old; /* Original loss denominator. */ + + /* statistics */ + unsigned cln; /* Current loss numerator. */ + unsigned cld; /* Current loss denominator. */ + long clt; /* Current loss tolerance. */ + unsigned late; /* Stats - number late pkts. */ + unsigned sent; /* Stats - number pkts sent. */ + unsigned violations; /* Stats - number loss tolerance violations. */ + unsigned long delay; /* Cumulative delay for this class. */ + int t; /* Simulated time to process pkt. */ + unsigned window; /* Packet window size. */ + unsigned wlate; /* Count of late pkts in a time window. */ + unsigned long bytes; /* Total bytes serviced for this class. */ + // long start_time; /* Real-time this class started. */ + + /* GL: since there is no per packet flag, it needs to be per stream... */ + int droppable; /* TRUE if packets may be dropped. */ + unsigned int flags; /* Flags as specified by user */ +} dwcs_class_attr_t; + + +/* Deadline heap attributes. */ +struct dl_heap { + long deadline; /* Packet deadline. */ + // int stream; /* Stream number. */ + u32 stream; /* Stream number. */ +}; + +struct sl_heap +{ + long readytime; + u32 stream; +}; + + +/* Loss tolerance heap attributes. */ +struct lt_heap { + int stream; /* Stream number. */ + long deadline; /* Packet deadline. */ + int cln; /* Current loss numerator. */ + int cld; /* Current loss denominator. */ + int oln; /* Original loss numerator. */ + int wlate; /* Late packets in window. */ + unsigned long arr_time; /* Packet arrival time. */ + long clt; /* Current loss tolerance. */ +}; + +struct dwcs_sched_data; + +struct dwcs_class +{ + struct dwcs_class *next; /* hash table link */ + struct dwcs_class *next_alive; /* next class with backlog in this priority band */ + + /* Parameters */ + u32 classid; /* the major:minor class id */ + unsigned char priority; /* class priority */ + unsigned int *socket_num; /* to be a socket number.... */ +#ifdef CONFIG_NET_CLS_POLICE + unsigned char police; +#endif + struct Qdisc *qdisc; /* Ptr to DWCS discipline that class belongs to */ + struct Qdisc *q; /* Elementary queueing discipline */ + + /* Variables */ + struct tcf_proto *filter_list; + int refcnt; /* used by _get() and _put() reference tracking */ + int filters; /* for keeping track the number of filters */ + struct tc_stats stats; /* ??? used by _NET_ESTIMATOR */ + + /* DWCS specific parameters */ + struct dwcs_class_attr attr; /* Low level attributes of a class */ +}; + + + + +struct dwcs_sched_data +{ + struct dwcs_class *classes[ 16 ]; /* Hash table of all classes. This is where all new calsses get inserted in */ + struct dwcs_class *link; /* Default class for case when filters don't match */ + unsigned classcount; /* the counder for total # of classes; q->classes[i] has the actual list */ + + + /* DWCS specific attributes */ + struct dwcs_class *next_class; /* next class from which we will try to dequeue (to be deleted) */ + + struct lt_heap ltheap[MAX_CONNS]; /* Loss-Tolerance Heap */ + int ltheap_size; + struct dl_heap dlheap[MAX_CONNS]; /* Deadline Heap */ + int dlheap_size; + struct sl_heap slheap[MAX_CONNS]; + int slheap_size; + struct timer_list wd_timer; /* Watchdog timer */ + + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif + +#ifdef CONFIG_NET_CLS_POLICE + struct dwcs_class *rx_class; +#endif + +}; + + + diff -Naur test-for-latech/include/linux/sched.h testqf-for-latech/include/linux/sched.h --- test-for-latech/include/linux/sched.h 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/include/linux/sched.h 2004-06-11 07:47:24.000000000 -0400 @@ -46,6 +46,10 @@ #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) +#ifdef CONFIG_QFABRIC +#define MAX_UTILIZATION 1000000 +#endif + /* * These are the constant used to fake the fixed-point load-average * counting. Some notes: @@ -119,13 +123,56 @@ #define SCHED_FIFO 1 #define SCHED_RR 2 +#ifdef CONFIG_DWCS +/* --RW-- */ +#define SCHED_DWCS 3 +#endif + +/* --CP-- */ +#ifdef CONFIG_QFABRIC +#define SCHED_UPCALL_OTHER 4 +#define SCHED_UPCALL_FIFO 5 +#define SCHED_UPCALL_RR 6 +extern struct wait_queue *global_wait_queue; +extern int upcall_sched_active; +extern int ECalls_current_flag; +extern struct task_struct *ECalls_current; +#endif + +#ifdef CONFIG_DWCS +/* --RW-- */ +#define DWCS_VIOLATION 0x00000001 /* Window-constraint violation. */ +#define DWCS_WORK_CONS 0x00000002 /* Does task support work-conservation? */ +#define DWCS_NON_PREEMPTIVE 0x00000004 /* Set when process is non-preemptive */ +#endif + /* * This is an additional bit set when we want to * yield the CPU for one re-schedule.. */ #define SCHED_YIELD 0x10 -struct sched_param { +#ifdef CONFIG_QFABRIC +#define NR_TASKS 512 +#define MAX_FDS 1024 +#endif + +#if defined(CONFIG_DWCS)||defined(CONFIG_QFABRIC) +struct dwcs_sched_param { + int pid; /* --FS-- The pid for which ioctl is done. */ + int policy; /* --FS-- The selected policy, -1 for unset. */ + int sched_priority; + unsigned long period; /* --RW-- Request period. Used for setting + DWCS deadlines. */ + unsigned int own; /* --RW-- Original window numerator. */ + unsigned int owd; /* --RW-- Original window denominator. */ + unsigned int flags; /* --RW-- Right now, work-conserving or not. */ + unsigned long service_time; /* --RW-- Time to service a process + every period. */ +}; +#endif + +struct sched_param{ int sched_priority; }; @@ -284,6 +331,70 @@ extern struct user_struct root_user; #define INIT_USER (&root_user) +/* --RW-- */ +#ifdef CONFIG_DWCS +struct dwcs_struct { + int cd; /* Class descriptor. */ + unsigned long deadline; + unsigned long period; /* Request period. */ + unsigned int own; /* Original window numerator. */ + unsigned int owd; /* Original window denominator. */ + unsigned int cwn; /* Current window numerator. */ + unsigned int cwd; /* Current window denominator. */ + unsigned int flags; /* Bitwise flags for future work. */ + unsigned long ready_time; /* Time when task can be serviced. */ + unsigned long service_time; /* Time to service a process every period. */ + unsigned long time_serviced; /* How much time process has been serviced + * so far, in the current processing period. + */ + /* Energy saving attributes */ + int cpu_speedup; /* Describes how much the clockrate can be lowered due + to not max. utilization of the processor scaled by + 100, e.g. if this proc. can be run at half + clockspeed it is 200 (clockrate * 100 / + cpu_speedup) */ + + /* Statistical attributes. */ + unsigned int wlate; /* Count of late tasks in a time window. */ + unsigned long late; /* Cumulative missed deadlines. */ + unsigned long on_time; /* Cumulative met deadlines. */ + unsigned long violations; /* Cumulative window-constraint violations. */ +}; +#endif + +/* --RW-- */ +#ifdef CONFIG_DWCS +#define INIT_DWCS { \ + 0, \ + (unsigned long)(-1), \ + (unsigned long)(-1), \ + 1, \ + 10, \ + 1, \ + 10, \ + DWCS_WORK_CONS, \ + 0, \ + 1, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0 } +#endif +/* End of --RW-- */ + +/* Artemis */ +#ifdef CONFIG_QFABRIC +struct qfabric_struct { + void *fdqfabric; + int orig_weight; + int weight; + int sw_pending; + unsigned long sleep_queue; + wait_queue_head_t kecho_queue; +}; +#endif + struct task_struct { /* * offsets of these are hardcoded elsewhere - touch with care @@ -409,6 +520,10 @@ int (*notifier)(void *priv); void *notifier_data; sigset_t *notifier_mask; + +#ifdef CONFIG_DWCS + struct dwcs_struct *dwcs_params; /* --RW-- */ +#endif /* Thread group tracking */ u32 parent_exec_id; @@ -418,6 +533,17 @@ /* journalling filesystem info */ void *journal_info; + +/* Artemis */ +#ifdef CONFIG_QFABRIC + struct qfabric_struct *qfabric; + int kthread; + int suser_flag; + int uaccess_flag; + int ecalls_flag; +/* Useful Measurement Stuff */ + long syscall_counter; +#endif }; /* @@ -470,6 +596,7 @@ * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) */ +#ifdef CONFIG_DWCS #define INIT_TASK(tsk) \ { \ state: 0, \ @@ -509,10 +636,54 @@ sig: &init_signals, \ pending: { NULL, &tsk.pending.head, {{0}}}, \ blocked: {{0}}, \ + dwcs_params: &init_dwcs, \ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ } - +#else +#define INIT_TASK(tsk) \ +{ \ + state: 0, \ + flags: 0, \ + sigpending: 0, \ + addr_limit: KERNEL_DS, \ + exec_domain: &default_exec_domain, \ + lock_depth: -1, \ + counter: DEF_COUNTER, \ + nice: DEF_NICE, \ + policy: SCHED_OTHER, \ + mm: NULL, \ + active_mm: &init_mm, \ + cpus_runnable: -1, \ + cpus_allowed: -1, \ + run_list: LIST_HEAD_INIT(tsk.run_list), \ + next_task: &tsk, \ + prev_task: &tsk, \ + p_opptr: &tsk, \ + p_pptr: &tsk, \ + thread_group: LIST_HEAD_INIT(tsk.thread_group), \ + wait_chldexit: __WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\ + real_timer: { \ + function: it_real_fn \ + }, \ + cap_effective: CAP_INIT_EFF_SET, \ + cap_inheritable: CAP_INIT_INH_SET, \ + cap_permitted: CAP_FULL_SET, \ + keep_capabilities: 0, \ + rlim: INIT_RLIMITS, \ + user: INIT_USER, \ + comm: "swapper", \ + thread: INIT_THREAD, \ + fs: &init_fs, \ + files: &init_files, \ + sigmask_lock: SPIN_LOCK_UNLOCKED, \ + sig: &init_signals, \ + pending: { NULL, &tsk.pending.head, {{0}}}, \ + blocked: {{0}}, \ + alloc_lock: SPIN_LOCK_UNLOCKED, \ + journal_info: NULL, \ +} +#endif #ifndef INIT_TASK_SIZE # define INIT_TASK_SIZE 2048*sizeof(long) @@ -718,6 +889,9 @@ */ static inline int suser(void) { +#ifdef CONFIG_QFABRIC + if (current->suser_flag == 1) return 1; +#endif if (!issecure(SECURE_NOROOT) && current->euid == 0) { current->flags |= PF_SUPERPRIV; return 1; @@ -727,6 +901,9 @@ static inline int fsuser(void) { +#ifdef CONFIG_QFABRIC + if (current->suser_flag == 1) return 1; +#endif if (!issecure(SECURE_NOROOT) && current->fsuid == 0) { current->flags |= PF_SUPERPRIV; return 1; @@ -742,6 +919,9 @@ static inline int capable(int cap) { +#ifdef CONFIG_QFABRIC + if (current->suser_flag == 1) return 1; +#endif #if 1 /* ok now */ if (cap_raised(current->cap_effective, cap)) #else @@ -884,6 +1064,25 @@ #define for_each_thread(task) \ for (task = next_thread(current) ; task != current ; task = next_thread(task)) + + +/* + * GANEV: This typedef and the external aligned_data symbol declaration + * are needed so that the "aligned_data" will be visible outside + * the kernel to loadable schedulers like DWCS. + */ +#ifdef CONFIG_DWCS +typedef union { + struct schedule_data { + struct task_struct * curr; + cycles_t last_schedule; + } schedule_data; + char __pad [SMP_CACHE_BYTES]; +} aligned_data_t; + +extern aligned_data_t aligned_data[NR_CPUS]; +#endif + #define next_thread(p) \ list_entry((p)->thread_group.next, struct task_struct, thread_group) @@ -945,5 +1144,4 @@ } #endif /* __KERNEL__ */ - #endif diff -Naur test-for-latech/include/linux/skbuff.h testqf-for-latech/include/linux/skbuff.h --- test-for-latech/include/linux/skbuff.h 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/include/linux/skbuff.h 2004-06-11 07:47:24.000000000 -0400 @@ -193,6 +193,10 @@ unsigned char *tail; /* Tail pointer */ unsigned char *end; /* End pointer */ + int drop_flag; + int urgent_flag; + int fragments; + void (*destructor)(struct sk_buff *); /* Destruct function */ #ifdef CONFIG_NETFILTER /* Can be used for communication between hooks. */ @@ -215,6 +219,10 @@ #ifdef CONFIG_NET_SCHED __u32 tc_index; /* traffic control index */ #endif +#ifdef CONFIG_QFABRIC + int deadline; + int flags; +#endif }; #define SK_WMEM_MAX 65535 diff -Naur test-for-latech/include/linux/sys.h testqf-for-latech/include/linux/sys.h --- test-for-latech/include/linux/sys.h 2004-06-11 07:40:04.000000000 -0400 +++ testqf-for-latech/include/linux/sys.h 2004-06-11 07:47:24.000000000 -0400 @@ -4,7 +4,7 @@ /* * system call entry points ... but not all are defined */ -#define NR_syscalls 256 +#define NR_syscalls 280 /* * These are system calls that will be removed at some time diff -Naur test-for-latech/include/net/bpf.h testqf-for-latech/include/net/bpf.h --- test-for-latech/include/net/bpf.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/bpf.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,463 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header: /tcpdump/master/libpcap/bpf/net/Attic/bpf.h,v 1.52.2.6 2002/06/07 04:31:57 guy Exp $ (LBL) + */ + +#ifndef BPF_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int bpf_int32; +typedef u_int bpf_u_int32; + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + * + * The first set is for compatibility with Sun's pcc style + * header files. If your using gcc, we assume that you + * have run fixincludes so the latter set should work. + */ +#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) +#define BIOCGBLEN _IOR(B,102, u_int) +#define BIOCSBLEN _IOWR(B,102, u_int) +#define BIOCSETF _IOW(B,103, struct bpf_program) +#define BIOCFLUSH _IO(B,104) +#define BIOCPROMISC _IO(B,105) +#define BIOCGDLT _IOR(B,106, u_int) +#define BIOCGETIF _IOR(B,107, struct ifreq) +#define BIOCSETIF _IOW(B,108, struct ifreq) +#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) +#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) +#define BIOCGSTATS _IOR(B,111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW(B,112, u_int) +#define BIOCVERSION _IOR(B,113, struct bpf_version) +#define BIOCSTCPF _IOW(B,114, struct bpf_program) +#define BIOCSUDPF _IOW(B,115, struct bpf_program) +#else +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSTCPF _IOW('B',114, struct bpf_program) +#define BIOCSUDPF _IOW('B',115, struct bpf_program) +#endif + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + bpf_u_int32 bh_caplen; /* length of captured portion */ + bpf_u_int32 bh_datalen; /* original length of packet */ + u_short bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; +/* + * Because the structure above is not a multiple of 4 bytes, some compilers + * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. + * Only the kernel needs to know about it; applications use bh_hdrlen. + */ +#if defined(KERNEL) || defined(_KERNEL) +#define SIZEOF_BPF_HDR 18 +#endif + +/* + * Data-link level type codes. + */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#ifdef __NetBSD__ +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ +#endif +#else +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#endif + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Reserved for Frame Relay; BSD/OS has a DLT_FR, with a value of 11, + * but that collides with other values. DLT_FR and DLT_FRELAY packets + * start with the Frame Relay header (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 as a DLT_ value. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * Reserved for RFC 2625 IP-over-Fibre Channel, as per a request from + * Don Lee . + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * Reserved for capturing on Solaris with SunATM. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) +/* + * Systems based on non-BSD kernels don't have ifnet's (or they don't mean + * anything if it is in ) and won't work like this. + */ +# if __STDC__ +extern void bpf_tap(struct ifnet *, u_char *, u_int); +extern void bpf_mtap(struct ifnet *, struct mbuf *); +extern void bpfattach(struct ifnet *, u_int, u_int); +extern void bpfilterattach(int); +# else +extern void bpf_tap(); +extern void bpf_mtap(); +extern void bpfattach(); +extern void bpfilterattach(); +# endif /* __STDC__ */ +#endif /* BSD && (_KERNEL || KERNEL) */ +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(struct bpf_insn *, int); +extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif diff -Naur test-for-latech/include/net/dwcs.h testqf-for-latech/include/net/dwcs.h --- test-for-latech/include/net/dwcs.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/dwcs.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,39 @@ + +void watchdog(unsigned long arg) +{ + struct net_device *dev = (struct net_device*) arg; + if(dev) + { + netif_schedule(dev); + } +} + + + +void dwcs_init_timer(struct timer_list *wd_timer, struct net_device *dev) +{ + init_timer(wd_timer); + wd_timer->function = watchdog; + wd_timer->data = (unsigned long)dev; +} + +/* + * Helper function to return the address of the class + * by providing the classid (that includes major and minor ids), + * Returns NULL, if no class is found. + */ +static __inline__ struct dwcs_class * +dwcs_class_lookup ( struct dwcs_sched_data *q, + u32 classid ) +{ + struct dwcs_class *cl; + + for ( cl = q->classes[dwcs_hash ( classid )]; cl; cl = cl->next ) + if ( cl->classid == classid ) + { + return cl; + } + + return NULL; +} + diff -Naur test-for-latech/include/net/ethernet.h testqf-for-latech/include/net/ethernet.h --- test-for-latech/include/net/ethernet.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/ethernet.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the FreeBSD version of this file. Curiously, that file + lacks a copyright in the header. */ + +#ifndef __NET_ETHERNET_H +#define __NET_ETHERNET_H 1 + +#include +#include +#include /* IEEE 802.3 Ethernet constants */ + +__BEGIN_DECLS + +/* This is a name for the 48 bit ethernet address available on many + systems. */ +struct ether_addr +{ + u_int8_t ether_addr_octet[ETH_ALEN]; +} __attribute__ ((__packed__)); + +/* 10Mb/s ethernet header */ +struct ether_header +{ + u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ + u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ + u_int16_t ether_type; /* packet type ID field */ +} __attribute__ ((__packed__)); + +/* Ethernet protocol ID's */ +#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */ +#define ETHERTYPE_IP 0x0800 /* IP */ +#define ETHERTYPE_ARP 0x0806 /* Address resolution */ +#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */ + +#define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ +#define ETHER_TYPE_LEN 2 /* bytes in type field */ +#define ETHER_CRC_LEN 4 /* bytes in CRC field */ +#define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ +#define ETHER_MIN_LEN (ETH_ZLEN + ETHER_CRC_LEN) /* min packet length */ +#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETHER_CRC_LEN) /* max packet length */ + +/* make sure ethenet length is valid */ +#define ETHER_IS_VALID_LEN(foo) \ + ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) + +/* + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed + * by an ETHER type (as given above) and then the (variable-length) header. + */ +#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ +#define ETHERTYPE_NTRAILER 16 + +#define ETHERMTU ETH_DATA_LEN +#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) + +__END_DECLS + +#endif /* net/ethernet.h */ diff -Naur test-for-latech/include/net/if_arp.h testqf-for-latech/include/net/if_arp.h --- test-for-latech/include/net/if_arp.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/if_arp.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,173 @@ +/* Definitions for Address Resolution Protocol. + Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_IF_ARP_H + +#define _NET_IF_ARP_H 1 +#include + +#include +#include + +__BEGIN_DECLS + +/* Some internals from deep down in the kernel. */ +#define MAX_ADDR_LEN 7 + + +/* This structure defines an ethernet arp header. */ + +/* ARP protocol opcodes. */ +#define ARPOP_REQUEST 1 /* ARP request. */ +#define ARPOP_REPLY 2 /* ARP reply. */ +#define ARPOP_RREQUEST 3 /* RARP request. */ +#define ARPOP_RREPLY 4 /* RARP reply. */ +#define ARPOP_InREQUEST 8 /* InARP request. */ +#define ARPOP_InREPLY 9 /* InARP reply. */ +#define ARPOP_NAK 10 /* (ATM)ARP NAK. */ + +/* See RFC 826 for protocol description. ARP packets are variable + in size; the arphdr structure defines the fixed-length portion. + Protocol type values are the same as those for 10 Mb/s Ethernet. + It is followed by the variable-sized fields ar_sha, arp_spa, + arp_tha and arp_tpa in that order, according to the lengths + specified. Field names used correspond to RFC 826. */ + +struct arphdr + { + unsigned short int ar_hrd; /* Format of hardware address. */ + unsigned short int ar_pro; /* Format of protocol address. */ + unsigned char ar_hln; /* Length of hardware address. */ + unsigned char ar_pln; /* Length of protocol address. */ + unsigned short int ar_op; /* ARP opcode (command). */ +#if 0 + /* Ethernet looks like this : This bit is variable sized + however... */ + unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */ + unsigned char __ar_sip[4]; /* Sender IP address. */ + unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */ + unsigned char __ar_tip[4]; /* Target IP address. */ +#endif + }; + + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* From KA9Q: NET/ROM pseudo. */ +#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet. */ +#define ARPHRD_AX25 3 /* AX.25 Level 2. */ +#define ARPHRD_PRONET 4 /* PROnet token ring. */ +#define ARPHRD_CHAOS 5 /* Chaosnet. */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB. */ +#define ARPHRD_ARCNET 7 /* ARCnet. */ +#define ARPHRD_APPLETLK 8 /* APPLEtalk. */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI. */ +#define ARPHRD_ATM 19 /* ATM. */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id). */ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 /* Notional KISS type. */ +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 /* CCITT X.25. */ +#define ARPHDR_HWX25 272 /* Boards with X.25 in firmware. */ +#define ARPHRD_PPP 512 +#define ARPHRD_CISCO 513 /* Cisco HDLC. */ +#define ARPHRD_HDLC ARPHRD_CISCO +#define ARPHRD_LAPB 516 /* LAPB. */ +#define ARPHRD_DDCMP 517 /* Digital's DDCMP. */ +#define ARPHRD_RAWHDLC 518 /* Raw HDLC. */ + +#define ARPHRD_TUNNEL 768 /* IPIP tunnel. */ +#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel. */ +#define ARPHRD_FRAD 770 /* Frame Relay Access Device. */ +#define ARPHRD_SKIP 771 /* SKIP vif. */ +#define ARPHRD_LOOPBACK 772 /* Loopback device. */ +#define ARPHRD_LOCALTLK 773 /* Localtalk device. */ +#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface. */ +#define ARPHRD_BIF 775 /* AP1000 BIF. */ +#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4. */ +#define ARPHRD_IPDDP 777 /* IP-in-DDP tunnel. */ +#define ARPHRD_IPGRE 778 /* GRE over IP. */ +#define ARPHRD_PIMREG 779 /* PIMSM register interface. */ +#define ARPHRD_HIPPI 780 /* High Performance Parallel I'face. */ +#define ARPHRD_ASH 781 /* (Nexus Electronics) Ash. */ +#define ARPHRD_ECONET 782 /* Acorn Econet. */ +#define ARPHRD_IRDA 783 /* Linux-IrDA. */ +#define ARPHRD_FCPP 784 /* Point to point fibrechanel. */ +#define ARPHRD_FCAL 785 /* Fibrechanel arbitrated loop. */ +#define ARPHRD_FCPL 786 /* Fibrechanel public loop. */ +#define ARPHRD_FCPFABRIC 787 /* Fibrechanel fabric. */ +#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR. */ +#define ARPHRD_IEEE80211 801 /* IEEE 802.11. */ + +/* ARP ioctl request. */ +struct arpreq + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + char arp_dev[16]; + }; + +struct arpreq_old + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + }; + +/* ARP Flag values. */ +#define ATF_COM 0x02 /* Completed entry (ha valid). */ +#define ATF_PERM 0x04 /* Permanent entry. */ +#define ATF_PUBL 0x08 /* Publish entry. */ +#define ATF_USETRAILERS 0x10 /* Has requested trailers. */ +#define ATF_NETMASK 0x20 /* Want to use a netmask (only + for proxy entries). */ +#define ATF_DONTPUB 0x40 /* Don't answer this addresses. */ +#define ATF_MAGIC 0x80 /* Automatically added entry. */ + + +/* Support for the user space arp daemon, arpd. */ +#define ARPD_UPDATE 0x01 +#define ARPD_LOOKUP 0x02 +#define ARPD_FLUSH 0x03 + +struct arpd_request + { + unsigned short int req; /* Request type. */ + u_int32_t ip; /* IP address of entry. */ + unsigned long int dev; /* Device entry is tied to. */ + unsigned long int stamp; + unsigned long int updated; + unsigned char ha[MAX_ADDR_LEN]; /* Hardware address. */ + }; + +__END_DECLS + +#endif /* net/if_arp.h */ diff -Naur test-for-latech/include/net/if.h testqf-for-latech/include/net/if.h --- test-for-latech/include/net/if.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/if.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,203 @@ +/* net/if.h -- declarations for inquiring about network interfaces + Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_H +#define _NET_IF_H 1 + +#include + +#ifdef __USE_MISC +# include +# include +#endif + + +/* Length of interface name. */ +#define IF_NAMESIZE 16 + +struct if_nameindex + { + unsigned int if_index; /* 1, 2, ... */ + char *if_name; /* null terminated name: "eth0", ... */ + }; + + +#ifdef __USE_MISC +/* Standard interface flags. */ +enum + { + IFF_UP = 0x1, /* Interface is up. */ +# define IFF_UP IFF_UP + IFF_BROADCAST = 0x2, /* Broadcast address valid. */ +# define IFF_BROADCAST IFF_BROADCAST + IFF_DEBUG = 0x4, /* Turn on debugging. */ +# define IFF_DEBUG IFF_DEBUG + IFF_LOOPBACK = 0x8, /* Is a loopback net. */ +# define IFF_LOOPBACK IFF_LOOPBACK + IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link. */ +# define IFF_POINTOPOINT IFF_POINTOPOINT + IFF_NOTRAILERS = 0x20, /* Avoid use of trailers. */ +# define IFF_NOTRAILERS IFF_NOTRAILERS + IFF_RUNNING = 0x40, /* Resources allocated. */ +# define IFF_RUNNING IFF_RUNNING + IFF_NOARP = 0x80, /* No address resolution protocol. */ +# define IFF_NOARP IFF_NOARP + IFF_PROMISC = 0x100, /* Receive all packets. */ +# define IFF_PROMISC IFF_PROMISC + + /* Not supported */ + IFF_ALLMULTI = 0x200, /* Receive all multicast packets. */ +# define IFF_ALLMULTI IFF_ALLMULTI + + IFF_MASTER = 0x400, /* Master of a load balancer. */ +# define IFF_MASTER IFF_MASTER + IFF_SLAVE = 0x800, /* Slave of a load balancer. */ +# define IFF_SLAVE IFF_SLAVE + + IFF_MULTICAST = 0x1000, /* Supports multicast. */ +# define IFF_MULTICAST IFF_MULTICAST + + IFF_PORTSEL = 0x2000, /* Can set media type. */ +# define IFF_PORTSEL IFF_PORTSEL + IFF_AUTOMEDIA = 0x4000 /* Auto media select active. */ +# define IFF_AUTOMEDIA IFF_AUTOMEDIA + }; + +/* The ifaddr structure contains information about one address of an + interface. They are maintained by the different address families, + are allocated and attached when an address is set, and are linked + together so all addresses for an interface can be located. */ + +struct ifaddr + { + struct sockaddr ifa_addr; /* Address of interface. */ + union + { + struct sockaddr ifu_broadaddr; + struct sockaddr ifu_dstaddr; + } ifa_ifu; + struct iface *ifa_ifp; /* Back-pointer to interface. */ + struct ifaddr *ifa_next; /* Next address for interface. */ + }; + +# define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ +# define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ + +/* Device mapping structure. I'd just gone off and designed a + beautiful scheme using only loadable modules with arguments for + driver options and along come the PCMCIA people 8) + + Ah well. The get() side of this is good for WDSETUP, and it'll be + handy for debugging things. The set side is fine for now and being + very small might be worth keeping for clean configuration. */ + +struct ifmap + { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned short int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ + }; + +/* Interface request structure used for socket ioctl's. All interface + ioctl's must have parameter definitions which begin with ifr_name. + The remainder may be interface specific. */ + +struct ifreq + { +# define IFHWADDRLEN 6 +# define IFNAMSIZ IF_NAMESIZE + union + { + char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ + } ifr_ifrn; + + union + { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short int ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + __caddr_t ifru_data; + } ifr_ifru; + }; +# define ifr_name ifr_ifrn.ifrn_name /* interface name */ +# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +# define ifr_addr ifr_ifru.ifru_addr /* address */ +# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +# define ifr_flags ifr_ifru.ifru_flags /* flags */ +# define ifr_metric ifr_ifru.ifru_ivalue /* metric */ +# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +# define ifr_map ifr_ifru.ifru_map /* device map */ +# define ifr_slave ifr_ifru.ifru_slave /* slave device */ +# define ifr_data ifr_ifru.ifru_data /* for use by interface */ +# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */ +# define ifr_newname ifr_ifru.ifru_newname /* New name */ +# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0) +# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0) +# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0) + + +/* Structure used in SIOCGIFCONF request. Used to retrieve interface + configuration for machine (useful for programs which must know all + networks accessible). */ + +struct ifconf + { + int ifc_len; /* Size of buffer. */ + union + { + __caddr_t ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; + }; +# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */ +# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */ +# define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) /* not right */ +#endif /* Misc. */ + +__BEGIN_DECLS + +/* Convert an interface name to an index, and vice versa. */ +extern unsigned int if_nametoindex (__const char *__ifname) __THROW; +extern char *if_indextoname (unsigned int __ifindex, char *__ifname) __THROW; + +/* Return a list of all interfaces and their indices. */ +extern struct if_nameindex *if_nameindex (void) __THROW; + +/* Free the data returned from if_nameindex. */ +extern void if_freenameindex (struct if_nameindex *__ptr) __THROW; + +__END_DECLS + +#endif /* net/if.h */ diff -Naur test-for-latech/include/net/if_packet.h testqf-for-latech/include/net/if_packet.h --- test-for-latech/include/net/if_packet.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/if_packet.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,37 @@ +/* Definitions for use with Linux SOCK_PACKET sockets. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __IF_PACKET_H +#define __IF_PACKET_H + +#include +#include + +/* This is the SOCK_PACKET address structure as used in Linux 2.0. + From Linux 2.1 the AF_PACKET interface is preferred and you should + consider using it in place of this one. */ + +struct sockaddr_pkt + { + __SOCKADDR_COMMON (spkt_); + unsigned char spkt_device[14]; + unsigned short spkt_protocol; + }; + +#endif diff -Naur test-for-latech/include/net/if_ppp.h testqf-for-latech/include/net/if_ppp.h --- test-for-latech/include/net/if_ppp.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/if_ppp.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,169 @@ +/* From: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * ==FILEVERSION 960926== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, please set the above date. + * if_ppp.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new if_ppp.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + + +#ifndef __NET_IF_PPP_H +#define __NET_IF_PPP_H 1 + +#include +#include + +#include +#include +#include + +__BEGIN_DECLS + +/* + * Packet sizes + */ + +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#define PPP_MAXMRU 65000 /* Largest MRU we allow */ +#define PPP_VERSION "2.2.0" +#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ +#define PROTO_IPX 0x002b /* protocol numbers */ +#define PROTO_DNA_RT 0x0027 /* DNA Routing */ + + +/* + * Bit definitions for flags. + */ + +#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ +#define SC_COMP_AC 0x00000002 /* header compression (output) */ +#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ +#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ +#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ +#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ +#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ +#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ +#define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */ +#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ +#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ +#define SC_DEBUG 0x00010000 /* enable debug messages */ +#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ +#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ +#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ +#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_MASK 0x0fE0ffff /* bits that user can change */ + +/* state bits */ +#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ +#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ +#define SC_VJ_RESET 0x20000000 /* Need to reset the VJ decompressor */ +#define SC_XMIT_BUSY 0x10000000 /* ppp_write_wakeup is active */ +#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ +#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ +#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ +#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ +#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */ +#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */ + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP protocol, e.g. PPP_IP */ + enum NPmode mode; +}; + +/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ +struct ppp_option_data { + u_int8_t *ptr; + u_int32_t length; + int transmit; +}; + +struct ifpppstatsreq { + struct ifreq b; + struct ppp_stats stats; /* statistic information */ +}; + +struct ifpppcstatsreq { + struct ifreq b; + struct ppp_comp_stats stats; +}; + +#define ifr__name b.ifr_ifrn.ifrn_name +#define stats_ptr b.ifr_ifru.ifru_data + +/* + * Ioctl definitions. + */ + +#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ +#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ +#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ +#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ +#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ +#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ +#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ +#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ +#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ +#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ +#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ +#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ +#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ +#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) +#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ +#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */ +#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */ +#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ + +#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) +#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */ +#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2) + +#if !defined(ifr_mtu) +#define ifr_mtu ifr_ifru.ifru_metric +#endif + +__END_DECLS + +#endif /* net/if_ppp.h */ diff -Naur test-for-latech/include/net/if_shaper.h testqf-for-latech/include/net/if_shaper.h --- test-for-latech/include/net/if_shaper.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/if_shaper.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,59 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_SHAPER_H +#define _NET_IF_SHAPER_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +#define SHAPER_QLEN 10 +/* + * This is a bit speed dependant (read it shouldnt be a constant!) + * + * 5 is about right for 28.8 upwards. Below that double for every + * halving of speed or so. - ie about 20 for 9600 baud. + */ +#define SHAPER_LATENCY (5 * HZ) +#define SHAPER_MAXSLIP 2 +#define SHAPER_BURST (HZ / 50) /* Good for >128K then */ + +#define SHAPER_SET_DEV 0x0001 +#define SHAPER_SET_SPEED 0x0002 +#define SHAPER_GET_DEV 0x0003 +#define SHAPER_GET_SPEED 0x0004 + +struct shaperconf +{ + u_int16_t ss_cmd; + union + { + char ssu_name[14]; + u_int32_t ssu_speed; + } ss_u; +#define ss_speed ss_u.ssu_speed +#define ss_name ss_u.ssu_name +}; + +__END_DECLS + +#endif /* net/if_shaper.h */ diff -Naur test-for-latech/include/net/if_slip.h testqf-for-latech/include/net/if_slip.h --- test-for-latech/include/net/if_slip.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/if_slip.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,25 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_SLIP_H +#define _NET_IF_SLIP_H 1 + +/* We can use the kernel header. */ +#include + +#endif /* net/if_slip.h. */ diff -Naur test-for-latech/include/net/pkt_cls.h testqf-for-latech/include/net/pkt_cls.h --- test-for-latech/include/net/pkt_cls.h 2004-06-11 07:40:23.000000000 -0400 +++ testqf-for-latech/include/net/pkt_cls.h 2004-06-11 07:47:33.000000000 -0400 @@ -81,7 +81,7 @@ extern int register_tcf_proto_ops(struct tcf_proto_ops *ops); extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); - +extern struct tcf_proto_ops cls_socket_ops; #endif diff -Naur test-for-latech/include/net/pkt_sched.h testqf-for-latech/include/net/pkt_sched.h --- test-for-latech/include/net/pkt_sched.h 2004-06-11 07:40:22.000000000 -0400 +++ testqf-for-latech/include/net/pkt_sched.h 2004-06-11 07:47:33.000000000 -0400 @@ -16,6 +16,17 @@ #include #endif +#ifdef CONFIG_QFABRIC +#define MAX_EVENTS 4096 +#define MAX_DEVS 5 + +struct rte_list { + struct sk_buff *skb; + int deadline; + int flags; +}; +#endif + struct rtattr; struct Qdisc; @@ -432,7 +443,15 @@ int tc_filter_init(void); int pktsched_init(void); +struct Qdisc_ops *qdisc_lookup_ops_string(char *kind); +u32 qdisc_alloc_handle(struct net_device *dev); +int qdisc_graft(struct net_device *dev, struct Qdisc *parent, u32 classid, + struct Qdisc *new, struct Qdisc **old); + extern int qdisc_restart(struct net_device *dev); +#ifdef CONFIG_QFABRIC +extern int qdisc_restart_rte(struct net_device *dev); +#endif static inline void qdisc_run(struct net_device *dev) { @@ -441,6 +460,15 @@ /* NOTHING */; } +#ifdef CONFIG_QFABRIC +static inline void qdisc_run_rte(struct net_device *dev) +{ + while (!netif_queue_stopped(dev) && + qdisc_restart_rte(dev)<0) + /* NOTHING */; +} +#endif + /* Calculate maximal size of packet seen by hard_start_xmit routine of this device. */ @@ -450,4 +478,12 @@ return dev->hard_header ? mtu + dev->hard_header_len : mtu; } +#ifdef CONFIG_QFABRIC +extern int rte_enqueue(struct net_device *dev, struct sk_buff *skb); +extern struct sk_buff *rte_dequeue(struct net_device *dev); +extern int rte_requeue(struct sk_buff *skb, struct net_device *dev); +extern int rte_init(struct net_device *dev); +extern int rte_avail; +#endif + #endif diff -Naur test-for-latech/include/net/ppp-comp.h testqf-for-latech/include/net/ppp-comp.h --- test-for-latech/include/net/ppp-comp.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/ppp-comp.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1 @@ +#include diff -Naur test-for-latech/include/net/ppp_defs.h testqf-for-latech/include/net/ppp_defs.h --- test-for-latech/include/net/ppp_defs.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/ppp_defs.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,10 @@ +#ifndef _NET_PPP_DEFS_H +#define _NET_PPP_DEFS_H 1 + +#define __need_time_t +#include + +#include +#include + +#endif /* net/ppp_defs.h */ diff -Naur test-for-latech/include/net/route.h testqf-for-latech/include/net/route.h --- test-for-latech/include/net/route.h 2004-06-11 07:40:22.000000000 -0400 +++ testqf-for-latech/include/net/route.h 2004-06-11 07:47:33.000000000 -0400 @@ -1,188 +1,145 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Definitions for the IP router. - * - * Version: @(#)route.h 1.0.4 05/27/93 - * - * Authors: Ross Biro, - * Fred N. van Kempen, - * Fixes: - * Alan Cox : Reformatted. Added ip_rt_local() - * Alan Cox : Support for TCP parameters. - * Alexey Kuznetsov: Major changes for new routing code. - * Mike McLagan : Routing by source - * Robert Olsson : Added rt_cache statistics - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#ifndef _ROUTE_H -#define _ROUTE_H - -#include -#include -#include -#include -#include -#include -#include -#include +/* Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. -#ifndef __KERNEL__ -#warning This file is not supposed to be used outside of kernel. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_ROUTE_H +#define _NET_ROUTE_H 1 + +#include +#include +#include +#include +#include + + +/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ +struct rtentry + { + unsigned long int rt_pad1; + struct sockaddr rt_dst; /* Target address. */ + struct sockaddr rt_gateway; /* Gateway addr (RTF_GATEWAY). */ + struct sockaddr rt_genmask; /* Target network mask (IP). */ + unsigned short int rt_flags; + short int rt_pad2; + unsigned long int rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; +#if __WORDSIZE == 64 + short int rt_pad4[3]; +#else + short int rt_pad4; #endif + short int rt_metric; /* +1 for binary compatibility! */ + char *rt_dev; /* Forcing the device at add. */ + unsigned long int rt_mtu; /* Per route MTU/Window. */ + unsigned long int rt_window; /* Window clamping. */ + unsigned short int rt_irtt; /* Initial RTT. */ + }; +/* Compatibility hack. */ +#define rt_mss rt_mtu + + +struct in6_rtmsg + { + struct in6_addr rtmsg_dst; + struct in6_addr rtmsg_src; + struct in6_addr rtmsg_gateway; + u_int32_t rtmsg_type; + u_int16_t rtmsg_dst_len; + u_int16_t rtmsg_src_len; + u_int32_t rtmsg_metric; + unsigned long int rtmsg_info; + u_int32_t rtmsg_flags; + int rtmsg_ifindex; + }; + + +#define RTF_UP 0x0001 /* Route usable. */ +#define RTF_GATEWAY 0x0002 /* Destination is a gateway. */ + +#define RTF_HOST 0x0004 /* Host entry (net otherwise). */ +#define RTF_REINSTATE 0x0008 /* Reinstate route after timeout. */ +#define RTF_DYNAMIC 0x0010 /* Created dyn. (by redirect). */ +#define RTF_MODIFIED 0x0020 /* Modified dyn. (by redirect). */ +#define RTF_MTU 0x0040 /* Specific MTU for this route. */ +#define RTF_MSS RTF_MTU /* Compatibility. */ +#define RTF_WINDOW 0x0080 /* Per route window clamping. */ +#define RTF_IRTT 0x0100 /* Initial round trip time. */ +#define RTF_REJECT 0x0200 /* Reject route. */ +#define RTF_STATIC 0x0400 /* Manually injected route. */ +#define RTF_XRESOLVE 0x0800 /* External resolver. */ +#define RTF_NOFORWARD 0x1000 /* Forwarding inhibited. */ +#define RTF_THROW 0x2000 /* Go to next class. */ +#define RTF_NOPMTUDISC 0x4000 /* Do not send packets with DF. */ + +/* for IPv6 */ +#define RTF_DEFAULT 0x00010000 /* default - learned via ND */ +#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */ +#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ + +#define RTF_LINKRT 0x00100000 /* link specific - device match */ +#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ + +#define RTF_CACHE 0x01000000 /* cache entry */ +#define RTF_FLOW 0x02000000 /* flow significant route */ +#define RTF_POLICY 0x04000000 /* policy route */ + +#define RTCF_VALVE 0x00200000 +#define RTCF_MASQ 0x00400000 +#define RTCF_NAT 0x00800000 +#define RTCF_DOREDIRECT 0x01000000 +#define RTCF_LOG 0x02000000 +#define RTCF_DIRECTSRC 0x04000000 + +#define RTF_LOCAL 0x80000000 +#define RTF_INTERFACE 0x40000000 +#define RTF_MULTICAST 0x20000000 +#define RTF_BROADCAST 0x10000000 +#define RTF_NAT 0x08000000 + +#define RTF_ADDRCLASSMASK 0xF8000000 +#define RT_ADDRCLASS(flags) ((__u_int32_t) flags >> 23) + +#define RT_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +#define RT_LOCALADDR(flags) ((flags & RTF_ADDRCLASSMASK) \ + == (RTF_LOCAL|RTF_INTERFACE)) + +#define RT_CLASS_UNSPEC 0 +#define RT_CLASS_DEFAULT 253 + +#define RT_CLASS_MAIN 254 +#define RT_CLASS_LOCAL 255 +#define RT_CLASS_MAX 255 + + +#define RTMSG_ACK NLMSG_ACK +#define RTMSG_OVERRUN NLMSG_OVERRUN + +#define RTMSG_NEWDEVICE 0x11 +#define RTMSG_DELDEVICE 0x12 +#define RTMSG_NEWROUTE 0x21 +#define RTMSG_DELROUTE 0x22 +#define RTMSG_NEWRULE 0x31 +#define RTMSG_DELRULE 0x32 +#define RTMSG_CONTROL 0x40 -#define RTO_ONLINK 0x01 +#define RTMSG_AR_FAILED 0x51 /* Address Resolution failed. */ -#define RTO_CONN 0 -/* RTO_CONN is not used (being alias for 0), but preserved not to break - * some modules referring to it. */ - -#define RT_CONN_FLAGS(sk) (RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute) - -struct rt_key -{ - __u32 dst; - __u32 src; - int iif; - int oif; -#ifdef CONFIG_IP_ROUTE_FWMARK - __u32 fwmark; -#endif - __u8 tos; - __u8 scope; -}; - -struct inet_peer; -struct rtable -{ - union - { - struct dst_entry dst; - struct rtable *rt_next; - } u; - - unsigned rt_flags; - unsigned rt_type; - - __u32 rt_dst; /* Path destination */ - __u32 rt_src; /* Path source */ - int rt_iif; - - /* Info on neighbour */ - __u32 rt_gateway; - - /* Cache lookup keys */ - struct rt_key key; - - /* Miscellaneous cached information */ - __u32 rt_spec_dst; /* RFC1122 specific destination */ - struct inet_peer *peer; /* long-living peer info */ - -#ifdef CONFIG_IP_ROUTE_NAT - __u32 rt_src_map; - __u32 rt_dst_map; -#endif -}; - -struct ip_rt_acct -{ - __u32 o_bytes; - __u32 o_packets; - __u32 i_bytes; - __u32 i_packets; -}; - -struct rt_cache_stat -{ - unsigned int in_hit; - unsigned int in_slow_tot; - unsigned int in_slow_mc; - unsigned int in_no_route; - unsigned int in_brd; - unsigned int in_martian_dst; - unsigned int in_martian_src; - unsigned int out_hit; - unsigned int out_slow_tot; - unsigned int out_slow_mc; - unsigned int gc_total; - unsigned int gc_ignored; - unsigned int gc_goal_miss; - unsigned int gc_dst_overflow; -} ____cacheline_aligned_in_smp; - -extern struct ip_rt_acct *ip_rt_acct; - -struct in_device; -extern void ip_rt_init(void); -extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw, - u32 src, u8 tos, struct net_device *dev); -extern void ip_rt_advice(struct rtable **rp, int advice); -extern void rt_cache_flush(int how); -extern int ip_route_output_key(struct rtable **, const struct rt_key *key); -extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin); -extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu); -extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu); -extern void ip_rt_send_redirect(struct sk_buff *skb); - -extern unsigned inet_addr_type(u32 addr); -extern void ip_rt_multicast_event(struct in_device *); -extern int ip_rt_ioctl(unsigned int cmd, void *arg); -extern void ip_rt_get_source(u8 *src, struct rtable *rt); -extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); - -/* Deprecated: use ip_route_output_key directly */ -static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) -{ - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; - - return ip_route_output_key(rp, &key); -} - - -static inline void ip_rt_put(struct rtable * rt) -{ - if (rt) - dst_release(&rt->u.dst); -} - -#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3) - -extern __u8 ip_tos2prio[16]; - -static inline char rt_tos2priority(u8 tos) -{ - return ip_tos2prio[IPTOS_TOS(tos)>>1]; -} - -static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif) -{ - int err; - err = ip_route_output(rp, dst, src, tos, oif); - if (err || (dst && src)) - return err; - dst = (*rp)->rt_dst; - src = (*rp)->rt_src; - ip_rt_put(*rp); - *rp = NULL; - return ip_route_output(rp, dst, src, tos, oif); -} - -extern void rt_bind_peer(struct rtable *rt, int create); - -static inline struct inet_peer *rt_get_peer(struct rtable *rt) -{ - if (rt->peer) - return rt->peer; - - rt_bind_peer(rt, 0); - return rt->peer; -} - -#endif /* _ROUTE_H */ +#endif /* net/route.h */ diff -Naur test-for-latech/include/net/sock.h testqf-for-latech/include/net/sock.h --- test-for-latech/include/net/sock.h 2004-06-11 07:40:22.000000000 -0400 +++ testqf-for-latech/include/net/sock.h 2004-06-11 07:47:33.000000000 -0400 @@ -678,6 +678,21 @@ int (*backlog_rcv) (struct sock *sk, struct sk_buff *skb); void (*destruct)(struct sock *sk); + + int drop_flag; + int urgent_flag; + int fragments; +#ifdef CONFIG_QFABRIC + int owner; + int kecho; + void *kecho_ptr; + short readable; + short writable; + int fd; + int counter; + long qos_priority; + long qos_deadline; +#endif }; /* The per-socket spinlock must be held here. */ diff -Naur test-for-latech/include/net/tcp.h testqf-for-latech/include/net/tcp.h --- test-for-latech/include/net/tcp.h 2004-06-11 07:40:22.000000000 -0400 +++ testqf-for-latech/include/net/tcp.h 2004-06-11 07:47:33.000000000 -0400 @@ -520,6 +520,10 @@ struct tcp_v6_open_req v6_req; #endif } af; +#ifdef CONFIG_QFABRIC + int priority; + long deadline_msec; +#endif }; /* SLAB cache for open requests. */ @@ -1590,6 +1594,94 @@ req->dl_next = NULL; } +#ifdef CONFIG_QFABRIC +static inline struct sock *tcp_acceptq_queue_prio(struct sock *sk, + struct open_request *req, struct sock *child, int drop) +{ + struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; + struct open_request *ptr, *prev; + struct sock *tmp; + + req->sk = child; + sk->qos_priority = req->priority; + sk->qos_deadline = req->deadline_msec; + child->qos_priority = req->priority; + child->qos_deadline = req->deadline_msec; + + if (!tp->accept_queue_tail) { + tp->accept_queue = req; + tp->accept_queue_tail = req; + req->dl_next = NULL; + } else { + ptr = tp->accept_queue; + prev = ptr; + if (req->priority >= 0) { + while ((ptr != NULL)&&(ptr->priority >= req->priority)) + { + prev = ptr; + ptr = ptr->dl_next; + } + if (ptr == NULL) { + if ((drop == 1) && (!tcp_acceptq_is_full(sk))) { + tp->accept_queue_tail = req; + req->dl_next = NULL; + } else { + tcp_openreq_free(req); + return child; + } + } else { + req->dl_next = ptr; + prev->dl_next = req; + if ((drop == 1) && (tcp_acceptq_is_full(sk))) { + while (ptr != NULL) { + ptr = ptr->dl_next; + if (ptr != NULL) prev = prev->dl_next; + } + tmp = prev->dl_next->sk; + tcp_openreq_free(prev->dl_next); + prev->dl_next = NULL; + return tmp; + } + } + } else if (req->deadline_msec != -1) { + while ((ptr != NULL) && + (ptr->deadline_msec <= req->deadline_msec)) { + prev = ptr; + ptr = ptr->dl_next; + } + if (ptr == NULL) { + if ((drop == 1) && (!tcp_acceptq_is_full(sk))) { + tp->accept_queue_tail = req; + req->dl_next = NULL; + } else { + tcp_openreq_free(req); + return child; + } + } else { + req->dl_next = ptr; + prev->dl_next = req; + if ((drop == 1) && (tcp_acceptq_is_full(sk))) { + while (ptr != NULL) { + ptr = ptr->dl_next; + if (ptr != NULL) prev = prev->dl_next; + } + tmp = prev->dl_next->sk; + tcp_openreq_free(prev->dl_next); + prev->dl_next = NULL; + return tmp; + } + } + } else { + tp->accept_queue_tail->dl_next = req; + tp->accept_queue_tail = req; + req->dl_next = NULL; + } + } + tcp_acceptq_added(sk); + return NULL; +} +#endif + struct tcp_listen_opt { u8 max_qlen_log; /* log_2 of maximal queued SYNs */ @@ -1665,6 +1757,10 @@ req->acked = 0; req->ecn_ok = 0; req->rmt_port = skb->h.th->source; +#ifdef CONFIG_QFABRIC + req->priority = -1; + req->deadline_msec = -1; +#endif } #define TCP_MEM_QUANTUM ((int)PAGE_SIZE) diff -Naur test-for-latech/include/net/utils.h testqf-for-latech/include/net/utils.h --- test-for-latech/include/net/utils.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/include/net/utils.h 2004-06-11 07:47:33.000000000 -0400 @@ -0,0 +1,19 @@ +static __inline__ int socket_hash(u32 handle) +{ + return handle&0xFF; +} + + +static __inline__ struct socket *socki_lookup(struct inode *inode) +{ + return &inode->u.socket_i; +} + +static __inline__ unsigned dwcs_hash(u32 h) +{ + h ^= h>>8; + h ^= h>>4; + return h&0xF; +} + + diff -Naur test-for-latech/kernel/diffs testqf-for-latech/kernel/diffs --- test-for-latech/kernel/diffs 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/kernel/diffs 2004-06-11 07:47:23.000000000 -0400 @@ -0,0 +1,923 @@ +51a52,56 +> #ifdef CONFIG_DWCS_DFS +> #include +> #endif +> +> //#define DWCS_DEBUG_ON 1 +81a87,90 +> MODULE_AUTHOR("Georgia Tech -- CoC"); +> MODULE_DESCRIPTION("DWCS Scheduler"); +> MODULE_LICENSE("GPL"); +> +117a127,139 +> +> #ifdef CONFIG_DWCS_DFS +> #define MAX_LONG (unsigned long)4294967295 +> unsigned int start_time; +> struct task_struct *dwcs_hyper_period_task = NULL; +> unsigned long int dwcs_hyper_period_old_violations = 0; +> unsigned long int dwcs_hyper_period_old_misses = 0; +> unsigned long int dwcs_hyper_period_old_idles = 0; +> unsigned long int dwcs_hyper_period_violations = 0; +> unsigned long int dwcs_hyper_period_misses = 0; +> unsigned long int dwcs_hyper_period_idles = 0; +> int dwcs_hyper_period_task_iterations = 0; +> int dwcs_hyper_period_task_count = 0; +118a141,142 +> +> #ifdef CONFIG_ARCH_ADIFCC +122a147,153 +> #endif +> +> #ifdef CONFIG_ARCH_SA1100 +> int current_sa1100_freq; +> unsigned int sa1100_freq[12] = {59000, 73700, 88500, 103200, 118000, 132700, 147500, 162200, 176900, 191700, 206400, 221200}; +> #endif +> #endif +123a155,160 +> /* Needed for delayed runqueue insertion */ +> static int first_dwcs_task = 1; +> #ifdef CONFIG_DWCS_DFS +> static int hyper_period_recalc_needed = 0; +> +> #endif +131a169,188 +> #ifdef DWCS_DEBUG_ON +> struct proc_dir_entry *proc_dwcs_debug_control; +> struct proc_dir_entry *proc_dwcs_debug_write; +> struct proc_dir_entry *proc_time; +> #endif +> #ifdef CONFIG_DWCS_DFS +> struct proc_dir_entry *proc_dwcs_dfs; +> #endif +> #ifdef DWCS_DEBUG_ON +> extern unsigned long dwcs_timer_max_time; +> extern long dwcs_max_counter; +> extern long dwcs_pid; +> extern unsigned long dwcs_sched_max_time; +> +> int DWCS_DEBUG; +> char *debug_area; +> int deb_pos; +> int debug_count; +> #endif +> +174a232 +> #ifdef CONFIG_DWCS_DFS +194a253,452 +> #endif +> +> #ifdef CONFIG_DWCS_DFS +> static int clk2mhz (int n) +> { +> switch(n) { +> case 4 : return 400; +> case 5 : return 466; +> case 6 : return 533; +> case 7 : return 600; +> case 8 : return 666; +> case 9 : return 733; +> default: return -1; +> } +> +> return 400; +> } +> #endif +> +> +> #ifdef CONFIG_DWCS_DFS +> static unsigned long euclid (unsigned long m, unsigned long n) +> { +> unsigned long r; +> +> r = m % n; +> if (!r) { +> return n; +> } +> return euclid (n, r); +> } +> #endif +> +> +> #ifdef CONFIG_DWCS_DFS +> static unsigned long least_common_period (unsigned long x, unsigned long y) +> { +> return ((x * y) / euclid (x, y)); +> } +> #endif +> +> +> #ifdef CONFIG_DWCS_DFS +> static int find_smallest (unsigned long *period, int size) +> { +> int i; +> int index = -1; +> unsigned long smallest = MAX_LONG; +> +> for (i = 0; i < size; i++) { +> if (period[i] < smallest) { +> index = i; +> smallest = period[i]; +> } +> } +> +> return index; +> } +> #endif +> +> +> #ifdef CONFIG_DWCS_DFS +> static void find_hyper_period_task (void) +> { +> int i; +> int lcp; +> unsigned long largest_period; +> unsigned long *period; +> int dwcs_task_count; +> int smallest_index; +> struct task_struct *temp; +> +> dwcs_task_count = 0; +> largest_period = 0; +> for_each_task (temp) { +> if ((int)temp->dwcs_params->period > 0) { +> dwcs_task_count++; +> if ((int)temp->dwcs_params->period > largest_period) { +> dwcs_hyper_period_task = temp; +> largest_period = temp->dwcs_params->period; +> } +> } +> } +> if (dwcs_task_count == 1) +> start_time = jiffies; +> +> period = kmalloc (dwcs_task_count * sizeof (unsigned long), GFP_KERNEL); +> for (i = 0; i < dwcs_task_count; i++) +> period[i] = MAX_LONG; +> i = 0; +> for_each_task (temp) { +> if ((int)temp->dwcs_params->period > 0) { +> period[i] = temp->dwcs_params->period; +> i++; +> } +> } +> +> lcp = 1; +> for (i = 0; i < dwcs_task_count; i++) { +> smallest_index = find_smallest (period, dwcs_task_count); +> lcp = least_common_period (lcp, period[smallest_index]); +> period[smallest_index] = MAX_LONG; +> } +> +> dwcs_hyper_period_task_iterations = lcp / largest_period; +> dwcs_hyper_period_task_count = 0; +> +> +> printk (KERN_DEBUG "Hyper Task PID = %d\tLeast Common Period = %d\n", dwcs_hyper_period_task->pid, lcp); +> +> kfree (period); +> +> hyper_period_recalc_needed = 0; +> } +> #endif +> +> +> #ifdef CONFIG_DWCS_DFS +> void dwcs_dfs_measurements (struct task_struct *p) +> { +> int misses; +> int violations; +> int idles; +> static int freq_change; +> volatile unsigned int cclkcfg; +> +> if (hyper_period_recalc_needed) +> find_hyper_period_task(); +> +> /* Make any scaling adjustments */ +> misses = dwcs_hyper_period_misses - dwcs_hyper_period_old_misses; +> violations = dwcs_hyper_period_violations - dwcs_hyper_period_old_violations; +> idles = dwcs_hyper_period_idles - dwcs_hyper_period_old_idles; +> +> freq_change = 0; +> if (violations > 0) { +> #ifdef CONFIG_ARCH_ADIFCC +> get_80200_CCLKCFG(cclkcfg); +> if (cclkcfg < 9) { +> /* cclkcfg += violations; */ +> cclkcfg++; +> if (cclkcfg > 9) +> cclkcfg = 9; +> set_80200_CCLKCFG(cclkcfg); +> freq_change = 1; +> } +> #endif +> #ifdef CONFIG_ARCH_SA1100 +> if (current_sa1100_freq < 12) { +> current_sa1100_freq++; +> cpufreq_set (sa1100_freq[current_sa1100_freq]); +> freq_change = 1; +> } +> #endif +> } +> else if ((misses > 0) && (violations == 0)) { +> #ifdef CONFIG_ARCH_ADIFCC +> /* +> get_80200_CCLKCFG(cclkcfg); +> if (cclkcfg < 9) { +> cclkcfg++; +> set_80200_CCLKCFG(cclkcfg); +> freq_change = 1; +> } +> */ +> #endif +> #ifdef CONFIG_ARCH_SA1100 +> +> #endif +> } +> else if ((violations == 0) && (misses == 0)) { +> #ifdef CONFIG_ARCH_ADIFCC +> get_80200_CCLKCFG(cclkcfg); +> if (cclkcfg > 4) { +> cclkcfg--; +> set_80200_CCLKCFG(cclkcfg); +> freq_change = 1; +> } +> #endif +> #ifdef CONFIG_ARCH_SA1100 +> if (current_sa1100_freq > 0) { +> current_sa1100_freq--; +> cpufreq_set (sa1100_freq[current_sa1100_freq]); +> freq_change = 1; +> } +> #endif +> } +> +> if (freq_change) { +> printk (KERN_DEBUG "%lu\t %d\t %d\t %d\t %d\t %d\n", +> jiffies - start_time, clk2mhz(cclkcfg), violations, misses, idles, utilization); +> } +> +> dwcs_hyper_period_old_violations = dwcs_hyper_period_violations; +> dwcs_hyper_period_old_idles = dwcs_hyper_period_idles; +> dwcs_hyper_period_old_misses = dwcs_hyper_period_misses; +> +> } +> #endif +> +196c454,540 +< /* calculates max. possble slowdown and calls do_set_slowest_cpuspeed */ +--- +> #ifdef CONFIG_DWCS_DFS +> void dwcs_dfs_theoretical (void) +> { +> #ifdef CONFIG_ARCH_ADIFCC +> unsigned int freq_matrix[6][6] = {{1000, 857, 749, 666, 599, 545}, +> {1166, 1000, 874, 777, 699, 636}, +> {1333, 1142, 1000, 888, 799, 727}, +> {1500, 1285, 1125, 1000, 899, 818}, +> {1666, 1428, 1250, 1111, 1000, 909}, +> {1832, 1570, 1373, 1221, 1099, 1000}}; +> volatile unsigned int cclkcfg; +> #endif +> #ifdef CONFIG_ARCH_SA1100 +> unsigned int freq_matrix[12][12] = { +> {1000, 792, 649, 552, 480, 425, 381, 343, 314, 289, 268, 268}, +> {1262, 1000, 820, 697, 606, 536, 481, 433, 396, 365, 339, 339}, +> {1538, 1219, 1000, 850, 739, 654, 587, 528, 483, 445, 413, 413}, +> {1809, 1433, 1175, 1000, 869, 769, 690, 621, 568, 524, 486, 486}, +> {2080, 1648, 1351, 1149, 1000, 884, 793, 714, 653, 602, 559, 559}, +> {2352, 1863, 1528, 1299, 1130, 1000, 897, 807, 739, 681, 632, 632}, +> {2621, 2077, 1703, 1448, 1260, 1114, 1000, 899, 823, 759, 704, 704}, +> {2913, 2308, 1893, 1609, 1400, 1238, 1111, 1000, 915, 844, 783, 783}, +> {3182, 2521, 2067, 1758, 1529, 1353, 1213, 1092, 1000, 922, 855, 855}, +> {3451, 2734, 2242, 1907, 1659, 1467, 1316, 1184, 1084, 1000, 928, 928}, +> {3719, 2947, 2416, 2055, 1787, 1581, 1418, 1276, 1168, 1077, 1000, 1000}, +> {3719, 2947, 2416, 2055, 1787, 1581, 1418, 1276, 1168, 1077, 999, 1000}}; +> +> #endif +> +> +> int i; +> int closest_freq = -1; +> int smallest_difference; +> int current_freq; +> int k_entries; +> +> smallest_difference = MAX_UTILIZATION; +> +> #ifdef CONFIG_ARCH_SA1100 +> current_freq = 11; +> k_entries = 12; +> #endif +> #ifdef CONFIG_ARCH_ADIFCC +> current_freq = 5; +> k_entries = 6; +> #endif +> +> for (i = 0; i < k_entries; i++) { +> int temp_utilization; +> +> temp_utilization = (utilization * freq_matrix[current_freq][i]); +> temp_utilization = temp_utilization / 1000; +> temp_utilization = (MAX_UTILIZATION - reserved_utilization) - temp_utilization; +> if ((temp_utilization >= 0) && (temp_utilization < smallest_difference)) { +> smallest_difference = temp_utilization; +> closest_freq = i; +> } +> /* +> printk (KERN_DEBUG "U = %d\t M = %d\t TU = %d\t SD = %d\n", utilization, freq_matrix[current_freq][i], +> temp_utilization, smallest_difference); +> */ +> } +> +> if (closest_freq > 0) { +> #ifdef CONFIG_ARCH_ADIFCC +> closest_freq += 4; +> get_80200_CCLKCFG(cclkcfg); +> if ((unsigned)closest_freq != cclkcfg) { +> cclkcfg = (unsigned) closest_freq; +> set_80200_CCLKCFG (cclkcfg); +> printk (KERN_DEBUG "%ld\t %ld\n", JIFFIES - start_time, clk2mhz (cclkcfg)); +> } +> #endif +> #ifdef CONFIG_ARCH_SA1100 +> if (cpufreq_get(0) != sa1100_freq[closest_freq]) { +> cpufreq_set (sa1100_freq[closest_freq]); +> } +> #endif +> } +> +> return; +> } +> #endif +> +> +> #ifdef CONFIG_DWCS_DFS +> /* calculates max. possible slowdown and calls do_set_slowest_cpuspeed */ +205a550 +> #endif +241a587,640 +> #ifdef DWCS_DEBUG_ON +> static int proc_dwcs_debug_c_read(char *page, char **start, off_t off, int count, int *eof, void *data){ +> int len; +> MOD_INC_USE_COUNT; +> len = sprintf(page, "%d\n", DWCS_DEBUG); +> MOD_DEC_USE_COUNT; +> return len; +> } +> +> static int proc_dwcs_debug_c_write(struct file *file, const char *buffer, unsigned long count, void *data){ +> unsigned char value; +> MOD_INC_USE_COUNT; +> +> if(copy_from_user(&value, buffer, 1)){ +> MOD_DEC_USE_COUNT; +> return -EFAULT; +> } +> if(value == '0'){ +> if(DWCS_DEBUG == 1){ +> kfree(debug_area); +> } +> DWCS_DEBUG = 0; +> printk("Disabling verbose debugging!\n"); +> } +> else if(value == '1'){ +> DWCS_DEBUG = 1; +> deb_pos = 0; +> debug_count = 0; +> debug_area = (char *)kmalloc(50*sizeof(char *)*100, GFP_KERNEL); +> memset(debug_area, '\0', sizeof(debug_area)); +> printk("Enabling verbose debugging!\n"); +> } +> +> MOD_DEC_USE_COUNT; +> +> return 1; +> } +> +> int proc_dwcs_debug_info_read(char *buf, char **start, off_t offset, int len, int *eof, void *data){ +> len = 0; +> len += sprintf(buf+len, "pid deadline current time period own owd cwn cwd flags ready_time service_time time_serviced wlate late on_time violation\n"); +> /* len += sprintf(buf+len, "%s\n", debug_area); */ +> len += strlen(strncat(buf+len, debug_area, 500*100*sizeof(char *))); +> return len; +> } +> +> int proc_time_read(char *buf, char **start, off_t offset, int len, int *eof, void *data){ +> len = 0; +> len += sprintf(buf+len, "pid %ld\ntimer time %lu\ncounter %lu\nsched %lu\n", dwcs_pid, dwcs_timer_max_time, dwcs_max_counter, dwcs_sched_max_time); +> dwcs_sched_max_time = 0; +> return len; +> } +> #endif +> +279a679,695 +> #ifdef CONFIG_DWCS_DFS +> static int proc_dwcs_dfs_read (char *page, char **start, off_t off, +> int count, int *eof, void *data) +> { +> int len; +> volatile unsigned int cclkcfg; +> +> MOD_INC_USE_COUNT; +> get_80200_CCLKCFG(cclkcfg); +> len = sprintf (page, "\tFrequency = %d\n\tMisses = %ld\n\tViolations = %ld\n\tIdles = %ld\n", +> cclkcfg, dwcs_hyper_period_misses, dwcs_hyper_period_violations, dwcs_hyper_period_idles); +> MOD_DEC_USE_COUNT; +> return len; +> } +> #endif +> +> +340a757,903 +> +> +> +> static void runqueue_insert (struct dwcs_sched_param sp, int first_dwcs_process) +> { +> #ifdef CONFIG_DWCS_DFS +> volatile unsigned int cclkcfg; +> #endif +> struct task_struct *p; +> +> +> if (sp.pid < 0) +> goto runqueue_out_nounlock; +> +> /* +> * We play safe to avoid deadlocks. +> */ +> read_lock_irq(&tasklist_lock); +> spin_lock(&runqueue_lock); +> +> p = find_task_by_pid(sp.pid); +> +> #ifdef CONFIG_QFABRIC +> if ((DWCS_module_loaded) && (DWCS_admission_control)) { +> printk (KERN_DEBUG "Requesting admission!\n"); +> /* --FS-- is this shortcut leagl? */ +> if (DWCS_request_admission(p, &sp) < 0) +> goto runqueue_out_unlock; +> } +> #endif +> +> if (!p) +> goto runqueue_out_unlock; +> if (sp.policy < 0) +> sp.policy = p->policy; +> else { +> if (sp.policy != SCHED_FIFO && sp.policy != SCHED_RR && +> sp.policy != SCHED_OTHER && sp.policy != SCHED_DWCS) +> goto runqueue_out_unlock; +> } +> +> /* Begin of DWCS specific handling */ +> if (sp.policy == SCHED_DWCS) { +> /* --CP-- +> * Set flag for computation of utilization. +> */ +> DWCS_update_utilization = 1; +> +> /* Check ranges of scheduling parameters. */ +> /* The following should never be true, since `own' and `owd' +> * are `unsigned'. */ +> if ((sp.own < 0) || (sp.owd < 0)) +> goto runqueue_out_unlock; +> +> /* Restrict who can set scheduling parameters. */ +> if (!capable(CAP_SYS_NICE)) +> goto runqueue_out_unlock; +> +> /* +> * --RW-- +> * Should really set p->policy = SCHED_DWCS, so that +> * sched_setparam() works with DWCS. But, if we no +> * longer use DWCS, we need to set p->policy to SCHED_OTHER. +> */ +> p->dwcs_params->period = sp.period; +> p->dwcs_params->own = sp.own; +> p->dwcs_params->owd = sp.owd; +> if (sp.period == (unsigned long)-1) { +> p->dwcs_params->deadline = (unsigned long)-1; +> p->dwcs_params->flags |= DWCS_WORK_CONS; +> p->dwcs_params->ready_time = 0; +> } +> else { +> if (first_dwcs_process) { +> p->dwcs_params->deadline = jiffies + sp.period; +> p->dwcs_params->ready_time = jiffies; +> } +> else { +> #ifdef CONFIG_DWCS_DFS +> unsigned long new_ready_time; +> +> new_ready_time = dwcs_hyper_period_task->dwcs_params->deadline; +> while ((new_ready_time - sp.period) > JIFFIES) +> new_ready_time -= sp.period; +> p->dwcs_params->ready_time = new_ready_time; +> p->dwcs_params->deadline = new_ready_time + sp.period; +> hyper_period_recalc_needed = 1; +> #else +> p->dwcs_params->ready_time = jiffies; +> p->dwcs_params->deadline = p->dwcs_params->ready_time +> + sp.period; +> #endif +> } +> if (sp.flags & DWCS_WORK_CONS) +> p->dwcs_params->flags |= DWCS_WORK_CONS; +> else +> p->dwcs_params->flags &= ~DWCS_WORK_CONS; +> } +> +> if (sp.flags & DWCS_NON_PREEMPTIVE) +> p->dwcs_params->flags |= DWCS_NON_PREEMPTIVE; +> else if (sp.flags == 0) +> p->dwcs_params->flags &= ~(DWCS_WORK_CONS | DWCS_NON_PREEMPTIVE); +> +> p->dwcs_params->service_time = sp.service_time; +> p->dwcs_params->cwn = sp.own; +> p->dwcs_params->cwd = sp.owd; +> +> if (task_on_runqueue(p)) +> move_first_runqueue(p); +> current->need_resched = 1; +> +> +> goto runqueue_out_unlock; +> } +> /* End of DWCS specific handling */ +> +> /* +> * Valid priorities for SCHED_FIFO and SCHED_RR are 1..99, valid +> * priority for SCHED_OTHER is 0. +> */ +> if (sp.sched_priority < 0 || sp.sched_priority > 99) +> goto runqueue_out_unlock; +> if ((sp.policy == SCHED_OTHER) != (sp.sched_priority == 0)) +> goto runqueue_out_unlock; +> +> if ((sp.policy == SCHED_FIFO || sp.policy == SCHED_RR) && !capable(CAP_SYS_NICE)) +> goto runqueue_out_unlock; +> if ((current->euid != p->euid) && (current->euid != p->uid) && !capable(CAP_SYS_NICE)) +> goto runqueue_out_unlock; +> +> p->policy = sp.policy; +> p->rt_priority = sp.sched_priority; +> if (task_on_runqueue(p)) +> move_first_runqueue(p); +> +> current->need_resched = 1; +> runqueue_out_unlock: +> spin_unlock(&runqueue_lock); +> read_unlock_irq(&tasklist_lock); +> +> runqueue_out_nounlock: +> return; +> } +> +> +> +349d911 +< printk(KERN_DEBUG "IOCTL called\n"); +377d938 +< +388,389c949,950 +< case 1: /* set the schedule paramteres for given pid */ +< retval = -EFAULT; +--- +> /* Here is where the new DWCS tasks come to be added to the runqueue */ +> case 1: +391,411c952,959 +< goto out_nounlock; +< +< retval = -EINVAL; +< if (sp.pid < 0) +< goto out_nounlock; +< +< /* +< * We play safe to avoid deadlocks. +< */ +< read_lock_irq(&tasklist_lock); +< spin_lock(&runqueue_lock); +< +< p = find_task_by_pid(sp.pid); +< +< #ifdef CONFIG_QFABRIC +< if ((DWCS_module_loaded) && (DWCS_admission_control)) { +< retval = -EADMISSION; +< /* --FS-- is this shortcut leagl? */ +< if (DWCS_request_admission(p, &sp) < 0) +< goto out_unlock; +< } +--- +> return -EINVAL; +> +> +> /* If this is the first DWCS task, add it to the runqueue immediately */ +> if (first_dwcs_task) { +> runqueue_insert (sp, 1); +> #ifdef CONFIG_DWCS_DFS +> find_hyper_period_task(); +413,424c961,962 +< +< retval = -ESRCH; +< if (!p) +< goto out_unlock; +< +< if (sp.policy < 0) +< sp.policy = p->policy; +< else { +< retval = -EINVAL; +< if (sp.policy != SCHED_FIFO && sp.policy != SCHED_RR && +< sp.policy != SCHED_OTHER && sp.policy != SCHED_DWCS) +< goto out_unlock; +--- +> first_dwcs_task = 0; +> return 0; +426,486c964,968 +< +< /* Begin of DWCS specific handling */ +< if (sp.policy == SCHED_DWCS) { +< +< /* --CP-- +< * Set flag for computation of utilization. +< */ +< DWCS_update_utilization = 1; +< +< /* Check ranges of scheduling parameters. */ +< retval = -EINVAL; +< +< /* The following should never be true, since `own' and `owd' +< * are `unsigned'. */ +< if ((sp.own < 0) || (sp.owd < 0)) +< goto out_unlock; +< +< /* Restrict who can set scheduling parameters. */ +< retval = -EPERM; +< if (!capable(CAP_SYS_NICE)) +< goto out_unlock; +< +< retval = 0; +< /* +< * --RW-- +< * Should really set p->policy = SCHED_DWCS, so that +< * sched_setparam() works with DWCS. But, if we no +< * longer use DWCS, we need to set p->policy to SCHED_OTHER. +< */ +< p->dwcs_params->period = sp.period; +< p->dwcs_params->own = sp.own; +< p->dwcs_params->owd = sp.owd; +< if (sp.period == (unsigned long)-1) { +< p->dwcs_params->deadline = (unsigned long)-1; +< p->dwcs_params->flags |= DWCS_WORK_CONS; +< p->dwcs_params->ready_time = 0; +< } +< else { +< p->dwcs_params->deadline = jiffies + sp.period; +< p->dwcs_params->ready_time = jiffies; +< if (sp.flags & DWCS_WORK_CONS) +< p->dwcs_params->flags |= DWCS_WORK_CONS; +< else +< p->dwcs_params->flags &= ~DWCS_WORK_CONS; +< } +< +< if (sp.flags & DWCS_NON_PREEMPTIVE) +< p->dwcs_params->flags |= DWCS_NON_PREEMPTIVE; +< else if (sp.flags == 0) /* Reset. */ +< p->dwcs_params->flags &= ~(DWCS_WORK_CONS | +< DWCS_NON_PREEMPTIVE); +< +< p->dwcs_params->service_time = sp.service_time; +< p->dwcs_params->cwn = sp.own; +< p->dwcs_params->cwd = sp.owd; +< +< if (task_on_runqueue(p)) +< move_first_runqueue(p); +< current->need_resched = 1; +< +< goto out_unlock; +--- +> /* If it is not the first DWCS task, delay its entry */ +> else { +> runqueue_insert (sp, 0); +> +> return 0; +488,521c970 +< /* End of DWCS specific handling */ +< +< /* +< * Valid priorities for SCHED_FIFO and SCHED_RR are 1..99, valid +< * priority for SCHED_OTHER is 0. +< */ +< retval = -EINVAL; +< if (sp.sched_priority < 0 || sp.sched_priority > 99) +< goto out_unlock; +< if ((sp.policy == SCHED_OTHER) != (sp.sched_priority == 0)) +< goto out_unlock; +< +< retval = -EPERM; +< if ((sp.policy == SCHED_FIFO || sp.policy == SCHED_RR) && +< !capable(CAP_SYS_NICE)) +< goto out_unlock; +< if ((current->euid != p->euid) && (current->euid != p->uid) && +< !capable(CAP_SYS_NICE)) +< goto out_unlock; +< +< retval = 0; +< p->policy = sp.policy; +< p->rt_priority = sp.sched_priority; +< if (task_on_runqueue(p)) +< move_first_runqueue(p); +< +< current->need_resched = 1; +< +< out_unlock: +< spin_unlock(&runqueue_lock); +< read_unlock_irq(&tasklist_lock); +< +< out_nounlock: +< return retval; +--- +> +547a997 +> DWCS_admission_control = 1; +570a1021,1049 +> #ifdef DWCS_DEBUG_ON +> proc_dwcs_debug_control = create_proc_entry("debugging_control", 0644, +> proc_dwcs_dir); +> proc_dwcs_debug_control->owner = THIS_MODULE; +> proc_dwcs_debug_control->write_proc = proc_dwcs_debug_c_write; +> proc_dwcs_debug_control->read_proc = proc_dwcs_debug_c_read; +> +> proc_dwcs_debug_write = create_proc_read_entry("debug_info", 0444, +> proc_dwcs_dir, proc_dwcs_debug_info_read, NULL); +> proc_dwcs_debug_write->owner = THIS_MODULE; +> proc_time = create_proc_read_entry("time", 0444, proc_dwcs_dir, proc_time_read, +> NULL); +> proc_time->owner = THIS_MODULE; +> #endif +> +> #ifdef CONFIG_DWCS_DFS +> proc_dwcs_dfs = create_proc_entry("dfs", 0444, proc_dwcs_dir); +> proc_dwcs_dfs->owner = THIS_MODULE; +> proc_dwcs_dfs->read_proc = proc_dwcs_dfs_read; +> +> #ifdef CONFIG_ARCH_SA1100 +> current_sa1100_freq = 0; +> do { +> if (cpufreq_get(0) == sa1100_freq[current_sa1100_freq]) break; +> current_sa1100_freq++; +> } while (current_sa1100_freq < 16); +> #endif +> #endif +> +588a1068,1077 +> utilization = 0; +> +> #ifdef DWCS_DEBUG_ON +> if (DWCS_DEBUG) { +> kfree(debug_area); +> } +> remove_proc_entry("time", proc_dwcs_dir); +> remove_proc_entry("debug_info", proc_dwcs_dir); +> remove_proc_entry("debugging_control", proc_dwcs_dir); +> #endif +593a1083,1085 +> #ifdef CONFIG_DWCS_DFS +> remove_proc_entry("dfs", proc_dwcs_dir); +> #endif +681,683c1173,1178 +< /* printk (KERN_DEBUG "(%d) Deadline missed!\n", +< p->dwcs_params->cd); */ +< +--- +> /* +> printk (KERN_DEBUG "(%d) Deadline missed! %d\n", p->dwcs_params->cd, JIFFIES - p->dwcs_params->deadline); +> */ +> #ifdef CONFIG_DWCS_DFS +> dwcs_hyper_period_misses++; +> #endif +693,694c1188,1193 +< /*printk (KERN_DEBUG "(%d) VIOLATION!\n", +< p->dwcs_params->cd);*/ +--- +> #ifdef CONFIG_DWCS_DFS +> dwcs_hyper_period_violations++; +> #endif +> /* +> printk (KERN_DEBUG "(%d) VIOLATION!\n", p->dwcs_params->cd); +> */ +699a1199 +> p->dwcs_params->ready_time += p->dwcs_params->period; +775c1275 +< if (p->dwcs_params->deadline != (unsigned long)-1) +--- +> if (p->dwcs_params->deadline != (unsigned long)-1) { +776a1277,1288 +> #ifdef CONFIG_DWCS_DFS +> /* +> if (p == dwcs_hyper_period_task) { +> dwcs_hyper_period_task_count++; +> if (dwcs_hyper_period_task_count == dwcs_hyper_period_task_iterations) { +> dwcs_dfs_measurements (p); +> dwcs_hyper_period_task_count = 0; +> } +> } +> */ +> #endif +> } +784,787c1296 +< if (((p->dwcs_params->on_time + +< p->dwcs_params->late) % +< p->dwcs_params->owd) == 0) { +< +--- +> if (((p->dwcs_params->on_time + p->dwcs_params->late) % p->dwcs_params->owd) == 0) { +789a1299,1301 +> #ifdef CONFIG_DWCS_DFS +> dwcs_hyper_period_violations++; +> #endif +794a1307,1311 +> } +> #ifdef DWCS_DEBUG_ON +> if (DWCS_DEBUG && (p->dwcs_params->deadline != -1) && (debug_count < 50)) { +> char tmp[100]; +> sprintf(tmp, "%d %ld %ld %ld %d %d %d %d %d %ld %ld %ld %d %ld %ld %ld\n", p->pid, p->dwcs_params->deadline, JIFFIES, p->dwcs_params->period, p->dwcs_params->own, p->dwcs_params->owd, p->dwcs_params->cwn, p->dwcs_params->cwd, p->dwcs_params->flags, p->dwcs_params->ready_time, p->dwcs_params->service_time, p->dwcs_params->time_serviced, p->dwcs_params->wlate, p->dwcs_params->late, p->dwcs_params->on_time, p->dwcs_params->violations); +795a1313 +> strcat(debug_area, tmp); +796a1315 +> #endif +828c1347 +< if ((p->dwcs_params->deadline == next->dwcs_params->deadline) && +--- +> /* if ((p->dwcs_params->deadline == next->dwcs_params->deadline) && +831a1351,1353 +> */ +> if ((p->dwcs_params->deadline == next->dwcs_params->deadline) && +> (p->dwcs_params->deadline == (unsigned long) -1)) { +894c1416 +< ((utilization - old_utilization + new_utilization) > MAX_UTILIZATION)) +--- +> ((utilization - old_utilization + new_utilization) > (MAX_UTILIZATION - reserved_utilization))) +897d1418 +< +915a1437,1440 +> printk (KERN_DEBUG "Utilization now %d\n", utilization); +> #ifdef CONFIG_DWCS_DFS +> dwcs_dfs_theoretical(); +> #endif +917a1443,1449 +> #ifdef CONFIG_DWCS_DFS +> /* +> if (tptr == dwcs_hyper_period_task) { +> find_hyper_period_task(); +> } +> */ +> #endif +921a1454,1456 +> #ifdef CONFIG_DWCS_DFS +> dwcs_dfs_theoretical(); +> #endif +939a1475 +> +1032a1569 +> +1096c1633 +< if (can_schedule(p, this_cpu)) +--- +> if (can_schedule(p, this_cpu)) { +1097a1635,1642 +> } +> #ifdef DWCS_DEBUG_ON +> else { +> char tmp[100]; +> sprintf(tmp, "no csc\n%d %ld %ld %ld %d %d %d %d %d %ld %ld %ld %d %ld %ld %ld\n", p->pid, p->dwcs_params->deadline, JIFFIES, p->dwcs_params->period, p->dwcs_params->own, p->dwcs_params->owd, p->dwcs_params->cwn, p->dwcs_params->cwd, p->dwcs_params->flags, p->dwcs_params->ready_time, p->dwcs_params->service_time, p->dwcs_params->time_serviced, p->dwcs_params->wlate, p->dwcs_params->late, p->dwcs_params->on_time, p->dwcs_params->violations); +> strcat(debug_area, tmp); +> } +> #endif +1113a1659,1666 +> #ifdef DWCS_DEBUG_ON +> if (DWCS_DEBUG && (debug_count < 50)) { +> char tmp[5]; +> debug_count++; +> sprintf(tmp, "%d\n", p->pid); +> strcat(debug_area, tmp); +> } +> #endif +1140a1694,1698 +> #ifdef CONFIG_DWCS_DFS +> if (next == idle_task(this_cpu)) { +> dwcs_hyper_period_idles++; +> } +> #endif +1147a1706 +> /* +1161d1719 +< /* set to default processor speed */ +1164c1722 +< +--- +> */ +1172d1729 +< diff -Naur test-for-latech/kernel/dwcs.c testqf-for-latech/kernel/dwcs.c --- test-for-latech/kernel/dwcs.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/kernel/dwcs.c 2004-06-11 07:47:23.000000000 -0400 @@ -0,0 +1,1933 @@ +/* + * linux/dwcs/dwcs.c + * + * Copyright (C) 1999 Rich West + * + * 1999-10-26 Modified by Ivan Ganev (along with a + * bunch of other files) to make DWCS SMP-safe. + */ + +/* + * DWCS kernel-loadable module. + */ + +/* Required definitions. */ +#ifndef MODULE +#define MODULE +#endif +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +/* Various required header files. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_DWCS_DFS +#include +#include +#endif + +//#define DWCS_DEBUG_ON 1 + +#if HZ < 200 +#define TICK_SCALE(x) ((x) >> 2) +#elif HZ < 400 +#define TICK_SCALE(x) ((x) >> 1) +#elif HZ < 800 +#define TICK_SCALE(x) (x) +#elif HZ < 1600 +#define TICK_SCALE(x) ((x) << 1) +#else +#define TICK_SCALE(x) ((x) << 2) +#endif + +#define NICE_TO_TICKS(nice) (TICK_SCALE(20-(nice))+1) + +/* + * GANEV: nasty bug here... definitions for idle_task and can_schedule + * depend ALOT on whether we're an SMP kernel or not... + */ +#ifdef CONFIG_SMP +#define idle_task(cpu) (init_tasks[cpu_number_map(cpu)]) +#define can_schedule(p,cpu) ((p)->cpus_runnable & \ + (p)->cpus_allowed & (1 << cpu)) +#else +#define idle_task(cpu) (&init_task) +#define can_schedule(p,cpu) (1) +#endif + +#define LIMIT (PAGE_SIZE-80) /* Set limit on amount of data in /proc/dwcs. */ + +MODULE_AUTHOR("Georgia Tech -- CoC"); +MODULE_DESCRIPTION("DWCS Scheduler"); +MODULE_LICENSE("GPL"); + +/* Prototypes. */ +int init_module(void); +void cleanup_module(void); +void my_printk(char *string); +void (*_dummy_update_utilization)(void); +void (*_dummy_request_admission)(void); + +extern void (*DWCS_scheduler)(struct task_struct **, struct task_struct **); +void DWCS_schedule(struct task_struct **, struct task_struct **); +void do_update_utilization(int flag, struct task_struct *tptr); +int DWCS_request_admission(struct task_struct *tptr,struct dwcs_sched_param *param); + +extern void *sys_call_table[]; +extern int DWCS_module_loaded; +extern struct list_head runqueue_head; +extern int DWCS_update_utilization; +extern int utilization; +extern int nr_running; +extern unsigned long volatile jiffies_sim; +//#ifdef CONFIG_QFABRIC +extern int DWCS_admission_control; +extern int call_admission_control(struct task_struct *, struct sched_param *); +//#endif + +/* Power saving related definitions */ +#define DWCS_EM_NORMAL 0x00000000 /* No DFS,DVS done by dwcs */ +#define DWCS_EM_AVERAGE_CONSERVATIVE 0x00000001 /* Averaging proc. speed without missed deadlines */ +#define DWCS_EM_AVERAGE_AGGRESSIVE 0x00000002 /* Averaging proc. speed with max missed deadlines */ +#define DWCS_EM_ADAPTIVE_CONSERVATIVE 0x00000003 /* Individual proc. speed without missed deadlines */ +#define DWCS_EM_ADAPTIVE_AGGRESSIVE 0x00000004 /* Individual proc. speed with max missed deadlines */ +int energy_mode; /* Initially non power saving mode */ +int reserved_utilization = MAX_UTILIZATION / 10; /* How much of MAX_UTILIZATION should be reserved for non DWCS proc. */ +int av_cons_utilization(void); /* Calculates the utilization if no deadline is missed */ +int av_aggr_utilization(void); /* Calculates the utilization with max possible missed deadlines */ +int ad_cons_utilization(void); +int ad_aggr_utilization(void); + +#ifdef CONFIG_DWCS_DFS +#define DWCS_MODE_VMI 0 +#define DWCS_MODE_THEORETICAL 1 +#endif +#define MAX_PER (unsigned long)999999 +unsigned int start_time; +struct task_struct *dwcs_hyper_period_task = NULL; +unsigned long int dwcs_hyper_period_old_violations = 0; +unsigned long int dwcs_hyper_period_old_misses = 0; +unsigned long int dwcs_hyper_period_old_idles = 0; +unsigned long int dwcs_hyper_period_violations = 0; +unsigned long int dwcs_hyper_period_misses = 0; +unsigned long int dwcs_hyper_period_idles = 0; +int dwcs_hyper_period_task_iterations = 0; +int dwcs_hyper_period_task_count = 0; +static int hyper_period_recalc_needed = 0; +#ifdef CONFIG_DWCS_DFS +void set_slowest_cpuspeed(struct task_struct *); /* Sets cpu to slowest speed possible */ + +#ifdef CONFIG_ARCH_ADIFCC +#define get_80200_CCLKCFG(out) asm volatile("mrc P14, 0, %0, c6, c0, 0" : \ + "=r"(out)) +#define set_80200_CCLKCFG(val) asm volatile("mcr P14, 0, %0, c6, c0, 0" : \ + : "r"(val)) +#endif + +#ifdef CONFIG_ARCH_SA1100 +int current_sa1100_freq; +unsigned int sa1100_freq[12] = {59000, 73700, 88500, 103200, 118000, 132700, 147500, 162200, 176900, 191700, 206400, 221200}; +#endif +#endif + +/* Variable to determine which mode the scheduler is running in */ +int DWCS_module_mode; + +/* Needed for delayed runqueue insertion */ +static int first_dwcs_task = 1; +#ifdef CONFIG_DWCS_DFS +struct proc_dir_entry *proc_dwcs_dfs; +struct proc_dir_entry *proc_dwcs_mode; +struct proc_dir_entry *proc_freq_entry; +#endif + +struct proc_dir_entry *proc_dwcs_dir; +struct proc_dir_entry *proc_dwcs_enabled; +struct proc_dir_entry *proc_dwcs_info; +struct proc_dir_entry *proc_dwcs_energy_mode; +struct proc_dir_entry *proc_dwcs_control; +#ifdef DWCS_DEBUG_ON +struct proc_dir_entry *proc_dwcs_debug_control; +struct proc_dir_entry *proc_dwcs_debug_write; +struct proc_dir_entry *proc_time; + +extern unsigned long dwcs_timer_max_time; +extern long dwcs_max_counter; +extern long dwcs_pid; +extern unsigned long dwcs_sched_max_time; + +int DWCS_DEBUG; +char *debug_area; +int deb_pos; +int debug_count; +#endif + + +#ifdef SIM_MODE +#define JIFFIES jiffies_sim +#else +#define JIFFIES jiffies +#endif + +#define DWCS_SERVICED_THIS_PERIOD 0x10000000 + + +/* + * Careful! + * + * This has to add the process to the _beginning_ of the + * run-queue, not the end. See the comment about "This is + * subtle" in the scheduler proper.. + */ +static inline void add_to_runqueue(struct task_struct * p) +{ + list_add(&p->run_list, &runqueue_head); + nr_running++; +} + +static inline void move_last_runqueue(struct task_struct * p) +{ + list_del(&p->run_list); + list_add_tail(&p->run_list, &runqueue_head); +} + +static inline void move_first_runqueue(struct task_struct * p) +{ + list_del(&p->run_list); + list_add(&p->run_list, &runqueue_head); +} + +#ifdef CONFIG_DWCS_DFS +/* Resets cpu to default clockrate */ +void set_default_cpuspeed(void) +{ +#ifdef CONFIG_ARCH_ADIFCC + set_80200_CCLKCFG(9); +#endif +#ifdef CONFIG_ARCH_SA1100 + cpufreq_set (sa1100_freq[10]); +#endif +} +#endif + +#ifdef CONFIG_DWCS_DFS +/* Calculates real clockrate and changes cpu register */ +void do_set_slowest_cpuspeed(int speedup) +{ +#ifdef CONFIG_ARCH_ADIFCC + int clockrate = 733; + clockrate = clockrate * 100 / speedup; + if (clockrate < 400) + set_80200_CCLKCFG(4); + else if (clockrate < 466) + set_80200_CCLKCFG(5); + else if (clockrate < 533) + set_80200_CCLKCFG(6); + else if (clockrate < 600) + set_80200_CCLKCFG(7); + else if (clockrate < 666) + set_80200_CCLKCFG(8); + else + set_80200_CCLKCFG(9); +#endif +#ifdef CONFIG_ARCH_SA1100 + int clockrate = 206; + clockrate = clockrate * 100 / speedup; + if (clockrate < 59) + cpufreq_set (sa1100_freq[0]); + else if (clockrate < 73) + cpufreq_set (sa1100_freq[1]); + else if (clockrate < 88) + cpufreq_set (sa1100_freq[2]); + else if (clockrate < 103) + cpufreq_set (sa1100_freq[3]); + else if (clockrate < 118) + cpufreq_set (sa1100_freq[4]); + else if (clockrate < 132) + cpufreq_set (sa1100_freq[5]); + else if (clockrate < 147) + cpufreq_set (sa1100_freq[6]); + else if (clockrate < 162) + cpufreq_set (sa1100_freq[7]); + else if (clockrate < 176) + cpufreq_set (sa1100_freq[8]); + else if (clockrate < 191) + cpufreq_set (sa1100_freq[9]); + else if (clockrate < 207) + cpufreq_set (sa1100_freq[10]); + else + cpufreq_set (sa1100_freq[11]); +#endif +} +#endif + +#ifdef CONFIG_DWCS_DFS +static int clk2mhz (int n) +{ + switch(n) { + case 4 : return 400; + case 5 : return 466; + case 6 : return 533; + case 7 : return 600; + case 8 : return 666; + case 9 : return 733; + default: return -1; + } + + return 400; +} +#endif + +static unsigned long euclid (unsigned long m, unsigned long n) +{ + unsigned long r; + + r = m % n; + if (!r) { + return n; + } + return euclid (n, r); +} + +static unsigned long least_common_period (unsigned long x, unsigned long y) +{ + return ((x * y) / euclid (x, y)); +} + +static int find_smallest (unsigned long *period, int size) +{ + int i; + int index = -1; + unsigned long smallest = MAX_PER; + + for (i = 0; i < size; i++) { + if (period[i] < smallest) { + index = i; + smallest = period[i]; + } + } + + return index; +} + +static void find_hyper_period_task (int flag) +{ + int i; + int lcp; + unsigned long largest_period; + unsigned long *period; + int dwcs_task_count; + int smallest_index; + struct task_struct *temp; + + dwcs_hyper_period_task = NULL; + dwcs_task_count = 0; + largest_period = 0; + for_each_task (temp) { + if ((flag == 1) && (current == temp)) { + } else { + if ((temp->dwcs_params->deadline != (unsigned long)-1) && + ((int)temp->dwcs_params->period > 0)) { + dwcs_task_count++; + if ((int)temp->dwcs_params->period > largest_period) { + dwcs_hyper_period_task = temp; + largest_period = temp->dwcs_params->period; + } + } + } + } + + if (dwcs_task_count == 0) { + printk (KERN_DEBUG "No Hyper Period Task\n"); + first_dwcs_task = 1; + hyper_period_recalc_needed = 0; + return; + } + + if (dwcs_task_count == 1) + start_time = jiffies; + + period = kmalloc (dwcs_task_count * sizeof (unsigned long), GFP_KERNEL); + for (i = 0; i < dwcs_task_count; i++) + period[i] = MAX_PER; + i = 0; + for_each_task (temp) { + if ((temp->dwcs_params->deadline != (unsigned int)-1) && + ((int)temp->dwcs_params->period > 0)) { + period[i] = temp->dwcs_params->period; + i++; + } + } + + lcp = 1; + for (i = 0; i < dwcs_task_count; i++) { + smallest_index = find_smallest (period, dwcs_task_count); + lcp = least_common_period (lcp, period[smallest_index]); + period[smallest_index] = MAX_PER; + } + + dwcs_hyper_period_task_iterations = lcp / largest_period; + dwcs_hyper_period_task_count = 0; + + printk (KERN_DEBUG "Hyper Task PID = %d\tLeast Common Period = %d\n", dwcs_hyper_period_task->pid, lcp); + + kfree (period); + + hyper_period_recalc_needed = 0; +} + + +#ifdef CONFIG_DWCS_DFS +void dwcs_dfs_measurements (struct task_struct *p) +{ + int misses; + int violations; + int idles; + static int freq_change; + volatile unsigned int cclkcfg; + siginfo_t si; + + misses = dwcs_hyper_period_misses - dwcs_hyper_period_old_misses; + violations = dwcs_hyper_period_violations - dwcs_hyper_period_old_violations; + idles = dwcs_hyper_period_idles - dwcs_hyper_period_old_idles; + + freq_change = 0; + +#ifdef CONFIG_ARCH_ADIFCC + if (violations > 0) { + get_80200_CCLKCFG(cclkcfg); + if (cclkcfg < 9) { + cclkcfg++; + if (cclkcfg > 9) + cclkcfg = 9; + set_80200_CCLKCFG(cclkcfg); + freq_change = 1; + } + } else if ((misses > 0) && (violations == 0)) { + } else if ((violations == 0) && (misses == 0)) { + get_80200_CCLKCFG(cclkcfg); + if (cclkcfg > 4) { + cclkcfg--; + set_80200_CCLKCFG(cclkcfg); + freq_change = 1; + } + } +#endif +#ifdef CONFIG_ARCH_SA1100 + if ((violations > 0) || (idles < 1)) { + if (current_sa1100_freq < 11) { + current_sa1100_freq++; + si.si_signo = SIGUSR1; + si.si_errno = 0; + si.si_code = SI_KERNEL; + send_sig_info(SIGUSR1, &si, p); + //cpufreq_set (sa1100_freq[current_sa1100_freq]); + freq_change = 1; + } + } else if ((misses == 0) && (violations == 0) && (idles > 0)) { + if (current_sa1100_freq > 0) { + current_sa1100_freq++; + si.si_signo = SIGUSR1; + si.si_errno = 0; + si.si_code = SI_KERNEL; + send_sig_info(SIGUSR2, &si, p); + current_sa1100_freq--; + //cpufreq_set (sa1100_freq[current_sa1100_freq]); + freq_change = 1; + } + } +#endif + + if (freq_change) { + printk (KERN_DEBUG "%lu\t %d\t %d\t %d\t %d\t %d\n", + jiffies - start_time, clk2mhz(cclkcfg), violations, + misses, idles, utilization); + } + + dwcs_hyper_period_old_violations = dwcs_hyper_period_violations; + dwcs_hyper_period_old_idles = dwcs_hyper_period_idles; + dwcs_hyper_period_old_misses = dwcs_hyper_period_misses; + +} +#endif + + +#ifdef CONFIG_DWCS_DFS +void dwcs_dfs_theoretical (void) +{ +#ifdef CONFIG_ARCH_ADIFCC + unsigned int freq_matrix[6][6] = {{1000, 857, 749, 666, 599, 545}, + {1166, 1000, 874, 777, 699, 636}, + {1333, 1142, 1000, 888, 799, 727}, + {1500, 1285, 1125, 1000, 899, 818}, + {1666, 1428, 1250, 1111, 1000, 909}, + {1832, 1570, 1373, 1221, 1099, 1000}}; + volatile unsigned int cclkcfg; +#endif +#ifdef CONFIG_ARCH_SA1100 + unsigned int freq_matrix[12][12] = { + {1000, 792, 649, 552, 480, 425, 381, 343, 314, 289, 268, 268}, + {1262, 1000, 820, 697, 606, 536, 481, 433, 396, 365, 339, 339}, + {1538, 1219, 1000, 850, 739, 654, 587, 528, 483, 445, 413, 413}, + {1809, 1433, 1175, 1000, 869, 769, 690, 621, 568, 524, 486, 486}, + {2080, 1648, 1351, 1149, 1000, 884, 793, 714, 653, 602, 559, 559}, + {2352, 1863, 1528, 1299, 1130, 1000, 897, 807, 739, 681, 632, 632}, + {2621, 2077, 1703, 1448, 1260, 1114, 1000, 899, 823, 759, 704, 704}, + {2913, 2308, 1893, 1609, 1400, 1238, 1111, 1000, 915, 844, 783, 783}, + {3182, 2521, 2067, 1758, 1529, 1353, 1213, 1092, 1000, 922, 855, 855}, + {3451, 2734, 2242, 1907, 1659, 1467, 1316, 1184, 1084, 1000, 928, 928}, + {3719, 2947, 2416, 2055, 1787, 1581, 1418, 1276, 1168, 1077, 1000, 1000}, + {3719, 2947, 2416, 2055, 1787, 1581, 1418, 1276, 1168, 1077, 999, 1000}}; + +#endif + + + int i; + int closest_freq = -1; + int smallest_difference; + int current_freq; + int k_entries; + + if (hyper_period_recalc_needed) { + find_hyper_period_task(0); + } + + smallest_difference = MAX_UTILIZATION; + +#ifdef CONFIG_ARCH_SA1100 + current_freq = 11; + k_entries = 12; +#endif +#ifdef CONFIG_ARCH_ADIFCC + current_freq = 5; + k_entries = 6; +#endif + + for (i = 0; i < k_entries; i++) { + int temp_utilization; + + temp_utilization = (utilization * freq_matrix[current_freq][i]); + temp_utilization = temp_utilization / 1000; + temp_utilization = (MAX_UTILIZATION - reserved_utilization) - temp_utilization; + if ((temp_utilization >= 0) && (temp_utilization < smallest_difference)) { + smallest_difference = temp_utilization; + closest_freq = i; + } + printk (KERN_DEBUG "U = %d\t M = %d\t TU = %d\t SD = %d\n", utilization, freq_matrix[current_freq][i], + temp_utilization, smallest_difference); + } + + if (closest_freq > 0) { +#ifdef CONFIG_ARCH_ADIFCC + closest_freq += 4; + get_80200_CCLKCFG(cclkcfg); + if ((unsigned)closest_freq != cclkcfg) { + cclkcfg = (unsigned) closest_freq; + set_80200_CCLKCFG (cclkcfg); + printk (KERN_DEBUG "%ld\t %ld\n", JIFFIES - start_time, clk2mhz (cclkcfg)); + } +#endif +#ifdef CONFIG_ARCH_SA1100 + if (cpufreq_get(0) != sa1100_freq[closest_freq]) { + cpufreq_set (sa1100_freq[closest_freq]); + } +#endif + } + + return; +} +#endif + +#ifdef CONFIG_DWCS_DFS +/* calculates max. possible slowdown and calls do_set_slowest_cpuspeed */ +void set_slowest_cpuspeed(struct task_struct *p) +{ + int max_slowdown; + max_slowdown = 100 * (p->dwcs_params->deadline - JIFFIES) / p->dwcs_params->service_time; + if (max_slowdown < p->dwcs_params->cpu_speedup) { + p->dwcs_params->cpu_speedup = max_slowdown; + } + do_set_slowest_cpuspeed(p->dwcs_params->cpu_speedup); +} +#endif + +static int proc_dwcs_enabled_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + MOD_INC_USE_COUNT; + len = sprintf(page, "%d\n", DWCS_module_loaded); + MOD_DEC_USE_COUNT; + return len; +} + +static int proc_dwcs_enabled_write (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char value; + MOD_INC_USE_COUNT; + + if (copy_from_user(&value, buffer, 1)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + + if (value == '0') { + DWCS_module_loaded = 0; + printk (KERN_DEBUG "Disabling DWCS!\n"); + } + else if (value == '1') { + DWCS_module_loaded = 1; + printk (KERN_DEBUG "Enabling DWCS!\n"); + } + + MOD_DEC_USE_COUNT; + + return 1; +} + +#ifdef CONFIG_DWCS_DFS +static int proc_dwcs_mode_read (char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int len; + + MOD_INC_USE_COUNT; + len = sprintf(page, "%d\n", DWCS_module_mode); + MOD_DEC_USE_COUNT; + + return len; +} + +static int proc_dwcs_mode_write (struct file *file, const char *buffer, unsigned long + counter, void *data) +{ + unsigned char value; + + MOD_INC_USE_COUNT; + if (copy_from_user(&value, buffer, 1)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + + if (value == '0') { + DWCS_module_mode = DWCS_MODE_VMI; + printk (KERN_DEBUG "DWCS mode now VMI!\n"); + find_hyper_period_task(0); + } else if (value == '1') { + DWCS_module_mode = DWCS_MODE_THEORETICAL; + printk (KERN_DEBUG "DWCS mode now theoretical!\n"); + dwcs_dfs_theoretical(); + } + + MOD_DEC_USE_COUNT; + + return 1; +} +#endif + +#ifdef DWCS_DEBUG_ON +static int proc_dwcs_debug_c_read(char *page, char **start, off_t off, int count, int *eof, void *data){ + int len; + MOD_INC_USE_COUNT; + len = sprintf(page, "%d\n", DWCS_DEBUG); + MOD_DEC_USE_COUNT; + return len; +} + +static int proc_dwcs_debug_c_write(struct file *file, const char *buffer, unsigned long count, void *data){ + unsigned char value; + MOD_INC_USE_COUNT; + + if(copy_from_user(&value, buffer, 1)){ + MOD_DEC_USE_COUNT; + return -EFAULT; + } + if(value == '0'){ + if(DWCS_DEBUG == 1){ + kfree(debug_area); + } + DWCS_DEBUG = 0; + printk("Disabling verbose debugging!\n"); + } + else if(value == '1'){ + DWCS_DEBUG = 1; + deb_pos = 0; + debug_count = 0; + debug_area = (char *)kmalloc(50*sizeof(char *)*100, GFP_KERNEL); + memset(debug_area, '\0', sizeof(debug_area)); + printk("Enabling verbose debugging!\n"); + } + + MOD_DEC_USE_COUNT; + + return 1; +} + +int proc_dwcs_debug_info_read(char *buf, char **start, off_t offset, int len, int *eof, void *data){ + len = 0; + len += sprintf(buf+len, "pid deadline current time period own owd cwn cwd flags ready_time service_time time_serviced wlate late on_time violation\n"); + /* len += sprintf(buf+len, "%s\n", debug_area); */ + len += strlen(strncat(buf+len, debug_area, 500*100*sizeof(char *))); + memset(debug_area, '\0', sizeof(debug_area)); + debug_count = 0; + return len; +} + +int proc_time_read(char *buf, char **start, off_t offset, int len, int *eof, void *data){ + len = 0; + len += sprintf(buf+len, "pid %ld\ntimer time %lu\ncounter %lu\nsched %lu\n", dwcs_pid, dwcs_timer_max_time, dwcs_max_counter, dwcs_sched_max_time); + dwcs_sched_max_time = 0; + return len; +} +#endif + +int proc_dwcs_info_read (char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + + struct list_head *tmp; + struct task_struct * p; + + len = 0; + + len += sprintf (buf+len, " pid name deadline period own " + "owd cwn cwd viols late on-time " + "flags srv-time(x10mS) state\n"); + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (len > LIMIT) + return len; + + len += sprintf (buf+len, + "%5d %-8.8s %-10ld %-10ld %-5d %-5d %-5d %-5d " + "%-10lu %-10lu %-10lu %-5x %-15lu %-5ld\n", + p->pid, + p->comm, + p->dwcs_params->deadline, + p->dwcs_params->period, + p->dwcs_params->own, + p->dwcs_params->owd, + p->dwcs_params->cwn, + p->dwcs_params->cwd, + p->dwcs_params->violations, + p->dwcs_params->late, + p->dwcs_params->on_time, + p->dwcs_params->flags, + p->dwcs_params->service_time, + p->state); + } + return len; +} + +#ifdef CONFIG_DWCS_DFS +static int proc_dwcs_dfs_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; +#ifdef CONFIG_ARCH_ADIFCC + volatile unsigned int cclkcfg = 0; +#endif + + MOD_INC_USE_COUNT; +#ifdef CONFIG_ARCH_ADIFCC + get_80200_CCLKCFG(cclkcfg); + len = sprintf (page, "\tFreq.level = %d\n\tMisses = %ld\n\tViolations = %ld\n\tIdles = %ld\n\tUtilization = %d\n", + cclkcfg, + dwcs_hyper_period_misses, dwcs_hyper_period_violations, + dwcs_hyper_period_idles, utilization); +#endif +#ifdef CONFIG_ARCH_SA1100 + len = sprintf (page, "\tFreq.level = %d\n\tFrequency=%d\n\tMisses = %ld\n\tViolations = %ld\n\tIdles = %ld\n\tUtilization = %d\n", + current_sa1100_freq, (int)sa1100_freq[current_sa1100_freq], + dwcs_hyper_period_misses, dwcs_hyper_period_violations, + dwcs_hyper_period_idles, utilization); + +#endif + MOD_DEC_USE_COUNT; + return len; +} +#endif + + +static int proc_dwcs_energy_mode_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + MOD_INC_USE_COUNT; + len = sprintf(page, "%d\n", energy_mode); + MOD_DEC_USE_COUNT; + return len; +} + +static int proc_dwcs_energy_mode_write (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned char value; + MOD_INC_USE_COUNT; + + if (copy_from_user(&value, buffer, 1)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + + if ((value >= '0') && (value < '5')) { + energy_mode = value - '0'; + printk (KERN_DEBUG "Changed DWCS energy mode to %d!\n", energy_mode); + } + + MOD_DEC_USE_COUNT; + + return 1; +} + +static int proc_dwcs_control_read(struct file *file, char *buf, size_t nbytes, + loff_t *ppos) +{ + int len, left; + char msg[255]; + + MOD_INC_USE_COUNT; + len = sprintf(msg, "%s", "This node provides an ioctl to read and set the schedule parameters of processes using dwcs\n"); + + if (!access_ok(VERIFY_WRITE, buf, len)) { + MOD_DEC_USE_COUNT; + return -EINVAL; + } + + left = len - *ppos; + if (nbytes > left) nbytes = left; + if (nbytes == 0) { + MOD_DEC_USE_COUNT; + return 0; + } + if (copy_to_user(buf, msg + *ppos, nbytes)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + + MOD_DEC_USE_COUNT; + *ppos += nbytes; + return nbytes; +} + +static void runqueue_insert (struct dwcs_sched_param sp, int first_dwcs_process) +{ + struct task_struct *p; + + + if (sp.pid < 0) + goto runqueue_out_nounlock; + + /* + * We play safe to avoid deadlocks. + */ + read_lock_irq(&tasklist_lock); + spin_lock(&runqueue_lock); + + p = find_task_by_pid(sp.pid); + + if ((DWCS_module_loaded) && (DWCS_admission_control)) { + if (DWCS_request_admission(p, &sp) < 0) + goto runqueue_out_unlock; + } + + if (!p) + goto runqueue_out_unlock; + if (sp.policy < 0) + sp.policy = p->policy; + else { + if (sp.policy != SCHED_FIFO && sp.policy != SCHED_RR && + sp.policy != SCHED_OTHER && sp.policy != SCHED_DWCS) + goto runqueue_out_unlock; + } + + /* Begin of DWCS specific handling */ + if (sp.policy == SCHED_DWCS) { + /* --CP-- + * Set flag for computation of utilization. + */ + DWCS_update_utilization = 1; + + /* Check ranges of scheduling parameters. */ + /* The following should never be true, since `own' and `owd' + * are `unsigned'. */ + if ((sp.own < 0) || (sp.owd < 0)) + goto runqueue_out_unlock; + + /* Restrict who can set scheduling parameters. */ + if (!capable(CAP_SYS_NICE)) + goto runqueue_out_unlock; + + /* + * --RW-- + * Should really set p->policy = SCHED_DWCS, so that + * sched_setparam() works with DWCS. But, if we no + * longer use DWCS, we need to set p->policy to SCHED_OTHER. + */ + + p->dwcs_params->period = sp.period; + p->dwcs_params->own = sp.own; + p->dwcs_params->owd = sp.owd; + if (sp.period == (unsigned long)-1) { + p->dwcs_params->deadline = (unsigned long)-1; + p->dwcs_params->flags |= DWCS_WORK_CONS; + p->dwcs_params->ready_time = 0; + } + else { + if (first_dwcs_process) { + p->dwcs_params->deadline = jiffies + sp.period; + p->dwcs_params->ready_time = jiffies; + } + else { +#ifdef CONFIG_DWCS_DFS + unsigned long new_ready_time; + + new_ready_time = dwcs_hyper_period_task->dwcs_params->deadline; + while ((new_ready_time - sp.period) > JIFFIES) + new_ready_time -= sp.period; + p->dwcs_params->ready_time = new_ready_time; + p->dwcs_params->deadline = new_ready_time + sp.period; + hyper_period_recalc_needed = 1; +#else + p->dwcs_params->ready_time = jiffies; + p->dwcs_params->deadline = p->dwcs_params->ready_time + + sp.period; +#endif + } + if (sp.flags & DWCS_WORK_CONS) + p->dwcs_params->flags |= DWCS_WORK_CONS; + else + p->dwcs_params->flags &= ~DWCS_WORK_CONS; + } + + if (sp.flags & DWCS_NON_PREEMPTIVE) + p->dwcs_params->flags |= DWCS_NON_PREEMPTIVE; + else if (sp.flags == 0) + p->dwcs_params->flags &= ~(DWCS_WORK_CONS | DWCS_NON_PREEMPTIVE); + + p->dwcs_params->service_time = sp.service_time; + p->dwcs_params->cwn = sp.own; + p->dwcs_params->cwd = sp.owd; + + if (task_on_runqueue(p)) + move_first_runqueue(p); + current->need_resched = 1; + + + goto runqueue_out_unlock; + } + /* End of DWCS specific handling */ + + /* + * Valid priorities for SCHED_FIFO and SCHED_RR are 1..99, valid + * priority for SCHED_OTHER is 0. + */ + if (sp.sched_priority < 0 || sp.sched_priority > 99) + goto runqueue_out_unlock; + if ((sp.policy == SCHED_OTHER) != (sp.sched_priority == 0)) + goto runqueue_out_unlock; + + if ((sp.policy == SCHED_FIFO || sp.policy == SCHED_RR) && !capable(CAP_SYS_NICE)) + goto runqueue_out_unlock; + if ((current->euid != p->euid) && (current->euid != p->uid) && !capable(CAP_SYS_NICE)) + goto runqueue_out_unlock; + + p->policy = sp.policy; + p->rt_priority = sp.sched_priority; + if (task_on_runqueue(p)) + move_first_runqueue(p); + + current->need_resched = 1; +runqueue_out_unlock: + spin_unlock(&runqueue_lock); + read_unlock_irq(&tasklist_lock); + +runqueue_out_nounlock: + return; +} + +static int proc_dwcs_control_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct dwcs_sched_param sp; + struct task_struct *p; + int retval = 0; + + + switch (_IOC_NR(cmd)) { + case 0: /* return the schedule parameters for given pid */ + retval = -EFAULT; + if (copy_from_user(&sp, (unsigned long *)arg, + sizeof(struct dwcs_sched_param))) + goto out_nounlock_0; + retval = -EINVAL; + if (sp.pid < 0) + goto out_nounlock_0; + /* + * We play safe to avoid deadlocks. + */ + read_lock_irq(&tasklist_lock); + spin_lock(&runqueue_lock); + p = find_task_by_pid(sp.pid); + + if (!p) + goto out_unlock_0; + + sp.policy = p->policy; + sp.sched_priority = p->rt_priority; + sp.period = p->dwcs_params->period; + sp.own = p->dwcs_params->own; + sp.owd = p->dwcs_params->owd; + sp.flags = p->dwcs_params->flags; + sp.service_time = p->dwcs_params->service_time; + + copy_to_user((unsigned long *)arg, &sp, sizeof(struct dwcs_sched_param)); + + retval = 0; + +out_unlock_0: + spin_unlock(&runqueue_lock); + read_unlock_irq(&tasklist_lock); + +out_nounlock_0: + return retval; + + + case 1: + if(copy_from_user(&sp, (unsigned long *)arg, + sizeof(struct dwcs_sched_param))) + return -EINVAL; + + if (first_dwcs_task) { + runqueue_insert(sp, 1); + find_hyper_period_task(0); + first_dwcs_task = 0; + return 0; + } + else { + read_lock_irq(&tasklist_lock); + p = find_task_by_pid(sp.pid); + if ((p) && (p->dwcs_params->period != (unsigned long)-1)) { + printk (KERN_DEBUG "Task exists! Update parameters!\n"); + p->dwcs_params->period = sp.period; + p->dwcs_params->own = sp.own; + p->dwcs_params->owd = sp.owd; + p->dwcs_params->flags = sp.flags; + p->dwcs_params->service_time = sp.service_time; + spin_unlock(&runqueue_lock); + read_unlock_irq(&tasklist_lock); + + do_update_utilization(0, NULL); + find_hyper_period_task(0); + } else { + read_unlock_irq(&tasklist_lock); + printk(KERN_DEBUG "New task...\n"); + runqueue_insert(sp, 0); + } + + return 0; + } + + default: + return -ENOIOCTLCMD; + } +} + +static struct file_operations proc_dwcs_control_operations = { + read: proc_dwcs_control_read, + ioctl: proc_dwcs_control_ioctl, +}; + +#ifdef CONFIG_DWCS_DFS +static int proc_read_freq(char *page, char **start, off_t off, int count, + int *eof, void *data) { + int len; + int clk_rate = 0; +#ifdef CONFIG_ARCH_ADIFCC + int cclkcfg = 0; +#endif + + MOD_INC_USE_COUNT; +#ifdef CONFIG_ARCH_SA1100 + clk_rate = (int) cpufreq_get (0); +#endif +#ifdef CONFIG_ARCH_ADIFCC + get_80200_CCLKCFG(cclkcfg); + clk_rate = (int) cclkcfg; +#endif + len = sprintf(page, "%d\n", clk_rate); + MOD_DEC_USE_COUNT; + + return len; +} + +static int proc_write_freq(struct file *file, const char *buffer, + unsigned long count, void *data) { + int clk_rate; + unsigned char kbuffer; + + MOD_INC_USE_COUNT; + if (copy_from_user(&kbuffer, buffer, 1)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + +#ifdef CONFIG_ARCH_SA1100 + if (kbuffer == '0') { clk_rate = sa1100_freq[0]; + current_sa1100_freq = 0; } + else if (kbuffer == '1') { clk_rate = sa1100_freq[1]; + current_sa1100_freq = 1; } + else if (kbuffer == '2') { clk_rate = sa1100_freq[2]; + current_sa1100_freq = 2; } + else if (kbuffer == '3') { clk_rate = sa1100_freq[3]; + current_sa1100_freq = 3; } + else if (kbuffer == '4') { clk_rate = sa1100_freq[4]; + current_sa1100_freq = 4; } + else if (kbuffer == '5') { clk_rate = sa1100_freq[5]; + current_sa1100_freq = 5; } + else if (kbuffer == '6') { clk_rate = sa1100_freq[6]; + current_sa1100_freq = 6; } + else if (kbuffer == '7') { clk_rate = sa1100_freq[7]; + current_sa1100_freq = 7; } + else if (kbuffer == '8') { clk_rate = sa1100_freq[8]; + current_sa1100_freq = 8; } + else if (kbuffer == '9') { clk_rate = sa1100_freq[9]; + current_sa1100_freq = 9; } + else if (kbuffer == 'A') { clk_rate = sa1100_freq[10]; + current_sa1100_freq = 10; } + else if (kbuffer == 'B') { clk_rate = sa1100_freq[11]; + current_sa1100_freq = 11; } + else { + MOD_DEC_USE_COUNT; + return 1; + } + printk (KERN_DEBUG "[IPAQ-FREQ] Frequency now %d KHz!\n", clk_rate); + cpufreq_set((unsigned int) clk_rate); +#endif +#ifdef CONFIG_ARCH_ADIFCC + if (kbuffer == '4') { clk_rate = 4; + } else if (kbuffer == '5') { clk_rate = 5; + } else if (kbuffer == '6') { clk_rate = 6; + } else if (kbuffer == '7') { clk_rate = 7; + } else if (kbuffer == '8') { clk_rate = 8; + } else if (kbuffer == '9') { clk_rate = 9; + } else { + printk("Invalid CCLKCF setting!\n"); + MOD_DEC_USE_COUNT; + return 1; + } + if (clk_rate < 4 || clk_rate > 9) { + printk("Invalid cclkcfg setting: %d (Valid = 4,5,6,7,8,9)\n", + clk_rate); + } else { + set_80200_CCLKCFG(cclkcfg); + get_80200_CCLKCFG(cclkcfg); + printk("Clock rate now %d (%d MHz)\n", cclkcfg, ((cclkcfg+2)*200)/3); + } +#endif + MOD_DEC_USE_COUNT; + return 1; +} +#endif + +/* Initialize module. */ +int init_module(void) +{ + /* Store original dummy functions for system calls. */ + _dummy_update_utilization = sys_call_table[__NR_update_utilization- + __NR_SYSCALL_BASE]; + _dummy_request_admission = sys_call_table[__NR_admission_control- + __NR_SYSCALL_BASE]; + + /* Redirect syscall table entries to the syscall fns in this module. */ + DWCS_scheduler = DWCS_schedule; + sys_call_table[__NR_update_utilization-__NR_SYSCALL_BASE] = do_update_utilization; + sys_call_table[__NR_admission_control-__NR_SYSCALL_BASE] = DWCS_request_admission; + DWCS_admission_control = 1; + + proc_dwcs_dir = proc_mkdir("dwcs", NULL); + proc_dwcs_dir->owner = THIS_MODULE; + + proc_dwcs_enabled = create_proc_entry("enabled", 0644, proc_dwcs_dir); + proc_dwcs_enabled->owner = THIS_MODULE; + proc_dwcs_enabled->read_proc = proc_dwcs_enabled_read; + proc_dwcs_enabled->write_proc = proc_dwcs_enabled_write; + + proc_dwcs_info = create_proc_read_entry("info", 0444, proc_dwcs_dir, + proc_dwcs_info_read, NULL); + proc_dwcs_info->owner = THIS_MODULE; + + proc_dwcs_energy_mode = create_proc_entry("energy_mode", 0644, proc_dwcs_dir); + proc_dwcs_energy_mode->owner = THIS_MODULE; + proc_dwcs_energy_mode->read_proc = proc_dwcs_energy_mode_read; + proc_dwcs_energy_mode->write_proc = proc_dwcs_energy_mode_write; + + proc_dwcs_control = create_proc_entry("control", 0444, proc_dwcs_dir); + proc_dwcs_control->owner = THIS_MODULE; + proc_dwcs_control->proc_fops = &proc_dwcs_control_operations; + +#ifdef DWCS_DEBUG_ON + proc_dwcs_debug_control = create_proc_entry("debugging_control", 0644, + proc_dwcs_dir); + proc_dwcs_debug_control->owner = THIS_MODULE; + proc_dwcs_debug_control->write_proc = proc_dwcs_debug_c_write; + proc_dwcs_debug_control->read_proc = proc_dwcs_debug_c_read; + + proc_dwcs_debug_write = create_proc_read_entry("debug_info", 0444, + proc_dwcs_dir, proc_dwcs_debug_info_read, NULL); + proc_dwcs_debug_write->owner = THIS_MODULE; + proc_time = create_proc_read_entry("time", 0444, proc_dwcs_dir, proc_time_read, + NULL); + proc_time->owner = THIS_MODULE; +#endif + +#ifdef CONFIG_DWCS_DFS + DWCS_module_mode = DWCS_MODE_VMI; + //DWCS_module_mode = DWCS_MODE_THEORETICAL; + proc_dwcs_mode = create_proc_entry("mode", 0444, proc_dwcs_dir); + proc_dwcs_mode->owner = THIS_MODULE; + proc_dwcs_mode->read_proc = proc_dwcs_mode_read; + proc_dwcs_mode->write_proc = proc_dwcs_mode_write; + proc_dwcs_dfs = create_proc_entry("dfs", 0444, proc_dwcs_dir); + proc_dwcs_dfs->owner = THIS_MODULE; + proc_dwcs_dfs->read_proc = proc_dwcs_dfs_read; + proc_freq_entry = create_proc_entry("cpu_freq", 0644, proc_dwcs_dir); + proc_freq_entry->owner = THIS_MODULE; + proc_freq_entry->read_proc = proc_read_freq; + proc_freq_entry->write_proc = proc_write_freq; + +#ifdef CONFIG_ARCH_SA1100 + current_sa1100_freq = 0; + do { + if (cpufreq_get(0) == sa1100_freq[current_sa1100_freq]) break; + current_sa1100_freq++; + } while (current_sa1100_freq < 12); +#endif +#endif + DWCS_module_loaded = 1; + + //if (start_khtread(send_data + + return 0; +} + + +/* Remove module. */ +void cleanup_module(void) +{ + if (DWCS_module_loaded) + printk (KERN_DEBUG "Disabling DWCS!\n"); + + DWCS_admission_control = 0; + DWCS_module_loaded = 0; + utilization = 0; + + /* Restore original dummy functions for system calls. */ + DWCS_scheduler = NULL; + sys_call_table[__NR_update_utilization-__NR_SYSCALL_BASE] = + _dummy_update_utilization; + sys_call_table[__NR_admission_control-__NR_SYSCALL_BASE] = + _dummy_request_admission; + +#ifdef DWCS_DEBUG_ON + if (DWCS_DEBUG) { + kfree(debug_area); + } + remove_proc_entry("time", proc_dwcs_dir); + remove_proc_entry("debug_info", proc_dwcs_dir); + remove_proc_entry("debugging_control", proc_dwcs_dir); +#endif + + remove_proc_entry("control", proc_dwcs_dir); + remove_proc_entry("energy_mode", proc_dwcs_dir); + remove_proc_entry("info", proc_dwcs_dir); + remove_proc_entry("enabled", proc_dwcs_dir); +#ifdef CONFIG_DWCS_DFS + remove_proc_entry("dfs", proc_dwcs_dir); + remove_proc_entry("mode", proc_dwcs_dir); + remove_proc_entry("cpu_freq", proc_dwcs_dir); +#endif + remove_proc_entry("dwcs", NULL); +} + + +/* + * This is the function that decides how desirable a process is.. + * You can weigh different processes against each other depending + * on what CPU they've run on lately etc to try to handle cache + * and TLB miss penalties. + * + * Return values: + * -1000: never select this + * 0: out of time, recalculate counters (but it might still be + * selected) + * +ve: "goodness" value (the larger, the better) + * +1000: realtime process, select this. + */ + +static inline int goodness (struct task_struct * p, + int this_cpu, struct mm_struct *this_mm) +{ + int weight; + + /* + * select the current process after every other + * runnable process, but before the idle thread. + * Also, dont trigger a counter recalculation. + */ + weight = -1; + if (p->policy & SCHED_YIELD) + goto out; + + /* + * Non-RT process - normal case first. + */ + if (p->policy == SCHED_OTHER) { + /* + * Give the process a first-approximation goodness value + * according to the number of clock-ticks it has left. + * + * Don't do any other calculations if the time slice is + * over.. + */ + weight = p->counter; + if (!weight) + goto out; + +#ifdef CONFIG_SMP + /* Give a largish advantage to the same processor... */ + /* (this is equivalent to penalizing other processors) */ + if (p->processor == this_cpu) + weight += PROC_CHANGE_PENALTY; +#endif + + /* .. and a slight advantage to the current MM */ + if (p->mm == this_mm || !p->mm) + weight += 1; + weight += 20 - p->nice; + goto out; + } + + /* + * Realtime process, select the first one on the + * runqueue (taking priorities within processes + * into account). + */ + weight = 1000 + p->rt_priority; +#ifdef CONFIG_QFABRIC + if (p->qfabric != NULL) { + if (p->qfabric->weight > 0) { + weight = -1000; + p->qfabric->weight--; + } else + p->qfabric->weight = p->qfabric->orig_weight; + } +#endif +out: + return weight; +} + +static void update_service_constraints (struct task_struct * p, + int check_deadlines) +{ + + if (check_deadlines) { + while (JIFFIES > p->dwcs_params->deadline) { + /* printk (KERN_DEBUG "(%d) Deadline missed!\n", + p->dwcs_params->cd); */ + +#ifdef CONFIG_DWCS_DFS + dwcs_hyper_period_misses++; +#endif + /* Statistics. */ + p->dwcs_params->late++; + p->dwcs_params->wlate++; + if (((p->dwcs_params->on_time + + p->dwcs_params->late) % + p->dwcs_params->owd) == 0) { + + if (p->dwcs_params->wlate > p->dwcs_params->own) { + p->dwcs_params->violations++; +#ifdef CONFIG_DWCS_DFS + dwcs_hyper_period_violations++; +#endif + /*printk (KERN_DEBUG "(%d) VIOLATION!\n", + p->dwcs_params->cd);*/ + } + p->dwcs_params->wlate = 0; + } + + p->dwcs_params->deadline += p->dwcs_params->period; + p->dwcs_params->ready_time += p->dwcs_params->period; + + if (p->dwcs_params->cwn > 0) { + p->dwcs_params->cwn--; + p->dwcs_params->cwd--; + if ((p->dwcs_params->cwd == 0) && (p->dwcs_params->cwn == 0)) { + p->dwcs_params->cwn = p->dwcs_params->own; + p->dwcs_params->cwd = p->dwcs_params->owd; + } + } + else { /* p->dwcs_params->cwn == 0. */ + if (p->dwcs_params->owd > 0) { + /* + * NOTE: This is not pure EDF if we got here, + * since if it were, x/y = 0/0 and, therefore, + * p->dwcs_params->owd = 0. + * + * Now, we have a window-constraint violation. + * These next instructions will eventually + * avoid starvation of p. + */ + /* CP: changed s.t. windowsize is always the same */ + //p->dwcs_params->cwd++; + p->dwcs_params->cwd--; + if ((p->dwcs_params->cwd == 0) && + (p->dwcs_params->cwn == 0)) { + p->dwcs_params->cwn = p->dwcs_params->own; + p->dwcs_params->cwd = p->dwcs_params->owd; + } + //p->dwcs_params->flags |= DWCS_VIOLATION; + } + } + } + } + + else { + + /* Service time (and time serviced) is at the resolution of + * jiffies right now. That is, it is currently some multiple the + * clock interrupt resolution (10mS on Intels). + */ + p->dwcs_params->time_serviced++; + + /* Adjust service attributes only when a process is serviced in + its entirety "on-time". */ + if (p->dwcs_params->time_serviced == p->dwcs_params->service_time) { + + if ((p->dwcs_params->cwd > p->dwcs_params->cwn) && + (p->dwcs_params->deadline != (unsigned long)-1)) + p->dwcs_params->cwd--; + /* --FS-- missing case of x == y added */ + else if ((p->dwcs_params->cwd == p->dwcs_params->cwn) && + (p->dwcs_params->cwd > 0) && + (p->dwcs_params->deadline != (unsigned long)-1)) { + p->dwcs_params->cwd--; + p->dwcs_params->cwn--; + } + + if (((p->dwcs_params->cwd == 0) && (p->dwcs_params->cwn == 0)) || + (p->dwcs_params->flags & DWCS_VIOLATION)) { + p->dwcs_params->cwn = p->dwcs_params->own; + p->dwcs_params->cwd = p->dwcs_params->owd; + p->dwcs_params->flags &= ~DWCS_VIOLATION; + } + } + + /* Disable any possible servicing of this task until its next + request period if it does not support work-conservation. */ + if ((!(p->dwcs_params->flags & DWCS_WORK_CONS)) && + (p->dwcs_params->time_serviced == p->dwcs_params->service_time)) + p->dwcs_params->ready_time += p->dwcs_params->period; + else + if (p->dwcs_params->deadline != (unsigned long)-1) { + if (p->dwcs_params->time_serviced == p->dwcs_params->service_time) { + p->dwcs_params->flags |= DWCS_SERVICED_THIS_PERIOD; + + /* The following line tells us when it's safe to + reset the DWCS_SERVICED_THIS_PERIOD flag. */ + p->dwcs_params->ready_time += p->dwcs_params->period; + } + } + + if (p->dwcs_params->time_serviced == p->dwcs_params->service_time) { + if (p->dwcs_params->deadline != (unsigned long)-1) + p->dwcs_params->deadline += p->dwcs_params->period; +#ifdef CONFIG_DWCS_DFS + if (p == dwcs_hyper_period_task) { + dwcs_hyper_period_task_count++; + if (dwcs_hyper_period_task_count == dwcs_hyper_period_task_iterations) { + if (hyper_period_recalc_needed) { + find_hyper_period_task(0); + } + if (DWCS_module_mode == DWCS_MODE_VMI) { + dwcs_dfs_measurements(p); + } + dwcs_hyper_period_task_count = 0; + } + } +#endif + p->dwcs_params->time_serviced = 0; + } + + /* Statistics. */ + p->dwcs_params->on_time++; + + if (((p->dwcs_params->on_time + + p->dwcs_params->late) % + p->dwcs_params->owd) == 0) { + + if (p->dwcs_params->wlate > p->dwcs_params->own) { + p->dwcs_params->violations++; +#ifdef CONFIG_DWCS_DFS + dwcs_hyper_period_violations++; +#endif + /*printk (KERN_DEBUG "(%d) VIOLATION!\n", + p->dwcs_params->cd);*/ + } + p->dwcs_params->wlate = 0; + } + + } +#ifdef DWCS_DEBUG_ON + if (DWCS_DEBUG && (p->dwcs_params->deadline != -1) && (debug_count < 50)) { + char tmp[100]; + sprintf(tmp, "%d %ld %ld %ld %d %d %d %d %d %ld %ld %ld %d %ld %ld %ld\n", p->pid, p->dwcs_params->deadline, JIFFIES, p->dwcs_params->period, p->dwcs_params->own, p->dwcs_params->owd, p->dwcs_params->cwn, p->dwcs_params->cwd, p->dwcs_params->flags, p->dwcs_params->ready_time, p->dwcs_params->service_time, p->dwcs_params->time_serviced, p->dwcs_params->wlate, p->dwcs_params->late, p->dwcs_params->on_time, p->dwcs_params->violations); + + strcat(debug_area, tmp); + debug_count++; + } +#endif +} + + +struct task_struct * +compare_service_constraints (struct task_struct * p, + struct task_struct * next, + struct task_struct * prev, + int weight_of_p) { + + if ((next->dwcs_params->flags & DWCS_NON_PREEMPTIVE) && + (next->dwcs_params->time_serviced < next->dwcs_params->service_time) && + (next->dwcs_params->time_serviced > 0)) + return next; + + if ((p->dwcs_params->ready_time > JIFFIES) && + (!(p->dwcs_params->flags & DWCS_WORK_CONS))) + return next; + + /* In aggressive energy_mode ignore dwcs tasks handled owd-own times already */ + if ((energy_mode == DWCS_EM_AVERAGE_AGGRESSIVE) && + (p->policy == SCHED_DWCS) && + (p->dwcs_params->cwd == p->dwcs_params->cwn)) + return next; + + + /* + * Search run queue for highest priority i.e. lowest + * window-constrained, EDF task and set to `next' task for + * service in the run queue. + */ + + if ((p->dwcs_params->deadline == next->dwcs_params->deadline) && + (p->dwcs_params->deadline == (unsigned long)-1) && + (p->dwcs_params->cwn == next->dwcs_params->cwn) && + (p->dwcs_params->cwd == next->dwcs_params->cwd)) { + + int this_cpu = prev->processor; + int weight_of_next = goodness(next, this_cpu, prev->active_mm); + + /* + * NOTE: For non-time-constrained tasks. + * + * We could've decided not do deal with `weights'. In that + * case, a non-blocking process could hog the CPU even if + * other processes are in the runqueue and have the same DWCS + * service constraints. To be more `fair' even though we're + * supposed to be real-time, we let the process that has the + * largest weight have the CPU if two processes have the same DWCS + * service constraints. This behaviour is in keeping with + * the default Linux scheduler's behaviour. + */ + if (weight_of_p > weight_of_next) + next = p; + } + else { + /* --FS-- Moved serviced_this_period comparison to first place */ + if ((p->dwcs_params->deadline != (unsigned long)-1) && + (!(p->dwcs_params->flags & DWCS_SERVICED_THIS_PERIOD)) && + (next->dwcs_params->flags & DWCS_SERVICED_THIS_PERIOD)) + next = p; + else + if ((p->dwcs_params->deadline < next->dwcs_params->deadline) || + ((p->dwcs_params->deadline == next->dwcs_params->deadline) && + (p->dwcs_params->cwn * next->dwcs_params->cwd < + next->dwcs_params->cwn * p->dwcs_params->cwd)) || + ((p->dwcs_params->deadline == next->dwcs_params->deadline) && + (p->dwcs_params->cwn == 0) && (next->dwcs_params->cwn == 0) && + (p->dwcs_params->cwd > next->dwcs_params->cwd)) || + ((p->dwcs_params->deadline == next->dwcs_params->deadline) && + (p->dwcs_params->cwn * next->dwcs_params->cwd == + next->dwcs_params->cwn * p->dwcs_params->cwd) && + ((p->dwcs_params->cwn > 0 && p->dwcs_params->cwd > 0)))) { + // || + //(p->dwcs_params->cwn < 0 && p->dwcs_params->cwd < 0)) && + //(p->dwcs_params->cwn < next->dwcs_params->cwn))) { + next = p; + } + } + + return next; +} + +int DWCS_request_admission(struct task_struct *tptr, struct dwcs_sched_param *param) +{ + int old_utilization; + int new_utilization; + + new_utilization = MAX_UTILIZATION * (param->owd - param->own) \ + * param->service_time \ + / (param->period * param->owd); + old_utilization = MAX_UTILIZATION \ + * (tptr->dwcs_params->owd - tptr->dwcs_params->own) \ + * tptr->dwcs_params->service_time \ + / (tptr->dwcs_params->period * tptr->dwcs_params->owd); + + if ((new_utilization > old_utilization) && + ((utilization - old_utilization + new_utilization) > (MAX_UTILIZATION - reserved_utilization))) { + return -EADMISSION; + } + + return 1; +} + +/* flag = 0 (recompute all), 1 (remove task) */ +void do_update_utilization(int flag, struct task_struct *tptr) +{ + struct task_struct *ptr; + + if (flag == 0) { + utilization = 0; + for_each_task(ptr) { + if (ptr->dwcs_params->period != (unsigned long)-1) { + utilization += MAX_UTILIZATION \ + * (ptr->dwcs_params->owd - ptr->dwcs_params->own) \ + * ptr->dwcs_params->service_time \ + / (ptr->dwcs_params->period * ptr->dwcs_params->owd); + } + } +#ifdef CONFIG_DWCS_DFS + if (DWCS_module_mode == DWCS_MODE_THEORETICAL) + dwcs_dfs_theoretical(); +#endif + } else if (flag == 1) { + if (tptr->dwcs_params->deadline != (unsigned long)-1) { + find_hyper_period_task(1); + utilization -= MAX_UTILIZATION \ + * (tptr->dwcs_params->owd - tptr->dwcs_params->own) \ + * tptr->dwcs_params->service_time \ + / (tptr->dwcs_params->period * tptr->dwcs_params->owd); +#ifdef CONFIG_DWCS_DFS + if (DWCS_module_mode == DWCS_MODE_THEORETICAL) + dwcs_dfs_theoretical(); +#endif + } + } +} + +int av_cons_utilization() +{ + int utilization = 0; + struct list_head *tmp; + struct task_struct *p; + + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (p->dwcs_params->period != (unsigned long)-1) { + utilization += MAX_UTILIZATION + * p->dwcs_params->service_time + / p->dwcs_params->period; + } + } + return utilization; +} + +int av_aggr_utilization() +{ + int utilization = 0; + struct list_head *tmp; + struct task_struct *p; + + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (p->dwcs_params->period != (unsigned long)-1) { + utilization += MAX_UTILIZATION + * (p->dwcs_params->owd - p->dwcs_params->own) + * p->dwcs_params->service_time + / (p->dwcs_params->period * p->dwcs_params->owd); + } + } + return utilization; +} + +int ad_cons_utilization() +{ + int utilization = 0; + struct list_head *tmp; + struct task_struct *p; + + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (p->dwcs_params->period != (unsigned long)-1) { + utilization += MAX_UTILIZATION + * (p->dwcs_params->service_time * p->dwcs_params->cpu_speedup / 100) + / p->dwcs_params->period; + } + } + return utilization; +} + +int ad_aggr_utilization() +{ + int utilization = 0; + struct list_head *tmp; + struct task_struct *p; + + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (p->dwcs_params->period != (unsigned long)-1) { + utilization += MAX_UTILIZATION + * (p->dwcs_params->owd - p->dwcs_params->own) + * (p->dwcs_params->service_time * p->dwcs_params->cpu_speedup / 100) + / (p->dwcs_params->period * p->dwcs_params->owd); + } + } + return utilization; +} + +/* + * 'schedule()' is the scheduler function. It's a very simple and nice + * scheduler: it's not perfect, but certainly works for most things. + * + * The goto is "interesting". + * + * NOTE!! Task 0 is the 'idle' task, which gets called when no other + * tasks can run. It can not be killed, and it cannot sleep. The 'state' + * information in task[0] is never used. + */ + +void DWCS_schedule(struct task_struct **prv, + struct task_struct **nxt) +{ + struct schedule_data * sched_data; + struct task_struct *prev, *next, *p; +#ifdef CONFIG_QFABRIC + struct task_struct *old_p; +#endif + struct list_head *tmp; + int this_cpu, c; + +#ifdef CONFIG_QFABRIC + asmlinkage void (*upcall_sched)(struct task_struct **, + struct task_struct **, + int *, + int); +#endif + + jiffies_sim++; + + spin_lock_prefetch(&runqueue_lock); + + BUG_ON(!current->active_mm); +need_resched_back: + prev = current; + this_cpu = prev->processor; + + if (unlikely(in_interrupt())) { + printk("Scheduling in interrupt\n"); + BUG(); + } + + release_kernel_lock(prev, this_cpu); + + /* + * 'sched_data' is protected by the fact that we can run + * only one process per CPU. + */ + sched_data = & aligned_data[this_cpu].schedule_data; + + spin_lock_irq(&runqueue_lock); + + /* move an exhausted RR process to be last.. */ + if (unlikely(prev->policy == SCHED_RR)) + if (!prev->counter) { + prev->counter = NICE_TO_TICKS(prev->nice); + move_last_runqueue(prev); + } + + switch (prev->state) { + case TASK_INTERRUPTIBLE: + if (signal_pending(prev)) { + prev->state = TASK_RUNNING; + break; + } + default: + del_from_runqueue(prev); + case TASK_RUNNING:; + } + prev->need_resched = 0; + + /* + * this is the scheduler proper: + */ + +repeat_schedule: + /* + * Default process to select.. + */ + next = idle_task(this_cpu); + c = -1000; + + if ((prev->state == TASK_RUNNING) && (prev->dwcs_params->ready_time <= JIFFIES)) { + prev->dwcs_params->flags &= ~DWCS_SERVICED_THIS_PERIOD; + c = goodness(prev, this_cpu, prev->active_mm); + next = prev; + } + + /* + * GANEV: update service constraints here... + */ + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (can_schedule(p, this_cpu)) { + update_service_constraints(p, 1); + } +#ifdef DWCS_DEBUG_ON + else if (DWCS_DEBUG && (debug_count < 50)) { + char tmp[100]; + sprintf(tmp, "no csc\n%d %ld %ld %ld %d %d %d %d %d %ld %ld %ld %d %ld %ld %ld\n", p->pid, p->dwcs_params->deadline, JIFFIES, p->dwcs_params->period, p->dwcs_params->own, p->dwcs_params->owd, p->dwcs_params->cwn, p->dwcs_params->cwd, p->dwcs_params->flags, p->dwcs_params->ready_time, p->dwcs_params->service_time, p->dwcs_params->time_serviced, p->dwcs_params->wlate, p->dwcs_params->late, p->dwcs_params->on_time, p->dwcs_params->violations); + strcat(debug_area, tmp); + debug_count++; + } +#endif + } + if (DWCS_update_utilization == 1) { + do_update_utilization(0, NULL); + DWCS_update_utilization = 0; + } + + list_for_each(tmp, &runqueue_head) { + p = list_entry(tmp, struct task_struct, run_list); + if (can_schedule(p, this_cpu)) { + int weight = goodness(p, this_cpu, prev->active_mm); + if (weight > c) + c = weight; + next = compare_service_constraints(p,next,prev,weight); + } + } +#ifdef DWCS_DEBUG_ON +/* + if (DWCS_DEBUG && (debug_count < 50)) { + char tmp[5]; + debug_count++; + sprintf(tmp, "%d\n", p->pid); + strcat(debug_area, tmp); + } +*/ +#endif + +#ifdef CONFIG_QFABRIC + if (upcall_sched_active) { + upcall_sched = sys_call_table[__NR_upcall_scheduler-__NR_SYSCALL_BASE]; + old_p = next; + upcall_sched(&old_p, &next, &c, utilization); + } +#endif + + /* Do we need to re-calculate counters? */ + if (unlikely(!c)) { + struct task_struct *p; + + spin_unlock_irq(&runqueue_lock); + read_lock(&tasklist_lock); + for_each_task(p) + p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); + read_unlock(&tasklist_lock); + spin_lock_irq(&runqueue_lock); + goto repeat_schedule; + } + + /* + * from this point on nothing can prevent us from + * switching to the next task, save this fact in + * sched_data. + */ +#ifdef CONFIG_DWCS_DFS + if (next == idle_task(this_cpu)) { + dwcs_hyper_period_idles++; + } +#endif + sched_data->curr = next; + task_set_cpu(next, this_cpu); + spin_unlock_irq(&runqueue_lock); + + update_service_constraints(next, 0); + + /* --FS-- if next process is a dwcs proc. do powermgmnt */ + /* + if ((next->dwcs_params->period != (unsigned long)-1) && (energy_mode != 0)){ + int utilization = MAX_UTILIZATION; + if (energy_mode == DWCS_EM_AVERAGE_CONSERVATIVE) { + utilization = av_cons_utilization(); + } + else if (energy_mode == DWCS_EM_AVERAGE_AGGRESSIVE) { + utilization = av_aggr_utilization(); + } + if (utilization < MAX_UTILIZATION / 100) + utilization = MAX_UTILIZATION / 100; + next->dwcs_params->cpu_speedup = (MAX_UTILIZATION - reserved_utilization) * 100 / utilization; +#ifdef CONFIG_DWCS_DFS + set_slowest_cpuspeed(next); +#endif + } else { + set_default_cpuspeed(); + } +*/ + + /* --FS-- do this check early since we can't jump to + * same_process in dwcs_switch */ + if (unlikely(prev == next) && (current->need_resched)) { + /* We won't go through the normal tail, so do this by hand */ + prev->policy &= ~SCHED_YIELD; + goto same_process; + } + + *prv = prev; + *nxt = next; + + return; + +same_process: + reacquire_kernel_lock(current); + goto need_resched_back; + +} diff -Naur test-for-latech/kernel/ecalls.c testqf-for-latech/kernel/ecalls.c --- test-for-latech/kernel/ecalls.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/kernel/ecalls.c 2004-06-11 07:47:23.000000000 -0400 @@ -0,0 +1,240 @@ +/* + * linux/kernel/ecalls.c + * + * Copyright (C) 1999/2000 Christian Poellabauer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#include +#include + +#define MAX_LENGTH 32 +#define NR_THREADS 512 + +extern void *sys_call_table[]; +#ifdef CONFIG_QFABRIC +#ifdef CONFIG_X86 +#define __NR_SYSCALL_BASE 0 +extern void *fast_sys_call_table[]; +#endif +#endif +extern atomic_t access_lock; +extern int sysctl_max_syn_backlog; + +struct ecall_down { + int shmid; + void *shmaddr; +}; +typedef struct ecall_down *t_downcall_data; + +struct ecall_up { + int shmid; + void *shmaddr; +}; +typedef struct ecall_up *t_upcall_data; + +/* Start ecall mechanism. */ +asmlinkage int sys_start_ecalls(void) +{ +#ifdef CONFIG_QFABRIC + return request_module("ecalls"); +#endif + return 1; +} + +/* End ecall mechanism. */ +asmlinkage int sys_end_ecalls(void) +{ + return 1; +} + +/* Register ECall. */ +asmlinkage int sys_register_ecall(char *service, int len, + struct ecall_down *downcall, struct ecall_up *upcall) +{ + return -ENOSYS; +} + +/* Do Downcall. */ +asmlinkage int sys_do_downcall(struct ecall_down *downcall, + void *data, int len) +{ + return -ENOSYS; +} + +/* Event handler function. */ +asmlinkage void sys_run_event_handler(void) +{ + return; +} + +/* Fast event handler function. */ +asmlinkage int sys_fast_do_downcall(struct ecall_down *downcall, + void *data, int len) +{ + return -ENOSYS; +} + +/* Call upcall scheduler. */ +asmlinkage int sys_upcall_scheduler(void) +{ + return -ENOSYS; +} + +/* Dummy sys_wake_up_ecalls. */ +asmlinkage int sys_wake_up_ecalls(void) +{ + return -ENOSYS; +} + +/* Dummy code download function. */ +asmlinkage int sys_download_code(void) +{ + return -ENOSYS; +} + +/* Set sock->readable or sock->writeable. */ +int set_sock_ecalls(struct socket *sock, int readable, int writable, int kecho, + void *ptr, int fd, int pid) +{ +#ifdef CONFIG_QFABRIC + if (readable == 1) + sock->sk->readable = 1; + else + sock->sk->readable = 0; + if (writable == 1) + sock->sk->writable = 1; + else + sock->sk->writable = 0; + if (kecho == 1) + sock->sk->kecho = 1; + else + sock->sk->kecho = 0; + sock->sk->kecho_ptr = ptr; + if (fd != -1) + sock->sk->fd = fd; + if (pid != -1) + sock->sk->owner = pid; +#endif + return 0; +} + +void call_event_handler(void) +{ +#ifdef CONFIG_QFABRIC + void (*ECalls_event_handler)(void); + + ECalls_event_handler = sys_call_table[__NR_run_event_handler-__NR_SYSCALL_BASE]; + ECalls_event_handler(); +#endif +} + +void call_upcall_sched(struct task_struct **ts1, struct task_struct **ts2, + int *weight) +{ +#ifdef CONFIG_QFABRIC + void (*upcall_sched)(struct task_struct **ts1, + struct task_struct **ts2, int *weight); + + upcall_sched = sys_call_table[__NR_upcall_scheduler-__NR_SYSCALL_BASE]; + upcall_sched(ts1, ts2, weight); +#endif +} + +int call_admission_control(struct task_struct *ts1, struct sched_param *pa1) +{ +#ifdef CONFIG_QFABRIC + int (*request_task_admission)(struct task_struct *ts1, + struct sched_param *pa1); + + request_task_admission = sys_call_table[__NR_admission_control-__NR_SYSCALL_BASE]; + return (request_task_admission(ts1, pa1)); +#else + return -1; +#endif +} + +void call_update_util(int flag, struct task_struct *ts1) +{ +#ifdef CONFIG_QFABRIC + void (*update_utilization)(int, struct task_struct *); + + update_utilization = sys_call_table[__NR_update_utilization-__NR_SYSCALL_BASE]; + update_utilization(1, current); +#endif +} + +void call_wake_up(int i1, int i2, int i3, int i4, void *ptr) +{ +#ifdef CONFIG_QFABRIC + void (*wake_up_using_ecalls)(int, int, int, int, void *); + + wake_up_using_ecalls = sys_call_table[__NR_wake_up_ecalls-__NR_SYSCALL_BASE]; + wake_up_using_ecalls(i1, i2, i3, i4, ptr); +#endif +} + +int get_sock_info(void *pointer, int flag) +{ +#ifdef CONFIG_QFABRIC + struct sock *sk; + + sk = (struct sock *) pointer; + + if (flag == 0) + return sk->rcvbuf; + if (flag == 1) + return sk->rmem_alloc.counter; + if (flag == 2) + return sk->receive_queue.qlen; + if (flag == 3) + return sk->ack_backlog; + if (flag == 4) + return sysctl_max_syn_backlog; + if (flag == 5) + return tcp_synq_is_full(sk); + if (flag == 6) + return sk->socket->state; + if (flag == 7) + return sk->counter; + if (flag == 8) + return sk->rmem_alloc.counter; + if (flag == 9) + return sk->wmem_alloc.counter; +#endif + return -1; +} + +int set_sock_info(void *pointer, int flag, int value) +{ +#ifdef CONFIG_QFABRIC + struct sock *sk; + + sk = (struct sock *) pointer; + + if (flag == 0) + sk->rcvbuf = value; + if (flag == 3) + sk->max_ack_backlog = value; + if (flag == 4) + sysctl_max_syn_backlog = value; + return 0; +#endif + return -1; +} diff -Naur test-for-latech/kernel/exit.c testqf-for-latech/kernel/exit.c --- test-for-latech/kernel/exit.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/exit.c 2004-06-11 07:47:23.000000000 -0400 @@ -5,6 +5,9 @@ */ #include +#ifdef CONFIG_QFABRIC +#include +#endif #include #include #include @@ -23,10 +26,19 @@ extern void sem_exit (void); extern struct task_struct *child_reaper; +#ifdef CONFIG_DWCS +#include +extern void *sys_call_table[]; +extern int DWCS_module_loaded; +#endif int getrusage(struct task_struct *, int, struct rusage *); +#ifdef CONFIG_QFABRIC +void release_task(struct task_struct * p) +#else static void release_task(struct task_struct * p) +#endif { if (p != current) { #ifdef CONFIG_SMP @@ -449,6 +461,23 @@ tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); + /* + * Set flag for computation of utilization. + */ +#ifdef CONFIG_DWCS + if (DWCS_module_loaded) { + void (*update_utilization)(int, struct task_struct *); + update_utilization = sys_call_table[__NR_update_utilization-__NR_SYSCALL_BASE]; + update_utilization(1, current); + } +#endif +#ifdef CONFIG_QFABRIC + if (tsk->qfabric != NULL) { + kfree(tsk->qfabric->fdqfabric); + kfree(tsk->qfabric); + } +#endif + fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); diff -Naur test-for-latech/kernel/fork.c testqf-for-latech/kernel/fork.c --- test-for-latech/kernel/fork.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/fork.c 2004-06-11 07:47:23.000000000 -0400 @@ -690,9 +690,46 @@ goto bad_fork_cleanup_sighand; if (copy_namespace(clone_flags, p)) goto bad_fork_cleanup_mm; + +#ifdef CONFIG_DWCS + /* --RW-- + * Initialize the dwcs_params structure, in case the DWCS + * scheduler is in operation. + */ + p->dwcs_params = kmalloc(sizeof(struct dwcs_struct), GFP_ATOMIC); + if (!p->dwcs_params) { + retval = -ENOMEM; + goto bad_fork_cleanup_namespace; + } + + p->dwcs_params->cd = p->pid; + /* Default = no deadline */ + p->dwcs_params->deadline = (unsigned long) -1; + p->dwcs_params->period = (unsigned long) -1; + /* `period' is a multiple of jiffies. */ + p->dwcs_params->own = 1; + p->dwcs_params->owd = 10; + p->dwcs_params->cwn = 1; + p->dwcs_params->cwd = 10; + p->dwcs_params->flags = DWCS_WORK_CONS; + p->dwcs_params->ready_time = 0; + p->dwcs_params->service_time = 1; /* x 10mS for each clock tick. */ + p->dwcs_params->time_serviced = 0; + p->dwcs_params->wlate = 0; + p->dwcs_params->late = 0; + p->dwcs_params->on_time = 0; + p->dwcs_params->violations = 0; + /* End of --RW-- */ +#endif + + retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); if (retval) +#ifdef CONFIG_DWCS + goto bad_fork_cleanup_dwcs; +#else goto bad_fork_cleanup_namespace; +#endif p->semundo = NULL; /* Our parent execution domain becomes current domain @@ -700,6 +737,15 @@ p->parent_exec_id = p->self_exec_id; +#ifdef CONFIG_QFABRIC + p->qfabric = NULL; + p->kthread = 0; + p->suser_flag = 0; + p->uaccess_flag = 0; + p->ecalls_flag = 0; + p->syscall_counter = 0; +#endif + /* ok, now we should be set up.. */ p->swappable = 1; p->exit_signal = clone_flags & CSIGNAL; @@ -758,7 +804,10 @@ fork_out: return retval; - +#ifdef CONFIG_DWCS +bad_fork_cleanup_dwcs: + kfree(p->dwcs_params); +#endif bad_fork_cleanup_namespace: exit_namespace(p); bad_fork_cleanup_mm: diff -Naur test-for-latech/kernel/ksyms.c testqf-for-latech/kernel/ksyms.c --- test-for-latech/kernel/ksyms.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/ksyms.c 2004-06-11 07:47:23.000000000 -0400 @@ -39,6 +39,12 @@ #include #include #include +#ifdef CONFIG_QFABRIC +#include +#include +#include +#include +#endif #include #include #include @@ -47,6 +53,11 @@ #include #include #include +#ifdef CONFIG_QFABRIC +#include +#include +#include +#endif #include #if defined(CONFIG_PROC_FS) @@ -56,9 +67,57 @@ #include #endif +//#define DWCS_DEBUG_ON 1 + +#ifdef CONFIG_QFABRIC +#define NR_THREADS 512 + +extern int get_pseudofd(struct socket *sock, struct socket *fd_array[]); +extern int release_pseudofd(int fd, struct socket *fd_array[]); +extern struct socket *look_up_pseudofd(int fd, struct socket *fd_array[]); +extern int poll_socket(struct socket *socket); +extern int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags); +extern long sys_sched_yield(void); +extern void initialize_qfabric(void); +extern int ECalls_active; +#endif + +#ifdef CONFIG_DWCS +extern int DWCS_module_loaded; /* --RW-- */ +extern void (*DWCS_scheduler)(struct task_struct **, struct task_struct **); /* --FS-- */ +extern struct list_head runqueue_head; /* --FS-- */ +extern int DWCS_admission_control; /* --CP-- */ +extern int DWCS_update_utilization; /* --CP-- */ +extern int utilization; /* --CP-- */ +#ifdef DWCS_DEBUG_ON +extern unsigned long dwcs_timer_max_time; +extern long dwcs_max_counter; +extern long dwcs_pid; +extern unsigned long dwcs_sched_max_time; +#endif +#endif +#ifdef CONFIG_QFABRIC +extern int security_off; /* --CP-- */ +extern int SOCKWATCH_module_loaded; /* --CP-- */ +extern int set_sock_ecalls(struct socket *, int, int, int, void*); /* --CP-- */ +extern int get_sock_info(void *, int); /* --CP-- */ +extern int set_sock_info(void *, int, int); /* --CP-- */ +extern int wake_up_process(struct task_struct * tsk); +extern struct socket *sockfd_lookup(int fd, int *err); +extern unsigned long total_forks; +extern struct page *grab_cache_page_ex(struct address_space *mapping, + unsigned long index, struct page **cached_page); +#endif +extern unsigned long volatile jiffies_sim; + extern void set_device_ro(kdev_t dev,int flag); extern void *sys_call_table; +#ifdef CONFIG_QFABRIC +#ifdef CONFIG_X86 +extern void *fast_sys_call_table; +#endif +#endif extern struct timezone sys_tz; extern int request_dma(unsigned int dmanr, char * deviceID); @@ -80,6 +139,33 @@ EXPORT_SYMBOL(inter_module_put); EXPORT_SYMBOL(try_inc_mod_count); +/* --RW-- + * Dionisys and DWCS module symbols. + */ +#ifdef CONFIG_DWCS +EXPORT_SYMBOL(DWCS_module_loaded); +EXPORT_SYMBOL(DWCS_scheduler); /* --FS-- */ +EXPORT_SYMBOL(init_tasks); /* --CP-- */ +#ifdef DWCS_DEBUG_ON +EXPORT_SYMBOL(dwcs_timer_max_time); +EXPORT_SYMBOL(dwcs_max_counter); +EXPORT_SYMBOL(dwcs_pid); +EXPORT_SYMBOL(dwcs_sched_max_time); +#endif + +/* +EXPORT_SYMBOL(do_bottom_half); +*/ +EXPORT_SYMBOL(jiffies_sim); +/* + * GANEV: exported various symbols so that they would be accessible to + * loadable kernel schedulers like DWCS. + */ +EXPORT_SYMBOL(aligned_data); +EXPORT_SYMBOL(runqueue_head); /* --FS-- */ +EXPORT_SYMBOL(runqueue_lock); +#endif + /* process memory management */ EXPORT_SYMBOL(do_mmap_pgoff); EXPORT_SYMBOL(do_munmap); @@ -394,6 +480,9 @@ #ifdef CONFIG_SMP /* Various random spinlocks we want to export */ EXPORT_SYMBOL(tqueue_lock); +#ifdef CONFIG_DWCS +EXPORT_SYMBOL(global_irq_lock); /* --RW-- */ +#endif /* Big-Reader lock implementation */ EXPORT_SYMBOL(__brlock_array); @@ -440,7 +529,6 @@ EXPORT_SYMBOL(complete_and_exit); EXPORT_SYMBOL(__wake_up); EXPORT_SYMBOL(__wake_up_sync); -EXPORT_SYMBOL(wake_up_process); EXPORT_SYMBOL(sleep_on); EXPORT_SYMBOL(sleep_on_timeout); EXPORT_SYMBOL(interruptible_sleep_on); @@ -480,6 +568,11 @@ #ifndef __mips__ EXPORT_SYMBOL(sys_call_table); #endif +#ifdef CONFIG_QFABRIC +#ifdef CONFIG_X86 +EXPORT_SYMBOL(fast_sys_call_table); +#endif +#endif EXPORT_SYMBOL(machine_restart); EXPORT_SYMBOL(machine_halt); EXPORT_SYMBOL(machine_power_off); @@ -570,3 +663,43 @@ EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(pidhash); + +/* --CP-- */ +#ifdef CONFIG_QFABRIC +EXPORT_SYMBOL(get_pseudofd); +EXPORT_SYMBOL(release_pseudofd); +EXPORT_SYMBOL(look_up_pseudofd); +EXPORT_SYMBOL(poll_socket); +EXPORT_SYMBOL(sys_shmat); +EXPORT_SYMBOL(sys_recvmsg); +EXPORT_SYMBOL(upcall_sched_active); +#endif +#ifdef CONFIG_DWCS +EXPORT_SYMBOL(DWCS_update_utilization); +EXPORT_SYMBOL(DWCS_admission_control); +EXPORT_SYMBOL(utilization); +#endif +#ifdef CONFIG_QFABRIC +EXPORT_SYMBOL(security_off); +EXPORT_SYMBOL(ECalls_current_flag); +EXPORT_SYMBOL(ECalls_current); +EXPORT_SYMBOL(global_wait_queue); +//EXPORT_SYMBOL(sys_sched_yield); +EXPORT_SYMBOL(SOCKWATCH_module_loaded); +EXPORT_SYMBOL(set_sock_ecalls); +EXPORT_SYMBOL(get_sock_info); +EXPORT_SYMBOL(set_sock_info); +EXPORT_SYMBOL(sockfd_lookup); +EXPORT_SYMBOL(initialize_qfabric); +EXPORT_SYMBOL(ECalls_active); +EXPORT_SYMBOL(avenrun); +EXPORT_SYMBOL(nr_free_pages); +EXPORT_SYMBOL(swapper_space); +EXPORT_SYMBOL(si_swapinfo); +EXPORT_SYMBOL(page_cache_size); +EXPORT_SYMBOL(nr_inactive_pages); +EXPORT_SYMBOL(nr_active_pages); +EXPORT_SYMBOL(total_forks); +EXPORT_SYMBOL(grab_cache_page_ex); +#endif +EXPORT_SYMBOL(wake_up_process); diff -Naur test-for-latech/kernel/Makefile testqf-for-latech/kernel/Makefile --- test-for-latech/kernel/Makefile 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/Makefile 2004-06-11 07:47:23.000000000 -0400 @@ -14,12 +14,16 @@ obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ sysctl.o acct.o capability.o ptrace.o timer.o user.o \ - signal.o sys.o kmod.o context.o + signal.o sys.o kmod.o context.o ecalls.o qfabric.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o obj-$(CONFIG_PM) += pm.o +ifeq ($(CONFIG_DWCS),y) +obj-m += dwcs.o +endif + ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is # needed for x86 only. Why this used to be enabled for all architectures is beyond diff -Naur test-for-latech/kernel/qfabric.c testqf-for-latech/kernel/qfabric.c --- test-for-latech/kernel/qfabric.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/kernel/qfabric.c 2004-06-11 07:47:23.000000000 -0400 @@ -0,0 +1,190 @@ +/* + * linux/kernel/qfabric.c + * + * Copyright (C) 1999/2000 Christian Poellabauer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +//#include + +#define MAX_LENGTH 32 +#define NR_THREADS 512 + +extern void *sys_call_table[]; +extern atomic_t access_lock; + +/* Load Kernel ECho modules. */ +asmlinkage int sys_kecho_load(char * module_name, int argument) +{ + char k_module_name[MAX_LENGTH]; + + /* Copy argument into kernel space. */ + copy_from_user(k_module_name, module_name, MAX_LENGTH); + + /* Load requested module. */ + return request_module(k_module_name); +} + +#ifdef CONFIG_QFABRIC +/* Look up pseudo fd number. */ +struct socket *look_up_pseudofd(int fd, struct socket *fd_array[]) +{ + return fd_array[fd]; +} + +/* Get pseudofd */ +int get_pseudofd(struct socket *sock, struct socket *fd_array[]) +{ + int i = 0; + + while ((i < MAX_FDS) && (fd_array[i] != NULL)) i++; + + if (i == MAX_FDS) return -1; + + fd_array[i] = sock; + + return i; +} + +/* Release pseudo fd. */ +int release_pseudofd(int i, struct socket *fd_array[]) +{ + fd_array[i] = NULL; + + return 0; +} + +/* Poll socket for incoming data. */ +int poll_socket(struct socket *socket) +{ + struct sock *sock; + + sock = socket->sk; + if ((sock == NULL) || (sock->receive_queue.next == NULL) || + (sock->receive_queue.next->len <= 0) || + (sock->receive_queue.next->len > sock->receive_queue.next->truesize)) + return 0; + else + return 1; +} + +extern mm_segment_t kernel_get_fs(void) +{ + return current->addr_limit; +} + +#ifdef CONFIG_X86_WP_WORKS_OK + +extern int kernel_access_ok(int type, const void *addr, size_t size) +{ + if (__range_ok(addr,size) == 0) + return 1; + return 0; +} + +#else +#ifdef CONFIG_ARM +extern int kernel_access_ok(int type, const void *addr, size_t size) +{ + if (__range_ok(addr,size) == 0) + return 1; + return 0; +} +#else +#ifndef CONFIG_IA64 +extern int kernel_access_ok(int type, const void *addr, size_t size) +{ + if ((__range_ok(addr,size) == 0) && + ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || + segment_eq(get_fs(),KERNEL_DS) || + __verify_write((void *)(addr),(size)))) + return 1; + return 0; +} +#endif +#endif +#endif /* CPU */ + +/* Initialize qfabric data structure. */ +void initialize_qfabric(void) +{ + if (current->qfabric == NULL) { + current->qfabric = (struct qfabric_struct *) + kmalloc(sizeof(struct qfabric_struct), GFP_KERNEL); + current->qfabric->fdqfabric = kmalloc (MAX_FDS, GFP_KERNEL); + memset(current->qfabric->fdqfabric, 0, MAX_FDS); + init_waitqueue_head(¤t->qfabric->kecho_queue); + current->qfabric->weight = 0; + current->qfabric->orig_weight = 0; + current->qfabric->sw_pending = 0; + } +} +#endif +/* KECho System Call API: */ +asmlinkage int sys_KECho_syscall_echo(void *echo_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_fast_KECho_syscall_echo(void *echo_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_KECho_syscall_cm(void *cm_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_fast_KECho_syscall_cm(void *cm_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_KECho_syscall_cg(void *cg_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_fast_KECho_syscall_cg(void *cg_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_KECho_syscall_atl(void *atl_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_fast_KECho_syscall_atl(void *atl_data) +{ + return -ENOSYS; +} + +asmlinkage int sys_KECho_sw_callback(int fd, int pid, void *ptr) +{ + return -ENOSYS; +} + +asmlinkage int sys_qos_configure(void) +{ + return -ENOSYS; +} diff -Naur test-for-latech/kernel/sched.c testqf-for-latech/kernel/sched.c --- test-for-latech/kernel/sched.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/sched.c 2004-06-11 07:47:23.000000000 -0400 @@ -33,6 +33,20 @@ #include #include +//#define DWCS_DEBUG_ON 1 + +#ifdef CONFIG_DWCS +#include +#include +#endif + +#ifdef CONFIG_QFABRIC +extern void call_event_handler(void); +extern void call_upcall_sched(struct task_struct **, + struct task_struct **, int *); +extern int call_admission_control(struct task_struct *, struct sched_param *); +#endif + extern void timer_bh(void); extern void tqueue_bh(void); extern void immediate_bh(void); @@ -41,10 +55,21 @@ * scheduler variables */ +#ifdef CONFIG_QFABRIC +atomic_t access_lock; +atomic_t access_lock2; +struct socket *fd_array[MAX_FDS]; +int ECalls_active = 0; + +struct wait_queue *global_wait_queue = NULL; +#endif + unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ extern void mem_use(void); +unsigned long volatile jiffies_sim = 0; /* --RW-- */ + /* * Scheduling quanta. * @@ -70,6 +95,31 @@ #define NICE_TO_TICKS(nice) (TICK_SCALE(20-(nice))+1) +#ifdef CONFIG_DWCS +#define MAX_TASKS 128 +/* + * Module variables for DWCS scheduling and ECalls. + */ +#ifdef DWCS_DEBUG_ON +unsigned long dwcs_sched_max_time = 0; +unsigned long dwcs_old_time = 0; +long dwcs_pid = -2; +#endif +int DWCS_module_loaded = 0; /* Not initially loaded. */ +void (*DWCS_scheduler)(struct task_struct **, struct task_struct **) = NULL; +int DWCS_update_utilization = 1;/* Initially set. */ +int utilization = 0; +int DWCS_admission_control = 0; /* Not initially active. */ +#endif +#ifdef CONFIG_QFABRIC +int upcall_sched_active = 0; /* Not initially active. */ +int security_off = 0; /* Not initially active. */ +int ECalls_current_flag = 0; /* Not initially set. */ +struct task_struct *ECalls_current; +int SOCKWATCH_module_loaded = 0; + +#endif +extern void *sys_call_table[]; /* * Init task must be ok at boot for the ix86 as we will check its signals @@ -92,19 +142,27 @@ spinlock_t runqueue_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; /* inner */ rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */ -static LIST_HEAD(runqueue_head); +LIST_HEAD(runqueue_head); /* * We align per-CPU scheduling data on cacheline boundaries, * to prevent cacheline ping-pong. + * + * GANEV: moved the data type description into a "typedef" in + * to make it accessible from a separately compiled loadable kernel + * module. */ +#ifdef CONFIG_DWCS +aligned_data_t aligned_data[NR_CPUS] __cacheline_aligned = { {{&init_task,0}}}; +#else static union { struct schedule_data { - struct task_struct * curr; + struct task_struct *curr; cycles_t last_schedule; } schedule_data; char __pad [SMP_CACHE_BYTES]; -} aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}}; +} aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task, 0}}}; +#endif #define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr #define last_schedule(cpu) aligned_data[(cpu)].schedule_data.last_schedule @@ -189,6 +247,15 @@ * into account). */ weight = 1000 + p->rt_priority; +#ifdef CONFIG_QFABRIC + if (p->qfabric != NULL) { + if (p->qfabric->weight > 0) { + weight = -1000; + p->qfabric->weight--; + } else + p->qfabric->weight = p->qfabric->orig_weight; + } +#endif out: return weight; } @@ -536,6 +603,97 @@ __schedule_tail(prev); } +/* --RW-- */ +#ifdef CONFIG_DWCS +void dwcs_switch (struct task_struct *prev, struct task_struct *next) { + + /* GANEV/FS: added definitions for "sched_data" which is needed in the + * conditional below. */ + int this_cpu; +#ifdef CONFIG_SMP + struct schedule_data * sched_data; +#endif + + this_cpu = prev->processor; + + /* We might have switched CPUs: */ +#ifdef CONFIG_SMP + sched_data = & aligned_data[this_cpu].schedule_data; +#endif + + + if (unlikely(prev == next)) { + /* We won't go through the normal tail, so do this by hand */ + prev->policy &= ~SCHED_YIELD; + goto same_process; + } + +#ifdef CONFIG_SMP + /* + * maintain the per-process 'last schedule' value. + * (this has to be recalculated even if we reschedule to + * the same process) Currently this is only used on SMP, + * and it's approximate, so we do not have to maintain + * it while holding the runqueue spinlock. + */ + sched_data->last_schedule = get_cycles(); + + /* + * We drop the scheduler lock early (it's a global spinlock), + * thus we have to lock the previous process from getting + * rescheduled during switch_to(). + */ + +#endif /* CONFIG_SMP */ + + kstat.context_swtch++; + /* + * there are 3 processes which are affected by a context switch: + * + * prev == .... ==> (last => next) + * + * It's the 'much more previous' 'prev' that is on next's stack, + * but prev is set to (the just run) 'last' process by switch_to(). + * This might sound slightly confusing but makes tons of sense. + */ + prepare_to_switch(); + { + struct mm_struct *mm = next->mm; + struct mm_struct *oldmm = prev->active_mm; + if (!mm) { + BUG_ON(next->active_mm); + next->active_mm = oldmm; + atomic_inc(&oldmm->mm_count); + enter_lazy_tlb(oldmm, next, this_cpu); + } else { + BUG_ON(next->active_mm != mm); + switch_mm(oldmm, mm, next, this_cpu); + } + + if (!prev->mm) { + prev->active_mm = NULL; + mmdrop(oldmm); + } + } + + /* + * This just switches the register state and the + * stack. + */ + switch_to(prev, next, prev); + __schedule_tail(prev); + +same_process: + reacquire_kernel_lock(current); + /* --FS-- this check is moved to kernel/dwcs.c:schedule() + * if (current->need_resched) + * goto need_resched_back; + */ + return; +} +#endif + + /* * 'schedule()' is the scheduler function. It's a very simple and nice * scheduler: it's not perfect, but certainly works for most things. @@ -550,10 +708,56 @@ { struct schedule_data * sched_data; struct task_struct *prev, *next, *p; +#ifdef CONFIG_QFABRIC + struct task_struct *old_p; +#endif struct list_head *tmp; int this_cpu, c; +#ifdef DWCS_DEBUG_ON + if (dwcs_old_time == 0) { + dwcs_old_time = jiffies; + } else { + unsigned long tmp; + tmp = jiffies - dwcs_old_time; + dwcs_old_time = jiffies; + if (dwcs_sched_max_time < tmp) { + dwcs_sched_max_time = tmp; + dwcs_pid = current->pid; + } + } +#endif + /* + * POELLABAUER: check if the current process created any + * events via ECalls and if so process them. + */ +#ifdef CONFIG_QFABRIC + if ((ECalls_active > 0) && (current->ecalls_flag)) + call_event_handler(); +#endif + + /* --RW-- + * First, check to see if the DWCS module is loaded. + * If so, call the DWCS scheduler instead. + */ + + /* + * GANEV: modified the scheduler function pointer to accept + * two "struct task_struct *" parameters for the automatic + * "prev" and "nexxt" variables, and pass back the chosen + * task to run in them. Global variables to do this work no + * longer if we want to be SMP-safe... + */ + +#ifdef CONFIG_DWCS + if (DWCS_module_loaded && DWCS_scheduler) { + DWCS_scheduler(&prev, &next); + dwcs_switch(prev,next); + return; + } +#endif + spin_lock_prefetch(&runqueue_lock); BUG_ON(!current->active_mm); @@ -614,6 +818,16 @@ } } + /* --CP-- */ +#ifdef CONFIG_DWCS +#ifdef CONFIG_QFABRIC + if (upcall_sched_active) { + old_p = next; + call_upcall_sched(&old_p, &next, &c); + } +#endif +#endif + /* Do we need to re-calculate counters? */ if (unlikely(!c)) { struct task_struct *p; @@ -930,10 +1144,10 @@ else { retval = -EINVAL; if (policy != SCHED_FIFO && policy != SCHED_RR && - policy != SCHED_OTHER) - goto out_unlock; + policy != SCHED_OTHER) + goto out_unlock; } - + /* * Valid priorities for SCHED_FIFO and SCHED_RR are 1..99, valid * priority for SCHED_OTHER is 0. diff -Naur test-for-latech/kernel/signal.c testqf-for-latech/kernel/signal.c --- test-for-latech/kernel/signal.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/signal.c 2004-06-11 07:47:23.000000000 -0400 @@ -52,7 +52,7 @@ { unsigned long i, *s, *m, x; int sig = 0; - + s = tsk->pending.signal.sig; m = mask->sig; switch (_NSIG_WORDS) { @@ -64,6 +64,22 @@ } break; +#ifdef CONFIG_QFABRIC + case 2: if (test_bit(SIGSTOP, &s[0]) == 1) + sig = SIGSTOP; + else if (test_bit(SIGKILL, &s[0]) == 1) + sig = SIGKILL; + else { + if ((x = s[1] &~ m[1]) != 0) + sig = _NSIG_BPW + 1; + else if ((x = s[0] &~ m[0]) != 0) + sig = 1; + else + break; + sig += ffz(~x); + break; + } +#else case 2: if ((x = s[0] &~ m[0]) != 0) sig = 1; else if ((x = s[1] &~ m[1]) != 0) @@ -72,6 +88,7 @@ break; sig += ffz(~x); break; +#endif case 1: if ((x = *s &~ *m) != 0) sig = ffz(~x) + 1; diff -Naur test-for-latech/kernel/sys.c testqf-for-latech/kernel/sys.c --- test-for-latech/kernel/sys.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/sys.c 2004-06-11 07:47:23.000000000 -0400 @@ -1279,6 +1279,47 @@ return error; } +/* --RW-- + * Replace this with the proper scheduler, when the + * corresponding module is loaded. + */ +asmlinkage void sys_load_scheduler (void) +{ + return; +} + +asmlinkage void sys_unload_scheduler (void) +{ + return; +} + +asmlinkage void sys_DWCS_scheduler (void) +{ + return; +} + +asmlinkage void sys_update_utilization (void) +{ + return; +} + +asmlinkage void sys_admission_control (void) +{ + return; +} + +asmlinkage long sys_getsyscalls (void) +{ +#ifdef CONFIG_QFABRIC + return current->syscall_counter; +#endif +} + +asmlinkage void sys_change_clock (void) +{ + return; +} + EXPORT_SYMBOL(notifier_chain_register); EXPORT_SYMBOL(notifier_chain_unregister); EXPORT_SYMBOL(notifier_call_chain); diff -Naur test-for-latech/kernel/timer.c testqf-for-latech/kernel/timer.c --- test-for-latech/kernel/timer.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/kernel/timer.c 2004-06-11 07:47:23.000000000 -0400 @@ -25,6 +25,12 @@ #include +//#define DWCS_DEBUG_ON 1 + +#ifdef CONFIG_DWCS +extern int DWCS_module_loaded; +#endif + /* * Timekeeping variables */ @@ -63,6 +69,12 @@ unsigned long event; +#ifdef DWCS_DEBUG_ON +unsigned long dwcs_timer_max_time = 0; +unsigned long dwcs_timer_old_time = 0; +long dwcs_max_counter = 0; +#endif + extern int do_setitimer(int, struct itimerval *, struct itimerval *); unsigned long volatile jiffies; @@ -597,8 +609,27 @@ struct task_struct *p = current; int cpu = smp_processor_id(), system = user_tick ^ 1; +#ifdef DWCS_DEBUG_ON + if (dwcs_timer_old_time == 0) { + dwcs_timer_old_time = jiffies; + } else { + unsigned long tmp; + tmp = jiffies - dwcs_timer_old_time; + dwcs_timer_old_time = jiffies; + if (dwcs_timer_max_time < tmp) { + dwcs_timer_max_time = tmp; + } + } +#endif + update_one_process(p, user_tick, system, cpu); - if (p->pid) { + //if (p->pid) { + if (1) { +#ifdef DWCS_DEBUG_ON + if (p->counter > dwcs_max_counter) { + dwcs_max_counter = p->counter; + } +#endif if (--p->counter <= 0) { p->counter = 0; p->need_resched = 1; @@ -695,6 +726,11 @@ update_process_times(user_mode(regs)); #endif +#ifdef CONFIG_DWCS + if (DWCS_module_loaded == 1) { + current->need_resched = 1; + } +#endif mark_bh(TIMER_BH); if (TQ_ACTIVE(tq_timer)) mark_bh(TQUEUE_BH); diff -Naur test-for-latech/Makefile testqf-for-latech/Makefile --- test-for-latech/Makefile 2004-06-11 07:39:56.000000000 -0400 +++ testqf-for-latech/Makefile 2004-06-11 07:47:19.000000000 -0400 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 19 -EXTRAVERSION = +EXTRAVERSION = -qfabric KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -Naur test-for-latech/mm/filemap.c testqf-for-latech/mm/filemap.c --- test-for-latech/mm/filemap.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/mm/filemap.c 2004-06-11 07:47:23.000000000 -0400 @@ -2883,6 +2883,14 @@ return page; } +#ifdef CONFIG_QFABRIC +struct page *grab_cache_page_ex(struct address_space *mapping, + unsigned long index, struct page **cached_page) +{ + return __grab_cache_page(mapping, index, cached_page); +} +#endif + inline void remove_suid(struct inode *inode) { unsigned int mode; diff -Naur test-for-latech/mm/mlock.c testqf-for-latech/mm/mlock.c --- test-for-latech/mm/mlock.c 2004-06-11 07:40:02.000000000 -0400 +++ testqf-for-latech/mm/mlock.c 2004-06-11 07:47:23.000000000 -0400 @@ -12,6 +12,10 @@ #include #include +#ifdef CONFIG_QFABRIC +extern int security_off; +#endif + static inline int mlock_fixup_all(struct vm_area_struct * vma, int newflags) { spin_lock(&vma->vm_mm->page_table_lock); @@ -151,8 +155,14 @@ struct vm_area_struct * vma, * next; int error; +#ifdef CONFIG_QFABRIC + if (security_off != 1) + if (on && !capable(CAP_IPC_LOCK)) + return -EPERM; +#else if (on && !capable(CAP_IPC_LOCK)) return -EPERM; +#endif len = PAGE_ALIGN(len); end = start + len; if (end < start) diff -Naur test-for-latech/net/Config.in testqf-for-latech/net/Config.in --- test-for-latech/net/Config.in 2004-06-11 07:40:47.000000000 -0400 +++ testqf-for-latech/net/Config.in 2004-06-11 07:47:57.000000000 -0400 @@ -94,6 +94,12 @@ #bool 'Network code profiler' CONFIG_NET_PROFILE endmenu +#mainmenu_option next_comment +#comment 'QSockets' +if [ "$CONFIG_NET_CLS_SOCKET" = "y" ]; then + bool ' QSocket support' CONFIG_NET_QSOCKET +fi + mainmenu_option next_comment comment 'Network testing' tristate 'Packet Generator (USE WITH CAUTION)' CONFIG_NET_PKTGEN diff -Naur test-for-latech/net/core/dev.c testqf-for-latech/net/core/dev.c --- test-for-latech/net/core/dev.c 2004-06-11 07:40:49.000000000 -0400 +++ testqf-for-latech/net/core/dev.c 2004-06-11 07:47:57.000000000 -0400 @@ -1,4 +1,4 @@ -/* + /* * NET3 Protocol independent device support routines. * * This program is free software; you can redistribute it and/or @@ -977,6 +977,7 @@ { struct net_device *dev = skb->dev; struct Qdisc *q; + int rt_data = 0; if (skb_shinfo(skb)->frag_list && !(dev->features&NETIF_F_FRAGLIST) && @@ -1009,14 +1010,16 @@ /* Grab device queue */ spin_lock_bh(&dev->queue_lock); - q = dev->qdisc; - if (q->enqueue) { - int ret = q->enqueue(skb, q); + if (rt_data != 1) { + q = dev->qdisc; + if (q->enqueue) { + int ret = q->enqueue(skb, q); - qdisc_run(dev); + qdisc_run(dev); - spin_unlock_bh(&dev->queue_lock); - return ret == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : ret; + spin_unlock_bh(&dev->queue_lock); + return ret == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : ret; + } } /* The device has no queue. Common case for software devices: @@ -1621,7 +1624,7 @@ * Thus we will need a 'compatibility mode'. */ -static int dev_ifconf(char *arg) +static int dev_ifconf2(char *arg, int flag) { struct ifconf ifc; struct net_device *dev; @@ -1633,9 +1636,12 @@ /* * Fetch the caller's info block. */ - - if (copy_from_user(&ifc, arg, sizeof(struct ifconf))) - return -EFAULT; + + if (flag == 0) { + if (copy_from_user(&ifc, arg, sizeof(struct ifconf))) + return -EFAULT; + } else + memcpy(&ifc, arg, sizeof(struct ifconf)); pos = ifc.ifc_buf; len = ifc.ifc_len; @@ -1667,8 +1673,11 @@ */ ifc.ifc_len = total; - if (copy_to_user(arg, &ifc, sizeof(struct ifconf))) - return -EFAULT; + if (flag == 0) { + if (copy_to_user(arg, &ifc, sizeof(struct ifconf))) + return -EFAULT; + } else + memcpy(arg, &ifc, sizeof(struct ifconf)); /* * Both BSD and Solaris return 0 here, so we do too. @@ -1676,6 +1685,11 @@ return 0; } +static int dev_ifconf(char *arg) +{ + return dev_ifconf2(arg, 0); +} + /* * This is invoked by the /proc filesystem handler to display a device * in detail. @@ -1956,7 +1970,7 @@ * Perform the SIOCxIFxxx calls. */ -static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) +static int dev_ifsioc2(struct ifreq *ifr, unsigned int cmd, int flag) { struct net_device *dev; int err; @@ -2123,6 +2137,11 @@ return -EINVAL; } +static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) +{ + return dev_ifsioc2(ifr, cmd, 0); +} + /* * This function handles all "interface"-type I/O control requests. The actual * 'doing' part of this is dev_ifsioc above. @@ -2139,7 +2158,7 @@ * positive or a negative errno code on error. */ -int dev_ioctl(unsigned int cmd, void *arg) +int dev_ioctl2(unsigned int cmd, void *arg, int flag) { struct ifreq ifr; int ret; @@ -2152,7 +2171,10 @@ if (cmd == SIOCGIFCONF) { rtnl_shlock(); - ret = dev_ifconf((char *) arg); + if (flag == 1) + ret = dev_ifconf2((char *) arg, 1); + else + ret = dev_ifconf((char *) arg); rtnl_shunlock(); return ret; } @@ -2160,8 +2182,11 @@ return dev_ifname((struct ifreq *)arg); } - if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) - return -EFAULT; + if (flag == 0) { + if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) + return -EFAULT; + } else + memcpy(&ifr, arg, sizeof(struct ifreq)); ifr.ifr_name[IFNAMSIZ-1] = 0; @@ -2192,13 +2217,19 @@ case SIOCGIFTXQLEN: dev_load(ifr.ifr_name); read_lock(&dev_base_lock); - ret = dev_ifsioc(&ifr, cmd); + if (flag == 1) + ret = dev_ifsioc2(&ifr, cmd, 1); + else + ret = dev_ifsioc(&ifr, cmd); read_unlock(&dev_base_lock); if (!ret) { if (colon) *colon = ':'; - if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) + if (flag == 0) { + if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; + } else + memcpy(arg, &ifr, sizeof(struct ifreq)); } return ret; @@ -2217,14 +2248,20 @@ dev_load(ifr.ifr_name); dev_probe_lock(); rtnl_lock(); - ret = dev_ifsioc(&ifr, cmd); + if (flag == 1) + ret = dev_ifsioc2(&ifr, cmd, 1); + else + ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); dev_probe_unlock(); if (!ret) { if (colon) *colon = ':'; - if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) + if (flag == 0) { + if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; + } else + memcpy(arg, &ifr, sizeof(struct ifreq)); } return ret; @@ -2258,7 +2295,10 @@ dev_load(ifr.ifr_name); dev_probe_lock(); rtnl_lock(); - ret = dev_ifsioc(&ifr, cmd); + if (flag == 1) + ret = dev_ifsioc2(&ifr, cmd, 1); + else + ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); dev_probe_unlock(); return ret; @@ -2281,11 +2321,18 @@ dev_load(ifr.ifr_name); dev_probe_lock(); rtnl_lock(); - ret = dev_ifsioc(&ifr, cmd); + if (flag == 1) + ret = dev_ifsioc2(&ifr, cmd, 1); + else + ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); dev_probe_unlock(); - if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) + if (flag == 0) { + if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; + } else { + memcpy(arg, &ifr, sizeof(struct ifreq)); + } return ret; } #ifdef WIRELESS_EXT @@ -2301,11 +2348,17 @@ dev_load(ifr.ifr_name); rtnl_lock(); /* Follow me in net/core/wireless.c */ - ret = wireless_process_ioctl(&ifr, cmd); + if (flag == 1) + ret = wireless_process_ioctl2(&ifr, cmd, 1); + else + ret = wireless_process_ioctl(&ifr, cmd); rtnl_unlock(); + if (flag == 0) { if (!ret && IW_IS_GET(cmd) && copy_to_user(arg, &ifr, sizeof(struct ifreq))) return -EFAULT; + } else + memcpy(arg, &ifr, sizeof(struct ifreq)); return ret; } #endif /* WIRELESS_EXT */ @@ -2313,6 +2366,10 @@ } } +int dev_ioctl(unsigned int cmd, void *arg) +{ + return dev_ioctl2(cmd, arg, 0); +} /** * dev_new_index - allocate an ifindex diff -Naur test-for-latech/net/core/filter.c testqf-for-latech/net/core/filter.c --- test-for-latech/net/core/filter.c 2004-06-11 07:40:49.000000000 -0400 +++ testqf-for-latech/net/core/filter.c 2004-06-11 07:47:57.000000000 -0400 @@ -325,9 +325,21 @@ continue; case BPF_RET|BPF_K: +/* +#ifdef CONFIG_QFABRIC + wake_up_interruptible((wait_queue_head_t *) + &global_wait_queue); +#endif +*/ return ((unsigned int)fentry->k); case BPF_RET|BPF_A: +/* +#ifdef CONFIG_QFABRIC + wake_up_interruptible((wait_queue_head_t *) + &global_wait_queue); +#endif +*/ return ((unsigned int)A); case BPF_ST: diff -Naur test-for-latech/net/core/skbuff.c testqf-for-latech/net/core/skbuff.c --- test-for-latech/net/core/skbuff.c 2004-06-11 07:40:49.000000000 -0400 +++ testqf-for-latech/net/core/skbuff.c 2004-06-11 07:47:57.000000000 -0400 @@ -204,6 +204,11 @@ skb->cloned = 0; skb->data_len = 0; +#ifdef CONFIG_QFABRIC + skb->deadline = -1; + skb->flags = 0; +#endif + atomic_set(&skb->users, 1); atomic_set(&(skb_shinfo(skb)->dataref), 1); skb_shinfo(skb)->nr_frags = 0; diff -Naur test-for-latech/net/core/sock.c testqf-for-latech/net/core/sock.c --- test-for-latech/net/core/sock.c 2004-06-11 07:40:49.000000000 -0400 +++ testqf-for-latech/net/core/sock.c 2004-06-11 07:47:57.000000000 -0400 @@ -119,6 +119,17 @@ #include #include #include +#include +#ifdef CONFIG_QFABRIC +//#include /* --CP-- */ +#include + +extern void *sys_call_table[]; +extern void call_wake_up(int, int, int, int, void*); + +extern int request_socket_deadline(struct sock *sk); +extern int request_socket_rt_flags(struct sock *sk); +#endif #ifdef CONFIG_FILTER #include @@ -435,6 +446,16 @@ switch(optname) { +#ifdef CONFIG_QFABRIC + case SO_QOS_PRIORITY: + v.val = sk->qos_priority; + break; + + case SO_QOS_DEADLINE: + v.val = sk->qos_deadline; + break; +#endif + case SO_DEBUG: v.val = sk->debug; break; @@ -672,6 +693,12 @@ struct sk_buff * skb = alloc_skb(size, priority); if (skb) { skb_set_owner_w(skb, sk); +#ifdef CONFIG_QFABRIC + if (sk->socket != NULL) { + skb->deadline = request_socket_deadline(sk); + skb->flags = request_socket_rt_flags(sk); + } +#endif return skb; } } @@ -1117,7 +1144,7 @@ void sock_def_wakeup(struct sock *sk) { read_lock(&sk->callback_lock); - if (sk->sleep && waitqueue_active(sk->sleep)) + if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible_all(sk->sleep); read_unlock(&sk->callback_lock); } @@ -1133,15 +1160,29 @@ void sock_def_readable(struct sock *sk, int len) { +#ifdef CONFIG_QFABRIC + struct task_struct *tsk; +#endif read_lock(&sk->callback_lock); if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); +#ifdef CONFIG_QFABRIC + if (sk->readable > 0) { + if ((tsk = find_task_by_pid(sk->owner)) != NULL) + if ((tsk->state >= 0) && (tsk->state < 2)) + call_wake_up(sk->fd,sk->owner,0,sk->kecho, + sk->kecho_ptr); + } +#endif sk_wake_async(sk,1,POLL_IN); read_unlock(&sk->callback_lock); } void sock_def_write_space(struct sock *sk) { +#ifdef CONFIG_QFABRIC + struct task_struct *tsk; +#endif read_lock(&sk->callback_lock); /* Do not wake up a writer until he can make "significant" @@ -1154,6 +1195,13 @@ /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk)) sk_wake_async(sk, 2, POLL_OUT); +#ifdef CONFIG_QFABRIC + if (sk->writable > 0) + if ((tsk = find_task_by_pid(sk->owner)) != NULL) + if ((tsk->state >= 0) && (tsk->state < 2)) + call_wake_up(sk->fd,sk->owner,1,sk->kecho, + sk->kecho_ptr); +#endif } read_unlock(&sk->callback_lock); diff -Naur test-for-latech/net/core/wireless.c testqf-for-latech/net/core/wireless.c --- test-for-latech/net/core/wireless.c 2004-06-11 07:40:49.000000000 -0400 +++ testqf-for-latech/net/core/wireless.c 2004-06-11 07:47:57.000000000 -0400 @@ -673,7 +673,7 @@ * (dev_ioctl() in net/core/dev.c). * Check the type of IOCTL and call the appropriate wrapper... */ -int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) +int wireless_process_ioctl2(struct ifreq *ifr, unsigned int cmd, int flag) { struct net_device *dev; iw_handler handler; @@ -731,3 +731,8 @@ /* Not reached */ return -EINVAL; } + +int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) +{ + return wireless_process_ioctl2(ifr, cmd, 0); +} diff -Naur test-for-latech/net/ipv4/tcp.c testqf-for-latech/net/ipv4/tcp.c --- test-for-latech/net/ipv4/tcp.c 2004-06-11 07:40:50.000000000 -0400 +++ testqf-for-latech/net/ipv4/tcp.c 2004-06-11 07:47:57.000000000 -0400 @@ -1511,6 +1511,10 @@ * handling. FIXME: Need to check this doesnt impact 1003.1g * and move it down to the bottom of the loop */ + +#ifdef CONFIG_QFABRIC + if (sk->kecho != 1) +#endif if (signal_pending(current)) { if (copied) break; @@ -1590,6 +1594,9 @@ if (tp->ucopy.task == user_recv) { /* Install new reader */ if (user_recv == NULL && !(flags&(MSG_TRUNC|MSG_PEEK))) { +#ifdef CONFIG_QFABRIC + if (sk->kecho != 1) +#endif user_recv = current; tp->ucopy.task = user_recv; tp->ucopy.iov = msg->msg_iov; diff -Naur test-for-latech/net/ipv4/tcp_ipv4.c testqf-for-latech/net/ipv4/tcp_ipv4.c --- test-for-latech/net/ipv4/tcp_ipv4.c 2004-06-11 07:40:50.000000000 -0400 +++ testqf-for-latech/net/ipv4/tcp_ipv4.c 2004-06-11 07:47:57.000000000 -0400 @@ -1521,7 +1521,12 @@ tcp_openreq_free(req); drop: TCP_INC_STATS_BH(TcpAttemptFails); +/* --CP-- */ +#ifdef CONFIG_QFABRIC + return -ENOTCONN; /* send reset */ +#else return 0; +#endif } diff -Naur test-for-latech/net/Makefile testqf-for-latech/net/Makefile --- test-for-latech/net/Makefile 2004-06-11 07:40:47.000000000 -0400 +++ testqf-for-latech/net/Makefile 2004-06-11 07:47:57.000000000 -0400 @@ -7,7 +7,8 @@ O_TARGET := network.o -mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core +mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched core \ + qsocket export-objs := netsyms.o subdir-y := core ethernet @@ -15,6 +16,7 @@ subdir-$(CONFIG_NET) += 802 sched netlink +subdir-$(CONFIG_NET_QSOCKET) += qsocket subdir-$(CONFIG_INET) += ipv4 subdir-$(CONFIG_NETFILTER) += ipv4/netfilter subdir-$(CONFIG_UNIX) += unix diff -Naur test-for-latech/net/netsyms.c testqf-for-latech/net/netsyms.c --- test-for-latech/net/netsyms.c 2004-06-11 07:40:47.000000000 -0400 +++ testqf-for-latech/net/netsyms.c 2004-06-11 07:47:57.000000000 -0400 @@ -28,6 +28,7 @@ #include #endif #include +#include #include #include #include @@ -35,6 +36,9 @@ #ifdef CONFIG_NET_DIVERT #include #endif /* CONFIG_NET_DIVERT */ +#ifdef CONFIG_NET_QSOCKET +#include +#endif #ifdef CONFIG_NET extern __u32 sysctl_wmem_max; @@ -106,11 +110,17 @@ EXPORT_SYMBOL(memcpy_fromiovec); EXPORT_SYMBOL(memcpy_tokerneliovec); EXPORT_SYMBOL(sock_create); +#ifdef CONFIG_QFABRIC +EXPORT_SYMBOL(make_rt_sock); +#endif EXPORT_SYMBOL(sock_alloc); EXPORT_SYMBOL(sock_release); EXPORT_SYMBOL(sock_setsockopt); EXPORT_SYMBOL(sock_getsockopt); EXPORT_SYMBOL(sock_sendmsg); +#ifdef CONFIG_QFABRIC +EXPORT_SYMBOL(rt_sock_sendmsg); +#endif EXPORT_SYMBOL(sock_recvmsg); EXPORT_SYMBOL(sk_alloc); EXPORT_SYMBOL(sk_free); @@ -500,6 +510,9 @@ EXPORT_SYMBOL(dev_load); #endif EXPORT_SYMBOL(dev_ioctl); +#ifdef CONFIG_QFABRIC +EXPORT_SYMBOL(dev_ioctl2); +#endif EXPORT_SYMBOL(dev_queue_xmit); #ifdef CONFIG_NET_HW_FLOWCONTROL EXPORT_SYMBOL(netdev_dropping); @@ -548,6 +561,9 @@ EXPORT_SYMBOL(qdisc_get_rtab); EXPORT_SYMBOL(qdisc_put_rtab); EXPORT_SYMBOL(qdisc_copy_stats); +EXPORT_SYMBOL(qdisc_lookup_ops_string); +EXPORT_SYMBOL(qdisc_alloc_handle); +EXPORT_SYMBOL(qdisc_graft); #ifdef CONFIG_NET_ESTIMATOR EXPORT_SYMBOL(qdisc_new_estimator); EXPORT_SYMBOL(qdisc_kill_estimator); @@ -562,6 +578,9 @@ #ifdef CONFIG_NET_CLS EXPORT_SYMBOL(register_tcf_proto_ops); EXPORT_SYMBOL(unregister_tcf_proto_ops); +#ifdef CONFIG_NET_CLS_SOCKET +EXPORT_SYMBOL(cls_socket_ops); +#endif #endif #ifdef CONFIG_NETFILTER #include @@ -588,4 +607,13 @@ EXPORT_SYMBOL(net_call_rx_atomic); EXPORT_SYMBOL(softnet_data); +#ifdef CONFIG_NET_QSOCKET +EXPORT_SYMBOL(qop_base); +#endif + +#ifdef CONFIG_QFABRIC +EXPORT_SYMBOL(tcp_mem_schedule); +EXPORT_SYMBOL(tcp_memory_pressure); +#endif + #endif /* CONFIG_NET */ diff -Naur test-for-latech/net/qsocket/dwcs.h testqf-for-latech/net/qsocket/dwcs.h --- test-for-latech/net/qsocket/dwcs.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/qsocket/dwcs.h 2004-06-11 07:48:02.000000000 -0400 @@ -0,0 +1,110 @@ + +void watchdog(unsigned long arg) +{ + struct net_device *dev = (struct net_device*) arg; + if(dev) + { + netif_schedule(dev); + } +} + + + +void dwcs_init_timer(struct timer_list *wd_timer, struct net_device *dev) +{ + init_timer(wd_timer); + wd_timer->function = watchdog; + wd_timer->data = (unsigned long)dev; +} + + +/* +** dwcs_link_class() inserts the class in qdisc's linked list. +** It should be executed atomically. +*/ +static void dwcs_link_class(struct dwcs_class *this) +{ + struct dwcs_sched_data *q = (struct dwcs_sched_data*)this->qdisc->data; + unsigned h = dwcs_hash(this->classid); + + this->next = q->classes[h]; + q->classes[h] = this; + +} + +/* + * Helper function to return the address of the class + * by providing the classid (that includes major and minor ids), + * Returns NULL, if no class is found. + */ +static __inline__ struct dwcs_class * +dwcs_class_lookup ( struct dwcs_sched_data *q, + u32 classid ) +{ + struct dwcs_class *cl; + + for ( cl = q->classes[dwcs_hash ( classid )]; cl; cl = cl->next ) + if ( cl->classid == classid ) + { + return cl; + } + + return NULL; +} + + + +static int q_dwcs_init(struct Qdisc *sch) +{ + struct dwcs_sched_data *q = (void*)sch->data; + + q->dlheap_size = 0; + q->ltheap_size = 0; + q->slheap_size = 0; + + q->link = (struct dwcs_class*) kmalloc(sizeof(struct dwcs_class), GFP_KERNEL); + if(q->link == NULL) + { + return -ENOBUFS; + } + memset(q->link, 0, sizeof(struct dwcs_class)); + + q->link->filter_list = NULL; + q->link->refcnt = 1; + q->link->classid = sch->handle; + q->link->qdisc = sch; + + if(!(q->link->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) + { + printk("no op qdisc \n"); + q->link->q = &noop_qdisc; + } + + if(sch->dev == NULL) + printk("dev == NULL : qsocket\n"); + else + dwcs_init_timer(&q->wd_timer, sch->dev); + + + q->link->attr.ipg = 1; + q->link->attr.oln = 0; + q->link->attr.old = 1; + q->link->attr.flags = 0; + q->link->attr.cln = 0; /* Current loss numerator. */ + q->link->attr.cld = 0; /* Current loss denominator. */ + q->link->attr.droppable = FALSE; /* TRUE if packets can be dropped */ + q->link->attr.cln = q->link->attr.oln; + q->link->attr.cld = q->link->attr.old; + q->link->attr.clt = (100 * q->link->attr.oln / q->link->attr.old); + q->link->attr.deadline = -1; + q->link->attr.readytime = -1; + + memset(q->classes, 0, sizeof(struct dwcs_class*) * 16); + + dwcs_link_class(q->link); + q->classcount = 1; + + return 0; + +} + diff -Naur test-for-latech/net/qsocket/Makefile testqf-for-latech/net/qsocket/Makefile --- test-for-latech/net/qsocket/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/qsocket/Makefile 2004-06-11 07:48:02.000000000 -0400 @@ -0,0 +1,7 @@ +#Makefile for qsocket + +O_TARGET := qsocket.o + +obj-$(CONFIG_NET_QSOCKET) += qsock.o + +include $(TOPDIR)/Rules.make diff -Naur test-for-latech/net/qsocket/qsock.c testqf-for-latech/net/qsocket/qsock.c --- test-for-latech/net/qsocket/qsock.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/qsocket/qsock.c 2004-06-11 07:48:02.000000000 -0400 @@ -0,0 +1,1115 @@ +/* Mohammed Hasan Abbasi + Qsocket.c - implementation for the Qsocket api calls + API list: + qsocket(int, int, int, struct qos_params*) + qchange(int, struct qos_params*) + qshutdown(int) + + qsocket() creates a socket and associates it with a class + it expects to be called after qos_conf() + + qchange() takes a socket and associates it with a class in much the + same way that qsocket does. Only change is that it can take a socket + already associated with a class, delete the class, and add a new one. + + qhutdown will simply delete the socket, the class etc etc. + + Based on code snippetes from the file sch_dwcs.c, + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define SLEEP_TIME HZ +#define PORT_START 5100 +#define PORT_RANGE 100 +#define MAX_SOCK_ADDR 128 +#define QERROR(code) do {err = code; goto err_out;}while(0); + +#define SYS_QCHANNEL 13 + +/* Global variables. */ +//static char hostname[MAXHOSTNAMELEN]; + +extern void * sys_call_table[]; +int (*orig_qsocketcall)(int, unsigned long*); +int (*socketcall)(int, unsigned long*); +//int (*qos_conf)(int, int, int, char *, struct socket *, void *); +int (*pidcall)(void); +int (*sched_setscheduler)(pid_t, int, struct sched_param *); + +#include "utils.h" +#include "dwcs.h" + +/*this is just for compatibility with teh newer version so that it can be compiled by just dropping it in*/ +struct qop_list *qop_base; + +/* +static char *strdup(char *s) +{ + char *p; + + p = (char *)kmalloc(strlen(s)+1, GFP_KERNEL); + if (p != NULL) + strcpy(p,s); + return p; +} +*/ + +/* +static void my_gethostname() +{ + down_read(&uts_sem); + memset(hostname, '\0', MAXHOSTNAMELEN); + memcpy(hostname, system_utsname.nodename, strlen(system_utsname.nodename)); + if (memchr(hostname, '.', MAXHOSTNAMELEN) == NULL) { + strcat (hostname, "."); + strcat (hostname, system_utsname.domainname); + } + up_read(&uts_sem); +} +*/ + +static int register_identifier(int server, int use_cpu, int use_net, char *app_id, int fd, struct dwcs_class *cl) +{ + //call qos_register +// struct sock *sk; + struct socket *sock; + int err = 0; + + + sock = sockfd_lookup(fd, &err); + if(!sock) + { + goto out; + } + + printk("calling qos_register\n"); +// qos_register(server, use_cpu, use_net, app_id, sock, cl); + + sockfd_put(sock); + out: + return err; +} + +static inline void unregister_identifier(int fd) +{ + //call qos_register +// struct sock *sk; + struct socket *sock; + int err = 0; + + + sock = sockfd_lookup(fd, &err); + if(!sock) + { + goto out; + } + + printk("calling qos_unregister\n"); +// qos_unregister(sock); + + sockfd_put(sock); + out: + return; +} + + + +static struct Qdisc * qsock_init_qdisc(struct net_device *dev) +{ + /*at some future time we can allow init to set up specific QDiscs and stuff*/ + + /*Start by adding a new DWCS QDisc as the root on this device + *if there is already a qdisc installed there .. return + *The DWCS QDisc will have a default best effort queue class in it + */ + + /****************************************** + * dev->qdisc is the pointer to the root - this should be null + * + ******************************************/ + + int err = 0; + struct Qdisc *sch; + struct Qdisc *old_sch = NULL; + struct Qdisc *parent = NULL; + struct Qdisc_ops *ops; + int size; + int handle = 0; // = TC_H_MAKE(1, 0); + + ops = qdisc_lookup_ops_string("dwcs"); + + if(ops == NULL) + { + char module_name[4+IFNAMSIZ+1]; + sprintf(module_name, "sch_%s", "dwcs"); + request_module(module_name); + ops = qdisc_lookup_ops_string("dwcs"); + } + + if(ops == NULL) + { + return NULL; + } + + size = sizeof(*sch) + ops->priv_size; + + sch = kmalloc(size, GFP_KERNEL); + if(sch == NULL) + { + return NULL; + } + + if(ops != qdisc_lookup_ops_string("dwcs")) + { + kfree(sch); + return NULL; + } + + skb_queue_head_init(&sch->q); + + sch->ops = ops; + + sch->enqueue = ops->enqueue; + sch->dequeue = ops->dequeue; + sch->dev = dev; + + atomic_set(&sch->refcnt, 1); + sch->stats.lock = &dev->queue_lock; + + handle = qdisc_alloc_handle(dev); + if(handle == 0) + { + kfree(sch); + return NULL; + } + + sch->handle = handle; + /*initialize the dwcs qdisc here*/ + if((err = q_dwcs_init(sch)) < 0) + { + kfree(sch); + return NULL; + } + ops->init(sch, NULL); + + if(qdisc_graft(dev, parent, 0, sch, &old_sch) < 0) + { + kfree(sch); + return NULL; + } + +// write_lock(&qdisc_tree_lock); +// sch->next = dev->qdisc_list; +// dev->qdisc_list = sch; +// write_unlock(&qdisc_tree_lock); + + return sch; + +} + +asmlinkage long sys_qsocket(int family, int type, int protocol, + struct qos_params *args, unsigned long *a) +{ + + //a heck of a lot of definitions + //at some future time I will cut these down to a bare min + + //network device to attach the qdisc to - we can later modify this + //to attach to ALL the registered network devices .. probably + // a better option. + + struct net_device *temp = dev_base; + + //a kernel copy of the parameters passed in from user space + struct qos_params params; + + //the qdisc we are going to work on + struct Qdisc *qdisc = NULL; + + //class ops for the qdisc + struct Qdisc_class_ops *cops = NULL; + + //sched data for this qdisc + struct dwcs_sched_data *q = NULL; + + //a dwcs class + struct dwcs_class *cl = NULL; + struct dwcs_class *temp_cl = NULL; + + //the socket filter + struct socket_filter *fh = NULL; + + //socket head - this contains all the socket filters + //attached to a class + struct socket_head *head = NULL; + + //tcp protos - these contain the pointer to a list + // of all the filters + struct tcf_proto *tp = NULL; + + //operations allowed for a filter + struct tcf_proto_ops *t = NULL; + + + int hash; + int i = 0; + int x = 0; + int err = 0; + int sockfd = 0; + struct socket *sock; + + //check if the argument set is null? + if(args == NULL) + QERROR(-EINVAL); + //copy the parameters from the user space. The name has to be copied separately + if(copy_from_user(¶ms, args, sizeof(struct qos_params))) + QERROR(-EFAULT); + + if(copy_from_user(params.dev, args->dev, sizeof(char) * IFNAMSIZ)) + QERROR(-EFAULT); + + if (params.disable == 1) { + sockfd = create_socket(a); + sock = sockfd_lookup(sockfd, &err); + sock->sk->reuse = 1; + if (params.qos_on == 1) { + //qos_conf = sys_call_table[__NR_qos_conf]; + //qos_conf(0, 0, 0, params.app_id, sock, NULL); + } + return sockfd; + } + + //find the device + //in a future implementation it might be necessary + //to attach the qdisc to all the devices + for(; temp != NULL; temp = temp->next) + if(!strcmp(params.dev, temp->name)) + break; + //get the root qdisc and perform the operation on this + + qdisc = temp->qdisc; + /*clean up*/ + + cops = qdisc->ops->cl_ops; + + if(qdisc == NULL) + { + qdisc = qsock_init_qdisc(temp); + if(qdisc == NULL) + QERROR(-EINVAL); + } + + if(strcmp("dwcs", qdisc->ops->id)) + { + qdisc = qsock_init_qdisc(temp); + if(qdisc == NULL || strcmp("dwcs", qdisc->ops->id)) + QERROR(-EINVAL); + } + + cops = qdisc->ops->cl_ops; + + //create class and add it to teh queue. + + q = (struct dwcs_sched_data *)qdisc->data; + + cl = (struct dwcs_class*) kmalloc(sizeof(struct dwcs_class), GFP_KERNEL); + if(cl == NULL) + QERROR(-EFAULT); + + memset(cl, 0, sizeof(struct dwcs_class)); + + cl->refcnt = 1; + if(!(cl->q = qdisc_create_dflt(qdisc->dev, &pfifo_qdisc_ops))) + cl->q = &noop_qdisc; + + cl->qdisc = qdisc; + cl->attr.ipg = params.ipg; + cl->attr.oln = params.oln; + cl->attr.old = params.old; + cl->attr.flags = params.flags; + cl->attr.droppable = params.attribute; /* TRUE if packets can be dropped */ + cl->attr.deadline = -1; + cl->attr.readytime = -1; + cl->attr.delay = 0; + cl->attr.cln = 0; /* Current loss numerator. */ + cl->attr.cld = 0; /* Current loss denominator. */ + cl->attr.cln = cl->attr.oln; + cl->attr.cld = cl->attr.old; + cl->attr.clt = (100 * cl->attr.oln / cl->attr.old ); + //attach class to qdisc + + x = 0; + + for(i = 0; i < 16; i ++) + { + struct dwcs_class *c; + c = q->classes[i]; + for(; c != NULL; c = c->next) + { + if(x <= TC_H_MIN(c->classid)) + x = TC_H_MIN(c->classid); + } + } + + + cl->classid = TC_H_MAKE(qdisc->handle, (x+2)); //generate a proper value here + + hash = dwcs_hash(cl->classid); + + //add the class to the queieing discpline + //should delay this until everything is done + //this will prevent spurious class constructions + + dwcs_link_class(cl); + + + q->classcount++; + + //ok now the class has been added to teh qdisc + //next step is to add the filter + //We will create the socket LAST + //go that its possible to revert changes without creating anything + //for the time being I won't do the error handling + //some time later we will have to modify this to support rollback + //which means deleting the class and the filter + + //we need some way of getting our hands on the priority + //for the tcf + + //get the class + + + t = &cls_socket_ops; + if(t == NULL) + QERROR(-EINVAL); + + + //now we have our hands on the tcf_proto_ops + tp = (struct tcf_proto *) kmalloc(sizeof(struct tcf_proto), GFP_KERNEL); + memset(tp, 0, sizeof(*tp)); + tp->ops = t; + tp->protocol = __constant_htons(ETH_P_ALL); // protocol; //this should be IP + tp->prio = TC_H_MAKE(0xC0000000U,0U); + tp->q = qdisc; //points to the parent qdisc + tp->classify = t->classify; + tp->classid = cl->classid; //points to the class which we just created + tp->root = NULL; + + err = t->init(tp); + if (err) + QERROR(err); + + //get the filter handle + if(fh == NULL) + { + if(tp->root == NULL) + { + head = kmalloc(sizeof(struct socket_head), GFP_KERNEL); + if(head == NULL) + QERROR(-ENOBUFS); + memset(head, 0, sizeof(*head)); + tp->root = head; + } + + fh = kmalloc(sizeof(struct socket_filter), GFP_KERNEL); + if(fh == NULL) + return -ENOBUFS; + memset(fh, 0, sizeof(*fh)); + + fh->id = cl->classid; + fh->res.classid = cl->classid; + fh->pid = pidcall(); + fh->res.class = (unsigned long)cl; + sockfd = create_socket(a); + fh->fd = sockfd; + + //ok now we must create the socket!! + + if(sockfd < 0) + QERROR(sockfd); + + read_lock(&tasklist_lock); + { + struct task_struct *ts = find_task_by_pid( fh->pid ); + struct file *fl = NULL; + + if ( ts && (fl=fcheck_files(ts->files,fh->fd) ) ) + { + if ( fl->f_dentry && fl->f_dentry->d_inode ) + { + fh->i_ino = fl->f_dentry->d_inode->i_ino; + } + } + } + + read_unlock(&tasklist_lock); + + + write_lock(&qdisc_tree_lock); + spin_lock_bh(&temp->queue_lock); + + fh->next = head->ht[socket_hash(0)]; + wmb(); + head->ht[socket_hash(0)] = fh; + + q = (struct dwcs_sched_data*) qdisc->data; + + temp_cl = q->link; + tp->next = temp_cl->filter_list; + temp_cl->filter_list = tp; + temp_cl->filters++; + spin_unlock_bh(&temp->queue_lock); + write_unlock(&qdisc_tree_lock); + } + else + QERROR(-EEXIST); + + register_identifier(params.server, params.use_cpu, params.use_net, params.app_id, sockfd, cl); + + + return sockfd; + + err_out: + + if(cl) + kfree(cl); + + if(tp) + kfree(tp); + + if(head) + kfree(head); + + if(fh) + kfree(fh); + + return err; +} + +asmlinkage long sys_qshutdown(int fd, int how, unsigned long *a) +{ + struct net_device *dev = dev_base; + int err = 0; + struct Qdisc *qdisc; + struct Qdisc *leaf; + struct Qdisc_class_ops *cops; + struct dwcs_sched_data *sch_dwcs; + struct dwcs_class *cl, *link; + struct socket_filter *fh = NULL; + struct socket_head *head = NULL; + struct tcf_proto *tp = NULL; + int i_ino = 0; + + + +// unregister_identifier(fd); +// printk("registered\n"); + + read_lock(&tasklist_lock); + { + struct task_struct *ts = find_task_by_pid(pidcall() ); + struct file *fl = NULL; + + if ( ts && (fl=fcheck_files(ts->files, fd) ) ) + { + + if ( fl->f_dentry && fl->f_dentry->d_inode ) + { + i_ino = fl->f_dentry->d_inode->i_ino; + } + } + } + read_unlock(&tasklist_lock); + + + err = socketcall(SYS_SHUTDOWN, a); + + if(i_ino == 0) + return -EINVAL; + + + for(; dev !=NULL; dev = dev->next) + { + qdisc = dev->qdisc; + if(qdisc == NULL) + continue; + + leaf = qdisc; + + + if(strcmp("dwcs", leaf->ops->id)) + continue; + + + sch_dwcs = (struct dwcs_sched_data*) leaf->data; + + link = sch_dwcs->link; + + for(tp = link->filter_list; tp; tp = tp->next) + { + if(tp->ops) + { + if(!strcmp("socket", tp->ops->kind)) + { + head = tp->root; + if(head) + fh = head->ht[socket_hash(0)]; + if(fh == NULL) + { + continue; + } + for(; fh; fh = fh->next) + if(fh->i_ino == i_ino) + goto out; + } + } + } + out: + if(fh == NULL) + { + return -EINVAL; + } + + //decrease ref count for the root class + if ( ( cl = ( void * ) fh->res.class ) == NULL ) + { + if ( TC_H_MAJ ( fh->res.classid ) ) + cl = dwcs_class_lookup ( sch_dwcs, fh->res.classid ); + + } + + + if(cl == NULL) + { + printk(KERN_ERR "cl == NULL\n"); + return -EINVAL; + } + + + cops = leaf->ops->cl_ops; + + //sadly this has to be done + //because of the way that the classifier is used + //only the 0th entry is ever used + fh->id = 0; + tp->ops->destroy(tp); + if(cl->filters) + cl->filters = 0; + link->filters--; + err = cops->delete(leaf, (unsigned long)cl); + return err; + } + return err; +} + +asmlinkage long sys_qchange(int fd, struct qos_params *args, unsigned long *a) +{ + + struct net_device *dev = dev_base; + struct Qdisc *qdisc; + struct Qdisc *leaf; + struct dwcs_sched_data *sch_dwcs; + struct dwcs_class *cl, *link; + struct socket_filter *fh = NULL; + struct socket_head *head = NULL; + struct tcf_proto *tp = NULL; + int i_ino = 0; + int ipg = 0, oln = 0, old = 0; + struct qos_params params; + + //check if teh argument set is null? + if(args == NULL) + { + return -EINVAL; + } + + //copy the parameters from the user space. The name has to be copied seperatly + if(copy_from_user(¶ms, args, sizeof(struct qos_params))) + return -EFAULT; + + if(copy_from_user(params.dev, args->dev, sizeof(char) * IFNAMSIZ)) + { + return -EFAULT; + } + + //find the device + //in a future implementation it might be necessary + //to attach the qdisc to all the devices + for(; dev != NULL; dev = dev->next) + if(!strcmp(params.dev, dev->name)) + break; + + if(dev == NULL) + return -EINVAL; + + ipg = params.ipg; + oln = params.oln; + old = params.old; + + if(ipg == 0 || old == 0) + return -1; + + + read_lock(&tasklist_lock); + { + struct task_struct *ts = find_task_by_pid(pidcall() ); + struct file *fl = NULL; + + if ( ts && (fl=fcheck_files(ts->files, fd) ) ) + { + + if ( fl->f_dentry && fl->f_dentry->d_inode ) + { + i_ino = fl->f_dentry->d_inode->i_ino; + } + } + } + read_unlock(&tasklist_lock); + + if(i_ino == 0) + return -EINVAL; + + + qdisc = dev->qdisc; + if(qdisc == NULL) + return -EINVAL; + + leaf = qdisc; + + + if(strcmp("dwcs", leaf->ops->id)) + return -EINVAL; + + + sch_dwcs = (struct dwcs_sched_data*) leaf->data; + + link = sch_dwcs->link; + + for(tp = link->filter_list; tp; tp = tp->next) + { + if(tp->ops) + { + if(!strcmp("socket", tp->ops->kind)) + { + head = tp->root; + if(head) + fh = head->ht[socket_hash(0)]; + if(fh == NULL) + { + continue; + } + for(; fh; fh = fh->next) + if(fh->i_ino == i_ino) + goto out; + } + } + } + out: + if(fh == NULL) + { + return -EINVAL; + } + + //decrease ref count for the root class + if ( ( cl = ( void * ) fh->res.class ) == NULL ) + { + if ( TC_H_MAJ ( fh->res.classid ) ) + cl = dwcs_class_lookup ( sch_dwcs, fh->res.classid ); + + } + + + if(cl == NULL) + { + printk(KERN_ERR "cl == NULL\n"); + return -EINVAL; + } + + + cl->attr.ipg = ipg; + cl->attr.oln = oln; + cl->attr.old = old; + cl->attr.flags = params.flags; + cl->attr.cln = 0; /* Current loss numerator. */ + cl->attr.cld = 0; /* Current loss denominator. */ + cl->attr.droppable = params.attribute; /* TRUE if packets can be dropped */ + cl->attr.cln = cl->attr.oln; + cl->attr.cld = cl->attr.old; + cl->attr.clt = (100 * cl->attr.oln / cl->attr.old ); + return 0; +} + + +asmlinkage long sys_qsendto(int fd, void *buff, size_t len, unsigned int flags, + struct sockaddr *addr, int addr_len, + struct packet_flags *pflags, unsigned long *user_args) +{ + struct socket *sock; + char address[MAX_SOCK_ADDR]; + int err; + struct msghdr msg; + struct iovec iov; + struct sock *sk; + struct packet_flags kpflags; + + sock = sockfd_lookup(fd, &err); + if (!sock){ + goto out; + } + iov.iov_base=buff; + iov.iov_len=len; + msg.msg_name=NULL; + msg.msg_iov=&iov; + msg.msg_iovlen=1; + msg.msg_control=NULL; + msg.msg_controllen=0; + msg.msg_namelen=addr_len; + + if(addr) + { + err = move_addr_to_kernel(addr, addr_len, address); + if (err < 0) + goto out_put; + msg.msg_name=address; + } + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; + msg.msg_flags = flags; + +/*qsocket specific stuff*/ + sk = sock->sk; + + if((err = copy_from_user(&kpflags, pflags, sizeof(kpflags)))) + goto out_put; + sk->drop_flag = kpflags.drop_flag; + sk->urgent_flag = kpflags.urgent_flag; + + if(kpflags.fragments != 0) + { + //application is defining its own fragmentation behaviour + //a value of 2 means that this is the last fragment + sk->fragments = kpflags.fragments; + } + else + { + sk->fragments = 0; + } + + err = sock_sendmsg(sock, &msg, len); + +out_put: + sockfd_put(sock); +out: + return err; +} + + +asmlinkage long sys_qsend(int fd, void *buff, size_t len, unsigned int flags, + struct packet_flags *pflags, unsigned long *user_args) +{ + return sys_qsendto(fd, buff, len, flags, NULL, 0, pflags, user_args); +} + +asmlinkage long sys_qchannel(int fd, int server) +{ + struct socket *sock; + int err = 0; + + + sock = sockfd_lookup(fd, &err); + if(!sock) + { + goto out; + } + + printk("calling qos_changerole\n"); +// qos_changerole(sock, server); + + sockfd_put(sock); + out: + return err; + + + return 0; +} + + + +asmlinkage long sys_qinfo(int fd, struct qsocket_info *info) +{ + struct qsocket_info kinfo; + struct socket *sock; + struct sock* sk; + struct net_device *dev = dev_base; + struct Qdisc *qdisc = NULL, *leaf = NULL; + struct dwcs_sched_data *sch_dwcs = NULL; + struct dwcs_class *cl = NULL, *link = NULL; + struct socket_filter *fh = NULL; + struct socket_head *head = NULL; + struct tcf_proto *tp = NULL; + int i_ino = 0; + struct task_struct *ts; + int err = 0; + + //if(copy_from_user(&kinfo, info, sizeof(*info))) + //return -EFAULT; + + sock = sockfd_lookup(fd, &err); + if (!sock) + { + goto out; + } + sk = sock->sk; + + + memset(&kinfo, 0, sizeof(kinfo)); + + + kinfo.input_qlen = sk->receive_queue.qlen; + +//atomic_read(&sk->rmem_alloc); + //debug +// printk(KERN_INFO "input qlen = %ld\n", skb_queue_len(&sk->receive_queue)); + + read_lock(&tasklist_lock); + { + struct file *fl = NULL; + ts = find_task_by_pid(pidcall() ); + if ( ts && (fl=fcheck_files(ts->files, fd) ) ) + { + + if ( fl->f_dentry && fl->f_dentry->d_inode ) + { + i_ino = fl->f_dentry->d_inode->i_ino; + } + } + } + kinfo.cpu_time = (unsigned long) ts->times.tms_utime + + (unsigned long) ts->times.tms_stime + + ts->times.tms_cutime + ts->times.tms_cstime; + //debug +// printk(KERN_INFO "taks time = %ld, %ld\n", ts->times.tms_utime, ts->times.tms_stime); +// printk(KERN_INFO "cpu time = %ld, %ld\n", ts->per_cpu_stime[0], ts->per_cpu_utime[0]); + + read_unlock(&tasklist_lock); + + + for(; dev !=NULL; dev = dev->next) + { + qdisc = dev->qdisc; + if(qdisc == NULL) + continue; + + leaf = qdisc; + + + if(strcmp("dwcs", leaf->ops->id)) + continue; + + + sch_dwcs = (struct dwcs_sched_data*) leaf->data; + + link = sch_dwcs->link; + + for(tp = link->filter_list; tp; tp = tp->next) + { + if(tp->ops) + { + if(!strcmp("socket", tp->ops->kind)) + { + head = tp->root; + if(head) + fh = head->ht[socket_hash(0)]; + if(fh == NULL) + { + continue; + } + for(; fh; fh = fh->next) + if(fh->i_ino == i_ino) + goto loop_out; + } + } + } + loop_out: + if(fh == NULL) + { + // return -EINVAL; + goto out_put; + } + + //decrease ref count for the root class + if ( ( cl = ( void * ) fh->res.class ) == NULL ) + { + if ( TC_H_MAJ ( fh->res.classid ) ) + cl = dwcs_class_lookup ( sch_dwcs, fh->res.classid ); + + } + + + if(cl == NULL) + { + printk(KERN_ERR "cl == NULL\n"); + goto out_put; + } + + kinfo.output_qlen = cl->q->q.qlen; + kinfo.missed_deadlines = cl->attr.late; + kinfo.delay_jif = cl->attr.delay; + kinfo.sent_packets = cl->attr.sent; + err = 0; + goto out_put; + } + + +out_put: + sockfd_put(sock); + if(info != NULL) + { + copy_to_user(info, &kinfo, sizeof(kinfo)); + } + +out: + return err; +} + + + +asmlinkage long sys_qsocketcall(int call, unsigned long *args) +{ + unsigned long a[10]; + int err; + + if((call<1||call>SYS_QRECVMSG)) + return -EINVAL; + + switch(call) + { + case SYS_QSOCKET: + if(copy_from_user(a, args, 4*sizeof(unsigned long))) + return -EFAULT; + err = sys_qsocket(a[0],a[1],a[2], (struct qos_params*) a[3], args); + break; + case SYS_QSHUTDOWN: + if(copy_from_user(a, args, 2*sizeof(unsigned long))) + return -EFAULT; + err = sys_qshutdown(a[0],a[1], args); + break; + case SYS_QCHANGE: + if(copy_from_user(a, args, 2*sizeof(unsigned long))) + return -EFAULT; + err = sys_qchange(a[0], (struct qos_params*) a[1], args); + break; + case SYS_QSENDTO: + if(copy_from_user(a, args, 7*sizeof(unsigned long))) + return -EFAULT; + err = sys_qsendto(a[0], (void*)a[1], a[2], a[3], (struct sockaddr*)a[4], + a[5], (struct packet_flags*)a[6], args); + break; + case SYS_QSEND: + if(copy_from_user(a, args, 5*sizeof(unsigned long))) + return -EFAULT; + err = sys_qsend(a[0], (void*)a[1], a[2], a[3], + (struct packet_flags*)a[4], args); + break; + case SYS_QINFO: + if(copy_from_user(a, args, 2 * sizeof(unsigned long))) + return -EFAULT; + err = sys_qinfo(a[0], (struct qsocket_info*)a[1]); + break; + case SYS_QCHANNEL: + if(copy_from_user(a, args, 2 * sizeof(unsigned long))) + return -EFAULT; + err = sys_qchannel(a[0], a[1]); + break; + default: + err = socketcall(call, args); + break; + } + return err; +} + +#ifdef MODULE +int init_module(void) +{ + orig_qsocketcall = sys_call_table[__NR_qsocketcall]; + socketcall = sys_call_table[__NR_socketcall]; + //qos_conf = sys_call_table[__NR_qos_conf]; + pidcall = sys_call_table[__NR_getpid]; + sys_call_table[__NR_qsocketcall] = sys_qsocketcall; + + return 0; +} + +void cleanup_module(void) +{ + sys_call_table[__NR_qsocketcall] = orig_qsocketcall; +} +#endif + + +#ifdef CONFIG_X86 +void qsocket_init(void) +{ + socketcall = sys_call_table[__NR_socketcall]; + pidcall = sys_call_table[__NR_getpid]; + sched_setscheduler = sys_call_table[__NR_sched_setscheduler]; + //qos_conf = sys_call_table[__NR_qos_conf]; +} +#endif +MODULE_LICENSE("GPL"); + diff -Naur test-for-latech/net/qsocket/sch_dwcs.h testqf-for-latech/net/qsocket/sch_dwcs.h --- test-for-latech/net/qsocket/sch_dwcs.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/qsocket/sch_dwcs.h 2004-06-11 07:48:02.000000000 -0400 @@ -0,0 +1,163 @@ +/* + * net/sched/sch_dwcs.h DWCS algorithm scheduler. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Gregory Losik + * Richard West + * Christian Poellabauer + * + * Changes: J.D. Hollis + * cleaned up the formatting and added some comments + * + */ + + +#define TRUE 1 +#define FALSE 0 +#define MAX_CONNS 255 // GL: Technically it should be 2^16 but lets risk it... + +#define DWCS_VIOLATION 0x00000001 /* Window-constraint violation. */ +#define DWCS_WORK_CONS 0x00000002 /* Does task support work-conservation? */ +#define DWCS_NON_DROPPABLE 0x00000008 + + + +#include + + +/* Scheduler attributes. Not all members are necessary for all scheduling policies. */ +typedef struct dwcs_class_attr { + // int cd; /* Class descriptor. */ + // unsigned cnt; /* Number pkts queued for this class. */ + + /* JDH: w, s, and f might not be needed as we've got a DWCS qdisc now */ + double w; /* Weight. (For SFQ) */ + double s; /* Start tag. (For SFQ) */ + double f; /* Finish tag. (For SFQ) */ + + /* these are the actual, user-definable attributes */ + long deadline; + long readytime;/* ok this requires a little explanation + this is to maintain a specific throughput from the class + thus a stream with packets to send, on an idle network + won't send packets until the ready time has elasped for the + stream + */ + + unsigned long ipg; /* Inter-packet/msg gap. */ + unsigned oln; /* Original loss numerator. */ + unsigned old; /* Original loss denominator. */ + + /* statistics */ + unsigned cln; /* Current loss numerator. */ + unsigned cld; /* Current loss denominator. */ + long clt; /* Current loss tolerance. - not a float anymore + * it indicates the percentage of loss tolerance instead of a fraction. + *essentially multiplied by a 100 */ + unsigned late; /* Stats - number late pkts. */ + unsigned sent; /* Stats - number pkts sent. */ + unsigned violations; /* Stats - number loss tolerance violations. */ + unsigned long delay; /* Cumulative delay for this class. */ + int t; /* Simulated time to process pkt. */ + unsigned window; /* Packet window size. */ + unsigned wlate; /* Count of late pkts in a time window. */ + unsigned long bytes; /* Total bytes serviced for this class. */ + // long start_time; /* Real-time this class started. */ + + /* GL: since there is no per packet flag, it needs to be per stream... */ + int droppable; /* TRUE if packets may be dropped. */ + unsigned int flags; /* Flags as specified by user */ +} dwcs_class_attr_t; + + +/* Deadline heap attributes. */ +struct dl_heap { + long deadline; /* Packet deadline. */ + // int stream; /* Stream number. */ + u32 stream; /* Stream number. */ +}; + +struct sl_heap +{ + long readytime; + u32 stream; +}; + + +/* Loss tolerance heap attributes. */ +struct lt_heap { + int stream; /* Stream number. */ + long deadline; /* Packet deadline. */ + int cln; /* Current loss numerator. */ + int cld; /* Current loss denominator. */ + int oln; /* Original loss numerator. */ + int wlate; /* Late packets in window. */ + unsigned long arr_time; /* Packet arrival time. */ + long clt; /* Current loss tolerance. */ +}; + +struct dwcs_sched_data; + +struct dwcs_class +{ + struct dwcs_class *next; /* hash table link */ + struct dwcs_class *next_alive; /* next class with backlog in this priority band */ + + /* Parameters */ + u32 classid; /* the major:minor class id */ + unsigned char priority; /* class priority */ + unsigned int *socket_num; /* to be a socket number.... */ +#ifdef CONFIG_NET_CLS_POLICE + unsigned char police; +#endif + struct Qdisc *qdisc; /* Ptr to DWCS discipline that class belongs to */ + struct Qdisc *q; /* Elementary queueing discipline */ + + /* Variables */ + struct tcf_proto *filter_list; + int refcnt; /* used by _get() and _put() reference tracking */ + int filters; /* for keeping track the number of filters */ + struct tc_stats stats; /* ??? used by _NET_ESTIMATOR */ + + /* DWCS specific parameters */ + struct dwcs_class_attr attr; /* Low level attributes of a class */ +}; + + + + +struct dwcs_sched_data +{ + struct dwcs_class *classes[ 16 ]; /* Hash table of all classes. This is where all new calsses get inserted in */ + struct dwcs_class *link; /* Default class for case when filters don't match */ + unsigned classcount; /* the counder for total # of classes; q->classes[i] has the actual list */ + + + /* DWCS specific attributes */ + struct dwcs_class *next_class; /* next class from which we will try to dequeue (to be deleted) */ + + struct lt_heap ltheap[MAX_CONNS]; /* Loss-Tolerance Heap */ + int ltheap_size; + struct dl_heap dlheap[MAX_CONNS]; /* Deadline Heap */ + int dlheap_size; + struct sl_heap slheap[MAX_CONNS]; + int slheap_size; + struct timer_list wd_timer; /* Watchdog timer */ + + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif + +#ifdef CONFIG_NET_CLS_POLICE + struct dwcs_class *rx_class; +#endif + +}; + + + diff -Naur test-for-latech/net/qsocket/utils.h testqf-for-latech/net/qsocket/utils.h --- test-for-latech/net/qsocket/utils.h 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/qsocket/utils.h 2004-06-11 07:48:02.000000000 -0400 @@ -0,0 +1,69 @@ +static __inline__ int socket_hash(u32 handle) +{ + return handle&0xFF; +} + + +static __inline__ struct socket *socki_lookup(struct inode *inode) +{ + return &inode->u.socket_i; +} + +/** + * sockfd_lookup - Go from a file number to its socket slot + * @fd: file handle + * @err: pointer to an error code return + * + * The file handle passed in is locked and the socket it is bound + * too is returned. If an error occurs the err pointer is overwritten + * with a negative errno code and NULL is returned. The function checks + * for both invalid handles and passing a handle which is not a socket. + * + * On a success the socket object pointer is returned. + */ + +static struct socket *sockfd_lookup(int fd, int *err) +{ + struct file *file; + struct inode *inode; + struct socket *sock; + + if (!(file = fget(fd))) + { + *err = -EBADF; + return NULL; + } + + inode = file->f_dentry->d_inode; + if (!inode->i_sock || !(sock = socki_lookup(inode))) + { + *err = -ENOTSOCK; + fput(file); + return NULL; + } + + if (sock->file != file) { + printk(KERN_ERR "socki_lookup: socket file changed!\n"); + sock->file = file; + } + return sock; +} + +static __inline__ void sockfd_put(struct socket *sock) +{ + fput(sock->file); +} + + +static __inline__ unsigned dwcs_hash(u32 h) +{ + h ^= h>>8; + h ^= h>>4; + return h&0xF; +} + +static inline int create_socket(unsigned long *args) +{ + return socketcall(SYS_SOCKET, args); +} + diff -Naur test-for-latech/net/sched/cls_api.c testqf-for-latech/net/sched/cls_api.c --- test-for-latech/net/sched/cls_api.c 2004-06-11 07:40:56.000000000 -0400 +++ testqf-for-latech/net/sched/cls_api.c 2004-06-11 07:48:00.000000000 -0400 @@ -42,6 +42,21 @@ /* Protects list of registered TC modules. It is pure SMP lock. */ static rwlock_t cls_mod_lock = RW_LOCK_UNLOCKED; +struct tcf_proto_ops * tcf_proto_lookup_ops_string(const char *kind) +{ + struct tcf_proto_ops *t = NULL; + + if (kind) { + read_lock(&cls_mod_lock); + for (t = tcf_proto_base; t; t = t->next) { + if (strcmp(kind, t->kind) == 0) + break; + } + read_unlock(&cls_mod_lock); + } + return t; +} + /* Find classifier type by string name */ struct tcf_proto_ops * tcf_proto_lookup_ops(struct rtattr *kind) @@ -448,6 +463,10 @@ register_tcf_proto_ops(&cls_##name##_ops); \ } +#ifdef CONFIG_NET_CLS_SOCKET + INIT_TC_FILTER(socket); +#endif + #ifdef CONFIG_NET_CLS_U32 INIT_TC_FILTER(u32); #endif diff -Naur test-for-latech/net/sched/cls_socket.c testqf-for-latech/net/sched/cls_socket.c --- test-for-latech/net/sched/cls_socket.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/sched/cls_socket.c 2004-06-11 07:48:00.000000000 -0400 @@ -0,0 +1,544 @@ +/* + * net/sched/cls_socket.c Classifier mapping of open sockets to traffic class. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Gregory Losik, + * This clasifier is similar to other provided classifiers, but + * is implemented for the different use purposes. One can + * use it to classify packets based on the packets associated + * PID and FD, or simply by provided INODE number. + * + * Changes: + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for inode struct */ +#include /* for socket struct */ +#include /* for fcheck_task() */ +#include + +/* +struct socket_head +{ + struct socket_filter *ht[256]; +}; + + +struct socket_filter +{ + struct socket_filter *next; + u32 id; + u32 pid; + unsigned long fd; + unsigned long i_ino; + struct tcf_result res; +#ifdef CONFIG_NET_CLS_POLICE + struct tcf_police *police; +#endif +}; +*/ + +/* + * The hash table for storing socket_filter structures in socket_head->ht + */ +static __inline__ int socket_hash(u32 handle) +{ + return handle&0xFF; +} + + + +/* + * Used to match a packet to a class based on certain properties of + * the packet. Socket filter determines the inode from which the + * packet was sent, and then compares this inode number to filter's + * inode # that it monitors for. + */ +static int socket_classify(struct sk_buff *skb, struct tcf_proto *tp, + struct tcf_result *res) +{ + struct socket_head *head = (struct socket_head*)tp->root; + struct socket_filter *f = NULL; + unsigned long i_ino = 0; +#ifdef CONFIG_IP_FIREWALL + u32 id = skb->fwmark; +#else + u32 id = 0; +#endif + + { + /* we try to get the inode, given the pointer to sk_buff */ + struct sock *sk = NULL; + struct socket *sket = NULL; + struct inode *node = NULL; + + if (skb && (sk=skb->sk) && (sket=sk->socket) && (node=sket->inode) && node ) + i_ino = node->i_ino; + } + + /* tying to access socket_filter structure(s) of a current filter, and + * determine if it matches inode number */ + if (head == NULL) + goto old_method; + + + + + for (f=head->ht[socket_hash(id)]; f; f=f->next) { + if (f->i_ino == i_ino) { + *res = f->res; +#ifdef CONFIG_NET_CLS_POLICE + if (f->police) + return tcf_police(skb, f->police); +#endif +// printk(KERN_INFO __FUNCTION__ "classified successfully to classid = %d\n", res->classid); + + return 0; + } + } + return -1; + +old_method: + /* + if (id && (TC_H_MAJ(id) == 0 || + !(TC_H_MAJ(id^tp->q->handle)))) { + res->classid = id; + res->class = 0; + return 0; + } + */ + return -1; +} + + + + +/* + * Returns the internal ID corresponding to the handle. The internal + * id is the address of the socket_filter structure. + */ +static unsigned long socket_get(struct tcf_proto *tp, u32 handle) +{ + struct socket_head *head = (struct socket_head*)tp->root; + struct socket_filter *f; + + if (head == NULL) { + return 0; + } + + for (f=head->ht[socket_hash(handle)]; f; f=f->next) { + if (f->id == handle) { + return (unsigned long)f; + } + } + + return 0; +} + + +/* + * The put function on a filter is used to de-reference a filter that was + * previouslly referenced using the get function. In our case, we don't + * keep track of references and therefore can ignore this function. + */ +static void socket_put(struct tcf_proto *tp, unsigned long f) +{ +} + + +/* + * The init function on a filter is used to initialize the parameters for + * a filter. + */ +static int socket_init(struct tcf_proto *tp) +{ + MOD_INC_USE_COUNT; + return 0; +} + + +/* + * The destory function on a filter is used to remove a filter. We + * find the filter structure and then if the filter was bounded to + * a class, we unbind it, so that class knows about it. Finally we + * free the memory allocated by the filter stucture. + */ +static void socket_destroy(struct tcf_proto *tp) +{ + struct socket_head *head = (struct socket_head*)xchg(&tp->root, NULL); + struct socket_filter *f; + int h; + + if (head == NULL) { + MOD_DEC_USE_COUNT; + return; + } + + for (h=0; h<256; h++) { + while ((f=head->ht[h]) != NULL) { + unsigned long cl; + head->ht[h] = f->next; + + if ((cl = __cls_set_class(&f->res.class, 0)) != 0) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); +#ifdef CONFIG_NET_CLS_POLICE + tcf_police_release(f->police); +#endif + kfree(f); + } + } + kfree(head); + MOD_DEC_USE_COUNT; +} + + + +/* + * The delete function on a filter is used to delete a particular element of the + * filter. Similar to destroy() we call unbind on a class. + */ +static int socket_delete(struct tcf_proto *tp, unsigned long arg) +{ + struct socket_head *head = (struct socket_head*)tp->root; + struct socket_filter *f = (struct socket_filter*)arg; + struct socket_filter **fp; + + if (head == NULL || f == NULL) + return -EINVAL; + + for (fp=&head->ht[socket_hash(f->id)]; *fp; fp = &(*fp)->next) { + if (*fp == f) { + unsigned long cl; + + *fp = f->next; + //synchronize_bh(); + + if ((cl = __cls_set_class(&f->res.class, 0)) != 0) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); +#ifdef CONFIG_NET_CLS_POLICE + tcf_police_release(f->police); +#endif + kfree(f); + return 0; + } + } + return -EINVAL; +} + + + + +/* + * The change function on a filter is used to change the properties + * of a filter. This is similar to the change function on classes and + * queuing disciplines. + */ +static int socket_change(struct tcf_proto *tp, unsigned long base, + u32 handle, + struct rtattr **tca, + unsigned long *arg) +{ + struct socket_head *head = (struct socket_head*)tp->root; + struct socket_filter *f; + struct rtattr *opt = tca[TCA_OPTIONS-1]; + struct rtattr *tb[TCA_SOCKET_MAX]; + int err; + + if (!opt) + return handle ? -EINVAL : 0; + + if (rtattr_parse(tb, TCA_SOCKET_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0) + return -EINVAL; + + + if ((f = (struct socket_filter*)*arg) != NULL) { + /* Node exists: adjust only classid */ + + if (f->id != handle && handle) + return -EINVAL; + if (tb[TCA_SOCKET_CLASSID-1]) { + unsigned long cl; + + f->res.classid = *(u32*)RTA_DATA(tb[TCA_SOCKET_CLASSID-1]); + cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid); + cl = __cls_set_class(&f->res.class, cl); + if (cl) + tp->q->ops->cl_ops->unbind_tcf(tp->q, cl); + } + + if (tb[TCA_SOCKET_PROCESSID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_PROCESSID-1]) != 4) + goto errout; + f->pid = *(u32*)RTA_DATA(tb[TCA_SOCKET_PROCESSID-1]); + } + + if (tb[TCA_SOCKET_FDID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_FDID-1]) != 4) + goto errout; + f->fd = *(u32*)RTA_DATA(tb[TCA_SOCKET_FDID-1]); + } + + if (tb[TCA_SOCKET_INODEID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_INODEID-1]) != 4) + goto errout; + f->i_ino = *(unsigned long*)RTA_DATA(tb[TCA_SOCKET_INODEID-1]); + } + + +#ifdef CONFIG_NET_CLS_POLICE + if (tb[TCA_SOCKET_POLICE-1]) { + struct tcf_police *police = tcf_police_locate(tb[TCA_SOCKET_POLICE-1], tca[TCA_RATE-1]); + + police = xchg(&f->police, police); + //synchronize_bh(); + + tcf_police_release(police); + } +#endif + return 0; + } + + + if (!handle) + return -EINVAL; + + if (head == NULL) { + head = kmalloc(sizeof(struct socket_head), GFP_KERNEL); + if (head == NULL) + return -ENOBUFS; + memset(head, 0, sizeof(*head)); + + tp->root = head; + //synchronize_bh(); + } + + f = kmalloc(sizeof(struct socket_filter), GFP_KERNEL); + if (f == NULL) + return -ENOBUFS; + memset(f, 0, sizeof(*f)); + + f->id = handle; + + if (tb[TCA_SOCKET_CLASSID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_CLASSID-1]) != 4) + goto errout; + f->res.classid = *(u32*)RTA_DATA(tb[TCA_SOCKET_CLASSID-1]); + __cls_set_class(&f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid)); + } + + if (tb[TCA_SOCKET_PROCESSID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_PROCESSID-1]) != 4) + goto errout; + f->pid = *(u32*)RTA_DATA(tb[TCA_SOCKET_PROCESSID-1]); + } + + if (tb[TCA_SOCKET_FDID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_FDID-1]) != 4) + goto errout; + f->fd = *(u32*)RTA_DATA(tb[TCA_SOCKET_FDID-1]); + } + + if (tb[TCA_SOCKET_INODEID-1]) { + err = -EINVAL; + if (RTA_PAYLOAD(tb[TCA_SOCKET_INODEID-1]) != 4) + goto errout; + f->i_ino = *(unsigned long*)RTA_DATA(tb[TCA_SOCKET_INODEID-1]); + } + +#ifdef CONFIG_NET_CLS_POLICE + if (tb[TCA_SOCKET_POLICE-1]) + f->police = tcf_police_locate(tb[TCA_SOCKET_POLICE-1], tca[TCA_RATE-1]); +#endif + + + /* Determine inode by having pid and fd */ + + read_lock(&tasklist_lock); + if( !f->i_ino && f->pid ) { + struct task_struct *ts = find_task_by_pid( f->pid ); + struct file *fl = NULL; + + if ( ts && (fl=fcheck_files(ts->files,f->fd) ) ) { + if ( fl->f_dentry && fl->f_dentry->d_inode ) { + f->i_ino = fl->f_dentry->d_inode->i_ino; + } + } + } + read_unlock(&tasklist_lock); + + f->next = head->ht[socket_hash(handle)]; + wmb(); + head->ht[socket_hash(handle)] = f; + + *arg = (unsigned long)f; + return 0; + +errout: + if (f) + kfree(f); + return err; +} + + + +/* + * The walk function on a filter is used to iterate over all the elments of a + * filter and invoke a callback function for each of the elements. This is + * usually used to obtain diagnostic data for all the elements of a filter. + */ +static void socket_walk(struct tcf_proto *tp, struct tcf_walker *arg) +{ + struct socket_head *head = (struct socket_head*)tp->root; + int h; + + if (head == NULL) + arg->stop = 1; + + if (arg->stop) + return; + + for (h = 0; h < 256; h++) { + struct socket_filter *f; + + for (f = head->ht[h]; f; f = f->next) { + if (arg->count < arg->skip) { + arg->count++; + continue; + } + if (arg->fn(tp, (unsigned long)f, arg) < 0) { + arg->stop = 1; + break; + } + arg->count++; + } + } +} + + + +/* + * The dump function on a class is used to dump diagnostic data about + * the filter and one or more of its elements. + */ +#ifdef CONFIG_RTNETLINK +static int socket_dump(struct tcf_proto *tp, unsigned long fh, + struct sk_buff *skb, struct tcmsg *t) +{ + struct socket_filter *f = (struct socket_filter*)fh; + unsigned char *b = skb->tail; + struct rtattr *rta; + + + if (f == NULL) + return skb->len; + + + t->tcm_handle = f->id; + + if (!f->res.classid +#ifdef CONFIG_NET_CLS_POLICE + && !f->police +#endif + ) + return skb->len; + + rta = (struct rtattr*)b; + RTA_PUT(skb, TCA_OPTIONS, 0, NULL); + + if (f->res.classid) + RTA_PUT(skb, TCA_SOCKET_CLASSID, 4, &f->res.classid); +#ifdef CONFIG_NET_CLS_POLICE + if (f->police) { + struct rtattr * p_rta = (struct rtattr*)skb->tail; + + RTA_PUT(skb, TCA_SOCKET_POLICE, 0, NULL); + + if (tcf_police_dump(skb, f->police) < 0) + goto rtattr_failure; + + p_rta->rta_len = skb->tail - (u8*)p_rta; + } +#endif + + rta->rta_len = skb->tail - b; +#ifdef CONFIG_NET_CLS_POLICE + if (f->police) { + RTA_PUT(skb, TCA_STATS, sizeof(struct tc_stats), &f->police->stats); + } +#endif + return skb->len; + +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} +#endif + + + +struct tcf_proto_ops cls_socket_ops = { + NULL, + "socket", + socket_classify, + socket_init, + socket_destroy, + + socket_get, + socket_put, + socket_change, + socket_delete, + socket_walk, +#ifdef CONFIG_RTNETLINK + socket_dump +#else + NULL +#endif +}; + +#ifdef MODULE +int init_module(void) +{ + return register_tcf_proto_ops(&cls_socket_ops); +} + +void cleanup_module(void) +{ + unregister_tcf_proto_ops(&cls_socket_ops); +} +#endif diff -Naur test-for-latech/net/sched/Config.in testqf-for-latech/net/sched/Config.in --- test-for-latech/net/sched/Config.in 2004-06-11 07:40:56.000000000 -0400 +++ testqf-for-latech/net/sched/Config.in 2004-06-11 07:48:00.000000000 -0400 @@ -1,6 +1,7 @@ # # Traffic control configuration. -# +# +tristate ' DWCS packet scheduler' CONFIG_NET_SCH_DWCS tristate ' CBQ packet scheduler' CONFIG_NET_SCH_CBQ tristate ' CSZ packet scheduler' CONFIG_NET_SCH_CSZ #tristate ' H-PFQ packet scheduler' CONFIG_NET_SCH_HPFQ @@ -24,6 +25,7 @@ fi bool ' Packet classifier API' CONFIG_NET_CLS if [ "$CONFIG_NET_CLS" = "y" ]; then + bool ' Socket classifier' CONFIG_NET_CLS_SOCKET tristate ' TC index classifier' CONFIG_NET_CLS_TCINDEX tristate ' Routing table based classifier' CONFIG_NET_CLS_ROUTE4 if [ "$CONFIG_NET_CLS_ROUTE4" != "n" ]; then diff -Naur test-for-latech/net/sched/heap.c testqf-for-latech/net/sched/heap.c --- test-for-latech/net/sched/heap.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/sched/heap.c 2004-06-11 07:48:00.000000000 -0400 @@ -0,0 +1,286 @@ +/*********************************************/ +/* Project: Packet Scheduler */ +/* File: heap.c */ +/* Date: 10/17/1998 */ +/* Author: cp (chris@cc.gatech.edu) */ +/* Contents: heap functions */ + +/* Changes: + * J.D. Hollis, + * updated HCompare() to newest version of DWCS + * algorithm + */ + +#include + +#define FLOOR(x) (int)(x) + +/* Return parent element of i in heap array. */ +int HParent(int i) { + + return (FLOOR(i/2)); +} + +/* Return left child element. */ +int HLeft(int i) { + + return (2*i); +} + +/* Return right child element. */ +int HRight(int i) { + + return (2*i+1); +} + +/* Reorder heap. */ +void HHeapify(struct dl_heap heap[], int i, int size) { + + int l, r; + int smallest; + struct dl_heap tmp; + + l = HLeft(i); + r = HRight(i); + + if ((l <= size) && (heap[l-1].deadline < heap[i-1].deadline)) + smallest = l; + else + smallest = i; + + if ((r <= size) && (heap[r-1].deadline < heap[smallest-1].deadline)) + smallest = r; + + if (smallest != i) { + tmp = heap[i-1]; + heap[i-1] = heap[smallest-1]; + heap[smallest-1] = tmp; + HHeapify(heap, smallest, size); + } +} + +/* Insert element into heap. */ +void HInsert(struct dl_heap heap[], int stream, int value, int size) { + + int i = size; + + while ((i > 1) && (heap[HParent(i)-1].deadline > value)) { + heap[i-1] = heap[HParent(i)-1]; + i = HParent(i); + } + heap[i-1].deadline = value; + heap[i-1].stream = stream; +} + +/* Remove first element and reorders heap. */ +void HExtractMin(struct dl_heap heap[], int size) { + + heap[0] = heap[size]; + heap[size].deadline = 0; + heap[size].stream = 0; + HHeapify(heap, 1, size); +} + +/* Remove element from heap. */ +void HDelete(struct dl_heap heap[], int stream, int size) { + + int i=1; + + while ((i < size+1) && (heap[i-1].stream != stream)) + i++; + if (heap[i-1].stream == stream) { + heap[i-1] = heap[size]; + heap[size].deadline = 0; + heap[size].stream = 0; + HHeapify(heap, i, size); + } +} + +/*************************************************/ +/* Heap functions for loss-tolerance sorted heap */ + +/* Compare two elements in the heap structure. */ + +/* JDH: ok, cleaned up this function so that's it a little more readable + * and updated the ordering to fit the new DWCS algorithm: + * - earliest deadline first + * - equal deadlines, order lowest window-constraint first + * - equal deadlines and zero window-constraints, order highest window- + * denominator first + * - equal deadlines and equal non-zero window-constraints, order lowest + * window numerator first + * - all other cases: first-come-first-serve + */ +int HCompare(struct lt_heap heap1, struct lt_heap heap2) { + + if (heap1.deadline > heap2.deadline) + return TRUE; + else if (heap1.deadline == heap2.deadline) { + if (heap1.clt > heap2.clt) + return TRUE; + else if (heap1.clt == heap2.clt) { + if (heap2.clt == 0.0) { + if (heap1.cld < heap2.cld) + return TRUE; + } else if (heap2.clt > 0.0) { + if (heap1.cln > heap2.cln) + return TRUE; + } + } + } else if ((heap2.clt == heap1.clt) && + (heap2.cld == heap1.cld) && + (heap2.cln == heap1.cln) && + (heap2.deadline == heap1.deadline)) { + if ((heap2.oln - heap2.wlate) < (heap1.oln - heap1.wlate)) + return TRUE; + else if ((heap2.oln - heap2.wlate) == (heap1.oln - heap1.wlate) && + (heap2.arr_time < heap1.arr_time)) + return TRUE; + } + + return FALSE; + +} + + +/* Reorder heap. */ +void HHeapify2(struct lt_heap heap[], int i, int size) { + + int l, r; + int smallest; + struct lt_heap tmp_heap; + + l = HLeft(i); + r = HRight(i); + + if ((l <= size) && (HCompare(heap[i-1],heap[l-1]) == TRUE)) + smallest = l; + else + smallest = i; + + if ((r <= size) && (HCompare(heap[smallest-1],heap[r-1]) == TRUE)) + smallest = r; + + if (smallest != i) { + tmp_heap = heap[i-1]; + heap[i-1] = heap[smallest-1]; + heap[smallest-1] = tmp_heap; + HHeapify2(heap, smallest, size); + } +} + +/* Insert element into heap. */ +void HInsert2(struct lt_heap heap[], struct lt_heap tmp_heap, int size) { + + int i = size; + + while (i > 1) { + + if (HCompare(heap[HParent(i)-1], tmp_heap)) { + heap[i-1] = heap[HParent(i)-1]; + i = HParent(i); + } + else + break; + } + heap[i-1] = tmp_heap; +} + +/* Remove first element and reorder heap. */ +void HExtractMin2(struct lt_heap heap[], int size) { + + heap[0] = heap[size]; + heap[size].clt = 0.0; + heap[size].stream = 0; + heap[size].deadline = 0; + heap[size].cln = 0; + heap[size].cld = 0; + heap[size].oln = 0; + heap[size].arr_time = 0; + heap[size].wlate = 0; + HHeapify2(heap, 1, size); +} + +/* Remove element from heap. */ +void HDelete2(struct lt_heap heap[], int stream, int size) { + + int i=1; + + while ((i < size+1) && (heap[i-1].stream != stream)) + i++; + if (heap[i-1].stream == stream) { + heap[i-1] = heap[size]; + heap[size].clt = 0.0; + heap[size].stream = 0; + heap[size].deadline = 0; + heap[size].cln = 0; + heap[size].cld = 0; + heap[size].oln = 0; + heap[size].arr_time = 0; + heap[size].wlate = 0; + HHeapify2(heap, i, size); + } +} + +/* Reorder heap. */ +void HHeapify3(struct sl_heap heap[], int i, int size) { + + int l, r; + int smallest; + struct sl_heap tmp; + + l = HLeft(i); + r = HRight(i); + + if ((l <= size) && (heap[l-1].readytime < heap[i-1].readytime)) + smallest = l; + else + smallest = i; + + if ((r <= size) && (heap[r-1].readytime < heap[smallest-1].readytime)) + smallest = r; + + if (smallest != i) { + tmp = heap[i-1]; + heap[i-1] = heap[smallest-1]; + heap[smallest-1] = tmp; + HHeapify3(heap, smallest, size); + } +} + +/* Insert element into heap. */ +void HInsert3(struct sl_heap heap[], int stream, int value, int size) { + + int i = size; + + while ((i > 1) && (heap[HParent(i)-1].readytime > value)) { + heap[i-1] = heap[HParent(i)-1]; + i = HParent(i); + } + heap[i-1].readytime = value; + heap[i-1].stream = stream; +} + +/* Remove first element and reorders heap. */ +void HExtractMin3(struct sl_heap heap[], int size) { + + heap[0] = heap[size]; + heap[size].readytime = 0; + heap[size].stream = 0; + HHeapify3(heap, 1, size); +} + +/* Remove element from heap. */ +void HDelete3(struct sl_heap heap[], int stream, int size) { + + int i=1; + + while ((i < size+1) && (heap[i-1].stream != stream)) + i++; + if (heap[i-1].stream == stream) { + heap[i-1] = heap[size]; + heap[size].readytime = 0; + heap[size].stream = 0; + HHeapify3(heap, i, size); + } +} diff -Naur test-for-latech/net/sched/Makefile testqf-for-latech/net/sched/Makefile --- test-for-latech/net/sched/Makefile 2004-06-11 07:40:56.000000000 -0400 +++ testqf-for-latech/net/sched/Makefile 2004-06-11 07:48:00.000000000 -0400 @@ -30,5 +30,7 @@ obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o obj-$(CONFIG_NET_CLS_FW) += cls_fw.o +obj-$(CONFIG_NET_CLS_SOCKET) += cls_socket.o +obj-$(CONFIG_NET_SCH_DWCS) += sch_dwcs.o include $(TOPDIR)/Rules.make diff -Naur test-for-latech/net/sched/sch_api.c testqf-for-latech/net/sched/sch_api.c --- test-for-latech/net/sched/sch_api.c 2004-06-11 07:40:56.000000000 -0400 +++ testqf-for-latech/net/sched/sch_api.c 2004-06-11 07:48:00.000000000 -0400 @@ -200,6 +200,21 @@ return NULL; } +struct Qdisc_ops *qdisc_lookup_ops_string(char *kind) +{ + struct Qdisc_ops *q = NULL; + + if (kind) { + read_lock(&qdisc_mod_lock); + for (q = qdisc_base; q; q = q->next) { + if (strcmp(kind, q->id) == 0) + break; + } + read_unlock(&qdisc_mod_lock); + } + return q; +} + struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) { unsigned long cl; @@ -1202,6 +1217,10 @@ INIT_QDISC(pfifo); INIT_QDISC(bfifo); +#ifdef CONFIG_NET_SCH_DWCS + INIT_QDISC(dwcs); +#endif + #ifdef CONFIG_NET_SCH_CBQ INIT_QDISC(cbq); #endif diff -Naur test-for-latech/net/sched/sch_dwcs.c testqf-for-latech/net/sched/sch_dwcs.c --- test-for-latech/net/sched/sch_dwcs.c 1969-12-31 19:00:00.000000000 -0500 +++ testqf-for-latech/net/sched/sch_dwcs.c 2004-06-11 07:48:00.000000000 -0400 @@ -0,0 +1,1851 @@ + +/* + * net/sched/sch_dwcs.c DWCS algorithm scheduler. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Gregory Losik + * Christian Poellabauer + * Hasan Abbasi + * plus a bunch of other students during their + * summer projects/independent projects/etc. + * + * Known issues: 1) PROC_MONITORING is not inserting new object under /proc FS. + * 2) Assumes there are no more then MAX_CONNS classes. heap.c needs + * to be changed to allow greater number. Max can be 2^16. + * 3) The functionality of enabling packet dropping was not tested. + * + * Modification: (Hasan Abbasi + * 1) Fixed bug in dwcs_delete. The root class of the discipline + * could be deleted which caused a seg-fault in the kernel + * 2) Modified the dump function to return proper values instead of + * limit. + * 3) Added dump_class to display class information. (Same as dump). + * 4) Modified the scheduler to wake up the device at the minimum ready time + * this required adding two function to the sch_api.c file. + * However the functions have been kept very generic and can be used by all qdiscs + * 5) Add Best effor queuing to the default class. If the deadline of the the stream + * is -1, insert it into the default class (same with non classified packets). + * Modify the default class to exhibit queue like behaviour. Not so hard to do actually. + * 7) Modified the enqueue functions to handle slow streams. Normally the deadline for an empty queue was modified + * in such a way that a slow stream was not actually deadline constrained at the kernel level. This has been fixed + * + * 8) Added support for sending fragmented data at the scheduler level. This is tricky and relies on the usage of qsockets. + * When multiple fragments are to be sent with the same deadline we don't want to update teh deadline until the last + * fragment for a data packet has been sent. + * + * 9) FIXME: Add a new structure to support setting up qdics without using rtattrs. This will make life soo much simpler when + * we generalize qsockets. + * + */ + +#define GREGORY /* debugging message to get generall list of data */ +#define GREGORY_DETAILS /* low leve debuggin message */ +#define GREGORY_TRACE /* tells the association between sk_buff and classes */ + + +#define OVRHD 0 // GL: Not sure what it is... ???? +#define DROP_ON 1 // GL: Not sure what it is... ???? lets remove it. +#define PROC_MONITORING // GL: Define this to have /proc/ entry for status monitoring. + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +#include +#include + + +#include "heap.c" + +extern void * sys_call_table[]; + +int (*pidcall)(void); + + + +#ifdef PROC_MONITORING +int proc_read_dwcs ( char *, + char **, + off_t, + int, + int *, + void * ); + +// struct proc_dir_entry proc_dwcs; +#endif + +static __inline__ struct dwcs_class *dwcs_class_lookup ( struct + dwcs_sched_data *, + u32 ); +static void dwcs_destroy_class ( struct dwcs_class * ); +static void dwcs_link_class ( struct dwcs_class * ); +static void dwcs_destroy_filters ( struct dwcs_class * ); + + +static inline unsigned long tvtojiffies(struct timeval *value) +{ + unsigned long sec = (unsigned) value->tv_sec; + unsigned long usec = (unsigned) value->tv_usec; + + if (sec > (ULONG_MAX / HZ)) + return ULONG_MAX; + usec += 1000000 / HZ - 1; + usec /= 1000000 / HZ; + return HZ*sec+usec; +} + + +/* +** the hash function for indexing dwcs_sched_data->classes[] array. It +** _must_ return a value in [0,16] range. +*/ +static __inline__ unsigned +dwcs_hash ( u32 h ) +{ + h ^= h >> 8; + h ^= h >> 4; + return h & 0xF; +} + +void watchdog(unsigned long arg) +{ + struct net_device *dev = (struct net_device *) arg; + if (dev) + { + netif_schedule(dev); + } +} + +void dwcs_init_timer(struct timer_list *wd_timer, struct net_device *dev) +{ + init_timer(wd_timer); + wd_timer->function = watchdog; + wd_timer->data = (unsigned long) dev; +} + +/* + * The drop function is used to drop a packet from the + * queue. + */ +static int +dwcs_drop ( struct Qdisc *sch ) +{ + struct sk_buff *skb; + + skb = __skb_dequeue_tail ( &sch->q ); + if ( skb ) + { + sch->stats.backlog -= skb->len; + printk(KERN_ERR "dropping packet\n"); + kfree_skb ( skb ); + return 1; + } + return 0; + +} + + +/* + * The reset function of a queuing discipline is used to reset the + * queuing discipline to its innitial state. It clears all queuing + * disciplines, timers are stopped, etc. + */ +static void +dwcs_reset ( struct Qdisc *sch ) +{ + skb_queue_purge ( &sch->q ); + sch->stats.backlog = 0; +} + + +/* + * No documentation on ..._reclassify() was found, but it relates + * to "policer" + */ +static struct dwcs_class * +dwcs_reclassify ( struct sk_buff *skb, + struct dwcs_class *this ) +{ + return NULL; +} + + + +/* + * A helper function that tries to return the address of a + * class to which "skb" should belong. Returns NULL + * if can not be determined, and then packet usually gets + * dropped, or assigned to some "default" class. + */ +static struct dwcs_class * +dwcs_classify ( struct sk_buff *skb, + struct Qdisc *sch ) +{ + + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *head = q->link; + struct dwcs_class *cl = NULL; + struct tcf_result res; + int result = 0; + + /* + * tc_classify() calls each filter in a list, in order of priority and protocol id, + * * and returns the result in 'res' structure + */ + if ( !head->filter_list + || ( result = tc_classify ( skb, head->filter_list, &res ) ) < 0 ) + goto fallback; + + if ( ( cl = ( void * ) res.class ) == NULL ) + { + if ( TC_H_MAJ ( res.classid ) ) + cl = dwcs_class_lookup ( q, res.classid ); + + if ( cl == NULL ) + goto fallback; + + } + + return cl; + + fallback: + return head; +} + + +/* + * The enqueue function enqueues a packet with the queueing discipline. + * In our case, we basically first call classifier function, which in + * turn does most of the work and returns the pointer of a class + * on which packet should be enqueued. + */ +static int +dwcs_enqueue ( struct sk_buff *skb, + struct Qdisc *sch ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl; + struct sock *sk = NULL; + int ret = NET_XMIT_POLICED; + + cl = dwcs_classify ( skb, sch ); + +#ifdef CONFIG_NET_CLS_POLICE + q->rx_class = cl; +#endif + + if ( cl ) + { +#ifdef CONFIG_NET_CLS_POLICE + cl->q->__parent = sch; +#endif + if(skb) + { + sk = skb->sk; + skb->urgent_flag = jiffies; + if(sk) + { + skb->drop_flag = sk->drop_flag; + + if(sk->fragments == 0) + { + //initial fragment + skb->fragments = 0; + sk->fragments = 1; + } + else if(sk->fragments == 1) + { + skb->fragments = 1; + } + else + skb->fragments = 0; + } + + } + + if(cl == q->link) + { + /*link class - this is the best effort class - the packet didn't ge + *classified + */ + if((ret = cl->q->enqueue (skb, cl->q)) == 0) + { + /*queue the packet into the default class*/ + + sch->q.qlen ++; + sch->stats.packets++; + sch->stats.bytes += skb->len; + + /*we donot put the class into any of the heaps*/ + mod_timer ( &q->wd_timer, jiffies ); + + return 0; + + } + else + { + sch->stats.drops++; + + kfree_skb ( skb ); + if(cl != NULL); + { + cl->stats.drops++; + } + return ret; + + } + + } + else + { + + if ((ret = cl->q->enqueue ( skb, cl->q )) == 0) + { + + sch->q.qlen++; + sch->stats.packets++; + sch->stats.bytes += skb->len; + + /* + * DWCS specific initialization + */ + if ( cl->q->q.qlen == 1 ) + { // is it a head packet? + struct lt_heap tmp_heap; + + if(cl->attr.deadline == -1) + { + cl->attr.deadline = jiffies + cl->attr.ipg; // GL: init deadline attribute + } + + if(cl->attr.readytime == -1) + { + cl->attr.readytime = jiffies; + } + + while(cl->attr.deadline < jiffies) + { + cl->attr.late++; + cl->attr.wlate++; + if ( cl->attr.sent + cl->attr.late == cl->attr.window ) + { + cl->attr.window += cl->attr.old; + if ( cl->attr.wlate > cl->attr.oln ) + { + cl->attr.violations++; + } + cl->attr.wlate = 0; + } + cl->attr.deadline += ( cl->attr.ipg + OVRHD ); + cl->attr.readytime += (cl->attr.ipg + OVRHD ); + if ( cl->attr.cln > 0 ) + { + cl->attr.cln--; + cl->attr.cld--; + if ( ( cl->attr.cld == 0 ) + && ( cl->attr.cln == 0 ) ) + { + cl->attr.cln = cl->attr.oln; + cl->attr.cld = cl->attr.old; + } + } + else + { + if ( cl->attr.oln == 0 ) + cl->attr.cld += cl->attr.old; + else + { + cl->attr.cln = 2 * ( cl->attr.oln ) - 1; + cl->attr.cld = + 2 * ( cl->attr.old ) + ( cl->attr.cld - + 1 ); + } + } + cl->attr.clt = + ( cl->attr.cld == 0) ? 0.0 : ( float ) cl->attr.cln / cl->attr.cld; + + } + + + if ( cl->attr.flags != DWCS_WORK_CONS ) + { + /* + * Insert head packet into deadline heap if deadline constrained + */ + q->slheap_size++; + HInsert3 ( q->slheap, cl->classid, + cl->attr.readytime, + q->slheap_size ); + + } + else + { + q->dlheap_size++; + HInsert ( q->dlheap, cl->classid, + cl->attr.deadline, + q->dlheap_size ); + + /* + * Insert head packet into loss-tolerance heap. + */ + tmp_heap.clt = cl->attr.clt; + tmp_heap.stream = cl->classid; + tmp_heap.deadline = cl->attr.deadline; + tmp_heap.cln = cl->attr.cln; + tmp_heap.cld = cl->attr.cld; + tmp_heap.oln = cl->attr.oln; + // tmp_heap.old = cl->attr.old; + tmp_heap.wlate = cl->attr.wlate; + + /* + * this one is tvtojiffies() from kernel/itimer.c + */ + tmp_heap.arr_time = tvtojiffies(&(skb->stamp)); + + q->ltheap_size++; + HInsert2 ( q->ltheap, tmp_heap, + q->ltheap_size ); + } + } + +/*MHA: If there are any packets in the sleep heap + * set the timer to go off at the minimum ready time + * this gurantees that the packet will be sent + * after ready time but before deadline + * even on a non busy link + */ + + if ( q->slheap_size > 0) + mod_timer ( &q->wd_timer, q->slheap[0].readytime ); + + return 0; + } + else + { + sch->stats.drops++; + if(cl == NULL) + kfree_skb ( skb ); + if(cl != NULL); + { + cl->stats.drops++; + } + + return ret; + } + } + + } + + /* + * The dwcs_classify() has failed to classify the packet, + * so we are dropping it. Theoretically, this should never + * happen in our case because we have default class for + * this: q->link. However if this class gets explicitly + * deleted, by the user, we need to drop the packet. + */ + sch->stats.drops++; + if(cl == NULL) + kfree_skb ( skb ); + if(cl != NULL); + { + cl->stats.drops++; + } + + return ret; +} + + + +/* + * The requeue function of a queuing discipline requeues a packet for + * transmission. After dequeueing the packet, if for some reason, the + * packet is not transmitted, the packet needs to be put back in the + * queue at the same position from where it was dequeued. + * + * (needs to be finished since it doesn't run filters/classifiers, + * but then I also never seen this function beeing called by a kernel.) + */ +static int +dwcs_requeue ( struct sk_buff *skb, + struct Qdisc *sch ) +{ + printk(KERN_ERR "in dwcs_requeue\n"); + kfree_skb(skb); + return NET_XMIT_CN; + +} + + + + +/* + * The dequeue function dequeues a packet for sending. It returns the next + * packet that needs to be sent out on the output interface. This packet + * is determined by the scheduler in the queuing discipline. + * In our case we currently have something simmmilar to round-ribin + * scheduling algorithm, but this will be replaced by DWCS. + */ +static struct sk_buff * +dwcs_dequeue ( struct Qdisc *sch ) +{ + struct sk_buff *skb = NULL; + struct sk_buff *result = NULL; + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + + struct lt_heap tmp_heap; + int flag; + int not_drop_flag = FALSE; + u32 classid = 0; + u32 min_classid_index = 0; + struct dwcs_class *cl = NULL; + struct dwcs_class *tmp_cl = NULL; + struct dwcs_class *sl_cl = NULL; + u32 qlen; + struct sl_heap temp_slheap; + + + result = NULL; + + + /* + * are there any packets to send? + */ + if ( !sch->q.qlen ) + return result; + + qlen = sch->q.qlen; + +/* MHA: Move all sleeping streams from the sleep heap + * to the deadline and lt heaps + * but only if the readytime is less then jiffies + * (ready time has elapsed) + */ + + while ( q->slheap_size > 0 && ( jiffies >= q->slheap[0].readytime ) ) + { + temp_slheap = q->slheap[0]; + sl_cl = dwcs_class_lookup ( q, q->slheap[0].stream ); + + if ( sl_cl != NULL ) + { + q->dlheap_size++; + HInsert ( q->dlheap, q->slheap[0].stream, + sl_cl->attr.deadline, q->dlheap_size ); + skb = skb_peek ( &sl_cl->q->q ); // gets the pointer to a packet at the head. + tmp_heap.clt = sl_cl->attr.clt; + tmp_heap.stream = sl_cl->classid; + tmp_heap.deadline = sl_cl->attr.deadline; + tmp_heap.cln = sl_cl->attr.cln; + tmp_heap.cld = sl_cl->attr.cld; + tmp_heap.oln = sl_cl->attr.oln; + // tmp_heap.old = tmp_cl->attr.old; + tmp_heap.wlate = sl_cl->attr.wlate; + + tmp_heap.arr_time = tvtojiffies(&(skb->stamp)); + + q->ltheap_size++; + HInsert2 ( q->ltheap, tmp_heap, q->ltheap_size ); + + q->slheap_size--; + HExtractMin3 ( q->slheap, q->slheap_size ); + } + else + { + q->slheap_size--; + HExtractMin3 ( q->slheap, q->slheap_size ); + } + } + skb = NULL; + result = NULL; + sl_cl = NULL; + +/*MHA: the flag is a bit suspect. I think its an + *artifact of some older code + */ + flag = TRUE; + while ( flag ) + { + +/*Check to see if the deadline of the heap can be met + * if the deadline cannot be met + * we can either drop the packet or perhaps still send it late + */ + + if ( ( q->dlheap_size > 0 ) && ( jiffies > q->dlheap[0].deadline ) ) + { + classid = q->dlheap[0].stream; + printk(KERN_ERR " Missed deadline - deadline = %ld jiffies = %ld\n", q->dlheap[0].deadline, jiffies); + + cl = dwcs_class_lookup ( q, classid ); + if(cl) + { + + while ( cl && ( jiffies > cl->attr.deadline ) ) + { + /*Update the deadline missed statistics - this is a bit strange and + *requires an explanation. For each ipg that jiffies is greater + *then deadline by - we need to update teh deadline missed stats + *since this is stream based + */ + cl->attr.late++; + cl->attr.wlate++; + if ( cl->attr.sent + cl->attr.late == cl->attr.window ) + { + cl->attr.window += cl->attr.old; + if ( cl->attr.wlate > cl->attr.oln ) + { + cl->attr.violations++; + } + cl->attr.wlate = 0; + } + cl->attr.deadline += ( cl->attr.ipg + OVRHD ); + cl->attr.readytime += (cl->attr.ipg + OVRHD ); + if ( cl->attr.cln > 0 ) + { + cl->attr.cln--; + cl->attr.cld--; + if ( ( cl->attr.cld == 0 ) + && ( cl->attr.cln == 0 ) ) + { + cl->attr.cln = cl->attr.oln; + cl->attr.cld = cl->attr.old; + } + } + else + { + if ( cl->attr.oln == 0 ) + cl->attr.cld += cl->attr.old; + else + { + cl->attr.cln = 2 * ( cl->attr.oln ) - 1; + cl->attr.cld = + 2 * ( cl->attr.old ) + ( cl->attr.cld - + 1 ); + } + } + } // end of "while ( (cl) && ( jiffies > cl->attr.deadline ) ) {" + + cl->attr.clt = + ( cl->attr.cld == 0) ? 0.0 : ( float ) cl->attr.cln / cl->attr.cld; + +#ifdef DROP_ON + if(cl->attr.droppable != DWCS_NON_DROPPABLE) + { + /*ok this is if the stream supports dropppable packets + *this needs to be added to the dwcs parameters obviously + *There are three possible scenarios + * 1) Stream is nondroppable packet is non droppable - don't drop anything + * 2) Stream is nondroppable packet is droppable - erm.. don't know what to do + * 3) Stream is droppable packet is non droppable - don't drop the packet + * 4) Stream is droppable packet is droppable - drop away + */ + skb = skb_peek ( &cl->q->q ); // gets the pointer to a packet at the head. + + if(skb && skb->drop_flag == DWCS_NON_DROPPABLE) + { + dwcs_drop ( cl->q ); + printk("dropped late packet\n"); + sch->q.qlen --; + q->ltheap_size--; + HDelete2 ( q->ltheap, classid, q->ltheap_size ); + q->dlheap_size--; + HExtractMin ( q->dlheap, q->dlheap_size ); + not_drop_flag = FALSE; + cl->attr.deadline += cl->attr.ipg; // GL: init deadline attribute + cl->attr.readytime += ( cl->attr.ipg + OVRHD ); + + /* + * insert new packet into both heaps. + */ + if ( cl->q->q.qlen > 0 ) + { + if ( cl->attr.flags != DWCS_WORK_CONS ) + { + + q->slheap_size++; + HInsert3 ( q->slheap, classid, + cl->attr.readytime, + q->slheap_size ); + } + else + { + skb = skb_peek ( &cl->q->q ); // gets the pointer to a packet at the head. + if(skb != NULL) + { + + q->dlheap_size++; + q->ltheap_size++; + + HInsert ( q->dlheap, classid, cl->attr.deadline, + q->dlheap_size ); + tmp_heap.clt = cl->attr.clt; + tmp_heap.stream = classid; + tmp_heap.deadline = cl->attr.deadline; + tmp_heap.cln = cl->attr.cln; + tmp_heap.cld = cl->attr.cld; + tmp_heap.oln = cl->attr.oln; + // tmp_heap.old = cl->attr.old; + tmp_heap.wlate = cl->attr.wlate; + tmp_heap.arr_time = tvtojiffies(&(skb->stamp)); + HInsert2 ( q->ltheap, tmp_heap, q->ltheap_size ); + } + } + } + } + else + { + not_drop_flag = TRUE; + flag = FALSE; + } + } + else + { + not_drop_flag = TRUE; + flag = FALSE; + } +#else + not_drop_flag = TRUE; + flag = FALSE; +#endif + } + } + else + { + flag = FALSE; + + if ( not_drop_flag == TRUE ) + { + cl = dwcs_class_lookup(q, q->dlheap[0].stream); + q->dlheap_size --; + q->ltheap_size --; + HExtractMin ( q->dlheap, q->dlheap_size ); + HDelete2 ( q->ltheap, classid, q->ltheap_size ); + skb = skb_peek ( &cl->q->q ); // gets the pointer to a packet at the head. + if(skb != NULL) + { + + cl->attr.deadline += cl->attr.ipg; // GL: init deadline attribute ???? do we need it??? + cl->attr.readytime += cl->attr.ipg; + q->dlheap_size ++; + q->ltheap_size ++; + HInsert ( q->dlheap, classid, cl->attr.deadline, + q->dlheap_size ); + tmp_heap.clt = cl->attr.clt; + tmp_heap.stream = classid; + tmp_heap.deadline = cl->attr.deadline; + tmp_heap.cln = cl->attr.cln; + tmp_heap.cld = cl->attr.cld; + tmp_heap.oln = cl->attr.oln; + // tmp_heap.old = cl->attr.old; + tmp_heap.wlate = cl->attr.wlate; + /* + * this one is tvtojiffies() from kernel/itimer.c + */ + tmp_heap.arr_time = tvtojiffies(&(skb->stamp)); + HInsert2 ( q->ltheap, tmp_heap, q->ltheap_size ); + } + skb = NULL; + + } + not_drop_flag = FALSE; + } // end of " } else { " + + + /* + * Send first element in loss tolerance heap. + */ + + if ( q->ltheap_size > 0 ) + { + min_classid_index = q->ltheap[0].stream; + tmp_cl = dwcs_class_lookup ( q, min_classid_index ); + } + else + { + tmp_cl = NULL; + } + + if ( tmp_cl && ( tmp_cl->q->q.qlen > 0 ) ) + { + if ( ( tmp_cl->attr.cld > tmp_cl->attr.cln ) + && ( tmp_cl->attr.deadline != -1 ) ) + tmp_cl->attr.cld--; + + if ( ( tmp_cl->attr.cld == 0 ) && ( tmp_cl->attr.cln == 0 ) ) + { + tmp_cl->attr.cln = tmp_cl->attr.oln; + tmp_cl->attr.cld = tmp_cl->attr.old; + } + + tmp_cl->attr.clt = ( tmp_cl->attr.cld == 0 ) ? 0.0 : + ( float ) tmp_cl->attr.cln / tmp_cl->attr.cld; + + tmp_cl->attr.sent++; + if ( tmp_cl->attr.sent + tmp_cl->attr.late == + tmp_cl->attr.window ) + { + tmp_cl->attr.window += tmp_cl->attr.old; + if ( tmp_cl->attr.wlate > tmp_cl->attr.oln ) + { + tmp_cl->attr.violations++; + } + tmp_cl->attr.wlate = 0; + } + + + /* + * Original implementation would send the packet now. + * * We instead deque the packet from class's internal + * * queue, and save the pointer to it. + */ + result = tmp_cl->q->dequeue ( tmp_cl->q ); + + if(result) + { + + tmp_cl->attr.bytes += result->len; /* Length of actuall data */ + // DStats ( .... ); + + /* + * Remove sent packet from deadline heap + */ + q->dlheap_size--; + HDelete ( q->dlheap, min_classid_index, + q->dlheap_size ); + + q->ltheap_size--; + HExtractMin2 ( q->ltheap, q->ltheap_size ); + + /* + * Insert next packet in stream if queue non-empty + */ + if ( tmp_cl->q->q.qlen > 0 ) + { + + skb = skb_peek(&tmp_cl->q->q); + + if(result->fragments == 0 || result->fragments == 1) + { + if(!(skb && skb->fragments == 1)) + { + tmp_cl->attr.deadline += ( tmp_cl->attr.ipg + OVRHD ); + tmp_cl->attr.readytime += ( tmp_cl->attr.ipg + OVRHD ); + } + } + else + { + tmp_cl->attr.deadline += ( tmp_cl->attr.ipg + OVRHD ); + tmp_cl->attr.readytime += ( tmp_cl->attr.ipg + OVRHD ); + } + + if ( tmp_cl->attr.flags != DWCS_WORK_CONS ) + { + q->slheap_size++; + HInsert3 ( q->slheap, min_classid_index, + tmp_cl->attr.readytime, + q->slheap_size ); + + } + else + { + skb = skb_peek(&tmp_cl->q->q); + if(!skb) + printk("SKB == NULL\n"); + + q->dlheap_size++; + HInsert ( q->dlheap, min_classid_index, + tmp_cl->attr.deadline, + q->dlheap_size ); + + q->ltheap_size++; + + tmp_heap.clt = tmp_cl->attr.clt; + tmp_heap.stream = min_classid_index; + tmp_heap.deadline = tmp_cl->attr.deadline; + tmp_heap.cln = tmp_cl->attr.cln; + tmp_heap.cld = tmp_cl->attr.cld; + tmp_heap.oln = tmp_cl->attr.oln; + tmp_heap.wlate = tmp_cl->attr.wlate; + /* + * this one is tvtojiffies() from kernel/itimer.c + */ + if(skb) + tmp_heap.arr_time = tvtojiffies(&(skb->stamp)); + + HInsert2 ( q->ltheap, tmp_heap, q->ltheap_size ); + } + } + + } + + } // end of "if ((tmp_cl->attr.cld > tmp_cl->attr.cln) && (tmp_cl->attr.deadline != -1)) " + + } // end of "while (flag)" + + + + if ( result ) + { + tmp_cl->attr.delay += (jiffies - result->urgent_flag); + sch->q.qlen--; + } + else + { + if(q->link && q->link->q && q->link->q->q.qlen > 0) + result = q->link->q->dequeue ( q->link->q ); + if(result) + { + q->link->attr.sent ++; + q->link->attr.delay += (jiffies - result->urgent_flag); + sch->q.qlen --; + } + } + + if ( q->slheap_size > 0) + mod_timer ( &q->wd_timer, q->slheap[0].readytime ); + + + return result; +} + + + +/* + * The init function of a queuing discipline is used to initialize and configure + * the parameters of a queuing discipline when it is created. + */ +static int +dwcs_init ( struct Qdisc *sch, + struct rtattr *opt ) +{ + struct dwcs_sched_data *q = ( void * ) sch->data; + struct rtattr *tb[TCA_DWCS_MAX]; + + MOD_INC_USE_COUNT; /* indicate that the module is in use */ + + /* + * initialization of DWCS two heaps + */ + if ( opt == NULL ) + return 0; + + q->dlheap_size = 0; + q->ltheap_size = 0; + + /* + * initialize default class "q->link" + */ + q->link = + ( struct dwcs_class * ) kmalloc ( sizeof ( struct dwcs_class ), + GFP_KERNEL ); + if ( q->link == NULL ) + return -ENOBUFS; + + q->link->filter_list = NULL; + q->link->refcnt = 1; + q->link->classid = sch->handle; + q->link->qdisc = sch; + if ( !( q->link->q = qdisc_create_dflt ( sch->dev, &pfifo_qdisc_ops ) ) ) + q->link->q = &noop_qdisc; + + + /* + * Process passed parameters here - We apply them to a + * * default class: 'sch->data->link' + */ + if ( opt == NULL || + rtattr_parse ( tb, TCA_DWCS_MAX, RTA_DATA ( opt ), + RTA_PAYLOAD ( opt ) ) ) + return -EINVAL; + + if ( tb[TCA_DWCS_DEADLINE - 1] && + RTA_PAYLOAD ( tb[TCA_DWCS_DEADLINE - 1] ) != 4 ) + return -EINVAL; + + if ( tb[TCA_DWCS_OLN - 1] && RTA_PAYLOAD ( tb[TCA_DWCS_OLN - 1] ) != 4 ) + return -EINVAL; + + if ( tb[TCA_DWCS_OLD - 1] && RTA_PAYLOAD ( tb[TCA_DWCS_OLD - 1] ) != 4 ) + return -EINVAL; + + if ( tb[TCA_DWCS_FLAGS - 1] && + RTA_PAYLOAD ( tb[TCA_DWCS_FLAGS - 1] ) != 4 ) + return -EINVAL; + + if ( tb[TCA_DWCS_DEADLINE - 1] ) + q->link->attr.ipg = + *( long * ) RTA_DATA ( tb[TCA_DWCS_DEADLINE - 1] ); + // q->link->attr.deadline = *(long*)RTA_DATA(tb[TCA_DWCS_DEADLINE-1]); + if ( tb[TCA_DWCS_OLN - 1] ) + q->link->attr.oln = + *( unsigned int * ) RTA_DATA ( tb[TCA_DWCS_OLN - 1] ); + if ( tb[TCA_DWCS_OLD - 1] ) + { + q->link->attr.old = + *( unsigned int * ) RTA_DATA ( tb[TCA_DWCS_OLD - 1] ); + if ( q->link->attr.old == 0 ) + return -EINVAL; + } + /* + * process optional DWCS parameters + */ + if ( tb[TCA_DWCS_FLAGS - 1] ) + q->link->attr.flags = + *( unsigned int * ) RTA_DATA ( tb[TCA_DWCS_FLAGS - 1] ); + q->link->attr.cln = 0; /* Current loss numerator. */ + q->link->attr.cld = 0; /* Current loss denominator. */ + q->link->attr.droppable = FALSE; /* TRUE if packets can be dropped */ + q->link->attr.cln = q->link->attr.oln; + q->link->attr.cld = q->link->attr.old; + q->link->attr.clt = ( ( float ) q->link->attr.oln ) / q->link->attr.old; + + + /* + * now, even though the q->link is our static, always existing class for + * * unmatched packets, we still add it to q->classes[] array for consistency. + * * q->classes[] is array/hash of all existing classes. + */ + dwcs_link_class ( q->link ); + + q->classcount = 1; /* number of classes; one is always created as default */ + + + /* + * if (opt == NULL) { + * if (sch->ops == &bdwcs_qdisc_ops) + * q->limit = sch->dev->tx_queue_len*sch->dev->mtu; + * else + * q->limit = sch->dev->tx_queue_len; + * } else { + * struct tc_dwcs_qopt *ctl = RTA_DATA(opt); + * if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) + * return -EINVAL; + * q->limit = ctl->limit; + * } + */ + + if(sch->dev == NULL) + printk("dev == NULL\n"); + else + dwcs_init_timer ( &q->wd_timer, sch->dev ); + + +#ifdef PROC_MONITORING + /* + * Create /proc/ file entry + */ + // proc_register(&proc_root, &proc_dwcs); + q->ent = create_proc_entry ( "net/sch_dwcs", 0, 0 ); + q->ent->read_proc = proc_read_dwcs; +#endif + + return 0; +} + + +int +dwcs_copy_xstats ( struct sk_buff *skb, + struct tc_stats *st ) +{ + RTA_PUT ( skb, TCA_XSTATS, sizeof ( *st ), st ); + return 0; + + rtattr_failure: + return -1; +} + + + +/* + * The dump function is used to dump diagnostic data associated with a + * queuing discipline. + */ +#ifdef CONFIG_RTNETLINK +static int +dwcs_dump ( struct Qdisc *sch, + struct sk_buff *skb ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + int ipg = 0, + oln = 0, + old = 0; + struct rtattr *rta = NULL; + unsigned char *b = skb->tail; + + rta = ( struct rtattr * ) b; + +#ifdef GREGORY_DETAILS + /* + * tell how many classes there are + */ + { + struct dwcs_class *tmp = NULL; + int count = 0, + i, + f_count = 0; + struct tcf_proto *ptr = NULL; + + + for ( i = 0; i < 16; i++ ) + { + tmp = q->classes[i]; + while ( tmp ) + { + count++; + tmp = tmp->next; + } + } + + /* + * Count how many filters there are + */ + if ( q->link ) + for ( ptr = q->link->filter_list; ptr; ptr = ptr->next ) + { + f_count++; + } + + } +#endif + + //opt.limit = q->limit; + //RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + + if ( q->link ) + { + ipg = q->link->attr.ipg; + oln = q->link->attr.oln; + old = q->link->attr.old; + } + + RTA_PUT ( skb, TCA_OPTIONS, 0, NULL ); + RTA_PUT ( skb, TCA_DWCS_DEADLINE, sizeof ( ipg ), &ipg ); + RTA_PUT ( skb, TCA_DWCS_OLD, sizeof ( oln ), &old ); + RTA_PUT ( skb, TCA_DWCS_OLN, sizeof ( oln ), &oln ); + + rta->rta_len = skb->tail - b; + spin_lock_bh ( &sch->dev->queue_lock ); + if ( dwcs_copy_xstats ( skb, &q->link->stats ) ) + { + spin_unlock_bh ( &sch->dev->queue_lock ); + goto rtattr_failure; + } + spin_unlock_bh ( &sch->dev->queue_lock ); + + return skb->len; + + + + return skb->len; + + rtattr_failure: + skb_trim ( skb, b - skb->data ); + return -1; +} +#endif + + + + +/* + * The destroy function of a queuing discipline is used to remove + * the queuing discipline. It also removes all the classes and + * filters associated with queuing discipline. + */ +static void +dwcs_destroy ( struct Qdisc *sch ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl; + unsigned h; + + + del_timer ( &q->wd_timer ); + +#ifdef CONFIG_NET_CLS_POLICE + q->rx_class = NULL; +#endif + for ( h = 0; h < 16; h++ ) + { + for ( cl = q->classes[h]; cl; cl = cl->next ) + dwcs_destroy_filters ( cl ); + } + + for ( h = 0; h < 16; h++ ) + { + for ( cl = q->classes[h]; cl; cl = cl->next ) + dwcs_destroy_class ( cl ); + } + +#ifdef PROC_MONITORING + /* + * Remove /proc/ file entry + */ + // proc_unregister(&proc_root, proc_dwcs.low_ino); +#endif + + MOD_DEC_USE_COUNT; /* indicate that the module is NOT in use */ +} + + + + +/* +************************************************************* +** +** Section for definition of class related functions. +** +************************************************************* +*/ + + + +/* +** ..._graft() is to attach a new queuing discipline to a class +*/ +static int +dwcs_graft ( struct Qdisc *sch, + unsigned long arg, + struct Qdisc *new, + struct Qdisc **old ) +{ + /* + * for DWCS, we can not have a _graft() function. This is because + * * when we dequeue() we frequently need to know which is the next + * * packet of class that is going to be dequeued. If queue is not FIFO, + * * current API doesn't allow us to access the next packet. Therefore, + * * we use FIFO queues in DWCS classes and don't allow this to be changed. + */ + return -ENOENT; +} + + +/* +** ..._leaf() - is not described in QoS API specifications...??? +*/ +static struct Qdisc * +dwcs_leaf ( struct Qdisc *sch, + unsigned long arg ) +{ + struct dwcs_class *cl = ( struct dwcs_class * ) arg; + + return cl ? cl->q : NULL; +} + + + +/* + * Helper function to return the address of the class + * by providing the classid (that includes major and minor ids), + * Returns NULL, if no class is found. + */ +static __inline__ struct dwcs_class * +dwcs_class_lookup ( struct dwcs_sched_data *q, + u32 classid ) +{ + struct dwcs_class *cl; + + for ( cl = q->classes[dwcs_hash ( classid )]; cl; cl = cl->next ) + if ( cl->classid == classid ) + { + return cl; + } + + return NULL; +} + + + +/* +** ..._get() returns the internal ID of a class in form of a +** pointer to corresponding dwcs class structure. +*/ +static unsigned long +dwcs_get ( struct Qdisc *sch, + u32 classid ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl; + + cl = dwcs_class_lookup ( q, classid ); + + if ( cl ) + { + cl->refcnt++; + return ( unsigned long ) cl; + } + return 0; +} + + +static void +dwcs_destroy_filters ( struct dwcs_class *cl ) +{ + struct tcf_proto *tp; + + while ( ( tp = cl->filter_list ) != NULL ) + { + cl->filter_list = tp->next; + tp->ops->destroy ( tp ); + } +} + + + +/* +** ..._put() - invoked when a class previously referenced using the get() function +** is de-referenced. It decrements the usage count of the class. +*/ +static void +dwcs_put ( struct Qdisc *sch, + unsigned long arg ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl = ( struct dwcs_class * ) arg; + + + if ( --cl->refcnt == 0 ) + { +#ifdef CONFIG_NET_CLS_POLICE + if ( q->rx_class == cl ) + q->rx_class = NULL; +#endif + dwcs_destroy_class ( cl ); + } + return; +} + + +/* +** dwcs_link_class() inserts the class in qdisc's linked list. +** It should be executed atomically. +*/ +static void +dwcs_link_class ( struct dwcs_class *this ) +{ + struct dwcs_sched_data *q = + ( struct dwcs_sched_data * ) this->qdisc->data; + unsigned h = dwcs_hash ( this->classid ); + + this->next = q->classes[h]; + q->classes[h] = this; + +} + + +/* +** dwcs_unlink_class() inserts the class in qdisc's linked list. +** It should be executed atomically. +*/ +static void +dwcs_unlink_class ( struct dwcs_class *this ) +{ + struct dwcs_sched_data *q = + ( struct dwcs_sched_data * ) this->qdisc->data; + struct dwcs_class *cl, + **clp; + + /* + * find the previous class in linked list + */ + for ( clp = &q->classes[dwcs_hash ( this->classid )]; + ( cl = *clp ) != NULL; clp = &cl->next ) + { + if ( cl == this ) + { + *clp = cl->next; + cl->next = NULL; + break; + } + } +} + + +/* +** ..._change() - is used to change the properties associated with a class. +** It is also used to create classes at times. +*/ +static int +dwcs_change_class ( struct Qdisc *sch, + u32 classid, + u32 parentid, + struct rtattr **tca, + unsigned long *arg ) +{ + int err; + struct rtattr *opt = tca[TCA_OPTIONS - 1]; + struct rtattr *tb[TCA_DWCS_MAX]; + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl = ( struct dwcs_class * ) *arg; + + + /* + * Process passed parameters here - We apply them to + * * a class that is about to be created. + */ +// if (opt==NULL || + if ( rtattr_parse + ( tb, TCA_DWCS_MAX, RTA_DATA ( opt ), RTA_PAYLOAD ( opt ) ) ) + return -EINVAL; + + if ( tb[TCA_DWCS_DEADLINE - 1] && + RTA_PAYLOAD ( tb[TCA_DWCS_DEADLINE - 1] ) != 4 ) + return -EINVAL; + + if ( tb[TCA_DWCS_OLN - 1] && RTA_PAYLOAD ( tb[TCA_DWCS_OLN - 1] ) != 4 ) + return -EINVAL; + + + if ( tb[TCA_DWCS_OLD - 1] && RTA_PAYLOAD ( tb[TCA_DWCS_OLD - 1] ) != 4 ) + return -EINVAL; + + if ( tb[TCA_DWCS_FLAGS - 1] && + RTA_PAYLOAD ( tb[TCA_DWCS_FLAGS - 1] ) != 4 ) + return -EINVAL; + + + /* + * #ifdef CONFIG_NET_CLS_POLICE + * if (tb[TCA_DWCS_POLICE-1] && + * RTA_PAYLOAD(tb[TCA_DWCS_POLICE-1]) < sizeof(struct tc_cbq_police)) + * return -EINVAL; + * #endif + */ + + + + /* + * We don't support dynamic parameter changes. + * * So, if classid exists, return error. Otherwise, + * * create a new class. + */ + if ( cl || dwcs_class_lookup ( q, classid ) ) + { // double check + return -EINVAL; + } + + if ( parentid == TC_H_ROOT ) + return -EINVAL; + + /* + * make sure the parent exists + */ + /* + * parent = &q->link; + * if (parentid) { + * parent = dwcs_class_lookup(q, parentid); + * err = -EINVAL; + * if (parent == NULL) + * goto failure; + * } + */ + + /* + * allocate memory for a class + */ + err = -ENOBUFS; + cl = kmalloc ( sizeof ( struct dwcs_class ), GFP_KERNEL ); + if ( cl == NULL ) + goto failure; + + memset ( cl, 0, sizeof ( struct dwcs_class ) ); + + cl->refcnt = 1; + if ( !( cl->q = qdisc_create_dflt ( sch->dev, &pfifo_qdisc_ops ) ) ) + cl->q = &noop_qdisc; + cl->classid = classid; + cl->qdisc = sch; + + /* + * DWCS parameters provided by the user + */ + if ( tb[TCA_DWCS_DEADLINE - 1] ) + cl->attr.ipg = *( long * ) RTA_DATA ( tb[TCA_DWCS_DEADLINE - 1] ); + // cl->attr.deadline = *(long*)RTA_DATA(tb[TCA_DWCS_DEADLINE-1]); + if ( tb[TCA_DWCS_OLN - 1] ) + cl->attr.oln = *( unsigned int * ) RTA_DATA ( tb[TCA_DWCS_OLN - 1] ); + if ( tb[TCA_DWCS_OLD - 1] ) + { + cl->attr.old = + *( unsigned int * ) RTA_DATA ( tb[TCA_DWCS_OLD - 1] ); + if ( cl->attr.old == 0 ) + return -EINVAL; + } + /* + * process optional DWCS parameters + */ + if ( tb[TCA_DWCS_FLAGS - 1] ) + cl->attr.flags = + *( unsigned int * ) RTA_DATA ( tb[TCA_DWCS_FLAGS - 1] ); + /* + * initialization of internal DWCS attributes + */ + cl->attr.cln = 0; /* Current loss numerator. */ + cl->attr.cld = 0; /* Current loss denominator. */ + cl->attr.droppable = FALSE; /* TRUE if packets can be dropped */ + cl->attr.cln = cl->attr.oln; + cl->attr.cld = cl->attr.old; + cl->attr.clt = ( ( float ) cl->attr.oln ) / cl->attr.old; + + + + dwcs_link_class ( cl ); /* atomicaly inserts the class in a liked list */ + q->classcount++; + + *arg = ( unsigned long ) cl; + return 0; + + failure: + return err; +} + + +/* + * a helper function to free the memory allocated by the class. It assumes that + * the class has been removed from a linked list. + */ +static void +dwcs_destroy_class ( struct dwcs_class *cl ) +{ + dwcs_destroy_filters ( cl ); + qdisc_destroy ( cl->q ); +#ifdef CONFIG_NET_ESTIMATOR + qdisc_kill_estimator ( &cl->stats ); +#endif + kfree ( cl ); +} + + + + +/* +** ..._delete() - is used to delete the class. +*/ +static int +dwcs_delete ( struct Qdisc *sch, + unsigned long arg ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl = ( struct dwcs_class * ) arg; + + if ( cl->filters || cl == ( struct dwcs_class * ) &q->link ) + return -EBUSY; + + q->classcount--; + dwcs_unlink_class ( cl ); /* remove the class from the linked list */ + + dwcs_destroy_class ( cl ); + + return ( 0 ); +} + + + +/* +** ..._walk() is used to iterate over all the classes of queuing discipline +** and invokes a callback function for each of the classes. +*/ +static void +dwcs_walk ( struct Qdisc *sch, + struct qdisc_walker *arg ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + unsigned h; + + if ( arg->stop ) + return; + + for ( h = 0; h < 16; h++ ) + { + struct dwcs_class *cl; + + for ( cl = q->classes[h]; cl; cl = cl->next ) + { + if ( arg->count < arg->skip ) + { + arg->count++; + continue; + } + if ( arg->fn ( sch, ( unsigned long ) cl, arg ) < 0 ) + { + arg->stop = 1; + return; + } + arg->count++; + } + } +} + + + +/* +** ..._find_tcf() - used to return the anchor to the list of filters that +** are associated to a class. +*/ +static struct tcf_proto ** +dwcs_find_tcf ( struct Qdisc *sch, + unsigned long arg ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl = ( struct dwcs_class * ) arg; + + if ( cl == NULL ) + cl = q->link; + + return &cl->filter_list; +} + + + + +/* +** ..._bind_tcf() - used to attach an instance of a filter to a class. +** We increment the class counter for the number of filters. +*/ +static unsigned long +dwcs_bind_filter ( struct Qdisc *sch, + unsigned long parent, + u32 classid ) +{ + struct dwcs_sched_data *q = ( struct dwcs_sched_data * ) sch->data; + struct dwcs_class *cl; + + + cl = dwcs_class_lookup ( q, classid ); + + if ( cl ) + { + cl->filters++; + return ( unsigned long ) cl; + } + return 0; +} + + + +/* +** ..._unbind() - is used to remove an instance of a filter attached to a class. +** We need to decrement the counter for the number of filters. +*/ +static void +dwcs_unbind_filter ( struct Qdisc *sch, + unsigned long arg ) +{ + struct dwcs_class *cl = ( struct dwcs_class * ) arg; + + + cl->filters--; +} + + +static int +dwcs_dump_attr ( struct sk_buff *skb, + struct dwcs_class *cl ) +{ + int ipg = 0, + oln = 0, + old = 0; + struct rtattr *rta = NULL; + unsigned char *b = skb->tail; + + rta = ( struct rtattr * ) b; + + if ( cl ) + { + ipg = cl->attr.ipg; + oln = cl->attr.oln; + old = cl->attr.old; + } + + RTA_PUT ( skb, TCA_OPTIONS, 0, NULL ); + RTA_PUT ( skb, TCA_DWCS_DEADLINE, sizeof ( ipg ), &ipg ); + RTA_PUT ( skb, TCA_DWCS_OLD, sizeof ( oln ), &old ); + RTA_PUT ( skb, TCA_DWCS_OLN, sizeof ( oln ), &oln ); + + return skb->len; + + rtattr_failure: + return -1; + +} + +/* +** ..._dump_class() - is used to dump diagnostic data about the class. +*/ +static int +dwcs_dump_class ( struct Qdisc *sch, + unsigned long arg, + struct sk_buff *skb, + struct tcmsg *tcm ) +{ + + struct dwcs_class *cl = ( struct dwcs_class * ) arg; + unsigned char *b = skb->tail; + struct rtattr *rta = ( struct rtattr * ) b; + + + if ( !cl ) + return -1; + + tcm->tcm_handle = TC_H_MAKE ( TC_H_MAJ ( sch->handle ), arg - 1 ); + tcm->tcm_handle = cl->classid; + if ( dwcs_dump_attr ( skb, cl ) < 0 ) + goto rtattr_failure; + + rta->rta_len = skb->tail - b; + + return skb->len; + + rtattr_failure: + skb_trim ( skb, b - skb->data ); + return -1; + + /* + * Magic will go here + */ + return -1; + +} + + +static struct Qdisc_class_ops dwcs_class_ops = { + dwcs_graft, + dwcs_leaf, + dwcs_get, + dwcs_put, + dwcs_change_class, + dwcs_delete, + dwcs_walk, + + dwcs_find_tcf, + dwcs_bind_filter, + dwcs_unbind_filter, + +#ifdef CONFIG_RTNETLINK + dwcs_dump_class, +#endif + +}; + +struct Qdisc_ops dwcs_qdisc_ops = { + NULL, + &dwcs_class_ops, + "dwcs", + sizeof ( struct dwcs_sched_data ), + + dwcs_enqueue, + dwcs_dequeue, + dwcs_requeue, + dwcs_drop, + + dwcs_init, + dwcs_reset, + dwcs_destroy, + dwcs_init, /* technically, should be dwcs_change() */ + +#ifdef CONFIG_RTNETLINK + dwcs_dump, +#endif +}; + +/* + * If we are compiling this as a module, then we need to define the + * following two functions. + */ +#ifdef MODULE +int +init_module ( void ) +{ + pidcall = sys_call_table[__NR_getpid]; + return register_qdisc ( &dwcs_qdisc_ops ); +} + +void +cleanup_module ( void ) +{ + unregister_qdisc ( &dwcs_qdisc_ops ); +} +#endif + + + + +/* ------------------------------------------------------- + * If specified, we create /proc/ entry for monitoring + * the scheduler. + */ +#ifdef PROC_MONITORING + +/* Create an entry in /proc for accessing DWCS state information. */ + +/* +struct proc_dir_entry proc_dwcs = { + 0, // low_ino: the inode -- dynamic + 8, "sch_dwcs", // len of name and name + S_IFREG | S_IRUGO, // mode + 1, 0, 0, // nlinks, owner, group + 0, NULL, // size - unused; operations - use default ops + &proc_read_dwcs, // function used to read data + // nothing more + }; +*/ + +int +proc_read_dwcs ( char *buf, + char **start, + off_t offset, + int length, + int *eof, + void *data ) +{ + int len; + + /* + * Display runqueue statistics. + */ + len = sprintf ( buf, "Jiffies=%lu Current=%d Prev=%d Next=%d\n\n", + jiffies, -1, -1, -1 ); + len -= offset; + if ( len > length ) + len = length; + else + len = 0; + + *start = buf + offset; + *eof = 1; + + return len; +} +#endif +MODULE_LICENSE("GPL"); diff -Naur test-for-latech/net/socket.c testqf-for-latech/net/socket.c --- test-for-latech/net/socket.c 2004-06-11 07:40:47.000000000 -0400 +++ testqf-for-latech/net/socket.c 2004-06-11 07:47:56.000000000 -0400 @@ -457,6 +457,9 @@ sock->ops = NULL; sock->sk = NULL; sock->file = NULL; +#ifdef CONFIG_QFABRIC + sock->rt_sock = 0; +#endif sockets_in_use[smp_processor_id()].counter++; return sock; @@ -498,6 +501,24 @@ sock->file=NULL; } +#ifdef CONFIG_QFABRIC +int rt_sock_sendmsg(struct socket *sock, struct msghdr *msg, int size, int deadline, + int flags) +{ + int err; + struct scm_cookie scm; + + sock->deadline = deadline; + sock->rt_flags = flags; + err = scm_send(sock, msg, &scm); + if (err >= 0) { + err = sock->ops->sendmsg(sock, msg, size, &scm); + scm_destroy(&scm); + } + return err; +} +#endif + int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size) { int err; @@ -819,6 +840,13 @@ return 0; } +#ifdef CONFIG_QFABRIC +int make_rt_sock(struct socket *sock) +{ + sock->rt_sock = 1; + return 0; +} +#endif int sock_create(int family, int type, int protocol, struct socket **res) { @@ -855,7 +883,7 @@ * Otherwise module support will break! */ if (net_families[family]==NULL) - { +{ char module_name[30]; sprintf(module_name,"net-pf-%d",family); request_module(module_name); @@ -883,6 +911,9 @@ } sock->type = type; +#ifdef CONFIG_QFABRIC + sock->rt_sock = 0; +#endif if ((i = net_families[family]->create(sock, protocol)) < 0) { @@ -909,6 +940,15 @@ retval = sock_map_fd(sock); if (retval < 0) goto out_release; +#ifdef CONFIG_QFABRIC + sock->sk->fd = retval; + sock->sk->owner = current->pid; + sock->sk->kecho = 0; + sock->sk->readable = 0; + sock->sk->writable = 0; + sock->sk->counter = 0; + sock->rt_sock = 0; +#endif out: /* It may be already another descriptor 8) Not kernel problem. */ @@ -919,6 +959,37 @@ return retval; } +#ifdef CONFIG_QFABRIC +asmlinkage long sys_rtsocket(int family, int type, int protocol) +{ + int retval; + struct socket *sock; + + retval = sock_create(family, type, protocol, &sock); + if (retval < 0) + goto out; + + retval = sock_map_fd(sock); + if (retval < 0) + goto out_release; + sock->sk->fd = retval; + sock->sk->owner = current->pid; + sock->sk->kecho = 0; + sock->sk->readable = 0; + sock->sk->writable = 0; + sock->sk->counter = 0; + sock->rt_sock = 1; + +out: + /* It may be already another descriptor 8) Not kernel problem. */ + return retval; + +out_release: + sock_release(sock); + return retval; +} +#endif + /* * Create a pair of connected sockets. */ @@ -1063,6 +1134,13 @@ if (err < 0) goto out_release; +#ifdef CONFIG_QFABRIC + sock->sk->fd = err; + sock->sk->owner = current->pid; + sock->sk->readable = 0; + sock->sk->writable = 0; +#endif + if (upeer_sockaddr) { if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { err = -ECONNABORTED; @@ -1258,6 +1336,9 @@ if(err2<0) err=err2; } +#ifdef CONFIG_QFABRIC + if (err > 0) sock->sk->counter++; +#endif sockfd_put(sock); out: return err; @@ -1553,6 +1634,11 @@ case SYS_SOCKET: err = sys_socket(a0,a1,a[2]); break; +#ifdef CONFIG_QFABRIC + case SYS_RTSOCKET: + err = sys_rtsocket(a0,a1,a[2]); + break; +#endif case SYS_BIND: err = sys_bind(a0,(struct sockaddr *)a1, a[2]); break; @@ -1662,6 +1748,10 @@ extern void bluez_init(void); #endif +#ifdef CONFIG_X86 +extern void qsocket_init(void); +#endif + void __init sock_init(void) { int i; @@ -1725,6 +1815,11 @@ #ifdef CONFIG_BLUEZ bluez_init(); #endif +#ifdef CONFIG_X86 +#ifdef CONFIG_NET_QSOCKET + qsocket_init(); +#endif +#endif } int socket_get_info(char *buffer, char **start, off_t offset, int length) @@ -1753,3 +1848,28 @@ len = 0; return len; } + +#ifdef CONFIG_QFABRIC +int set_socket_deadline(struct sock *sk, int deadline) +{ + sk->socket->deadline = deadline; + return 0; +} + +int request_socket_deadline(struct sock *sk) +{ + return sk->socket->deadline; +} + +int set_socket_rt_flags(struct sock *sk, int flags) +{ + sk->socket->rt_flags = flags; + return 0; +} + +int request_socket_rt_flags(struct sock *sk) +{ + return sk->socket->rt_flags; +} +#endif +