diff -Nur tipc-1.7.5/include/net/tipc/tipc.h tipc-1.7.5+tipcdump/include/net/tipc/tipc.h --- tipc-1.7.5/include/net/tipc/tipc.h 2007-08-31 01:22:30.000000000 +0800 +++ tipc-1.7.5+tipcdump/include/net/tipc/tipc.h 2008-07-18 20:36:55.000000000 +0800 @@ -254,4 +254,45 @@ #endif +/* + * definitions for tipc tracing utility. + */ +#ifdef TIPCDUMP + +/* +** ioctl defines. +*/ +#define TIPCDUMP_IOCTL_ENABLE_TRACE_ALL 5000 +#define TIPCDUMP_IOCTL_ENABLE_TRACE_PONLY 5001 +#define TIPCDUMP_IOCTL_ENABLE_TRACE_IONLY 5002 +#define TIPCDUMP_IOCTL_DISABLE_TRACE 5003 +#define TIPCDUMP_IOCTL_GET_OWN_NODE 5004 +#define TIPCDUMP_IOCTL_GET_DROPPED_COUNT 5005 + +#define TIPCDUMP_MSG_SENT 1 /* message sent by this node */ +#define TIPCDUMP_MSG_RECEIVED 2 /* message received by this node */ + +#define PAYLOAD_MSG 1 +#define INTERNAL_MSG 2 + +#define TIPCDUMP_ID "tipcdump" + +/* + * tipcdump header structure, make it same size for all architectures. + */ +struct timeval32 { + int tv_sec; + int tv_usec; +}; + +typedef struct tipcdump_header { + unsigned int direction; + unsigned int pid; + struct timeval32 tv; +} tipcdump_header_t; + +#define TIPCDUMP_HEADER_SIZE (sizeof(tipcdump_header_t)) + +#endif /* TIPCDUMP */ + #endif diff -Nur tipc-1.7.5/net/tipc/Makefile tipc-1.7.5+tipcdump/net/tipc/Makefile --- tipc-1.7.5/net/tipc/Makefile 2007-08-31 01:22:30.000000000 +0800 +++ tipc-1.7.5+tipcdump/net/tipc/Makefile 2008-07-18 20:52:30.000000000 +0800 @@ -2,12 +2,15 @@ # Makefile for the Linux TIPC layer # +CFLAGS += -DTIPCDUMP + obj-$(CONFIG_TIPC) := tipc.o tipc-y += tipc_addr.o tipc_bcast.o tipc_bearer.o tipc_cfgsrv.o \ tipc_core.o tipc_handler.o tipc_link.o tipc_discover.o tipc_msg.o \ tipc_name_distr.o tipc_topsrv.o tipc_name_table.o tipc_net.o \ tipc_netlink.o tipc_node.o tipc_port.o tipc_ref.o \ - tipc_socket.o tipc_user_reg.o tipc_dbg.o tipc_eth_media.o + tipc_socket.o tipc_user_reg.o tipc_dbg.o tipc_eth_media.o \ + tipc_dump.o # End of file diff -Nur tipc-1.7.5/net/tipc/Module.symvers tipc-1.7.5+tipcdump/net/tipc/Module.symvers --- tipc-1.7.5/net/tipc/Module.symvers 1970-01-01 07:00:00.000000000 +0700 +++ tipc-1.7.5+tipcdump/net/tipc/Module.symvers 2008-07-18 20:34:52.000000000 +0800 @@ -0,0 +1,46 @@ +0x88b73627 tipc_get_addr net/tipc/tipc EXPORT_SYMBOL +0x16f27683 tipc_block_bearer net/tipc/tipc EXPORT_SYMBOL +0x84c306d6 tipc_register_media net/tipc/tipc EXPORT_SYMBOL +0xeeebfbf9 tipc_send_buf net/tipc/tipc EXPORT_SYMBOL +0xadd203d0 tipc_connect2port net/tipc/tipc EXPORT_SYMBOL +0xd56f2040 tipc_send_buf2name net/tipc/tipc EXPORT_SYMBOL +0xbb2b2504 tipc_send net/tipc/tipc EXPORT_SYMBOL +0x5c0d4b5c tipc_ref_valid net/tipc/tipc EXPORT_SYMBOL +0xf0831eda tipc_createport net/tipc/tipc EXPORT_SYMBOL +0x1472b270 tipc_disconnect net/tipc/tipc EXPORT_SYMBOL +0x62a681a3 tipc_portunreturnable net/tipc/tipc EXPORT_SYMBOL +0x55fade82 tipc_createport_raw net/tipc/tipc EXPORT_SYMBOL +0xda7f9d3f tipc_attach net/tipc/tipc EXPORT_SYMBOL +0xce1e974a tipc_reject_msg net/tipc/tipc EXPORT_SYMBOL +0xae0103c3 tipc_shutdown net/tipc/tipc EXPORT_SYMBOL +0xcec8514a tipc_set_portunreturnable net/tipc/tipc EXPORT_SYMBOL +0x10d40fcd tipc_isconnected net/tipc/tipc EXPORT_SYMBOL +0x1479cb03 tipc_deleteport net/tipc/tipc EXPORT_SYMBOL +0xae803f4e tipc_forward_buf2name net/tipc/tipc EXPORT_SYMBOL +0xdf5008fc tipc_peer net/tipc/tipc EXPORT_SYMBOL +0xd44731e5 tipc_ownidentity net/tipc/tipc EXPORT_SYMBOL +0x310d1bc9 tipc_detach net/tipc/tipc EXPORT_SYMBOL +0x7f6fc085 tipc_forward_buf2port net/tipc/tipc EXPORT_SYMBOL +0xee26a4f5 tipc_send_buf2port net/tipc/tipc EXPORT_SYMBOL +0xb01ffc2c tipc_forward2name net/tipc/tipc EXPORT_SYMBOL +0x9c45558e tipc_enable_bearer net/tipc/tipc EXPORT_SYMBOL +0x10057a1f tipc_send_buf_fast net/tipc/tipc EXPORT_SYMBOL +0xeefd49b3 tipc_get_handle net/tipc/tipc EXPORT_SYMBOL +0x1433d019 tipc_continue net/tipc/tipc EXPORT_SYMBOL +0x5637ed44 tipc_get_mode net/tipc/tipc EXPORT_SYMBOL +0x4ba3cfc8 tipc_send2name net/tipc/tipc EXPORT_SYMBOL +0x15b5ecde tipc_set_portunreliable net/tipc/tipc EXPORT_SYMBOL +0xb35b672c tipc_publish net/tipc/tipc EXPORT_SYMBOL +0xef50a1ef tipc_disable_bearer net/tipc/tipc EXPORT_SYMBOL +0x27d8bb58 tipc_send2port net/tipc/tipc EXPORT_SYMBOL +0x74aaa3f5 tipc_recv_msg net/tipc/tipc EXPORT_SYMBOL +0x64357d3c tipc_multicast net/tipc/tipc EXPORT_SYMBOL +0x538b228a tipc_withdraw net/tipc/tipc EXPORT_SYMBOL +0x4b2243c6 tipc_portimportance net/tipc/tipc EXPORT_SYMBOL +0x1764459f tipc_get_port net/tipc/tipc EXPORT_SYMBOL +0x259b74f9 tipc_acknowledge net/tipc/tipc EXPORT_SYMBOL +0x08acf310 tipc_available_nodes net/tipc/tipc EXPORT_SYMBOL +0x8001e3d7 tipc_forward2port net/tipc/tipc EXPORT_SYMBOL +0xe7aece47 tipc_ispublished net/tipc/tipc EXPORT_SYMBOL +0x3712e340 tipc_portunreliable net/tipc/tipc EXPORT_SYMBOL +0x3976041f tipc_set_portimportance net/tipc/tipc EXPORT_SYMBOL diff -Nur tipc-1.7.5/net/tipc/tipc_core.c tipc-1.7.5+tipcdump/net/tipc/tipc_core.c --- tipc-1.7.5/net/tipc/tipc_core.c 2007-08-31 01:22:30.000000000 +0800 +++ tipc-1.7.5+tipcdump/net/tipc/tipc_core.c 2008-07-18 20:34:52.000000000 +0800 @@ -38,6 +38,9 @@ #include #include #include +#ifdef TIPCDUMP +#include +#endif #include "tipc_core.h" #include "tipc_dbg.h" @@ -48,6 +51,10 @@ #include "tipc_topsrv.h" #include "tipc_cfgsrv.h" +#ifdef TIPCDUMP +#include "tipc_dump.h" +#endif /* TIPCDUMP */ + /* * Declare routines in sub-systems that don't warrant their own .h file */ @@ -231,6 +238,27 @@ tipc_max_publications = delimit(CONFIG_TIPC_PUBL, 1, 65535); tipc_max_subscriptions = delimit(CONFIG_TIPC_SUBSCR, 1, 65535); +#ifdef TIPCDUMP + if ((res = tipcdump_register())) { + err("TIPC: Error registering tipcdump\n"); + return res; + } + +#ifdef CONFIG_COMPAT + // ioctl32_conversion + res = register_ioctl32_conversion(TIPCDUMP_IOCTL_ENABLE_TRACE_ALL, NULL); + res |= register_ioctl32_conversion(TIPCDUMP_IOCTL_ENABLE_TRACE_PONLY, NULL); + res |= register_ioctl32_conversion(TIPCDUMP_IOCTL_ENABLE_TRACE_IONLY, NULL); + res |= register_ioctl32_conversion(TIPCDUMP_IOCTL_DISABLE_TRACE, NULL); + res |= register_ioctl32_conversion(TIPCDUMP_IOCTL_GET_OWN_NODE, NULL); + res |= register_ioctl32_conversion(TIPCDUMP_IOCTL_GET_DROPPED_COUNT, NULL); + if(res){ + printk("TIPCDUMP: Error registering ioctl32 translations\n"); + return -EINVAL; + } +#endif +#endif /* TIPCDUMP */ + if ((res = tipc_core_start())) err("Unable to start in single node mode\n"); else @@ -240,6 +268,23 @@ static void __exit tipc_exit(void) { +#ifdef TIPCDUMP +#ifdef CONFIG_COMPAT + // ioctl32_conversion + int res; + res = unregister_ioctl32_conversion(TIPCDUMP_IOCTL_ENABLE_TRACE_ALL); + res |= unregister_ioctl32_conversion(TIPCDUMP_IOCTL_ENABLE_TRACE_PONLY); + res |= unregister_ioctl32_conversion(TIPCDUMP_IOCTL_ENABLE_TRACE_IONLY); + res |= unregister_ioctl32_conversion(TIPCDUMP_IOCTL_DISABLE_TRACE); + res |= unregister_ioctl32_conversion(TIPCDUMP_IOCTL_GET_OWN_NODE); + res |= unregister_ioctl32_conversion(TIPCDUMP_IOCTL_GET_DROPPED_COUNT); + if(res) + printk("TIPCDUMP: Error unregistering ioctl32 translations\n"); +#endif + + tipcdump_deregister(); +#endif /* TIPCDUMP */ + tipc_core_stop_net(); tipc_core_stop(); info("Deactivated\n"); diff -Nur tipc-1.7.5/net/tipc/tipc_dump.c tipc-1.7.5+tipcdump/net/tipc/tipc_dump.c --- tipc-1.7.5/net/tipc/tipc_dump.c 1970-01-01 07:00:00.000000000 +0700 +++ tipc-1.7.5+tipcdump/net/tipc/tipc_dump.c 2008-07-18 20:34:52.000000000 +0800 @@ -0,0 +1,580 @@ +/* + Author: Nortel Networks + + Copyright 2005 Nortel Networks + + July 2008 Alcatel-Lucent Adaptation from tipc 1.5.12 to 1.7.5 + + 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. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES,REPRESENTATIONS, AND CONDITIONS INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. See the GNU General Public License + for more details. + + IN NO EVENT SHALL THE COPYRIGHT OWNER 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. + + You should have received a copy of the GNU General Public License along + with this program; if not, contact the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA www.fsf.org/ for a copy. +*/ + +#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 "tipc_cfgsrv.h" +#include "tipc_msg.h" +#include "tipc_core.h" +//#include "msg.h" +#include "tipc_dump.h" + + +static tipcdump_info_t tipcdump_info; +#ifdef CONFIG_PROC_FS +#include +static tipc_stats_info_t tipc_stats_info; +static rwlock_t tipc_stats_lock = RW_LOCK_UNLOCKED; +#endif /* CONFIG_PROC_FS */ + + +/********************************************************* +* Function: tipcdump_flush_queue * +* * +* Purpose: Walk through queue and free all data. * +* * +* Returns: nothing * +**********************************************************/ +static void tipcdump_flush_queue(void) +{ + unsigned long flags; + struct list_head *pos, *q; + tdbuf_list_t *tmp; + + DEBUG0("tipcdump_flush_queue: begin\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + list_for_each_safe(pos, q, &tipcdump_info.td_list.list) + { + tmp = list_entry(pos, tdbuf_list_t, list); + tipcdump_info.queue_size -= tmp->data_size; + list_del(pos); + kfree(tmp->data); + kfree(tmp); + } + DEBUG1("queue_size=%d\n",tipcdump_info.queue_size); + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + DEBUG0("tipcdump_flush_queue: end\n"); +} + +/********************************************************* +* Function: tipcdump_open * +* * +* Purpose: Open /dev/tipcdump file and set status fields.* +* * +* Returns: 0 on success, -errno otherwise. * +**********************************************************/ +static int tipcdump_open(struct inode *inode, struct file *file_ptr) +{ + unsigned long flags; + int retval = 0; + + + DEBUG0("tipcdump_open: begin\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + + /* + * Only one user can use tipcdump. + */ + if (!tipcdump_info.opened) + { + tipcdump_info.opened = 1; + + tipcdump_info.dropped_messages = 0; + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,25)) + MOD_INC_USE_COUNT; +#endif /* LINUX_VERSION_CODE */ + } + else + { + DEBUG0("tipcdump_open: ERROR: already opened\n"); + retval = -EPERM; + } + + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + return(retval); +} + + +/********************************************************* +* Function: tipcdump_close * +* * +* Purpose: Close /dev/tipcdump file and set status * +* fields. * +* * +* Returns: 0 * +**********************************************************/ +static int tipcdump_close(struct inode *inode, struct file *file_ptr) +{ + unsigned long flags; + + DEBUG0("tipcdump_close: begin\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + tipcdump_info.opened = 0; + tipcdump_info.p_enabled = 0; + tipcdump_info.i_enabled = 0; + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + + /* + ** Flush out the queue. + */ + tipcdump_flush_queue(); + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,25)) + MOD_DEC_USE_COUNT; +#endif /* LINUX_VERSION_CODE */ + + return(0); +} + + +/********************************************************* +* Function: tipcdump_read * +* * +* Purpose: Pull next msg off queue and copy data to user.* +* fields. * +* * +* Returns: tipc message size, or -errno * +**********************************************************/ +static ssize_t tipcdump_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + unsigned long flags; + int retval; + ssize_t tipc_msg_size = 0; + struct list_head *pos; + tdbuf_list_t *tmp; + + DEBUG0("tipcdump_read: begin\n"); + + /* + ** Wait for a message to be enqueued. + */ + wait_event_interruptible(tipcdump_info.wait_queue, !list_empty(&(tipcdump_info.td_list.list))); + if(list_empty(&(tipcdump_info.td_list.list))) + { + DEBUG0("List is empty\n"); + return 0; + } + + spin_lock_irqsave(&(tipcdump_info.lock), flags); + pos = tipcdump_info.td_list.list.next; + tmp = list_entry(pos, tdbuf_list_t, list); + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + + if(tmp == NULL) + { + printk("Cannot get an entry\n"); + return -ENOMEM; + } + /* + ** Copy data to user buffer. + */ + tipc_msg_size = tmp->data_size; + if(tipc_msg_size > count) + tipc_msg_size = count; + + retval = copy_to_user(buf, tmp->data, tipc_msg_size); + + // free the entry and its buffer + spin_lock_irqsave(&(tipcdump_info.lock), flags); + list_del(pos); + kfree(tmp->data); + kfree(tmp); + tipcdump_info.queue_size -= (tipc_msg_size); + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + + if (retval > 0) + { + DEBUG1("tipcdump_read: ERROR: copy_to_user failed, retval=%d\n", retval); + tipc_msg_size = -EFAULT; + } + + DEBUG0("tipcdump_read: end\n"); + return tipc_msg_size; + +} + + +/********************************************************* +* Function: tipcdump_ioctl * +* * +* Purpose: Supports ioctl calls for /dev/tipcdump. * +* * +* Returns: 0 for success or -errno * +**********************************************************/ +static int tipcdump_ioctl(struct inode *inode, struct file *file_ptr, unsigned int cmd, unsigned long arg) +{ + unsigned long flags; + int retval = 0, count; + void *user_addr; + + + user_addr = (void *) arg; + DEBUG0("tipcdump_ioctl: begin\n"); + switch (cmd) + { + case TIPCDUMP_IOCTL_ENABLE_TRACE_ALL: + DEBUG0("tipcdump_ioctl: TIPCDUMP_IOCTL_ENABLE_TRACE\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + tipcdump_info.p_enabled = 1; + tipcdump_info.i_enabled = 1; + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + break; + + case TIPCDUMP_IOCTL_ENABLE_TRACE_PONLY: + DEBUG0("tipcdump_ioctl: TIPCDUMP_IOCTL_ENABLE_TRACE\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + tipcdump_info.p_enabled = 1; + tipcdump_info.i_enabled = 0; + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + break; + + case TIPCDUMP_IOCTL_ENABLE_TRACE_IONLY: + DEBUG0("tipcdump_ioctl: TIPCDUMP_IOCTL_ENABLE_TRACE\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + tipcdump_info.p_enabled = 0; + tipcdump_info.i_enabled = 1; + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + break; + + case TIPCDUMP_IOCTL_DISABLE_TRACE: + DEBUG0("tipcdump_ioctl: TIPCDUMP_IOCTL_DISABLE_TRACE\n"); + spin_lock_irqsave(&(tipcdump_info.lock), flags); + tipcdump_info.p_enabled = 0; + tipcdump_info.i_enabled = 0; + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + break; + + + case TIPCDUMP_IOCTL_GET_OWN_NODE: + DEBUG0("tipcdump_ioctl: TIPCDUMP_IOCTL_GET_OWN_NODE\n"); + count = copy_to_user(user_addr, &tipc_own_addr, sizeof(unsigned int)); + if (count > 0) + { + DEBUG1("tipcdump_ioctl: ERROR: copy_to_user failed, count=%d\n", count); + retval = -EFAULT; + } + break; + + + case TIPCDUMP_IOCTL_GET_DROPPED_COUNT: + DEBUG0("tipcdump_ioctl: TIPCDUMP_IOCTL_GET_DROPPED_COUNT\n"); + count = copy_to_user(user_addr, &(tipcdump_info.dropped_messages), sizeof(uint64_t)); + if (count > 0) + { + DEBUG1("tipcdump_ioctl: ERROR: copy_to_user failed, count=%d\n", count); + retval = -EFAULT; + } + break; + + + default: + retval = -EPERM; + break; + } + DEBUG0("tipcdump_ioctl: end\n"); + return(retval); +} + + +#ifdef CONFIG_PROC_FS +static int tipc_read_procstats(char *buf, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = 0; + uint32_t elapsed_time; + tipc_stats_info_t tstats; + + read_lock(&tipc_stats_lock); + tstats = tipc_stats_info; + read_unlock(&tipc_stats_lock); + + do_gettimeofday(&tstats.curr_time); + len += sprintf(buf + len, "TIPC STATS\n"); + elapsed_time = (tstats.curr_time.tv_sec - tstats.start_time.tv_sec); + len += sprintf(buf + len, "Elapsed Time (seconds) = %d\n", elapsed_time); +#if 0 + len += sprintf(buf + len, "\n Total messages sent = %llu", + tstats.msg_sent); + len += sprintf(buf + len, "\n Total bytes sent = %llu", + tstats.bytes_sent); + + len += sprintf(buf + len, "\n Total messages recv = %llu", + tstats.msg_recv); + len += sprintf(buf + len, "\n Total bytes recv = %llu", + tstats.bytes_recv); +#endif + len += sprintf(buf + len, "\n"); + + if (len <= offset + count) *eof = 1; + *start = buf + offset; + if (len > offset) + len -= offset; + else + len = 0; + return len < count ? len : count; +} +#endif /* CONFIG_PROC_FS */ + + +/********************************************************* +* Function: tipcdump_register * +* * +* Purpose: Register tipcdump structure when tipc module * +* is loaded. * +* * +* Returns: 0 for sucesss, -errno otherwise * +**********************************************************/ +int tipcdump_register() +{ + int retval = 0; + struct proc_dir_entry *tipc_proc; + + DEBUG0("tipcdump_register: begin\n"); + + /* + ** Register a chr device with the kernel. + */ + tipcdump_info.devops.open = tipcdump_open; + tipcdump_info.devops.release = tipcdump_close; + tipcdump_info.devops.read = tipcdump_read; + tipcdump_info.devops.ioctl = tipcdump_ioctl; + tipcdump_info.majornum = register_chrdev(0, TIPCDUMP_ID, &(tipcdump_info.devops)); + if (tipcdump_info.majornum <= 0) + { + DEBUG1("tipcdump_register: register_chrdev failed, majornum=%d\n", tipcdump_info.majornum); + return -ENODEV; + } + else + { + DEBUG1("tipcdump_register: register_chrdev OK, majornum=%d\n", tipcdump_info.majornum); + } + + /* + ** Initialize other fields. + */ + init_waitqueue_head(&(tipcdump_info.wait_queue)); + spin_lock_init(&(tipcdump_info.lock)); + tipcdump_info.opened = 0; + tipcdump_info.p_enabled = 0; + tipcdump_info.i_enabled = 0; + tipcdump_info.queue_size = 0; + INIT_LIST_HEAD(&(tipcdump_info.td_list.list)); + +#ifdef CONFIG_PROC_FS + tipc_proc = create_proc_entry("tipcstats", 0644, NULL); + memset(&tipc_stats_info, 0, sizeof(tipc_stats_info_t)); + if (tipc_proc != NULL){ + do_gettimeofday(&tipc_stats_info.start_time); + tipc_stats_info.in_use = 1; + tipc_proc->data = 0; + tipc_proc->read_proc = tipc_read_procstats; + tipc_proc->owner = THIS_MODULE; + } else + tipc_stats_info.in_use = 0; +#endif /* CONFIG_PROC_FS */ + DEBUG0("tipcdump_register: end\n"); + return(retval); +} + + +/********************************************************* +* Function: tipcdump_deregister * +* * +* Purpose: Deregister tipcdump structure when tipc module* +* is unloaded. * +* * +* Returns: 0 * +**********************************************************/ +int tipcdump_deregister() +{ + int retval = 0; + + DEBUG0("tipcdump_deregister: begin\n"); + + /* + ** Unregister the chr device from the kernel. + */ + unregister_chrdev(tipcdump_info.majornum, TIPCDUMP_ID); + + /* + ** Flush out the remaining queue. + */ + tipcdump_flush_queue(); + +#ifdef CONFIG_PROC_FS + if (tipc_stats_info.in_use){ + remove_proc_entry("tipcstats", NULL); + } +#endif /* CONFIG_PROC_FS */ + + + DEBUG0("tipcdump_deregister: end\n"); + return(retval); +} + + +/********************************************************* +* Function: tipcdump_enqueue * +* * +* Purpose: Add incoming msg to tipcdump retrieval queue. * +* * +* Returns: 0 for success, -1 for failure * +**********************************************************/ +int tipcdump_enqueue(struct sk_buff *skb, u32 msg_direction) +{ + unsigned long flags; + int tipc_msg_size = 0; + int retval = 0; + tdbuf_list_t *tmp; + struct tipc_msg *msg; + int user; + struct timeval tv; + tipcdump_header_t *td_hdr; + + DEBUG0("tipcdump_enqueue: begin\n"); + msg = buf_msg(skb); + if (msg == NULL) + { + info("tipcdump_enqueue: bad msg\n"); + return(-1); + } + + /* + ** If the tipcdump user app is running, then go ahead + ** and enqueue this msg. Otherwise, just return, leaving the queue unchanged. + */ + if(msg_version(msg) != TIPC_VERSION) + { + info("tipcdump_enqueue: strange msg received, first word: 0x%08x, pid: %d\n", msg->hdr[0], current->pid); + return -1; + } + if(msg_user(msg) < 5 || msg_user(msg) == 12) + user = PAYLOAD_MSG; + else + user = INTERNAL_MSG; + spin_lock_irqsave(&(tipcdump_info.lock), flags); + if ( (user == PAYLOAD_MSG && !tipcdump_info.p_enabled) || + (user == INTERNAL_MSG && !tipcdump_info.i_enabled)) + { + DEBUG0("TIPCDUMP is not enabled\n"); + retval = -1; + goto out; + } + + tipc_msg_size = msg_size(msg); + if((tipcdump_info.queue_size + tipc_msg_size + TIPCDUMP_HEADER_SIZE) >= TIPCDUMP_MAX_QUEUE_SIZE) + { + DEBUG1("tipcdump_enqueue: ERROR: queue maxed out; holding %d bytes hostage\n", + tipcdump_info.queue_size); + (tipcdump_info.dropped_messages)++; + retval = -1; + goto out; + } + + tmp = (tdbuf_list_t *)kmalloc(sizeof(tdbuf_list_t), GFP_ATOMIC); + if(tmp == NULL) + { + (tipcdump_info.dropped_messages)++; + retval = -1; + goto out; + } + tmp->data_size = tipc_msg_size + TIPCDUMP_HEADER_SIZE; + tmp->data = (char *)kmalloc(tmp->data_size + 1, GFP_ATOMIC); + if(tmp->data == NULL) + { + kfree(tmp); + (tipcdump_info.dropped_messages)++; + retval = -1; + goto out; + } + + td_hdr = (tipcdump_header_t *)tmp->data; + td_hdr->direction = htonl(msg_direction); + td_hdr->pid = htonl(current->pid); + do_gettimeofday(&tv); + td_hdr->tv.tv_sec = htonl(tv.tv_sec); + td_hdr->tv.tv_usec = htonl(tv.tv_usec); + + // do we really want copy the whole msg even when it is huge? + memcpy(tmp->data+TIPCDUMP_HEADER_SIZE, (char *)msg, tipc_msg_size); + + list_add_tail(&(tmp->list), &(tipcdump_info.td_list.list)); + tipcdump_info.queue_size += tmp->data_size; + + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); + wake_up_interruptible(&(tipcdump_info.wait_queue)); + return(retval); + +out: + spin_unlock_irqrestore(&(tipcdump_info.lock), flags); +#if 0 +#ifdef CONFIG_PROC_FS + if(tipc_msg_size == 0) + { + if(msg == NULL) + return(retval); + tipc_msg_size = msg_size(msg); + } + write_lock(&tipc_stats_lock); + if(msg_direction == TIPCDUMP_MSG_SENT) + { + (tipc_stats_info.msg_sent)++; + tipc_stats_info.bytes_sent += tipc_msg_size; + + } else + { + (tipc_stats_info.msg_recv)++; + tipc_stats_info.bytes_recv += tipc_msg_size; + } + write_unlock(&tipc_stats_lock); +#endif /* CONFIG_PROC_FS */ +#endif + DEBUG0("tipcdump_enqueue: end\n"); + return(retval); +} + diff -Nur tipc-1.7.5/net/tipc/tipc_dump.h tipc-1.7.5+tipcdump/net/tipc/tipc_dump.h --- tipc-1.7.5/net/tipc/tipc_dump.h 1970-01-01 07:00:00.000000000 +0700 +++ tipc-1.7.5+tipcdump/net/tipc/tipc_dump.h 2008-07-18 20:34:52.000000000 +0800 @@ -0,0 +1,136 @@ +/* + Author: Nortel Networks + + Copyright 2005 Nortel Networks + + July 2008 Alcatel-Lucent Adaptation from tipc 1.5.12 to 1.7.5 + + 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. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES,REPRESENTATIONS, AND CONDITIONS INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. See the GNU General Public License + for more details. + + IN NO EVENT SHALL THE COPYRIGHT OWNER 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. + + You should have received a copy of the GNU General Public License along + with this program; if not, contact the Free Software Foundation, Inc., + 675 Mass Ave, Cambridge, MA 02139, USA www.fsf.org/ for a copy. +*/ + + +#ifndef _TIPC_DUMP_H +#define _TIPC_DUMP_H + +#include +#include +#include +#include + +/* + * The tipcdump queue will allow this much space before it starts to + * drop messages. This prevents memory exhaustion. + */ +#define TIPCDUMP_MAX_QUEUE_SIZE (10 * 1024 * 1024) + +/* + * tipcdump buffer list. + */ +typedef struct tdbuf_list { + char *data; + int data_size; + struct list_head list; +} tdbuf_list_t; + +/* + * Global structure for holding tipcdump information. + */ +typedef struct tipcdump_info +{ + int majornum; /* register_chrdev major number */ + struct file_operations devops; /* structure for holding functions */ + + int32_t queue_size; /* number of bytes currently sitting on tipcdump queue */ + + /* + ** Status/lock fields. + */ + uint64_t dropped_messages; + wait_queue_head_t wait_queue; + spinlock_t lock; + int opened; + int p_enabled; + int i_enabled; + tdbuf_list_t td_list; +} tipcdump_info_t; + + +static inline void copy_timeval_64to32(struct timeval32 *t_dest, struct timeval *t_source) +{ + t_dest->tv_sec = t_source->tv_sec; + t_dest->tv_usec = t_source->tv_usec; +} + +#ifdef CONFIG_PROC_FS +typedef struct tipc_stats +{ + char in_use; + struct timeval start_time; + struct timeval curr_time; + uint64_t msg_recv; + uint64_t msg_sent; + uint64_t bytes_recv; + uint64_t bytes_sent; +} tipc_stats_info_t; +#endif /* CONFIG_PROC_FS */ + +extern int tipcdump_register(void); +extern int tipcdump_deregister(void); +extern int tipcdump_enqueue(struct sk_buff *skb, u32 msg_direction); + +#define PRINT printk + +#ifdef TIPCDUMP_CFGDEBUG +#define DEBUG0(string) \ + PRINT(string) +#define DEBUG1(string, arg1) \ + PRINT(string, arg1) +#define DEBUG2(string, arg1, arg2) \ + PRINT(string, arg1, arg2) +#define DEBUG3(string, arg1, arg2, arg3) \ + PRINT(string, arg1, arg2, arg3) +#define DEBUG4(string, arg1, arg2, arg3, arg4) \ + PRINT(string, arg1, arg2, arg3, arg4) +#define DEBUG5(string, arg1, arg2, arg3, arg4, arg5) \ + PRINT(string, arg1, arg2, arg3, arg4, arg5) +#define DEBUG6(string, arg1, arg2, arg3, arg4, arg5, arg6) \ + PRINT(string, arg1, arg2, arg3, arg4, arg5, arg6) +#define DEBUG7(string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ + PRINT(string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define DEBUG8(string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ + PRINT(string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +#else +#define DEBUG0(string) +#define DEBUG1(string, arg1) +#define DEBUG2(string, arg1, arg2) +#define DEBUG3(string, arg1, arg2, arg3) +#define DEBUG4(string, arg1, arg2, arg3, arg4) +#define DEBUG5(string, arg1, arg2, arg3, arg4, arg5) +#define DEBUG6(string, arg1, arg2, arg3, arg4, arg5, arg6) +#define DEBUG7(string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define DEBUG8(string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +#endif /* TIPCDUMP_CFGDEBUG */ + +#endif /* _TIPC_DUMP_H */ diff -Nur tipc-1.7.5/net/tipc/tipc_eth_media.c tipc-1.7.5+tipcdump/net/tipc/tipc_eth_media.c --- tipc-1.7.5/net/tipc/tipc_eth_media.c 2007-09-07 04:22:27.000000000 +0800 +++ tipc-1.7.5+tipcdump/net/tipc/tipc_eth_media.c 2008-07-18 20:34:52.000000000 +0800 @@ -42,6 +42,10 @@ #include #include +#ifdef TIPCDUMP +#include "tipc_dump.h" +#endif /* TIPCDUMP */ + #define MAX_ETH_BEARERS TIPC_MAX_BEARERS #define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI #define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL @@ -128,6 +132,9 @@ buf_clone->nh.raw = buf_clone->data; buf_clone->dev = dev; +#ifdef TIPCDUMP + tipcdump_enqueue(buf, TIPCDUMP_MSG_SENT); +#endif /* TIPCDUMP */ dev->hard_header(buf_clone, dev, ETH_P_TIPC, &dest->value[4], dev->dev_addr, buf_clone->len); dev_queue_xmit(buf_clone); @@ -150,6 +157,9 @@ if (likely(eb_ptr->bearer)) { if (likely(buf->pkt_type <= PACKET_BROADCAST)) { buf->next = NULL; +#ifdef TIPCDUMP + tipcdump_enqueue(buf, TIPCDUMP_MSG_RECEIVED); +#endif /* TIPCDUMP */ tipc_recv_msg(buf, eb_ptr->bearer); return TIPC_OK; } diff -Nur tipc-1.7.5/net/tipc/tipc.mod.c tipc-1.7.5+tipcdump/net/tipc/tipc.mod.c --- tipc-1.7.5/net/tipc/tipc.mod.c 1970-01-01 07:00:00.000000000 +0700 +++ tipc-1.7.5+tipcdump/net/tipc/tipc.mod.c 2008-07-18 20:34:52.000000000 +0800 @@ -0,0 +1,126 @@ +#include +#include +#include + +MODULE_INFO(vermagic, VERMAGIC_STRING); + +struct module __this_module +__attribute__((section(".gnu.linkonce.this_module"))) = { + .name = KBUILD_MODNAME, + .init = init_module, +#ifdef CONFIG_MODULE_UNLOAD + .exit = cleanup_module, +#endif +}; + +static const struct modversion_info ____versions[] +__attribute_used__ +__attribute__((section("__versions"))) = { + { 0x89e24b9c, "struct_module" }, + { 0xaacbc3a2, "release_sock" }, + { 0x1c5b2327, "kmem_cache_destroy" }, + { 0x12da5bb2, "__kmalloc" }, + { 0xff2ee19e, "sock_init_data" }, + { 0x8ab7ffea, "genl_register_family" }, + { 0xd6ee688f, "vmalloc" }, + { 0xcc4c11a9, "_write_unlock_bh" }, + { 0x3d7c39ea, "_read_lock" }, + { 0xae77b6d6, "genl_sock" }, + { 0xc7ec6c27, "strspn" }, + { 0xe1b7029c, "print_tainted" }, + { 0xfb80340d, "genl_unregister_family" }, + { 0xc8b57c27, "autoremove_wake_function" }, + { 0x79aa04a2, "get_random_bytes" }, + { 0x38f88db9, "sock_no_ioctl" }, + { 0xab978df6, "malloc_sizes" }, + { 0xc4f02fe7, "skb_clone" }, + { 0x14990642, "skb_copy" }, + { 0x1bcd461f, "_spin_lock" }, + { 0xf6a5a6c8, "schedule_work" }, + { 0x63ecad53, "register_netdevice_notifier" }, + { 0x5d57df57, "remove_proc_entry" }, + { 0xa03d6a57, "__get_user_4" }, + { 0x2fd1d81c, "vfree" }, + { 0x87cddf59, "_spin_lock_irqsave" }, + { 0x1d26aa98, "sprintf" }, + { 0x7d11c268, "jiffies" }, + { 0x343a1a8, "__list_add" }, + { 0xfe769456, "unregister_netdevice_notifier" }, + { 0x153390a7, "sock_no_sendpage" }, + { 0x12f237eb, "__kzalloc" }, + { 0x50648651, "__pskb_pull_tail" }, + { 0x233de288, "sock_no_mmap" }, + { 0xc659d5a, "del_timer_sync" }, + { 0x2bc95bd4, "memset" }, + { 0x2fc7657d, "sock_no_socketpair" }, + { 0x21968b7f, "_read_lock_bh" }, + { 0x975c62af, "sk_alloc" }, + { 0x93ba42f1, "_write_lock_bh" }, + { 0x1b7d4074, "printk" }, + { 0x859204af, "sscanf" }, + { 0x5152e605, "memcmp" }, + { 0xed5c73bf, "__tasklet_schedule" }, + { 0x2da418b5, "copy_to_user" }, + { 0x309b174c, "dev_base" }, + { 0xb689e344, "kmem_cache_free" }, + { 0x521445b, "list_del" }, + { 0x5730615d, "sk_free" }, + { 0xd5d1d27e, "dev_remove_pack" }, + { 0xa20fdde, "_spin_unlock_irqrestore" }, + { 0xf3b39202, "mod_timer" }, + { 0xca84dc11, "netlink_unicast" }, + { 0x79ad224b, "tasklet_kill" }, + { 0x9c0f4990, "lock_sock" }, + { 0x1c53db6e, "skb_over_panic" }, + { 0x7dceceac, "capable" }, + { 0xb2b4eeda, "proto_register" }, + { 0x19070091, "kmem_cache_alloc" }, + { 0xb2fd5ceb, "__put_user_4" }, + { 0x9aebf873, "__alloc_skb" }, + { 0x4f2fd580, "sock_register" }, + { 0x4292364c, "schedule" }, + { 0x17d59d01, "schedule_timeout" }, + { 0x89d282ea, "kfree_skb" }, + { 0x5da9930a, "proto_unregister" }, + { 0x6b2dc060, "dump_stack" }, + { 0xb08e0988, "skb_under_panic" }, + { 0x4086729e, "register_chrdev" }, + { 0xd5028665, "create_proc_entry" }, + { 0xf39bf4d9, "put_cmsg" }, + { 0xc39a6532, "pskb_expand_head" }, + { 0x8bf46c54, "_read_unlock_bh" }, + { 0xfc76e10b, "kmem_cache_create" }, + { 0x19cacd0, "init_waitqueue_head" }, + { 0xd0b91f9b, "init_timer" }, + { 0x59968f3c, "__wake_up" }, + { 0xb85ab97a, "kmem_cache_zalloc" }, + { 0x72270e35, "do_gettimeofday" }, + { 0xe32e66b5, "_spin_unlock_bh" }, + { 0x37a0cba, "kfree" }, + { 0x2e60bace, "memcpy" }, + { 0x801678, "flush_scheduled_work" }, + { 0x76fff869, "___pskb_trim" }, + { 0xc8f02aeb, "prepare_to_wait" }, + { 0x2394a062, "sock_unregister" }, + { 0x46d33fe1, "list_add" }, + { 0xc192d491, "unregister_chrdev" }, + { 0x865edc9b, "finish_wait" }, + { 0xf14d31c7, "genl_register_ops" }, + { 0x25da070, "snprintf" }, + { 0xb5d5e660, "dev_add_pack" }, + { 0xc6bf4844, "_spin_trylock_bh" }, + { 0x8235805b, "memmove" }, + { 0x10818a0c, "dev_queue_xmit" }, + { 0x6943ea4b, "_spin_lock_bh" }, + { 0xbfb6398, "skb_copy_bits" }, + { 0xf2a644fb, "copy_from_user" }, + { 0x782b0008, "vsprintf" }, +}; + +static const char __module_depends[] +__attribute_used__ +__attribute__((section(".modinfo"))) = +"depends="; + + +MODULE_INFO(srcversion, "53A7144BEDD60BDC0DD7B80"); diff -Nur tipc-1.7.5/net/tipc/tipc_msg.c tipc-1.7.5+tipcdump/net/tipc/tipc_msg.c --- tipc-1.7.5/net/tipc/tipc_msg.c 2007-08-31 01:22:30.000000000 +0800 +++ tipc-1.7.5+tipcdump/net/tipc/tipc_msg.c 2008-07-18 20:34:52.000000000 +0800 @@ -40,6 +40,10 @@ #include "tipc_msg.h" #include "tipc_bearer.h" +#ifdef TIPCDUMP +#include "tipc_dump.h" +#endif /* TIPCDUMP */ + /** * tipc_msg_build - create message using specified header and data @@ -84,8 +88,13 @@ msg_sect[cnt].iov_len); pos += msg_sect[cnt].iov_len; } - if (likely(res)) + if (likely(res)) { +#ifdef TIPCDUMP + if(msg_destnode(buf_msg(*buf)) == tipc_own_addr || msg_destnode(buf_msg(*buf)) == 0) + tipcdump_enqueue(*buf, TIPCDUMP_MSG_SENT); +#endif /* TIPCDUMP */ return dsz; + } buf_discard(*buf); *buf = NULL; diff -Nur tipc-1.7.5/net/tipc/tipc_port.c tipc-1.7.5+tipcdump/net/tipc/tipc_port.c --- tipc-1.7.5/net/tipc/tipc_port.c 2007-09-05 01:24:09.000000000 +0800 +++ tipc-1.7.5+tipcdump/net/tipc/tipc_port.c 2008-07-18 20:34:52.000000000 +0800 @@ -46,6 +46,10 @@ #include "tipc_msg.h" #include "tipc_bcast.h" +#ifdef TIPCDUMP +#include "tipc_dump.h" +#endif /* TIPCDUMP */ + /* Connection management: */ #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ #define CONFIRMED 0 @@ -1370,6 +1374,12 @@ } } err = p_ptr->dispatcher(&p_ptr->publ, buf); +#ifdef TIPCDUMP + if (likely(!err)) { + if (msg_orignode(msg) == tipc_own_addr) // local msg only + tipcdump_enqueue(buf, TIPCDUMP_MSG_RECEIVED); + } +#endif /* TIPCDUMP */ tipc_port_unlock(p_ptr); if (likely(!err)) return dsz;