diff -pruN src.000/pppoa3.c src/pppoa3.c --- src.000/pppoa3.c 2003-10-16 18:04:23.000000000 +0200 +++ src/pppoa3.c 2003-10-16 19:24:07.000000000 +0200 @@ -119,6 +119,10 @@ union semun { /* I/O Threads */ static void *read_from_usb_thread(void*); static void *write_to_usb_thread(void*); +/* I/O threads extra when reading from usb -> pipe -> ppp */ +static void *read_from_usb_to_pipe(void*); +static void *read_from_pipe_to_ppp(void*); + /* Pipe thread */ static void *read_named_pipe_thread(void*); @@ -174,6 +178,10 @@ static int clean_previous_instance; static int fdin; static int fdout; +/* usb-ppp pipe filedescriptors */ +static int usb_ppp_pipe_fd[2]; +static int use_usb_ppp_pipe; + /* Vpi and VCI numbers */ static int my_vpi; static int my_vci; @@ -205,6 +213,8 @@ static int pipe_fd; #define THREAD_WRITE_TO_USB 0 #define THREAD_READ_FROM_USB 1 #define THREAD_READ_PIPE 2 +#define THREAD_READ_USB_PIPE 3 +#define THREAD_READ_PIPE_PPP 4 typedef struct _thread_entry { @@ -238,6 +248,20 @@ thread_entry thread_array[]= (pthread_t)0, read_named_pipe_thread, "Control pipe" + }, + { + THREAD_READ_USB_PIPE, + (int)0, + (pthread_t)0, + read_from_usb_to_pipe, + "Read usb to pipe" + }, + { + THREAD_READ_PIPE_PPP, + (int)0, + (pthread_t)0, + read_from_pipe_to_ppp, + "Read pipe to ppp" } }; @@ -331,6 +355,7 @@ int main(int argc, char **argv) verbose = 0; log = NULL; use_pipe = 0; + use_usb_ppp_pipe = 0; pipe_fd =-1; sched_type = 0; my_vpi =-1; @@ -427,6 +452,7 @@ int main(int argc, char **argv) report(2, REPORT_INFO, "Using %s mode\n", (bridging)?"Bridged PPPoE":"PPPoA"); #endif report(2, REPORT_INFO, "Control pipe %sabled\n", (use_pipe)?"en":"dis"); + report(2, REPORT_INFO, "USB -> pipe -> PPP %sabled\n", (use_usb_ppp_pipe)?"en":"dis"); report(2, REPORT_INFO, "Previous instance cleaning %sabled\n", (clean_previous_instance)?"en":"dis"); if(device_name) report(2, REPORT_INFO, "Device name set to %s\n", device_name); @@ -702,23 +728,44 @@ int main(int argc, char **argv) /* Threads Creation */ if(thread_start(THREAD_WRITE_TO_USB) < 0) { - report( 0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", + report(0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", thread_array[thread_getindex(THREAD_WRITE_TO_USB)].name); exit(1); } - if(thread_start(THREAD_READ_FROM_USB) < 0) { - report( 0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", - thread_array[thread_getindex(THREAD_READ_FROM_USB)].name); - exit(1); + /* make distinction between using the usb<-->ppp with or without pipe construct */ + + if (use_usb_ppp_pipe == 1) { + /* use the special pipe construct between usb & ppp */ + /* open the pipe */ + if (pipe(usb_ppp_pipe_fd) == -1) { + report(0, REPORT_ERROR|REPORT_DATE, "Read pipe (usb - ppp) creation failed\n"); + exit(1); + } + if(thread_start(THREAD_READ_USB_PIPE) < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", + thread_array[thread_getindex(THREAD_READ_USB_PIPE)].name); + exit(1); + } + if(thread_start(THREAD_READ_PIPE_PPP) < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", + thread_array[thread_getindex(THREAD_READ_PIPE_PPP)].name); + exit(1); + } } + else { + if(thread_start(THREAD_READ_FROM_USB) < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", + thread_array[thread_getindex(THREAD_READ_FROM_USB)].name); + exit(1); + } + + } /* endif use_usb_ppp_pipe............*/ /* Create a thread to read named pipe data */ if(use_pipe) { if(thread_start(THREAD_READ_PIPE) < 0) { - report( 0, - REPORT_ERROR|REPORT_DATE, - "Thread creation failed (%s)\n", + report(0, REPORT_ERROR|REPORT_DATE, "Thread creation failed (%s)\n", thread_array[thread_getindex(THREAD_READ_PIPE)].name); exit(2); } @@ -740,7 +787,7 @@ int main(int argc, char **argv) /* * Waiting for an error * This main thread now consumes 0 CPU until an error is broadcasted - * Error is boadcasted by i/o threads or the signal handler + * Error is broadcasted by i/o threads or the signal handler */ sem_wait(&error_sem); @@ -945,7 +992,8 @@ static void *read_from_usb_thread(void* { sigset_t signal_set; - unsigned int pos; + int pos; + int num_bytes_read = 0; unsigned char *buffer; unsigned char *aal5_recv_buf; unsigned char *destination_buf; @@ -991,7 +1039,9 @@ static void *read_from_usb_thread(void* for(;;) { int n; + int n1; int pti; + int num_bytes_new; unsigned char lbuf[64*53]; unsigned char *unused_cells; @@ -1008,18 +1058,30 @@ static void *read_from_usb_thread(void* /* Debug information */ report(2, REPORT_DEBUG|REPORT_DATE|REPORT_DUMP, "ATM cells read from USB (%d bytes long)\n", lbuf, n, n); - /* Accumulates data in the aal5_recv buffer */ - /* pti will be equal to the last cell pti */ - pti = aal5_frame_from_atm_cells(aal5_recv_buf, lbuf, n, my_vpi, my_vci, &pos, &unused_cells); - - /* A buffer overflow has been detected */ - if(pti<0) { - report(0, REPORT_ERROR|REPORT_DATE, "Buffer overflow, too many cells for the same aal5 frame\n"); - pti = 0; - } - /* As the last pti is 1, we have to send the aal5_frame data */ - while(pti) { + num_bytes_read += n; /* save total number of bytes to be processed */ + num_bytes_new = n; + unused_cells = lbuf; /* point at start of lbuf */ + + /* Accumulate all cell-data in the aal5_recv buffer */ + /* Depending on how many cells and what type, we have to loop one or more times until everything */ + /* has been dealt with. (for example we read: cell-cell-cell-'end'cell-cell-cell-cell */ + /* Every call to aal5_etc stops after finding an 'end'cell and then pti = 1 ) 1 cell = 53 bytes */ + while (unused_cells != NULL) { + pti = aal5_frame_from_atm_cells(aal5_recv_buf, unused_cells, num_bytes_new, my_vpi, my_vci, &pos, &unused_cells); + + /* 'pos' saves the place, where we are in the aal5_recv_buf */ + + /* A buffer overflow has been detected */ + if(pti < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "Buffer overflow, too many cells for the same aal5 frame\n"); + pti = 0; + } + + /* pti = 0 (more frames to follow) or pti = 1 (end of frame-group) */ + /* When pti is 1, we have to send the aal5_frame data */ + + if (pti == 1) { /* Debug information */ report(2, REPORT_DEBUG|REPORT_DATE|REPORT_DUMP, "AAL5 frame joined up (%d bytes long)\n", aal5_recv_buf, pos, pos); @@ -1027,13 +1089,18 @@ static void *read_from_usb_thread(void* /* Prepares the aal5 data (no overwrite is done)*/ n = aal5_frame_dec(aal5_recv_buf, aal5_recv_buf, pos); - if(n<0) { + if (pos > 1536) /* for frames of idiotic length... */ + report(0, REPORT_ERROR|REPORT_DATE, "Idiotic frame length %d\n", pos); - report(0, REPORT_ERROR|REPORT_DATE, "CRC error in an AAL5 frame\n"); + if(n < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "CRC error in AAL5 frame\n"); } else { + report(2, REPORT_DEBUG|REPORT_DATE, "CRC okay %d\n", n); + + /* Writes the result buffer */ #ifdef BRIDGING_ENABLED n += (bridging)?-BRIDGING1483_HEADER:HDLC_HEADER_SIZE; @@ -1041,31 +1108,253 @@ static void *read_from_usb_thread(void* n += HDLC_HEADER_SIZE; #endif if(write_dest(fdout, destination_buf, n) > 0) - report(2, REPORT_DEBUG|REPORT_DATE, "Extracted PPP packet sent to destination device\n\n"); + report(2, REPORT_DEBUG|REPORT_DATE, "Extracted PPP packet sent to destination device\n"); + + } + } - /* Reinitializes pos and n*/ - pos = 0; - pti = 0; + /* adjust the values of num_bytes_read based on pos */ - /* Are cells unused in lbuf ? */ - if(unused_cells != NULL) { + if (pti == 1) { + n1 = pos / 48; /* = number of payload-frames processed */ + n1 *= 53; /* = length of same number of cells */ + num_bytes_new = num_bytes_read - n1; /* calculate the rest if there is any */ + num_bytes_read -= n1; + pos = 0; + } + } /* end while */ - int length; + /* Uses this as a cancel point, that's all */ + pthread_testcancel(); - length = sizeof(lbuf) - (unused_cells - lbuf); + } /* end for 'ever' */ - pti = aal5_frame_from_atm_cells(aal5_recv_buf, unused_cells, length, my_vpi, my_vci, &pos, &unused_cells); + free(buffer); - } + local_end: + /* Broadcasts the error cond to wake main thread */ + sem_post(&error_sem); + + /* Cleanup thread data */ + pthread_cleanup_pop(1); + + pthread_exit(0); + +} + +/* + * Function : read_from_usb_to_pipe + * Return value : none + * Description : thread function which reads from usb bus and sends data + * to a file descriptor (ppp(d)'s pty or tun/tap device) + */ +static void *read_from_usb_to_pipe(void* arg) +{ + sigset_t signal_set; + + /* Configures the thread behaviour */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + /* Blocks all signals so signals are only caught by main thread */ + sigfillset(&signal_set); + pthread_sigmask(SIG_SETMASK, &signal_set, NULL); + + /* Sets a cleanup function to unlink the named pipe on whatever exit*/ + pthread_cleanup_push(cleanup_iothread, &thread_array[thread_getindex(THREAD_READ_FROM_USB)].m_id); + + /* ... */ + report(0, REPORT_ERROR|REPORT_DATE, "read_from_usb_to_pipe thread created\n"); + + + + /* Reads from usb and writes to pipe */ + for(;;) { + + int n; + unsigned char lbuf[64*53]; + + /* Reads 64*53 bytes from usb */ + do { + n = pusb_endpoint_read(ep_data, lbuf, sizeof(lbuf), 0); + } while (n < 0 && (errno == EINTR || errno == ETIMEDOUT)); + + if(n < 0) { + report(0, REPORT_ERROR|REPORT_DATE|REPORT_PERROR, "Error reading usb urb\n"); + break; } + /* Debug information */ + report(1, REPORT_DEBUG|REPORT_DATE, "ATM cells read from USB (%d bytes long)\n", n); /* Uses this as a cancel point, that's all */ + + /* dump it down the pipe */ + write (usb_ppp_pipe_fd[1], &lbuf, n); + pthread_testcancel(); + } /* end for 'ever' */ + + + + /* Broadcasts the error cond to wake main thread */ + sem_post(&error_sem); + + /* Cleanup thread data */ + pthread_cleanup_pop(1); + + pthread_exit(0); +} + + +/* + * Function : read_from_pipe_to_ppp + * Return value : none + * Description : thread function which reads from usb bus and sends data + * to a file descriptor (ppp(d)'s pty or tun/tap device) + */ +static void *read_from_pipe_to_ppp(void* arg) +{ + sigset_t signal_set; + int pos; + int num_bytes_read = 0; + unsigned char *buffer; + unsigned char *aal5_recv_buf; + unsigned char *destination_buf; + + + /* Configures the thread behaviour */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + /* Blocks all signals so signals are only caught by main thread */ + sigfillset(&signal_set); + pthread_sigmask(SIG_SETMASK, &signal_set, NULL); + + /* Sets a cleanup function to unlink the named pipe on whatever exit*/ + pthread_cleanup_push(cleanup_iothread, &thread_array[thread_getindex(THREAD_READ_FROM_USB)].m_id); + + /* ... */ + report(0, REPORT_ERROR|REPORT_DATE, "read_from_pipe_to_ppp thread created\n"); + + /* Allocate buffer memory */ + if((buffer = malloc(BUFFER_SIZE)) == NULL) + goto local_end; + + /* Prepares ppp buffer for HDLC */ +#ifdef BRIDGING_ENABLED + if(bridging) { + destination_buf = buffer + BRIDGING1483_HEADER; + aal5_recv_buf = buffer; + } else { +#endif + destination_buf = buffer; + destination_buf[0] = FRAME_ADDR; + destination_buf[1] = FRAME_CTRL; + aal5_recv_buf = destination_buf + HDLC_HEADER_SIZE; +#ifdef BRIDGING_ENABLED } +#endif + + + /* Prepares pos */ + pos = 0; + + /* Reads from usb and writes to ppp(d) tty */ + for(;;) { + + int n; + int n1; + int pti; + int num_bytes_new; + unsigned char lbuf[64*53]; + unsigned char *unused_cells; + + /* Reads 64*53 bytes from the pipe */ + + n = read(usb_ppp_pipe_fd[0],&lbuf,64*53); + if (n <= 0) { + /* this seems not to be necessary; read waits for something to read... */ + usleep(500); + continue; + } + + /* Debug information */ + report(2, REPORT_DEBUG|REPORT_DATE|REPORT_DUMP, "ATM cells read from USB (%d bytes long)\n", lbuf,n, n); + num_bytes_read += n; /* save total number of bytes to be processed */ + num_bytes_new = n; + unused_cells = lbuf; /* point at start of lbuf */ + + /* Accumulate all cell-data in the aal5_recv buffer */ + /* Depending on how many cells and what type, we have to loop one or more times until everything */ + /* has been dealt with. (for example we read: cell-cell-cell-'end'cell-cell-cell-cell */ + /* Every call to aal5_etc stops after finding an 'end'cell and then pti = 1 ) 1 cell = 53 bytes */ + while (unused_cells != NULL) { + pti = aal5_frame_from_atm_cells(aal5_recv_buf, unused_cells, num_bytes_new, my_vpi, my_vci, &pos, &unused_cells); + + /* 'pos' saves the place, where we are in the aal5_recv_buf */ + + + /* A buffer overflow has been detected */ + if(pti < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "Buffer overflow, too many cells for the same aal5 frame\n"); + pti = 0; + } + + /* pti = 0 (more frames to follow) or pti = 1 (end of frame-group) */ + /* When pti is 1, we have to send the aal5_frame data */ + + if (pti == 1) { + + /* Debug information */ + report(2, REPORT_DEBUG|REPORT_DATE|REPORT_DUMP, "AAL5 frame joined up (%d bytes long)\n", aal5_recv_buf, pos, pos); + + /* Prepares the aal5 data (no overwrite is done)*/ + n = aal5_frame_dec(aal5_recv_buf, aal5_recv_buf, pos); + + if (pos > 1536) /* for frames of idiotic length... */ + report(0, REPORT_ERROR|REPORT_DATE, "Idiotic frame length %d\n", pos); + + if(n < 0) { + report(0, REPORT_ERROR|REPORT_DATE, "CRC error in AAL5 frame\n"); + } + else { + + report(2, REPORT_DEBUG|REPORT_DATE, "CRC okay %d\n", n); + + + /* Writes the result buffer */ +#ifdef BRIDGING_ENABLED + n += (bridging)?-BRIDGING1483_HEADER:HDLC_HEADER_SIZE; +#else + n += HDLC_HEADER_SIZE; +#endif + if(write_dest(fdout, destination_buf, n) > 0) + report(2, REPORT_DEBUG|REPORT_DATE, "Extracted PPP packet sent to destination device\n"); + + } + + + } + + /* adjust the values of num_bytes_read based on pos */ + + if (pti == 1) { + n1 = pos / 48; /* = number of payload-frames processed */ + n1 *= 53; /* = length of same number of cells */ + num_bytes_new = num_bytes_read - n1; /* calculate the rest if there is any */ + num_bytes_read -= n1; + pos = 0; + } + } /* end while */ + + /* Uses this as a cancel point, that's all */ + pthread_testcancel(); + + } /* end for 'ever' */ free(buffer); @@ -1440,7 +1729,8 @@ static int write_dest(int fd, unsigned c if(retries++ < NOBUF_RETRIES) { /* retry after delay */ - usleep(1000); + usleep(500); + report(0, REPORT_DEBUG|REPORT_DATE, "500 ms delay before retry in write_dest\n"); goto retry; } else { @@ -1895,6 +2185,8 @@ static void parse_commandline(int argc, } else if(strcmp(argv[i], "--pipehelp") == 0 || strcmp(argv[i], "-ph") == 0) { app_pipe_usage = 1; app_exit = 1; + } else if(strcmp(argv[i], "--readusbpipe") == 0 || strcmp(argv[i], "-r") == 0) { + use_usb_ppp_pipe = 1; } else if(strcmp(argv[i], "--async") == 0 || strcmp(argv[i], "-a") == 0) { syncHDLC = 0; #ifdef BRIDGING_ENABLED @@ -1988,6 +2280,9 @@ static void usage() fprintf(stderr, " -p | --pipe\n"); fprintf(stderr, " Enable named pipe control thread\n"); fprintf(stderr, " See the -ph option for more details\n"); + fprintf(stderr, " -r | --readusbpipe\n"); + fprintf(stderr, " Use an extra pipe construct in order to speed up the USB\n"); + fprintf(stderr, " reading process\n"); fprintf(stderr, " -s | --schedule policy\n"); fprintf(stderr, " Define the schedule policy used for the io threads\n"); fprintf(stderr, " 0 - SCHED_OTHER (Non realtime scheduling / default)\n"); @@ -2099,8 +2394,7 @@ static void dump(unsigned char *buf, int #ifndef USE_SYSLOG fprintf(log, "%c", give_char(buf[j])); #else - sprintf(ptr, "%c", give_char(buf[j])); - ptr++; + *ptr++ = give_char(buf[j]); #endif }