1 diff -Naur linux-2.6.32-27.planetlab.i686.orig/Documentation/web100/locking.txt linux-2.6.32-27.planetlab.i686/Documentation/web100/locking.txt
2 --- linux-2.6.32-27.planetlab.i686.orig/Documentation/web100/locking.txt 1969-12-31 19:00:00.000000000 -0500
3 +++ linux-2.6.32-27.planetlab.i686/Documentation/web100/locking.txt 2011-11-16 16:51:06.764471232 -0500
5 +Web100 Locking Model for Linux 2.4
6 +John Heffner <jheffner@psc.edu>
12 +The connections entries are kept linked together simultaneously in a table
13 +and in a list. Only entries in these structures can be looked up. To
14 +protect these lookup structures, we have a single global reader-writer
15 +spinlock, web100_linkage_lock. Since we grab the lock both from user space
16 +and in the bottom half, we must do a [read/write]_lock_bh. As this disables
17 +the local BH's, this lock should *not* be held for very long.
22 +The statistics are protected by the sock's lock. Any code modifying or
23 +reading the statistics should hold the sock lock while doing so. We assume
24 +that if the socket is gone, the statistics should not be modified, so
25 +readers need not hold any lock.
28 +3. Statistics Destruction
30 +A statistics structure keeps a count of the number of references to it,
31 +wc_users. When a lookup is performed, the reference count should be
32 +incremented (while the linkage lock is held) by calling web100_stats_use.
33 +When the reference is no longer needed, decrement the count by calling
34 +web100_stats_unuse. The latter function will free the statistics when there
35 +are no remaining references. The lookup structures keep one reference. The
36 +sock also keeps one, since the sock may be destroyed before it ever enters
37 +the ESTABLISHED state.
38 diff -Naur linux-2.6.32-27.planetlab.i686.orig/Documentation/web100/proc_interface.txt linux-2.6.32-27.planetlab.i686/Documentation/web100/proc_interface.txt
39 --- linux-2.6.32-27.planetlab.i686.orig/Documentation/web100/proc_interface.txt 1969-12-31 19:00:00.000000000 -0500
40 +++ linux-2.6.32-27.planetlab.i686/Documentation/web100/proc_interface.txt 2011-11-16 16:51:06.764471232 -0500
42 +WEB100 proc interface notes
43 +===========================
45 +The web100 modifications to the kernel collect information about the
46 +state of a TCP transfer in a kernel data structure that is linked
47 +out of the "sock" TCP structure in sock.h. Please see
48 +"include/net/web100_stats.h" for the structure definition.
50 +The API for this structure is provided through the /proc interface.
51 +This document provides a brief description of this interface. Please
52 +see fs/proc/web100.c for source code.
54 +First, kernel creates the /proc/web100 directory and the file
55 +/proc/web100/header at system boot time.
57 +Each new TCP connection is assigned a unique, unchanging number
58 +(similar to a pid), and its directory name is that number as ASCII
59 +decimal. These directories persist for about sixty seconds after the
60 +connection is terminated (goes into a CLOSED or TIME_WAIT state). The
61 +connection stats will not change after the connection is terminated.
62 +(So a connection whose state variable is TIME_WAIT is not necessarily
63 +still in TIME_WAIT.) It should be noted that what is meant by a
64 +"connection" here is actually one side of a connection. If a
65 +connection is created from the local host to the local host, two
66 +connection ID's will be created.
68 +When writing an application to read from the proc interface, it should be
69 +taken into consideration that the directories and their files can disappear at
70 +any time (they do so at an interrupt level). So if a file open fails on a
71 +file you just looked up (say, with glob), that's probably normal and the
72 +program should handle it gracefully.
74 +Another seemingly strange thing that can happen is that stats for multiple
75 +connections with the same four-tuple can show up. No more than one of the
76 +connections may be in any state but CLOSED or TIME_WAIT. This behavior is
77 +correct, and should be handled as such.
79 +The algorithms governing the connection numbers are not yet final.
80 +Currently, for simplification, it is only possible to have 32768
83 +Inside each connection directory is an identical set of files. One is
84 +spec-ascii, which contains the connection four-tuple in human-readable
85 +format. One can, for example, see all outgoing ssh connections by executing
86 +"grep ':22$' /proc/web100/*/spec-ascii" from the command prompt.
88 +The remaining files provide access to states of TCP-KIS variables in
89 +local host byte-order. Since the number, names, and contents of these
90 +files can and will change with releases, they are described in a
91 +header file -- /proc/web100/header. A file named spec, which contains the
92 +variables describing the connection's four-tuple, should be present
95 +The header file is in human-readable format as follows:
99 + <varname> <offset> <type>
100 + <varname> <offset> <type>
105 +The filename is the name of the file inside each connection directory. (The
106 +/ is prepended to make it clear it is a new file, not a new variable in the
107 +previous file. There is also an empty line before each filename.) Each
108 +file has an arbitrary number of variables, and there are an arbitrary number
109 +of files. The type is an integer, and is currently defined something like:
112 + WEB100_TYPE_INTEGER,
113 + WEB100_TYPE_INTEGER32,
114 + WEB100_TYPE_IP_ADDRESS,
115 + WEB100_TYPE_COUNTER32,
116 + WEB100_TYPE_GAUGE32,
117 + WEB100_TYPE_UNSIGNED32,
118 + WEB100_TYPE_TIME_TICKS,
119 + WEB100_TYPE_COUNTER64,
120 + WEB100_TYPE_UNSIGNED16
123 +in the kernel source file fs/proc/web100.c. These correspond to
124 +MIB-II types. (RFC2578)
126 +To read variables, seek to the appropriate offset, then read the appropriate
127 +amount of data. (Length is implied by the type.) Multiple variables may be
128 +read with a single read, and will be read atomically when doing so.
129 +Currently, all variables are readable, but this may not be true in the
132 +To write variables, seek to the appropriate offset, and write the
133 +appropriate amount of data. Only a single variable may be written at one
134 +time. If variables must be atomically written, a variable should be used as
135 +a flag to signal that the write is done, and the kernel code depending on
136 +the variables should be written to handle this.
138 +See: http://www.web100.org
139 +Please send coments to prog@web100.org
141 +John Heffner, Matt Mathis, R. Reddy
142 +August 2000, Jan 2001
144 diff -Naur linux-2.6.32-27.planetlab.i686.orig/Documentation/web100/sysctl.txt linux-2.6.32-27.planetlab.i686/Documentation/web100/sysctl.txt
145 --- linux-2.6.32-27.planetlab.i686.orig/Documentation/web100/sysctl.txt 1969-12-31 19:00:00.000000000 -0500
146 +++ linux-2.6.32-27.planetlab.i686/Documentation/web100/sysctl.txt 2011-11-16 16:51:06.764471232 -0500
148 +Web100 sysctl variables
149 +John Heffner <jheffner@psc.edu>
152 +net.ipv4.WAD_FloydAIMD
153 + This value is used for WAD_FloydAIMD by a connection when its KIS
154 + variable is 0. This variable requires that private extenisons be
158 + This value is used for WAD_IFQ by a connection when its KIS
159 + variable is 0. This variable requires that Net100 extensions be
162 +net.ipv4.WAD_MaxBurst
163 + This value is used for WAD_MaxBurst by a connection when its KIS
164 + variable is 0. This variable requires that Net100 extensions be
167 +net.ipv4.web100_fperms
168 + Sets the file permissions of the files in /proc/web100/*/
171 + Sets the group of the files in /proc/web100/*/
172 diff -Naur linux-2.6.32-27.planetlab.i686.orig/fs/proc/Makefile linux-2.6.32-27.planetlab.i686/fs/proc/Makefile
173 --- linux-2.6.32-27.planetlab.i686.orig/fs/proc/Makefile 2011-11-16 16:51:07.757475369 -0500
174 +++ linux-2.6.32-27.planetlab.i686/fs/proc/Makefile 2011-11-16 16:51:06.202465318 -0500
176 proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
177 proc-$(CONFIG_PRINTK) += kmsg.o
178 proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o
179 +proc-$(CONFIG_WEB100_STATS) += web100.o
180 diff -Naur linux-2.6.32-27.planetlab.i686.orig/fs/proc/root.c linux-2.6.32-27.planetlab.i686/fs/proc/root.c
181 --- linux-2.6.32-27.planetlab.i686.orig/fs/proc/root.c 2011-11-16 16:51:07.757475369 -0500
182 +++ linux-2.6.32-27.planetlab.i686/fs/proc/root.c 2011-11-16 16:51:06.194471290 -0500
184 proc_mkdir("bus", NULL);
188 +#ifdef CONFIG_WEB100_STATS
189 + proc_web100_init();
193 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
194 diff -Naur linux-2.6.32-27.planetlab.i686.orig/fs/proc/web100.c linux-2.6.32-27.planetlab.i686/fs/proc/web100.c
195 --- linux-2.6.32-27.planetlab.i686.orig/fs/proc/web100.c 1969-12-31 19:00:00.000000000 -0500
196 +++ linux-2.6.32-27.planetlab.i686/fs/proc/web100.c 2011-11-16 16:51:06.194471290 -0500
201 + * Copyright (C) 2001 Matt Mathis <mathis@psc.edu>
202 + * Copyright (C) 2001 John Heffner <jheffner@psc.edu>
204 + * The Web 100 project. See http://www.web100.org
206 + * This program is free software; you can redistribute it and/or
207 + * modify it under the terms of the GNU General Public License
208 + * as published by the Free Software Foundation; either version
209 + * 2 of the License, or (at your option) any later version.
213 +#include <linux/proc_fs.h>
214 +#include <net/sock.h>
215 +#include <net/tcp.h>
216 +#include <net/web100.h>
217 +#include <linux/init.h>
218 +#include <linux/sysctl.h>
219 +#include <linux/mount.h>
221 +#include "internal.h"
223 +#define WEB100MIB_BLOCK_SIZE PAGE_SIZE - 1024
225 +extern __u32 sysctl_wmem_default;
226 +extern __u32 sysctl_wmem_max;
228 +struct proc_dir_entry *proc_web100_dir;
229 +static struct proc_dir_entry *proc_web100_header;
233 + * Web100 variable reading/writing
236 +enum web100_connection_inos {
237 + PROC_CONN_SPEC_ASCII = 1,
242 + PROC_CONN_HIGH_INO /* Keep at the end */
246 + WEB100_TYPE_INTEGER = 0,
247 + WEB100_TYPE_INTEGER32,
248 + WEB100_TYPE_INET_ADDRESS_IPV4,
249 + WEB100_TYPE_IP_ADDRESS = WEB100_TYPE_INET_ADDRESS_IPV4, /* Depricated */
250 + WEB100_TYPE_COUNTER32,
251 + WEB100_TYPE_GAUGE32,
252 + WEB100_TYPE_UNSIGNED32,
253 + WEB100_TYPE_TIME_TICKS,
254 + WEB100_TYPE_COUNTER64,
255 + WEB100_TYPE_INET_PORT_NUMBER,
256 + WEB100_TYPE_UNSIGNED16 = WEB100_TYPE_INET_PORT_NUMBER, /* Depricated */
257 + WEB100_TYPE_INET_ADDRESS,
258 + WEB100_TYPE_INET_ADDRESS_IPV6,
262 +typedef int (*web100_rwfunc_t)(void *buf, struct web100stats *stats,
263 + struct web100_var *vp);
265 +/* The printed variable description should look something like this (in ASCII):
266 + * varname offset type
267 + * where offset is the offset into the file.
274 + web100_rwfunc_t read;
275 + unsigned long read_data; /* read handler-specific data */
277 + web100_rwfunc_t write;
278 + unsigned long write_data; /* write handler-specific data */
280 + struct web100_var *next;
283 +struct web100_file {
289 + struct web100_var *first_var;
292 +#define F(name,ino,perm) { sizeof (name) - 1, (name), (ino), (perm), NULL }
293 +static struct web100_file web100_file_arr[] = {
294 + F("spec-ascii", PROC_CONN_SPEC_ASCII, S_IFREG | S_IRUGO),
295 + F("spec", PROC_CONN_SPEC, S_IFREG | S_IRUGO),
296 + F("read", PROC_CONN_READ, 0),
297 + F("test", PROC_CONN_TEST, 0),
298 + F("tune", PROC_CONN_TUNE, 0),
301 +#define WEB100_FILE_ARR_SIZE (sizeof (web100_file_arr) / sizeof (struct web100_file))
303 +/* This works only if the array is built in the correct order. */
304 +static inline struct web100_file *web100_file_lookup(int ino) {
305 + return &web100_file_arr[ino - 1];
308 +static void add_var(struct web100_file *file, char *name, int type,
309 + web100_rwfunc_t read, unsigned long read_data,
310 + web100_rwfunc_t write, unsigned long write_data)
312 + struct web100_var *var;
314 + /* Again, assuming add_var is only called at init. */
315 + if ((var = kmalloc(sizeof (struct web100_var), GFP_KERNEL)) == NULL)
316 + panic("No memory available for Web100 var.\n");
321 + case WEB100_TYPE_INET_PORT_NUMBER:
324 + case WEB100_TYPE_INTEGER:
325 + case WEB100_TYPE_INTEGER32:
326 + case WEB100_TYPE_COUNTER32:
327 + case WEB100_TYPE_GAUGE32:
328 + case WEB100_TYPE_UNSIGNED32:
329 + case WEB100_TYPE_TIME_TICKS:
332 + case WEB100_TYPE_COUNTER64:
335 + case WEB100_TYPE_INET_ADDRESS:
339 + printk("Web100: Warning: Adding variable of unknown type.\n");
344 + var->read_data = read_data;
346 + var->write = write;
347 + var->write_data = write_data;
349 + var->next = file->first_var;
350 + file->first_var = var;
355 + * proc filesystem routines
358 +static struct inode *proc_web100_make_inode(struct super_block *sb, int ino)
360 + struct inode *inode;
362 + inode = new_inode(sb);
366 + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
367 + inode->i_ino = ino;
376 +static inline ino_t ino_from_cid(int cid)
378 + return (cid << 8) | 0x80000000;
381 +static inline ino_t ino_from_parts(ino_t dir_ino, __u16 low_ino)
383 + return (dir_ino & ~0xff) | low_ino;
386 +static inline int cid_from_ino(ino_t ino)
388 + return (ino & 0x7fffff00) >> 8;
391 +static inline int low_from_ino(ino_t ino)
396 +static int connection_file_open(struct inode *inode, struct file *file)
398 + int cid = cid_from_ino(inode->i_ino);
399 + struct web100stats *stats;
401 + read_lock_bh(&web100_linkage_lock);
402 + stats = web100stats_lookup(cid);
403 + if (stats == NULL || stats->wc_dead) {
404 + read_unlock_bh(&web100_linkage_lock);
407 + web100_stats_use(stats);
408 + read_unlock_bh(&web100_linkage_lock);
413 +static int connection_file_release(struct inode *inode, struct file *file)
415 + int cid = cid_from_ino(inode->i_ino);
416 + struct web100stats *stats;
418 + read_lock_bh(&web100_linkage_lock);
419 + stats = web100stats_lookup(cid);
420 + if (stats == NULL) {
421 + read_unlock_bh(&web100_linkage_lock);
424 + read_unlock_bh(&web100_linkage_lock);
425 + web100_stats_unuse(stats);
430 +/** /proc/web100/<connection>/<binary variable files> **/
431 +static ssize_t connection_file_rw(int read, struct file *file,
432 + char *buf, size_t nbytes, loff_t *ppos)
434 + int low_ino = low_from_ino(file->f_dentry->d_inode->i_ino);
435 + int cid = cid_from_ino(file->f_dentry->d_inode->i_ino);
436 + struct web100stats *stats;
437 + struct web100_file *fp;
438 + struct web100_var *vp;
442 + web100_rwfunc_t rwfunc;
445 + /* We're only going to let them read one page at a time.
446 + * We shouldn't ever read more than a page, anyway, though.
448 + if (nbytes > PAGE_SIZE)
449 + nbytes = PAGE_SIZE;
451 + if (!access_ok(read ? VERIFY_WRITE : VERIFY_READ, buf, nbytes))
454 + if ((page = (char *)__get_free_page(GFP_KERNEL)) == NULL)
458 + if (copy_from_user(page, buf, nbytes))
462 + fp = web100_file_lookup(low_ino);
464 + printk("Unregistered Web100 file.\n");
468 + read_lock_bh(&web100_linkage_lock);
469 + stats = web100stats_lookup(cid);
470 + read_unlock_bh(&web100_linkage_lock);
474 + lock_sock(stats->wc_sk);
476 + /* TODO: seek in constant time, not linear. -JWH */
479 + vp = fp->first_var;
480 + while (vp && nbytes > n) {
485 + if (pos == *ppos) {
486 + if (vp->len > nbytes - n)
492 + rwfunc = vp->write;
493 + if (rwfunc == NULL) {
498 + err = rwfunc(page + n, stats, vp);
509 + release_sock(stats->wc_sk);
512 + if (copy_to_user(buf, page, n))
515 + free_page((unsigned long)page);
520 + release_sock(stats->wc_sk);
525 +static ssize_t connection_file_read(struct file *file,
526 + char *buf, size_t nbytes, loff_t *ppos)
528 + return connection_file_rw(1, file, buf, nbytes, ppos);
531 +static ssize_t connection_file_write(struct file *file,
532 + const char *buf, size_t nbytes, loff_t *ppos)
534 + return connection_file_rw(0, file, (char *)buf, nbytes, ppos);
537 +static struct file_operations connection_file_fops = {
538 + open: connection_file_open,
539 + release: connection_file_release,
540 + read: connection_file_read,
541 + write: connection_file_write
545 +static size_t v6addr_str(char *dest, short *addr)
547 + int start = -1, end = -1;
551 + /* Find longest subsequence of 0's in addr */
552 + for (i = 0; i < 8; i++) {
553 + if (addr[i] == 0) {
554 + for (j = i + 1; addr[j] == 0 && j < 8; j++);
555 + if (j - i > end - start) {
562 + if (end - start == 1)
566 + for (i = 0; i < 8; i++) {
568 + pos += sprintf(dest + pos, ":");
570 + pos += sprintf(dest + pos, ":");
571 + i += end - start - 1;
573 + pos += sprintf(dest + pos, "%hx", ntohs(addr[i]));
580 +/** /proc/web100/<connection>/spec_ascii **/
581 +static ssize_t connection_spec_ascii_read(struct file * file, char * buf,
582 + size_t nbytes, loff_t *ppos)
584 + __u32 local_addr, remote_addr;
585 + __u16 local_port, remote_port;
587 + struct web100stats *stats;
588 + struct web100directs *vars;
595 + cid = cid_from_ino(file->f_dentry->d_parent->d_inode->i_ino);
597 + read_lock_bh(&web100_linkage_lock);
598 + stats = web100stats_lookup(cid);
599 + read_unlock_bh(&web100_linkage_lock);
602 + vars = &stats->wc_vars;
604 + if (vars->LocalAddressType == WC_ADDRTYPE_IPV4) {
605 + /* These values should not change while stats are linked.
606 + * We don't need to lock the sock. */
607 + local_addr = ntohl(vars->LocalAddress.v4addr);
608 + remote_addr = ntohl(vars->RemAddress.v4addr);
609 + local_port = vars->LocalPort;
610 + remote_port = vars->RemPort;
612 + len = sprintf(tmpbuf, "%d.%d.%d.%d:%d %d.%d.%d.%d:%d\n",
613 + (local_addr >> 24) & 0xff,
614 + (local_addr >> 16) & 0xff,
615 + (local_addr >> 8) & 0xff,
618 + (remote_addr >> 24) & 0xff,
619 + (remote_addr >> 16) & 0xff,
620 + (remote_addr >> 8) & 0xff,
621 + remote_addr & 0xff,
623 + } else if (vars->LocalAddressType == WC_ADDRTYPE_IPV6) {
624 + local_port = vars->LocalPort;
625 + remote_port = vars->RemPort;
627 + len += v6addr_str(tmpbuf + len, (short *)&vars->LocalAddress.v6addr.addr);
628 + len += sprintf(tmpbuf + len, ".%d ", local_port);
629 + len += v6addr_str(tmpbuf + len, (short *)&vars->RemAddress.v6addr.addr);
630 + len += sprintf(tmpbuf + len, ".%d\n", remote_port);
632 + printk(KERN_ERR "connection_spec_ascii_read: LocalAddressType invalid\n");
636 + len = len > nbytes ? nbytes : len;
637 + if (copy_to_user(buf, tmpbuf, len))
643 +static struct file_operations connection_spec_ascii_fops = {
644 + open: connection_file_open,
645 + release: connection_file_release,
646 + read: connection_spec_ascii_read
650 +/** /proc/web100/<connection>/ **/
651 +static int connection_dir_readdir(struct file *filp,
652 + void *dirent, filldir_t filldir)
655 + struct inode *inode = filp->f_dentry->d_inode;
656 + struct web100_file *p;
661 + if (filldir(dirent, ".", 1, i, inode->i_ino, DT_DIR) < 0)
667 + if (filldir(dirent, "..", 2, i, proc_web100_dir->low_ino, DT_DIR) < 0)
674 + if (i >= WEB100_FILE_ARR_SIZE)
676 + p = &web100_file_arr[i];
678 + if (filldir(dirent, p->name, p->len, filp->f_pos,
679 + ino_from_parts(inode->i_ino, p->low_ino),
680 + p->mode >> 12) < 0)
690 +static struct dentry *connection_dir_lookup(struct inode *dir,
691 + struct dentry *dentry, struct nameidata *nd)
693 + struct inode *inode;
694 + struct web100_file *p;
695 + struct web100stats *stats;
699 + for (p = &web100_file_arr[0]; p->name; p++) {
700 + if (p->len != dentry->d_name.len)
702 + if (!memcmp(dentry->d_name.name, p->name, p->len))
706 + return ERR_PTR(-ENOENT);
708 + read_lock_bh(&web100_linkage_lock);
709 + if ((stats = web100stats_lookup(cid_from_ino(dir->i_ino))) == NULL) {
710 + read_unlock_bh(&web100_linkage_lock);
711 + printk("connection_dir_lookup: stats == NULL\n");
712 + return ERR_PTR(-ENOENT);
714 + uid = sock_i_uid(stats->wc_sk);
715 + read_unlock_bh(&web100_linkage_lock);
717 + inode = proc_web100_make_inode(dir->i_sb, ino_from_parts(dir->i_ino, p->low_ino));
719 + return ERR_PTR(-ENOMEM);
720 + inode->i_mode = p->mode ? p->mode : S_IFREG | sysctl_web100_fperms;
721 + inode->i_uid = uid;
722 + inode->i_gid = sysctl_web100_gid;
724 + switch (p->low_ino) {
725 + case PROC_CONN_SPEC_ASCII:
726 + inode->i_fop = &connection_spec_ascii_fops;
728 + case PROC_CONN_SPEC:
729 + case PROC_CONN_READ:
730 + case PROC_CONN_TEST:
731 + case PROC_CONN_TUNE:
732 + inode->i_fop = &connection_file_fops;
735 + printk("Web100: impossible type (%d)\n", p->low_ino);
737 + return ERR_PTR(-EINVAL);
740 + d_add(dentry, inode);
744 +static struct inode_operations connection_dir_iops = {
745 + .lookup = connection_dir_lookup
748 +static struct file_operations connection_dir_fops = {
749 + .readdir = connection_dir_readdir
753 +/** /proc/web100/header **/
754 +static ssize_t header_read(struct file * file, char * buf,
755 + size_t nbytes, loff_t *ppos)
760 + struct web100_file *fp;
761 + struct web100_var *vp;
766 + /* We will assume the variable description list will not change
767 + * after init. (True at least right now.) Otherwise, we would have
768 + * to have a lock on it.
771 + if ((tmpbuf = (char *)__get_free_page(GFP_KERNEL)) == NULL)
774 + offset = sprintf(tmpbuf, "%s\n", web100_version_string);
776 + for (i = 0; i < WEB100_FILE_ARR_SIZE; i++) {
777 + int file_offset = 0;
779 + if ((fp = &web100_file_arr[i]) == NULL)
782 + if (fp->first_var == NULL)
785 + offset += sprintf(tmpbuf + offset, "\n/%s\n", fp->name);
787 + vp = fp->first_var;
789 + if (offset > WEB100MIB_BLOCK_SIZE) {
792 + n = min(offset, min_t(loff_t, nbytes, len - *ppos));
793 + if (copy_to_user(buf, tmpbuf + max_t(loff_t, *ppos - len + offset, 0), n))
805 + offset += sprintf(tmpbuf + offset, "%s %d %d %d\n",
806 + vp->name, file_offset, vp->type, vp->len);
807 + file_offset += vp->len;
814 + n = min(offset, min_t(loff_t, nbytes, len - *ppos));
815 + if (copy_to_user(buf, tmpbuf + max_t(loff_t, *ppos - len + offset, 0), n))
817 + if (nbytes <= len - *ppos) {
830 + free_page((unsigned long)tmpbuf);
834 +static struct file_operations header_file_operations = {
839 +/** /proc/web100/ **/
840 +#define FIRST_CONNECTION_ENTRY 256
841 +#define NUMBUF_LEN 11
843 +static int get_connection_list(int pos, int *cids, int max)
845 + struct web100stats *stats;
848 + pos -= FIRST_CONNECTION_ENTRY;
851 + read_lock_bh(&web100_linkage_lock);
853 + stats = web100stats_first;
854 + while (stats && n < max) {
855 + if (!stats->wc_dead) {
857 + cids[n++] = stats->wc_cid;
862 + stats = stats->wc_next;
865 + read_unlock_bh(&web100_linkage_lock);
870 +static int cid_to_str(int cid, char *buf)
874 + if (cid == 0) { /* a special case */
878 + for (len = 0; len < NUMBUF_LEN - 1 && tmp > 0; len++)
882 + for (i = 0; i < len; i++) {
883 + buf[len - i - 1] = '0' + (cid % 10);
891 +static int web100_dir_readdir(struct file *filp,
892 + void *dirent, filldir_t filldir)
899 + char name[NUMBUF_LEN];
902 + if (filp->f_pos < FIRST_CONNECTION_ENTRY) {
903 + if ((err = proc_readdir(filp, dirent, filldir)) < 0)
905 + filp->f_pos = FIRST_CONNECTION_ENTRY;
907 + n_conns = WEB100_MAX_CONNS * 2;
910 + cids = kmalloc(n_conns * sizeof (int), GFP_KERNEL);
911 + } while (cids == NULL && n_conns > 0);
914 + n = get_connection_list(filp->f_pos, cids, n_conns);
916 + for (i = 0; i < n; i++) {
917 + ino = ino_from_cid(cids[i]);
918 + len = cid_to_str(cids[i], name);
919 + if (filldir(dirent, name, len, filp->f_pos,
920 + ino, DT_DIR) < 0) {
931 +static inline struct dentry *web100_dir_dent(void)
935 + qstr.name = "web100";
937 + qstr.hash = full_name_hash(qstr.name, qstr.len);
939 + return d_lookup(proc_mnt->mnt_sb->s_root, &qstr);
942 +void web100_proc_nlink_update(nlink_t nlink)
944 + struct dentry *dent;
946 + dent = web100_dir_dent();
948 + dent->d_inode->i_nlink = nlink;
952 +int web100_proc_dointvec_update(ctl_table *ctl, int write,
953 + void *buffer, size_t *lenp, loff_t *ppos)
959 + struct dentry *web100_dent, *conn_dent, *dent;
960 + struct inode *inode;
961 + struct web100_file *p;
962 + char name[NUMBUF_LEN];
964 + if ((err = proc_dointvec(ctl, write, buffer, lenp, ppos)) != 0)
967 + if ((web100_dent = web100_dir_dent()) == NULL)
970 + if ((cids = kmalloc(WEB100_MAX_CONNS * sizeof (int), GFP_KERNEL)) == NULL)
972 + n = get_connection_list(FIRST_CONNECTION_ENTRY, cids, WEB100_MAX_CONNS);
973 + for (i = 0; i < n; i++) {
974 + qstr.len = cid_to_str(cids[i], name);
976 + qstr.hash = full_name_hash(qstr.name, qstr.len);
977 + if ((conn_dent = d_lookup(web100_dent, &qstr)) != NULL) {
978 + for (p = &web100_file_arr[0]; p->name; p++) {
979 + qstr.name = p->name;
981 + qstr.hash = full_name_hash(qstr.name, qstr.len);
982 + if ((dent = d_lookup(conn_dent, &qstr)) != NULL) {
983 + inode = dent->d_inode;
984 + if ((inode->i_mode = p->mode) == 0)
985 + inode->i_mode = S_IFREG | sysctl_web100_fperms;
986 + inode->i_gid = sysctl_web100_gid;
999 +static int web100_proc_connection_revalidate(struct dentry *dentry, struct nameidata *nd)
1003 + if (dentry->d_inode == NULL)
1005 + read_lock_bh(&web100_linkage_lock);
1006 + if (web100stats_lookup(cid_from_ino(dentry->d_inode->i_ino)) == NULL) {
1010 + read_unlock_bh(&web100_linkage_lock);
1015 +static struct dentry_operations web100_dir_dentry_operations = {
1016 + d_revalidate: web100_proc_connection_revalidate
1019 +static struct dentry *web100_dir_lookup(struct inode *dir,
1020 + struct dentry *dentry, struct nameidata *nd)
1026 + struct inode *inode;
1027 + unsigned long ino;
1028 + struct web100stats *stats;
1030 + if (proc_lookup(dir, dentry, nd) == NULL)
1034 + name = (char *)(dentry->d_name.name);
1035 + len = dentry->d_name.len;
1036 + if (len <= 0) /* I don't think this can happen */
1037 + return ERR_PTR(-EINVAL);
1038 + while (len-- > 0) {
1043 + if (c > 9 || c < 0 || (cid == 0 && len != 0) || cid >= WEB100_MAX_CONNS) {
1049 + return ERR_PTR(-ENOENT);
1051 + read_lock_bh(&web100_linkage_lock);
1052 + stats = web100stats_lookup(cid);
1053 + if (stats == NULL || stats->wc_dead) {
1054 + read_unlock_bh(&web100_linkage_lock);
1055 + return ERR_PTR(-ENOENT);
1057 + read_unlock_bh(&web100_linkage_lock);
1059 + ino = ino_from_cid(cid);
1060 + inode = proc_web100_make_inode(dir->i_sb, ino);
1061 + if (inode == NULL)
1062 + return ERR_PTR(-ENOMEM);
1063 + inode->i_nlink = 2;
1064 + inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
1065 + inode->i_flags |= S_IMMUTABLE; /* ? */
1066 + inode->i_op = &connection_dir_iops;
1067 + inode->i_fop = &connection_dir_fops;
1069 + dentry->d_op = &web100_dir_dentry_operations;
1070 + d_add(dentry, inode);
1074 +static struct file_operations web100_dir_fops = {
1075 + .readdir = web100_dir_readdir
1078 +static struct inode_operations web100_dir_iops = {
1079 + .lookup = web100_dir_lookup
1084 + * Read/write handlers
1087 +/* A read handler for reading directly from the stats */
1088 +/* read_data is the byte offset into struct web100stats */
1089 +static int read_stats(void *buf, struct web100stats *stats,
1090 + struct web100_var *vp)
1092 + memcpy(buf, (char *)stats + vp->read_data, vp->len);
1097 +/* A write handler for writing directly to the stats */
1098 +/* write_data is a byte offset into struct web100stats */
1099 +static int write_stats(void *buf, struct web100stats *stats,
1100 + struct web100_var *vp)
1102 + memcpy((char *)stats + vp->read_data, buf, vp->len);
1107 +int read_LimCwnd(void *buf, struct web100stats *stats, struct web100_var *vp)
1109 + struct tcp_sock *tp = tcp_sk(stats->wc_sk);
1110 + __u32 tmp = (__u32)(tp->snd_cwnd_clamp * tp->mss_cache);
1112 + memcpy(buf, &tmp, 4);
1117 +int write_LimCwnd(void *buf, struct web100stats *stats, struct web100_var *vp)
1119 + struct tcp_sock *tp = tcp_sk(stats->wc_sk);
1121 + tp->snd_cwnd_clamp = min(*(__u32 *)buf / tp->mss_cache, 65535U);
1126 +int write_LimRwin(void *buf, struct web100stats *stats, struct web100_var *vp)
1128 + __u32 val = *(__u32 *)buf;
1129 + struct tcp_sock *tp = tcp_sk(stats->wc_sk);
1131 + stats->wc_vars.LimRwin = tp->window_clamp =
1132 + min(val, 65535U << tp->rx_opt.rcv_wscale);
1137 +int write_Sndbuf(void *buf, struct web100stats *stats, struct web100_var *vp)
1140 + struct sock *sk = stats->wc_sk;
1142 + memcpy(&val, buf, sizeof (int));
1144 + sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
1145 + sk->sk_sndbuf = max_t(int, SOCK_MIN_SNDBUF, min_t(int, sysctl_wmem_max, val));
1146 + sk->sk_write_space(sk);
1151 +int write_Rcvbuf(void *buf, struct web100stats *stats, struct web100_var *vp)
1154 + struct sock *sk = stats->wc_sk;
1156 + memcpy(&val, buf, sizeof (int));
1158 + sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
1159 + sk->sk_rcvbuf = max_t(int, SOCK_MIN_RCVBUF, min_t(int, sysctl_rmem_max, val));
1164 +int write_State(void *buf, struct web100stats *stats, struct web100_var *vp)
1167 + struct sock *sk = stats->wc_sk;
1169 + memcpy(&val, buf, sizeof (int));
1170 + if (val != 12) /* deleteTCB, RFC 2012 */
1172 + sk->sk_prot->disconnect(sk, 0);
1177 +extern __u32 sysctl_wmem_default;
1178 +extern __u32 sysctl_rmem_default;
1180 +/* A read handler for reading directly from the sk */
1181 +/* read_data is a byte offset into the sk */
1182 +static int read_sk(void *buf, struct web100stats *stats,
1183 + struct web100_var *vp)
1185 + /* Fill data with 0's if the connection is gone. */
1186 + if (stats->wc_sk == NULL)
1187 + memset(buf, 0, vp->len);
1189 + memcpy(buf, (char *)(stats->wc_sk) + vp->read_data, vp->len);
1194 +static int write_sk(void *buf, struct web100stats *stats, struct web100_var *vp)
1196 + if (stats->wc_sk == NULL)
1199 + memcpy((char *)(stats->wc_sk) + vp->write_data, buf, vp->len);
1204 +__u64 web100_mono_time()
1207 + struct timespec now;
1209 + do_posix_clock_monotonic_gettime(&now);
1211 + return 1000000ULL * (__u64)now.tv_sec + now.tv_nsec / 1000;
1213 + struct timeval now;
1214 + static struct timeval before;
1216 + do_gettimeofday(&now);
1218 + /* assure monotonic, no matter what */
1219 + if ((now.tv_sec > before.tv_sec) ||
1220 + ((now.tv_sec == before.tv_sec) && (now.tv_usec > before.tv_usec))) {
1224 + if (before.tv_usec >= 1000000) {
1225 + before.tv_usec -= 1000000;
1230 + return (1000000ULL * (__u64)before.tv_sec + before.tv_usec);
1234 +/* A read handler to get the low part of the current time in usec */
1235 +static int read_now(void *buf, struct web100stats *stats,
1236 + struct web100_var *vp)
1240 + val = web100_mono_time();
1241 + val -= stats->wc_start_monotime;
1242 + memcpy(buf, (char *)&val, vp->len);
1247 +#ifdef CONFIG_WEB100_NET100
1248 +static int write_mss(void *buf, struct web100stats *stats, struct web100_var *vp)
1250 + struct sock *sk = stats->wc_sk;
1251 + struct tcp_sock *tp;
1252 + __u32 val = *(__u32 *)buf;
1258 + if (val > tp->mss_cache)
1263 + tp->mss_cache = val;
1264 + web100_update_mss(tp);
1269 +static int write_CwndAdjust(void *buf, struct web100stats *stats, struct web100_var *vp)
1271 + struct sock *sk = stats->wc_sk;
1272 + struct tcp_sock *tp;
1278 + memcpy(&stats->wc_vars.WAD_CwndAdjust, buf, 4);
1279 + tp->snd_ssthresh = min_t(__u32, tp->snd_ssthresh,
1280 + tp->snd_cwnd + stats->wc_vars.WAD_CwndAdjust);
1287 +static int rw_noop(void *buf, struct web100stats *stats, struct web100_var *vp)
1297 +void __init proc_web100_init(void)
1299 + /* Set up the proc files. */
1300 + proc_web100_dir = proc_mkdir("web100", NULL);
1301 + proc_web100_dir->proc_iops = &web100_dir_iops;
1302 + proc_web100_dir->proc_fops = &web100_dir_fops;
1304 + proc_web100_header = create_proc_entry("header", S_IFREG | S_IRUGO,
1306 + proc_web100_header->proc_fops = &header_file_operations;
1308 + /* Set up the contents of the proc files. */
1309 +#define OFFSET_IN(type,var) ((unsigned long)(&(((type *)NULL)->var)))
1310 +#define OFFSET_ST(field) ((unsigned long)(&(((struct web100stats *)NULL)->wc_vars.field)))
1311 +#define OFFSET_SK(field) ((unsigned long)(&(((struct sock *)NULL)->field)))
1312 +#define OFFSET_TP(field) ((unsigned long)(&(tcp_sk(NULL)->field)))
1314 +#define ADD_RO_STATSVAR(ino,name,type) \
1315 +add_var(web100_file_lookup(ino), #name, type, \
1316 + read_stats, OFFSET_ST(name), NULL, 0)
1318 +#define ADD_RO_STATSRENAME(ino,name,type,var) \
1319 +add_var(web100_file_lookup(ino), name, type, \
1320 + read_stats, OFFSET_ST(var), NULL, 0)
1322 +#define ADD_RO_STATSVAR_DEP(ino,name,type) \
1323 +add_var(web100_file_lookup(ino), "_" #name, type, \
1324 + read_stats, OFFSET_ST(name), NULL, 0)
1326 +#define ADD_WO_STATSVAR(ino,name,type) \
1327 +add_var(web100_file_lookup(ino), #name, type, NULL, 0, \
1328 + write_stats, OFFSET_ST(name))
1330 +#define ADD_WO_STATSVAR_DEP(ino,name,type) \
1331 +add_var(web100_file_lookup(ino), "_" #name, type, NULL, 0, \
1332 + write_stats, OFFSET_ST(name))
1334 +#define ADD_RW_STATSVAR(ino,name,type) \
1335 +add_var(web100_file_lookup(ino), #name, type, \
1336 + read_stats, OFFSET_ST(name), \
1337 + write_stats, OFFSET_ST(name))
1339 +#define ADD_RW_STATSVAR_DEP(ino,name,type) \
1340 +add_var(web100_file_lookup(ino), "_" #name, type, \
1341 + read_stats, OFFSET_ST(name), \
1342 + write_stats, OFFSET_ST(name))
1344 +#define ADD_RO_SKVAR(ino,name,type,var) \
1345 +add_var(web100_file_lookup(ino), #name, type, \
1346 + read_sk, OFFSET_SK(var), NULL, 0)
1348 +#define ADD_RW_SKVAR(ino,name,type,var) \
1349 +add_var(web100_file_lookup(ino), #name, type, \
1350 + read_sk, OFFSET_SK(var), write_sk, OFFSET_SK(var))
1352 +#define ADD_RO_TPVAR(ino,name,type,var) \
1353 +add_var(web100_file_lookup(ino), #name, type, \
1354 + read_sk, OFFSET_TP(var), write_sk, OFFSET_TP(var))
1356 +#define ADD_NOOP(ino,name,type) \
1357 +add_var(web100_file_lookup(ino), #name, type, \
1358 + rw_noop, 0, rw_noop, 0)
1361 + ADD_RO_STATSVAR(PROC_CONN_SPEC, LocalAddressType, WEB100_TYPE_INTEGER);
1362 + ADD_RO_STATSVAR(PROC_CONN_SPEC, LocalAddress, WEB100_TYPE_INET_ADDRESS);
1363 + ADD_RO_STATSVAR(PROC_CONN_SPEC, LocalPort, WEB100_TYPE_INET_PORT_NUMBER);
1364 + ADD_RO_STATSVAR(PROC_CONN_SPEC, RemAddress, WEB100_TYPE_INET_ADDRESS);
1365 + ADD_RO_STATSVAR(PROC_CONN_SPEC, RemPort, WEB100_TYPE_INET_PORT_NUMBER);
1366 + ADD_RO_STATSRENAME(PROC_CONN_SPEC, "_RemoteAddress", WEB100_TYPE_INET_ADDRESS, RemAddress);
1367 + ADD_RO_STATSRENAME(PROC_CONN_SPEC, "_RemotePort", WEB100_TYPE_INET_PORT_NUMBER, RemPort);
1371 + ADD_RO_STATSVAR(PROC_CONN_READ, State, WEB100_TYPE_INTEGER);
1372 + ADD_RO_STATSVAR(PROC_CONN_READ, SACKEnabled, WEB100_TYPE_INTEGER);
1373 + ADD_RO_STATSVAR(PROC_CONN_READ, TimestampsEnabled, WEB100_TYPE_INTEGER);
1374 + ADD_RO_STATSVAR(PROC_CONN_READ, NagleEnabled, WEB100_TYPE_INTEGER);
1375 + ADD_RO_STATSVAR(PROC_CONN_READ, ECNEnabled, WEB100_TYPE_INTEGER);
1376 + ADD_RO_STATSVAR(PROC_CONN_READ, SndWinScale, WEB100_TYPE_INTEGER);
1377 + ADD_RO_STATSVAR(PROC_CONN_READ, RcvWinScale, WEB100_TYPE_INTEGER);
1380 + ADD_RO_STATSVAR(PROC_CONN_READ, ActiveOpen, WEB100_TYPE_INTEGER);
1381 + ADD_RO_STATSVAR(PROC_CONN_READ, MSSRcvd, WEB100_TYPE_GAUGE32);
1382 + ADD_RO_STATSVAR(PROC_CONN_READ, WinScaleRcvd, WEB100_TYPE_INTEGER);
1383 + ADD_RO_STATSVAR(PROC_CONN_READ, WinScaleSent, WEB100_TYPE_INTEGER);
1386 + ADD_RO_STATSVAR(PROC_CONN_READ, PktsOut, WEB100_TYPE_COUNTER32);
1387 + ADD_RO_STATSVAR(PROC_CONN_READ, DataPktsOut, WEB100_TYPE_COUNTER32);
1388 + ADD_RO_STATSVAR_DEP(PROC_CONN_READ, AckPktsOut, WEB100_TYPE_COUNTER32);
1389 + ADD_RO_STATSVAR(PROC_CONN_READ, DataBytesOut, WEB100_TYPE_COUNTER64);
1390 + ADD_RO_STATSVAR(PROC_CONN_READ, PktsIn, WEB100_TYPE_COUNTER32);
1391 + ADD_RO_STATSVAR(PROC_CONN_READ, DataPktsIn, WEB100_TYPE_COUNTER32);
1392 + ADD_RO_STATSVAR_DEP(PROC_CONN_READ, AckPktsIn, WEB100_TYPE_COUNTER32);
1393 + ADD_RO_STATSVAR(PROC_CONN_READ, DataBytesIn, WEB100_TYPE_COUNTER64);
1394 + ADD_RO_STATSVAR(PROC_CONN_READ, SndUna, WEB100_TYPE_COUNTER32);
1395 + ADD_RO_STATSVAR(PROC_CONN_READ, SndNxt, WEB100_TYPE_UNSIGNED32);
1396 + ADD_RO_STATSVAR(PROC_CONN_READ, SndMax, WEB100_TYPE_COUNTER32);
1397 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_snd_una", WEB100_TYPE_COUNTER32, SndUna);
1398 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_snd_nxt", WEB100_TYPE_COUNTER32, SndNxt);
1399 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_snd_max", WEB100_TYPE_COUNTER32, SndMax);
1400 + ADD_RO_STATSVAR(PROC_CONN_READ, ThruBytesAcked, WEB100_TYPE_COUNTER64);
1401 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_ThruBytesSent", WEB100_TYPE_COUNTER64, ThruBytesAcked);
1402 + ADD_RO_STATSVAR(PROC_CONN_READ, SndISS, WEB100_TYPE_COUNTER32);
1403 + ADD_RO_STATSVAR_DEP(PROC_CONN_READ, SendWraps, WEB100_TYPE_COUNTER32);
1404 + ADD_RO_STATSVAR(PROC_CONN_READ, RcvNxt, WEB100_TYPE_COUNTER32);
1405 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_rcv_nxt", WEB100_TYPE_COUNTER32, RcvNxt);
1406 + ADD_RO_STATSVAR(PROC_CONN_READ, ThruBytesReceived, WEB100_TYPE_COUNTER64);
1407 + ADD_RO_STATSVAR(PROC_CONN_READ, RecvISS, WEB100_TYPE_COUNTER32);
1408 + ADD_RO_STATSVAR_DEP(PROC_CONN_READ, RecvWraps, WEB100_TYPE_COUNTER32);
1409 + ADD_RO_STATSVAR_DEP(PROC_CONN_READ, StartTime, WEB100_TYPE_INTEGER32);
1410 + ADD_RO_STATSVAR(PROC_CONN_READ, StartTimeSec, WEB100_TYPE_INTEGER32);
1411 + ADD_RO_STATSVAR(PROC_CONN_READ, StartTimeUsec, WEB100_TYPE_INTEGER32);
1412 + add_var(web100_file_lookup(PROC_CONN_READ), "Duration", WEB100_TYPE_COUNTER64, read_now, 0, NULL, 0);
1413 + add_var(web100_file_lookup(PROC_CONN_READ), "_CurrTime", WEB100_TYPE_COUNTER64, read_now, 0, NULL, 0);
1415 + /* SENDER CONGESTION */
1416 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimTransSender", WEB100_TYPE_COUNTER32, SndLimTrans[WC_SNDLIM_SENDER]);
1417 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimBytesSender", WEB100_TYPE_COUNTER64, SndLimBytes[WC_SNDLIM_SENDER]);
1418 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimTimeSender", WEB100_TYPE_COUNTER32, SndLimTime[WC_SNDLIM_SENDER]);
1419 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimTransCwnd", WEB100_TYPE_COUNTER32, SndLimTrans[WC_SNDLIM_CWND]);
1420 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimBytesCwnd", WEB100_TYPE_COUNTER64, SndLimBytes[WC_SNDLIM_CWND]);
1421 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimTimeCwnd", WEB100_TYPE_COUNTER32, SndLimTime[WC_SNDLIM_CWND]);
1422 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimTransRwin", WEB100_TYPE_COUNTER32, SndLimTrans[WC_SNDLIM_RWIN]);
1423 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimBytesRwin", WEB100_TYPE_COUNTER64, SndLimBytes[WC_SNDLIM_RWIN]);
1424 + ADD_RO_STATSRENAME(PROC_CONN_READ, "SndLimTimeRwin", WEB100_TYPE_COUNTER32, SndLimTime[WC_SNDLIM_RWIN]);
1425 + ADD_RO_STATSVAR(PROC_CONN_READ, SlowStart, WEB100_TYPE_COUNTER32);
1426 + ADD_RO_STATSVAR(PROC_CONN_READ, CongAvoid, WEB100_TYPE_COUNTER32);
1427 + ADD_RO_STATSVAR(PROC_CONN_READ, CongestionSignals, WEB100_TYPE_COUNTER32);
1428 + ADD_RO_STATSVAR(PROC_CONN_READ, OtherReductions, WEB100_TYPE_COUNTER32);
1429 + ADD_RO_STATSVAR(PROC_CONN_READ, X_OtherReductionsCV, WEB100_TYPE_COUNTER32);
1430 + ADD_RO_STATSVAR(PROC_CONN_READ, X_OtherReductionsCM, WEB100_TYPE_COUNTER32);
1431 + ADD_RO_STATSVAR(PROC_CONN_READ, CongestionOverCount, WEB100_TYPE_COUNTER32);
1432 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_Recoveries", WEB100_TYPE_COUNTER32, CongestionSignals);
1433 + ADD_RO_STATSVAR(PROC_CONN_READ, CurCwnd, WEB100_TYPE_GAUGE32);
1434 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrentCwnd", WEB100_TYPE_GAUGE32, CurCwnd);
1435 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxCwnd, WEB100_TYPE_GAUGE32);
1436 + ADD_RO_STATSVAR(PROC_CONN_READ, CurSsthresh, WEB100_TYPE_GAUGE32);
1437 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrentSsthresh", WEB100_TYPE_GAUGE32, CurSsthresh);
1438 + add_var(web100_file_lookup(PROC_CONN_READ), "LimCwnd", WEB100_TYPE_GAUGE32, read_LimCwnd, 0, NULL, 0);
1439 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxSsthresh, WEB100_TYPE_GAUGE32);
1440 + ADD_RO_STATSVAR(PROC_CONN_READ, MinSsthresh, WEB100_TYPE_GAUGE32);
1442 + /* SENDER PATH MODEL */
1443 + ADD_RO_STATSVAR(PROC_CONN_READ, FastRetran, WEB100_TYPE_COUNTER32);
1444 + ADD_RO_STATSVAR(PROC_CONN_READ, Timeouts, WEB100_TYPE_COUNTER32);
1445 + ADD_RO_STATSVAR(PROC_CONN_READ, SubsequentTimeouts, WEB100_TYPE_COUNTER32);
1446 + ADD_RO_STATSVAR(PROC_CONN_READ, CurTimeoutCount, WEB100_TYPE_GAUGE32);
1447 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrTimeoutCount", WEB100_TYPE_GAUGE32, CurTimeoutCount);
1448 + ADD_RO_STATSVAR(PROC_CONN_READ, AbruptTimeouts, WEB100_TYPE_COUNTER32);
1449 + ADD_RO_STATSVAR(PROC_CONN_READ, PktsRetrans, WEB100_TYPE_COUNTER32);
1450 + ADD_RO_STATSVAR(PROC_CONN_READ, BytesRetrans, WEB100_TYPE_COUNTER32);
1451 + ADD_RO_STATSVAR(PROC_CONN_READ, DupAcksIn, WEB100_TYPE_COUNTER32);
1452 + ADD_RO_STATSVAR(PROC_CONN_READ, SACKsRcvd, WEB100_TYPE_COUNTER32);
1453 + ADD_RO_STATSVAR(PROC_CONN_READ, SACKBlocksRcvd, WEB100_TYPE_COUNTER32);
1454 + ADD_RO_STATSVAR(PROC_CONN_READ, PreCongSumCwnd, WEB100_TYPE_COUNTER32);
1455 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_SumCwndAtCong", WEB100_TYPE_COUNTER32, PreCongSumCwnd);
1456 + ADD_RO_STATSVAR(PROC_CONN_READ, PreCongSumRTT, WEB100_TYPE_COUNTER32);
1457 + ADD_RO_STATSVAR_DEP(PROC_CONN_READ, PreCongCountRTT, WEB100_TYPE_COUNTER32);
1458 + ADD_RO_STATSVAR(PROC_CONN_READ, PostCongSumRTT, WEB100_TYPE_COUNTER32);
1459 + ADD_RO_STATSVAR(PROC_CONN_READ, PostCongCountRTT, WEB100_TYPE_COUNTER32);
1460 + ADD_RO_STATSVAR(PROC_CONN_READ, ECERcvd, WEB100_TYPE_COUNTER32);
1461 + ADD_RO_STATSVAR(PROC_CONN_READ, SendStall, WEB100_TYPE_COUNTER32);
1462 + ADD_RO_STATSVAR(PROC_CONN_READ, QuenchRcvd, WEB100_TYPE_COUNTER32);
1463 + ADD_RO_STATSVAR(PROC_CONN_READ, RetranThresh, WEB100_TYPE_GAUGE32);
1464 + ADD_RO_STATSVAR(PROC_CONN_READ, NonRecovDA, WEB100_TYPE_COUNTER32);
1465 + ADD_RO_STATSVAR(PROC_CONN_READ, AckAfterFR, WEB100_TYPE_COUNTER32);
1466 + ADD_RO_STATSVAR(PROC_CONN_READ, DSACKDups, WEB100_TYPE_COUNTER32);
1467 + ADD_RO_STATSVAR(PROC_CONN_READ, SampleRTT, WEB100_TYPE_GAUGE32);
1468 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_SampledRTT", WEB100_TYPE_GAUGE32, SampleRTT);
1469 + ADD_RO_STATSVAR(PROC_CONN_READ, SmoothedRTT, WEB100_TYPE_GAUGE32);
1470 + ADD_RO_STATSVAR(PROC_CONN_READ, RTTVar, WEB100_TYPE_GAUGE32);
1471 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxRTT, WEB100_TYPE_GAUGE32);
1472 + ADD_RO_STATSVAR(PROC_CONN_READ, MinRTT, WEB100_TYPE_GAUGE32);
1473 + ADD_RO_STATSVAR(PROC_CONN_READ, SumRTT, WEB100_TYPE_COUNTER64);
1474 + ADD_RO_STATSVAR(PROC_CONN_READ, CountRTT, WEB100_TYPE_COUNTER32);
1475 + ADD_RO_STATSVAR(PROC_CONN_READ, CurRTO, WEB100_TYPE_GAUGE32);
1476 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrentRTO", WEB100_TYPE_GAUGE32, CurRTO);
1477 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxRTO, WEB100_TYPE_GAUGE32);
1478 + ADD_RO_STATSVAR(PROC_CONN_READ, MinRTO, WEB100_TYPE_GAUGE32);
1479 + ADD_RO_STATSVAR(PROC_CONN_READ, CurMSS, WEB100_TYPE_GAUGE32);
1480 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrentMSS", WEB100_TYPE_GAUGE32, CurMSS);
1481 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxMSS, WEB100_TYPE_GAUGE32);
1482 + ADD_RO_STATSVAR(PROC_CONN_READ, MinMSS, WEB100_TYPE_GAUGE32);
1484 + /* SENDER BUFFER */
1485 +#define PROC_CONN_XTEST PROC_CONN_READ /* lazy */
1486 + ADD_RO_SKVAR(PROC_CONN_READ, _Sndbuf, WEB100_TYPE_GAUGE32, sk_sndbuf);
1487 + ADD_RO_SKVAR(PROC_CONN_READ, X_Sndbuf, WEB100_TYPE_GAUGE32, sk_sndbuf);
1488 + ADD_RO_SKVAR(PROC_CONN_READ, X_Rcvbuf, WEB100_TYPE_GAUGE32, sk_rcvbuf);
1489 + ADD_RO_STATSVAR(PROC_CONN_READ, CurRetxQueue, WEB100_TYPE_GAUGE32);
1490 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurRetranQueue", WEB100_TYPE_GAUGE32, CurRetxQueue);
1491 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxRetxQueue, WEB100_TYPE_GAUGE32);
1492 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_MaxRetranQueue", WEB100_TYPE_GAUGE32, MaxRetxQueue);
1493 + ADD_RO_STATSVAR(PROC_CONN_READ, CurAppWQueue, WEB100_TYPE_GAUGE32);
1494 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxAppWQueue, WEB100_TYPE_GAUGE32);
1496 + /* SENDER BUFFER TUNING - See below */
1498 + /* LOCAL RECEIVER */
1499 + ADD_RO_STATSVAR(PROC_CONN_READ, CurRwinSent, WEB100_TYPE_GAUGE32);
1500 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrentRwinSent", WEB100_TYPE_GAUGE32, CurRwinSent);
1501 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxRwinSent, WEB100_TYPE_GAUGE32);
1502 + ADD_RO_STATSVAR(PROC_CONN_READ, MinRwinSent, WEB100_TYPE_GAUGE32);
1503 + ADD_RO_STATSVAR(PROC_CONN_READ, LimRwin, WEB100_TYPE_GAUGE32);
1504 + ADD_RO_STATSVAR(PROC_CONN_READ, DupAcksOut, WEB100_TYPE_COUNTER32);
1505 + ADD_RO_SKVAR(PROC_CONN_READ, _Rcvbuf, WEB100_TYPE_GAUGE32, sk_rcvbuf);
1506 + ADD_RO_STATSVAR(PROC_CONN_READ, CurReasmQueue, WEB100_TYPE_GAUGE32);
1507 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxReasmQueue, WEB100_TYPE_GAUGE32);
1508 + ADD_RO_STATSVAR(PROC_CONN_READ, CurAppRQueue, WEB100_TYPE_GAUGE32);
1509 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxAppRQueue, WEB100_TYPE_GAUGE32);
1510 + ADD_RO_TPVAR(PROC_CONN_XTEST, X_rcv_ssthresh, WEB100_TYPE_GAUGE32, rcv_ssthresh);
1511 + ADD_RO_TPVAR(PROC_CONN_XTEST, X_wnd_clamp, WEB100_TYPE_GAUGE32, window_clamp);
1512 + ADD_RO_STATSVAR(PROC_CONN_XTEST, X_dbg1, WEB100_TYPE_GAUGE32);
1513 + ADD_RO_STATSVAR(PROC_CONN_XTEST, X_dbg2, WEB100_TYPE_GAUGE32);
1514 + ADD_RO_STATSVAR(PROC_CONN_XTEST, X_dbg3, WEB100_TYPE_GAUGE32);
1515 + ADD_RO_STATSVAR(PROC_CONN_XTEST, X_dbg4, WEB100_TYPE_GAUGE32);
1517 + /* OBSERVED RECEIVER */
1518 + ADD_RO_STATSVAR(PROC_CONN_READ, CurRwinRcvd, WEB100_TYPE_GAUGE32);
1519 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_CurrentRwinRcvd", WEB100_TYPE_GAUGE32, CurRwinRcvd);
1520 + ADD_RO_STATSVAR(PROC_CONN_READ, MaxRwinRcvd, WEB100_TYPE_GAUGE32);
1521 + ADD_RO_STATSVAR(PROC_CONN_READ, MinRwinRcvd, WEB100_TYPE_GAUGE32);
1523 + /* CONNECTION ID */
1524 + ADD_RO_STATSVAR(PROC_CONN_READ, LocalAddressType, WEB100_TYPE_INTEGER);
1525 + ADD_RO_STATSVAR(PROC_CONN_READ, LocalAddress, WEB100_TYPE_INET_ADDRESS);
1526 + ADD_RO_STATSVAR(PROC_CONN_READ, LocalPort, WEB100_TYPE_INET_PORT_NUMBER);
1527 + ADD_RO_STATSVAR(PROC_CONN_READ, RemAddress, WEB100_TYPE_INET_ADDRESS);
1528 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_RemoteAddress", WEB100_TYPE_INET_ADDRESS, RemAddress);
1529 + ADD_RO_STATSVAR(PROC_CONN_READ, RemPort, WEB100_TYPE_INET_PORT_NUMBER);
1530 + ADD_RO_STATSRENAME(PROC_CONN_READ, "_RemotePort", WEB100_TYPE_INET_PORT_NUMBER, RemPort);
1532 + ADD_RO_STATSVAR(PROC_CONN_READ, X_RcvRTT, WEB100_TYPE_GAUGE32);
1535 + add_var(web100_file_lookup(PROC_CONN_TUNE), "LimCwnd",
1536 + WEB100_TYPE_GAUGE32, read_LimCwnd, 0,
1537 + write_LimCwnd, 0);
1538 + add_var(web100_file_lookup(PROC_CONN_TUNE), "LimRwin",
1539 + WEB100_TYPE_GAUGE32, read_stats, OFFSET_ST(LimRwin),
1540 + write_LimRwin, 0);
1541 + add_var(web100_file_lookup(PROC_CONN_TUNE), "X_Sndbuf",
1542 + WEB100_TYPE_GAUGE32, read_sk, OFFSET_SK(sk_sndbuf),
1544 + add_var(web100_file_lookup(PROC_CONN_TUNE), "X_Rcvbuf",
1545 + WEB100_TYPE_GAUGE32, read_sk, OFFSET_SK(sk_rcvbuf),
1547 + add_var(web100_file_lookup(PROC_CONN_TUNE), "State",
1548 + WEB100_TYPE_INTEGER, read_stats, OFFSET_ST(State),
1550 +#ifdef CONFIG_WEB100_NET100
1551 + add_var(web100_file_lookup(PROC_CONN_TUNE), "CurMSS",
1552 + WEB100_TYPE_GAUGE32, read_stats, OFFSET_ST(CurMSS),
1556 +#ifdef CONFIG_WEB100_NET100
1557 + ADD_RW_STATSVAR(PROC_CONN_TUNE, WAD_IFQ, WEB100_TYPE_GAUGE32);
1558 + ADD_RW_STATSVAR(PROC_CONN_TUNE, WAD_MaxBurst, WEB100_TYPE_GAUGE32);
1559 + ADD_RW_STATSVAR(PROC_CONN_TUNE, WAD_MaxSsthresh, WEB100_TYPE_GAUGE32);
1560 + ADD_RW_STATSVAR(PROC_CONN_TUNE, WAD_NoAI, WEB100_TYPE_INTEGER);
1561 + add_var(web100_file_lookup(PROC_CONN_TUNE), "WAD_CwndAdjust",
1562 + WEB100_TYPE_INTEGER32, read_stats, OFFSET_ST(WAD_CwndAdjust),
1563 + write_CwndAdjust, 0);
1566 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/linux/netlink.h linux-2.6.32-27.planetlab.i686/include/linux/netlink.h
1567 --- linux-2.6.32-27.planetlab.i686.orig/include/linux/netlink.h 2011-11-16 16:51:07.258471024 -0500
1568 +++ linux-2.6.32-27.planetlab.i686/include/linux/netlink.h 2011-11-16 16:51:05.954471154 -0500
1570 /* leave room for NETLINK_DM (DM Events) */
1571 #define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
1572 #define NETLINK_ECRYPTFS 19
1573 +#define NETLINK_WEB100 29
1575 #define MAX_LINKS 32
1577 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/linux/proc_fs.h linux-2.6.32-27.planetlab.i686/include/linux/proc_fs.h
1578 --- linux-2.6.32-27.planetlab.i686.orig/include/linux/proc_fs.h 2011-11-16 16:51:07.251471052 -0500
1579 +++ linux-2.6.32-27.planetlab.i686/include/linux/proc_fs.h 2011-11-16 16:51:05.947470992 -0500
1580 @@ -105,6 +105,10 @@
1582 extern void proc_root_init(void);
1584 +#ifdef CONFIG_WEB100_STATS
1585 +extern void proc_web100_init(void);
1588 void proc_flush_task(struct task_struct *task);
1590 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
1591 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/linux/sysctl.h linux-2.6.32-27.planetlab.i686/include/linux/sysctl.h
1592 --- linux-2.6.32-27.planetlab.i686.orig/include/linux/sysctl.h 2011-11-16 16:51:07.289470904 -0500
1593 +++ linux-2.6.32-27.planetlab.i686/include/linux/sysctl.h 2011-11-16 16:51:05.985470940 -0500
1594 @@ -1007,6 +1007,10 @@
1595 void __user *, size_t *, loff_t *);
1596 extern int proc_do_large_bitmap(struct ctl_table *, int,
1597 void __user *, size_t *, loff_t *);
1598 +#ifdef CONFIG_WEB100_STATS
1599 +extern int web100_proc_dointvec_update(struct ctl_table *, int,
1600 + void __user *, size_t *, loff_t *);
1603 extern int do_sysctl (int __user *name, int nlen,
1604 void __user *oldval, size_t __user *oldlenp,
1605 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/linux/tcp.h linux-2.6.32-27.planetlab.i686/include/linux/tcp.h
1606 --- linux-2.6.32-27.planetlab.i686.orig/include/linux/tcp.h 2011-11-16 16:51:07.288470911 -0500
1607 +++ linux-2.6.32-27.planetlab.i686/include/linux/tcp.h 2011-11-16 16:51:05.983450204 -0500
1608 @@ -414,6 +414,10 @@
1609 thin_dupack : 1,/* Fast retransmit on first dupack */
1613 +#ifdef CONFIG_WEB100_STATS
1614 + struct web100stats *tcp_stats;
1618 static inline struct tcp_sock *tcp_sk(const struct sock *sk)
1619 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/net/tcp.h linux-2.6.32-27.planetlab.i686/include/net/tcp.h
1620 --- linux-2.6.32-27.planetlab.i686.orig/include/net/tcp.h 2011-11-16 16:51:07.240470973 -0500
1621 +++ linux-2.6.32-27.planetlab.i686/include/net/tcp.h 2011-11-16 16:51:05.935471062 -0500
1624 #include <linux/seq_file.h>
1626 +#include <net/web100.h>
1628 extern struct inet_hashinfo tcp_hashinfo;
1630 extern struct percpu_counter tcp_orphan_count;
1631 @@ -242,6 +244,14 @@
1632 extern int sysctl_tcp_max_ssthresh;
1633 extern int sysctl_tcp_thin_linear_timeouts;
1634 extern int sysctl_tcp_thin_dupack;
1635 +#ifdef CONFIG_WEB100_NET100
1636 +extern int sysctl_WAD_IFQ;
1637 +extern int sysctl_WAD_MaxBurst;
1639 +#ifdef CONFIG_WEB100_STATS
1640 +extern int sysctl_web100_fperms;
1641 +extern int sysctl_web100_gid;
1644 extern atomic_t tcp_memory_allocated;
1645 extern struct percpu_counter tcp_sockets_allocated;
1646 @@ -834,6 +844,10 @@
1648 static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp)
1650 +#ifdef CONFIG_WEB100_NET100
1651 + return max_t(int, tp->reordering,
1652 + NET100_WAD(tp, WAD_MaxBurst, sysctl_WAD_MaxBurst));
1654 return tp->reordering;
1657 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/net/web100.h linux-2.6.32-27.planetlab.i686/include/net/web100.h
1658 --- linux-2.6.32-27.planetlab.i686.orig/include/net/web100.h 1969-12-31 19:00:00.000000000 -0500
1659 +++ linux-2.6.32-27.planetlab.i686/include/net/web100.h 2011-11-16 16:51:05.931471093 -0500
1662 + * include/net/web100.h
1664 + * Copyright (C) 2001 Matt Mathis <mathis@psc.edu>
1665 + * Copyright (C) 2001 John Heffner <jheffner@psc.edu>
1667 + * The Web 100 project. See http://www.web100.org
1669 + * This program is free software; you can redistribute it and/or
1670 + * modify it under the terms of the GNU General Public License
1671 + * as published by the Free Software Foundation; either version
1672 + * 2 of the License, or (at your option) any later version.
1679 +#include <net/sock.h>
1680 +#include <net/web100_stats.h>
1681 +#include <linux/tcp.h>
1683 +#ifdef CONFIG_WEB100_STATS
1685 +#define WEB100_MAX_CONNS (1<<15)
1687 +#define WEB100_DELAY_MAX HZ
1690 +#define WC_NL_TYPE_CONNECT 0
1691 +#define WC_NL_TYPE_DISCONNECT 1
1693 +struct web100_netlink_msg {
1698 +/* The syntax of this version string is subject to future changes */
1699 +extern char *web100_version_string;
1701 +/* Stats structures */
1702 +extern struct web100stats *web100stats_arr[];
1703 +extern struct web100stats *web100stats_first;
1705 +/* For locking the creation and destruction of stats structures. */
1706 +extern rwlock_t web100_linkage_lock;
1708 +/* For /proc/web100 */
1709 +extern struct web100stats *web100stats_lookup(int cid);
1711 +/* For the TCP code */
1712 +extern int web100_stats_create(struct sock *sk);
1713 +extern void web100_stats_destroy(struct web100stats *stats);
1714 +extern void web100_stats_free(struct web100stats *stats);
1715 +extern void web100_stats_establish(struct sock *sk);
1717 +extern void web100_tune_sndbuf_ack(struct sock *sk);
1718 +extern void web100_tune_sndbuf_snd(struct sock *sk);
1719 +extern void web100_tune_rcvbuf(struct sock *sk);
1721 +extern void web100_update_snd_nxt(struct tcp_sock *tp);
1722 +extern void web100_update_snd_una(struct tcp_sock *tp);
1723 +extern void web100_update_rtt(struct sock *sk, unsigned long rtt_sample);
1724 +extern void web100_update_timeout(struct sock *sk);
1725 +extern void web100_update_mss(struct tcp_sock *tp);
1726 +extern void web100_update_cwnd(struct tcp_sock *tp);
1727 +extern void web100_update_rwin_rcvd(struct tcp_sock *tp);
1728 +extern void web100_update_sndlim(struct tcp_sock *tp, int why);
1729 +extern void web100_update_rcv_nxt(struct tcp_sock *tp);
1730 +extern void web100_update_rwin_sent(struct tcp_sock *tp);
1731 +extern void web100_update_congestion(struct tcp_sock *tp, int why);
1732 +extern void web100_update_segsend(struct sock *sk, int len, int pcount,
1733 + __u32 seq, __u32 end_seq, int flags);
1734 +extern void web100_update_segrecv(struct tcp_sock *tp, struct sk_buff *skb);
1735 +extern void web100_update_rcvbuf(struct sock *sk, int rcvbuf);
1736 +extern void web100_update_writeq(struct sock *sk);
1737 +extern void web100_update_recvq(struct sock *sk);
1738 +extern void web100_update_ofoq(struct sock *sk);
1740 +extern void web100_stats_init(void);
1742 +/* For the IP code */
1743 +extern int web100_delay_output(struct sk_buff *skb, int (*output)(struct sk_buff *));
1745 +extern __u64 web100_mono_time(void);
1747 +/* You may have to hold web100_linkage_lock here to prevent
1748 + stats from disappearing. */
1749 +static inline void web100_stats_use(struct web100stats *stats)
1751 + atomic_inc(&stats->wc_users);
1754 +/* You MUST NOT hold web100_linkage_lock here. */
1755 +static inline void web100_stats_unuse(struct web100stats *stats)
1757 + if (atomic_dec_and_test(&stats->wc_users))
1758 + web100_stats_free(stats);
1761 +/* A mapping between Linux and Web100 states. This could easily just
1763 +static inline int web100_state(int state)
1766 + case TCP_ESTABLISHED: return WC_STATE_ESTABLISHED;
1767 + case TCP_SYN_SENT: return WC_STATE_SYNSENT;
1768 + case TCP_SYN_RECV: return WC_STATE_SYNRECEIVED;
1769 + case TCP_FIN_WAIT1: return WC_STATE_FINWAIT1;
1770 + case TCP_FIN_WAIT2: return WC_STATE_FINWAIT2;
1771 + case TCP_TIME_WAIT: return WC_STATE_TIMEWAIT;
1772 + case TCP_CLOSE: return WC_STATE_CLOSED;
1773 + case TCP_CLOSE_WAIT: return WC_STATE_CLOSEWAIT;
1774 + case TCP_LAST_ACK: return WC_STATE_LASTACK;
1775 + case TCP_LISTEN: return WC_STATE_LISTEN;
1776 + case TCP_CLOSING: return WC_STATE_CLOSING;
1777 + default: return 0;
1781 +#endif /* CONFIG_WEB100_STATS */
1783 +#endif /* _WEB100_H */
1784 diff -Naur linux-2.6.32-27.planetlab.i686.orig/include/net/web100_stats.h linux-2.6.32-27.planetlab.i686/include/net/web100_stats.h
1785 --- linux-2.6.32-27.planetlab.i686.orig/include/net/web100_stats.h 1969-12-31 19:00:00.000000000 -0500
1786 +++ linux-2.6.32-27.planetlab.i686/include/net/web100_stats.h 2011-11-16 16:51:05.933470945 -0500
1789 + * include/net/web100_stats.h
1791 + * Copyright (C) 2001 Matt Mathis <mathis@psc.edu>
1792 + * Copyright (C) 2001 John Heffner <jheffner@psc.edu>
1793 + * Copyright (C) 2000 Jeff Semke <semke@psc.edu>
1795 + * The Web 100 project. See http://www.web100.org
1797 + * This program is free software; you can redistribute it and/or
1798 + * modify it under the terms of the GNU General Public License
1799 + * as published by the Free Software Foundation; either version
1800 + * 2 of the License, or (at your option) any later version.
1804 +/* TODO: make sure that the time duration states below include:
1805 + Congestion Avoidance, Slow Start, Timeouts, Idle Application, and
1806 + Window Limited cases */
1807 +/* TODO: Consider adding sysctl variable to enable/disable WC stats updates.
1808 + Probably should still create stats structures if compiled with WC support,
1809 + even if sysctl(wc) is turned off. That would allow the stats to be updated
1810 + if the sysctl(wc) is turned back on. */
1811 +/* TODO: Add all variables needed to do user-level auto-tuning, including
1812 + writeable parameters */
1815 +#ifndef _WEB100_STATS_H
1816 +#define _WEB100_STATS_H
1818 +enum wc_sndlim_states {
1819 + WC_SNDLIM_NONE = -1,
1823 + WC_SNDLIM_STARTUP,
1824 + WC_SNDLIM_NSTATES /* Keep at end */
1827 +#ifndef CONFIG_WEB100_STATS
1829 +#define WEB100_VAR_INC(tp,var) do {} while (0)
1830 +#define WEB100_VAR_DEC(tp,var) do {} while (0)
1831 +#define WEB100_VAR_SET(tp,var,val) do {} while (0)
1832 +#define WEB100_VAR_ADD(tp,var,val) do {} while (0)
1833 +#define WEB100_UPDATE_FUNC(tp,func) do {} while (0)
1834 +#define NET100_WAD(tp, var, def) (def)
1836 +#else /* CONFIG_WEB100_STATS */ /* { */
1838 +#include <linux/spinlock.h>
1840 +#define WEB100_CHECK(tp,expr) \
1841 + do { if ((tp)->tcp_stats) (expr); } while (0)
1842 +#define WEB100_VAR_INC(tp,var) \
1843 + WEB100_CHECK(tp, ((tp)->tcp_stats->wc_vars.var)++)
1844 +#define WEB100_VAR_DEC(tp,var) \
1845 + WEB100_CHECK(tp, ((tp)->tcp_stats->wc_vars.var)--)
1846 +#define WEB100_VAR_ADD(tp,var,val) \
1847 + WEB100_CHECK(tp, ((tp)->tcp_stats->wc_vars.var) += (val))
1848 +#define WEB100_VAR_SET(tp,var,val) \
1849 + WEB100_CHECK(tp, ((tp)->tcp_stats->wc_vars.var) = (val))
1850 +#define WEB100_UPDATE_FUNC(tp,func) \
1851 + WEB100_CHECK(tp, func)
1852 +#ifdef CONFIG_WEB100_NET100
1853 +#define NET100_WAD(tp, var, def) \
1854 + (((tp)->tcp_stats && (tp)->tcp_stats->wc_vars.var) ? (tp)->tcp_stats->wc_vars.var : (def))
1856 +#define NET100_WAD(tp, var, def) (def)
1859 +/* SMIv2 types - RFC 1902 */
1860 +typedef __s32 INTEGER;
1861 +typedef INTEGER Integer32;
1862 +typedef __u32 IpAddress;
1863 +typedef __u32 Counter32;
1864 +typedef __u32 Unsigned32;
1865 +typedef Unsigned32 Gauge32;
1866 +typedef __u32 TimeTicks;
1867 +typedef __u64 Counter64;
1868 +typedef __u16 Unsigned16;
1870 +/* New inet address types specified in INET-ADDRESS-MIB */
1871 +typedef Unsigned16 InetPortNumber;
1873 + WC_ADDRTYPE_UNKNOWN = 0,
1876 + WC_ADDRTYPE_DNS = 16
1878 +typedef IpAddress InetAddresIPv4;
1884 + InetAddresIPv4 v4addr;
1885 + InetAddresIPv6 v6addr;
1889 + truthValueTrue = 1,
1890 + truthValueFalse = 2
1894 + WC_STATE_CLOSED = 1,
1897 + WC_STATE_SYNRECEIVED,
1898 + WC_STATE_ESTABLISHED,
1899 + WC_STATE_FINWAIT1,
1900 + WC_STATE_FINWAIT2,
1901 + WC_STATE_CLOSEWAIT,
1904 + WC_STATE_TIMEWAIT,
1908 +enum wc_stunemodes {
1909 + WC_STUNEMODE_DEFAULT = 0, /* OS native */
1910 + WC_STUNEMODE_SETSOCKOPT, /* OS native setsockopt() */
1911 + WC_STUNEMODE_FIXED, /* Manual via the web100 API */
1912 + WC_STUNEMODE_AUTO,
1913 + WC_STUNEMODE_EXP1,
1917 +enum wc_rtunemodes {
1918 + WC_RTUNEMODE_DEFAULT = 0,
1919 + WC_RTUNEMODE_SETSOCKOPT,
1920 + WC_RTUNEMODE_FIXED,
1921 + WC_RTUNEMODE_AUTO,
1922 + WC_RTUNEMODE_EXP1,
1927 + WC_BUFMODE_OS = 0,
1928 + WC_BUFMODE_WEB100,
1932 + WC_SE_BELOW_DATA_WINDOW = 1,
1933 + WC_SE_ABOVE_DATA_WINDOW,
1934 + WC_SE_BELOW_ACK_WINDOW,
1935 + WC_SE_ABOVE_ACK_WINDOW,
1936 + WC_SE_BELOW_TSW_WINDOW,
1937 + WC_SE_ABOVE_TSW_WINDOW,
1938 + WC_SE_DATA_CHECKSUM
1943 + * Variables that can be read and written directly.
1945 + * Should contain most variables from TCP-KIS 0.1. Commented feilds are
1946 + * either not implemented or have handlers and do not need struct storage.
1948 +struct web100directs {
1951 + TruthValue SACKEnabled;
1952 + TruthValue TimestampsEnabled;
1953 + TruthValue NagleEnabled;
1954 + TruthValue ECNEnabled;
1955 + Integer32 SndWinScale;
1956 + Integer32 RcvWinScale;
1959 + INTEGER ActiveOpen;
1960 + /* Gauge32 MSSSent; */
1962 + Integer32 WinScaleRcvd;
1963 + Integer32 WinScaleSent;
1964 + /* INTEGER SACKokSent; */
1965 + /* INTEGER SACKokRcvd; */
1966 + /* INTEGER TimestampSent; */
1967 + /* INTEGER TimestampRcvd; */
1970 + Counter32 PktsOut;
1971 + Counter32 DataPktsOut;
1972 + Counter32 AckPktsOut; /* DEPRICATED */
1973 + Counter64 DataBytesOut;
1975 + Counter32 DataPktsIn;
1976 + Counter32 AckPktsIn; /* DEPRICATED */
1977 + Counter64 DataBytesIn;
1978 + /* Counter32 SoftErrors; */
1979 + /* INTEGER SoftErrorReason; */
1981 + Unsigned32 SndNxt;
1983 + Counter64 ThruBytesAcked;
1984 + Counter32 SndISS; /* SndInitial */
1985 + Counter32 SendWraps; /* DEPRICATED */
1987 + Counter64 ThruBytesReceived;
1988 + Counter32 RecvISS; /* RecInitial */
1989 + Counter32 RecvWraps; /* DEPRICATED */
1990 + /* Counter64 Duration; */
1991 + Integer32 StartTime; /* DEPRICATED */
1992 + Integer32 StartTimeSec;
1993 + Integer32 StartTimeUsec;
1995 + /* SENDER CONGESTION */
1996 + Counter32 SndLimTrans[WC_SNDLIM_NSTATES];
1997 + Counter32 SndLimTime[WC_SNDLIM_NSTATES];
1998 + Counter64 SndLimBytes[WC_SNDLIM_NSTATES];
1999 + Counter32 SlowStart;
2000 + Counter32 CongAvoid;
2001 + Counter32 CongestionSignals;
2002 + Counter32 OtherReductions;
2003 + Counter32 X_OtherReductionsCV;
2004 + Counter32 X_OtherReductionsCM;
2005 + Counter32 CongestionOverCount;
2008 + /* Gauge32 LimCwnd; */
2009 + Gauge32 CurSsthresh;
2010 + Gauge32 MaxSsthresh;
2011 + Gauge32 MinSsthresh;
2013 + /* SENDER PATH MODEL */
2014 + Counter32 FastRetran;
2015 + Counter32 Timeouts;
2016 + Counter32 SubsequentTimeouts;
2017 + Gauge32 CurTimeoutCount;
2018 + Counter32 AbruptTimeouts;
2019 + Counter32 PktsRetrans;
2020 + Counter32 BytesRetrans;
2021 + Counter32 DupAcksIn;
2022 + Counter32 SACKsRcvd;
2023 + Counter32 SACKBlocksRcvd;
2024 + Counter32 PreCongSumCwnd;
2025 + Counter32 PreCongSumRTT;
2026 + Counter32 PreCongCountRTT; /* DEPRICATED */
2027 + Counter32 PostCongSumRTT;
2028 + Counter32 PostCongCountRTT;
2029 + /* Counter32 ECNsignals; */
2030 + Counter32 ECERcvd;
2031 + Counter32 SendStall;
2032 + Counter32 QuenchRcvd;
2033 + Gauge32 RetranThresh;
2034 + /* Counter32 SndDupAckEpisodes; */
2035 + /* Counter64 SumBytesReordered; */
2036 + Counter32 NonRecovDA;
2037 + Counter32 AckAfterFR;
2038 + Counter32 DSACKDups;
2039 + Gauge32 SampleRTT;
2040 + Gauge32 SmoothedRTT;
2045 + Counter32 CountRTT;
2053 + /* LOCAL SENDER BUFFER */
2054 + Gauge32 CurRetxQueue;
2055 + Gauge32 MaxRetxQueue;
2056 + Gauge32 CurAppWQueue;
2057 + Gauge32 MaxAppWQueue;
2059 + /* LOCAL RECEIVER */
2060 + Gauge32 CurRwinSent;
2061 + Gauge32 MaxRwinSent;
2062 + Gauge32 MinRwinSent;
2063 + Integer32 LimRwin;
2064 + /* Counter32 DupAckEpisodes; */
2065 + Counter32 DupAcksOut;
2066 + /* Counter32 CERcvd; */
2067 + /* Counter32 ECNSent; */
2068 + /* Counter32 ECNNonceRcvd; */
2069 + Gauge32 CurReasmQueue;
2070 + Gauge32 MaxReasmQueue;
2071 + Gauge32 CurAppRQueue;
2072 + Gauge32 MaxAppRQueue;
2073 + Gauge32 X_rcv_ssthresh;
2074 + Gauge32 X_wnd_clamp;
2080 + /* OBSERVED RECEIVER */
2081 + Gauge32 CurRwinRcvd;
2082 + Gauge32 MaxRwinRcvd;
2083 + Gauge32 MinRwinRcvd;
2085 + /* CONNECTION ID */
2086 + InetAddressType LocalAddressType;
2087 + InetAddress LocalAddress;
2088 + InetPortNumber LocalPort;
2089 + /* InetAddressType RemAddressType; */
2090 + InetAddress RemAddress;
2091 + InetPortNumber RemPort;
2092 + /* Integer32 IdId; */
2096 +#ifdef CONFIG_WEB100_NET100
2097 + /* support for the NET100 Work Around Deamon (WAD) */
2099 + Gauge32 WAD_MaxBurst;
2100 + Gauge32 WAD_MaxSsthresh;
2102 + Integer32 WAD_CwndAdjust;
2106 +struct web100stats {
2109 + struct sock *wc_sk;
2111 + atomic_t wc_users;
2114 + struct web100stats *wc_next;
2115 + struct web100stats *wc_prev;
2117 + struct web100stats *wc_hash_next;
2118 + struct web100stats *wc_hash_prev;
2120 + struct web100stats *wc_death_next;
2123 + __u64 wc_limstate_bytes;
2124 + __u64 wc_limstate_time;
2126 + __u64 wc_start_monotime;
2128 + struct web100directs wc_vars;
2131 +#endif /* CONFIG_WEB100_STATS */ /* } */
2133 +#endif /*_WEB100_STATS_H */
2134 diff -Naur linux-2.6.32-27.planetlab.i686.orig/Makefile linux-2.6.32-27.planetlab.i686/Makefile
2135 --- linux-2.6.32-27.planetlab.i686.orig/Makefile 2011-11-16 16:51:08.409611307 -0500
2136 +++ linux-2.6.32-27.planetlab.i686/Makefile 2011-11-16 16:51:06.773471236 -0500
2142 +EXTRAVERSION = -web100
2143 NAME = Man-Eating Seals of Antiquity
2146 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/Kconfig linux-2.6.32-27.planetlab.i686/net/ipv4/Kconfig
2147 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/Kconfig 2011-11-16 16:51:07.412471138 -0500
2148 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/Kconfig 2011-11-16 16:51:06.107470833 -0500
2149 @@ -627,6 +627,70 @@
2154 + bool "IP: Web100 networking enhancements"
2155 + depends on INET && EXPERIMENTAL
2159 +config WEB100_STATS
2160 + bool "Web100: Extended TCP statistics"
2163 + Support for the Web100 implementation of the TCP extended stastics
2164 + MIB (see http://www.web100.org/mib/).
2168 +config WEB100_FPERMS
2169 + int "Web100: Default file permissions"
2170 + depends on WEB100_STATS
2173 + This controls the default file permission bits on the Web100
2174 + files in /proc/web100. This value can be changed at runtime using
2175 + the sysctl variable net.ipv4.web100_fperms. Unless all users on
2176 + the system are trusted, it is safest to limit both readability
2177 + and writability to trusted users.
2179 + Due to limitations of the kernel config scripts, this is a decimal
2180 + value rather than octal. Some common values:
2182 + 384 = 0600 = rw-------
2183 + 416 = 0640 = rw-r-----
2184 + 432 = 0660 = rw-rw----
2185 + 436 = 0664 = rw-rw-r--
2186 + 438 = 0666 = rw-rw-rw-
2189 + int "Web100: Default gid"
2190 + depends on WEB100_STATS
2193 + This will be the default group of the Web100 files in /proc/web100.
2194 + It may be useful to create a "web100" group on your system, and set
2195 + CONFIG_WEB100_FPERMS (above) with special group permissions. This
2196 + value can be changed at runtime using the sysctl variable
2197 + net.ipv4.web100_gid.
2199 +config WEB100_NET100
2200 + bool "Web100: Net100 extensions"
2201 + depends on WEB100_STATS
2203 + Enables certain "Net100" extensions to TCP that are controlled by
2204 + writable MIB variables. These controls may be particularly useful
2205 + for specially tuning a flow on a long fast network.
2209 +config WEB100_NETLINK
2210 + bool "Web100: Netlink event notification service"
2213 + Required by the Net100 Work Around Daemon (WAD).
2220 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/Makefile linux-2.6.32-27.planetlab.i686/net/ipv4/Makefile
2221 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/Makefile 2011-11-16 16:51:07.413470925 -0500
2222 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/Makefile 2011-11-16 16:51:06.109471129 -0500
2224 obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
2225 obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
2226 obj-$(CONFIG_IP_PNP) += ipconfig.o
2227 +obj-$(CONFIG_WEB100_STATS) += web100_stats.o
2228 obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
2229 obj-$(CONFIG_INET_DIAG) += inet_diag.o
2230 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
2231 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/sysctl_net_ipv4.c linux-2.6.32-27.planetlab.i686/net/ipv4/sysctl_net_ipv4.c
2232 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/sysctl_net_ipv4.c 2011-11-16 16:51:07.413470925 -0500
2233 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/sysctl_net_ipv4.c 2011-11-16 16:51:06.108471039 -0500
2234 @@ -719,6 +719,42 @@
2236 .proc_handler = proc_dointvec,
2238 +#ifdef CONFIG_WEB100_NET100
2240 + .ctl_name = CTL_UNNUMBERED,
2241 + .procname = "WAD_IFQ",
2242 + .data = &sysctl_WAD_IFQ,
2243 + .maxlen = sizeof(int),
2245 + .proc_handler = &proc_dointvec,
2248 + .ctl_name = CTL_UNNUMBERED,
2249 + .procname = "WAD_MaxBurst",
2250 + .data = &sysctl_WAD_MaxBurst,
2251 + .maxlen = sizeof(int),
2253 + .proc_handler = &proc_dointvec,
2256 +#ifdef CONFIG_WEB100_STATS
2258 + .ctl_name = CTL_UNNUMBERED,
2259 + .procname = "web100_fperms",
2260 + .data = &sysctl_web100_fperms,
2261 + .maxlen = sizeof(int),
2263 + .proc_handler = &web100_proc_dointvec_update,
2266 + .ctl_name = CTL_UNNUMBERED,
2267 + .procname = "web100_gid",
2268 + .data = &sysctl_web100_gid,
2269 + .maxlen = sizeof(int),
2271 + .proc_handler = &web100_proc_dointvec_update,
2275 .ctl_name = CTL_UNNUMBERED,
2276 .procname = "tcp_thin_linear_timeouts",
2277 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp.c
2278 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp.c 2011-11-16 16:51:07.413470925 -0500
2279 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp.c 2011-11-16 16:51:06.108471039 -0500
2280 @@ -289,6 +289,16 @@
2281 EXPORT_SYMBOL(sysctl_tcp_rmem);
2282 EXPORT_SYMBOL(sysctl_tcp_wmem);
2284 +#ifdef CONFIG_WEB100_NET100
2285 +int sysctl_WAD_IFQ = 0;
2286 +int sysctl_WAD_MaxBurst = 3;
2287 +EXPORT_SYMBOL(sysctl_WAD_MaxBurst);
2289 +#ifdef CONFIG_WEB100_STATS
2290 +int sysctl_web100_fperms = CONFIG_WEB100_FPERMS;
2291 +int sysctl_web100_gid = CONFIG_WEB100_GID;
2294 atomic_t tcp_memory_allocated; /* Current allocated memory. */
2295 EXPORT_SYMBOL(tcp_memory_allocated);
2297 @@ -835,8 +845,12 @@
2299 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
2303 tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
2304 +#ifdef CONFIG_WEB100_STATS
2305 + web100_update_writeq(sk);
2309 if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
2311 @@ -1084,8 +1098,12 @@
2313 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
2317 tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
2318 +#ifdef CONFIG_WEB100_STATS
2319 + web100_update_writeq(sk);
2323 if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
2325 @@ -1452,6 +1470,9 @@
2326 *seq, TCP_SKB_CB(skb)->seq,
2327 tp->rcv_nxt, flags);
2329 +#ifdef CONFIG_WEB100_STATS
2330 + web100_update_recvq(sk);
2333 /* Well, if we have backlog, try to process it now yet. */
2335 @@ -1754,6 +1775,8 @@
2337 int oldstate = sk->sk_state;
2339 + WEB100_VAR_SET(tcp_sk(sk), State, web100_state(state));
2342 case TCP_ESTABLISHED:
2343 if (oldstate != TCP_ESTABLISHED)
2344 @@ -2138,6 +2161,7 @@
2346 tp->nonagle &= ~TCP_NAGLE_OFF;
2348 + WEB100_VAR_SET(tp, NagleEnabled, !tp->nonagle);
2351 case TCP_THIN_LINEAR_TIMEOUTS:
2352 @@ -2174,6 +2198,7 @@
2353 tp->nonagle |= TCP_NAGLE_PUSH;
2354 tcp_push_pending_frames(sk);
2356 + WEB100_VAR_SET(tp, NagleEnabled, !tp->nonagle);
2360 @@ -2996,6 +3021,10 @@
2361 tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
2363 tcp_register_congestion_control(&tcp_reno);
2365 +#ifdef CONFIG_WEB100_STATS
2366 + web100_stats_init();
2370 EXPORT_SYMBOL(tcp_close);
2371 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_cong.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_cong.c
2372 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_cong.c 2011-11-16 16:51:07.414470925 -0500
2373 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_cong.c 2011-11-16 16:51:06.109471129 -0500
2377 if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh)
2378 - cnt = sysctl_tcp_max_ssthresh >> 1; /* limited slow start */
2379 + /* limited slow start */
2380 + cnt = NET100_WAD(tp, WAD_MaxSsthresh, sysctl_tcp_max_ssthresh) >> 1;
2382 cnt = tp->snd_cwnd; /* exponential increase */
2384 @@ -364,8 +365,10 @@
2387 /* In "safe" area, increase. */
2388 - if (tp->snd_cwnd <= tp->snd_ssthresh)
2389 + if (tp->snd_cwnd <= tp->snd_ssthresh) {
2391 + WEB100_VAR_INC(tp, SlowStart);
2394 /* In dangerous area, increase slowly. */
2395 else if (sysctl_tcp_abc) {
2396 @@ -377,8 +380,10 @@
2397 if (tp->snd_cwnd < tp->snd_cwnd_clamp)
2400 + WEB100_VAR_INC(tp, CongAvoid);
2402 tcp_cong_avoid_ai(tp, tp->snd_cwnd);
2403 + WEB100_VAR_INC(tp, CongAvoid);
2406 EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid);
2407 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_input.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_input.c
2408 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_input.c 2011-11-16 16:51:07.412471138 -0500
2409 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_input.c 2011-11-16 16:51:06.107470833 -0500
2412 if (tp->rcv_rtt_est.rtt != new_sample)
2413 tp->rcv_rtt_est.rtt = new_sample;
2414 + WEB100_VAR_SET(tp, X_RcvRTT, ((1000000*tp->rcv_rtt_est.rtt)/HZ)>>3);
2417 static inline void tcp_rcv_rtt_measure(struct tcp_sock *tp)
2420 if (skb->len >= 128)
2421 tcp_grow_window(sk, skb);
2422 + WEB100_UPDATE_FUNC(tp, web100_update_rcv_nxt(tp));
2425 /* Called to compute a smoothed rtt estimate. The data fed to this
2428 tcp_set_ca_state(sk, TCP_CA_CWR);
2430 + WEB100_UPDATE_FUNC(tp, web100_update_congestion(tp, 0));
2435 tp->reordering != dst_metric(dst, RTAX_REORDERING)) {
2436 tcp_disable_fack(tp);
2437 tp->reordering = dst_metric(dst, RTAX_REORDERING);
2438 + WEB100_VAR_SET(tp, RetranThresh, tp->reordering);
2441 if (dst_metric(dst, RTAX_RTT) == 0)
2445 tp->reordering = min(TCP_MAX_REORDERING, metric);
2446 + WEB100_VAR_SET(tp, RetranThresh, tp->reordering);
2448 /* This exciting event is worth to be remembered. 8) */
2450 @@ -1733,6 +1738,9 @@
2452 state.reord = tp->packets_out;
2454 + WEB100_VAR_INC(tp, SACKsRcvd);
2455 + WEB100_VAR_ADD(tp, SACKBlocksRcvd, num_sacks);
2457 if (!tp->sacked_out) {
2458 if (WARN_ON(tp->fackets_out))
2459 tp->fackets_out = 0;
2460 @@ -2208,6 +2216,8 @@
2461 struct tcp_sock *tp = tcp_sk(sk);
2462 struct sk_buff *skb;
2464 + WEB100_UPDATE_FUNC(tp, web100_update_congestion(tp, 0));
2466 /* Reduce ssthresh if it has not yet been made inside this window. */
2467 if (icsk->icsk_ca_state <= TCP_CA_Disorder || tp->snd_una == tp->high_seq ||
2468 (icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
2469 @@ -2253,6 +2263,7 @@
2471 tp->reordering = min_t(unsigned int, tp->reordering,
2472 sysctl_tcp_reordering);
2473 + WEB100_VAR_SET(tp, RetranThresh, tp->reordering);
2474 tcp_set_ca_state(sk, TCP_CA_Loss);
2475 tp->high_seq = tp->snd_nxt;
2476 TCP_ECN_queue_cwr(tp);
2477 @@ -2580,8 +2591,19 @@
2479 static inline void tcp_moderate_cwnd(struct tcp_sock *tp)
2481 +#ifdef CONFIG_WEB100_STATS
2483 + u32 t = tcp_packets_in_flight(tp) + tcp_max_burst(tp);
2484 + if (t < tp->snd_cwnd) {
2486 + WEB100_VAR_INC(tp, OtherReductions);
2487 + WEB100_VAR_INC(tp, X_OtherReductionsCM);
2491 tp->snd_cwnd = min(tp->snd_cwnd,
2492 tcp_packets_in_flight(tp) + tcp_max_burst(tp));
2494 tp->snd_cwnd_stamp = tcp_time_stamp;
2497 @@ -2677,6 +2699,7 @@
2499 tcp_moderate_cwnd(tp);
2500 tp->snd_cwnd_stamp = tcp_time_stamp;
2501 + WEB100_VAR_INC(tp, CongestionOverCount); /* XXX This is wrong. -JWH */
2504 static inline int tcp_may_undo(struct tcp_sock *tp)
2505 @@ -3069,6 +3092,8 @@
2506 tp->snd_cwnd_cnt = 0;
2507 tcp_set_ca_state(sk, TCP_CA_Recovery);
2509 + WEB100_UPDATE_FUNC(tp, web100_update_congestion(tp, 0));
2510 + WEB100_VAR_INC(tp, FastRetran); /* WEB100_XXX */
2513 if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk)))
2514 @@ -3082,6 +3107,7 @@
2515 tcp_rtt_estimator(sk, seq_rtt);
2517 inet_csk(sk)->icsk_backoff = 0;
2518 + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_rtt(sk, seq_rtt));
2521 /* Read draft-ietf-tcplw-high-performance before mucking
2522 @@ -3140,6 +3166,27 @@
2523 static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
2525 const struct inet_connection_sock *icsk = inet_csk(sk);
2526 +#ifdef CONFIG_WEB100_STATS
2527 + struct tcp_sock *tp = tcp_sk(sk);
2528 + struct web100stats *stats = tp->tcp_stats;
2529 + struct web100directs *vars = &stats->wc_vars;
2531 + if (tp->snd_cwnd > tp->snd_cwnd_clamp) {
2536 +#ifdef CONFIG_WEB100_NET100
2537 + if (vars->WAD_NoAI) {
2538 + tp->snd_cwnd += vars->WAD_CwndAdjust;
2539 + vars->WAD_CwndAdjust = 0;
2540 + tp->snd_cwnd_stamp = tcp_time_stamp;
2541 + tp->snd_cwnd = min(tp->snd_cwnd, (__u32)tp->snd_cwnd_clamp);
2547 icsk->icsk_ca_ops->cong_avoid(sk, ack, in_flight);
2548 tcp_sk(sk)->snd_cwnd_stamp = tcp_time_stamp;
2550 @@ -3428,10 +3475,12 @@
2551 tp->max_window = nwin;
2552 tcp_sync_mss(sk, inet_csk(sk)->icsk_pmtu_cookie);
2554 + WEB100_UPDATE_FUNC(tp, web100_update_rwin_rcvd(tp));
2559 + WEB100_UPDATE_FUNC(tp, web100_update_snd_una(tp));
2563 @@ -3623,6 +3672,7 @@
2565 tcp_update_wl(tp, ack_seq);
2567 + WEB100_UPDATE_FUNC(tp, web100_update_snd_una(tp));
2568 flag |= FLAG_WIN_UPDATE;
2570 tcp_ca_event(sk, CA_EVENT_FAST_ACK);
2571 @@ -3639,8 +3689,10 @@
2572 if (TCP_SKB_CB(skb)->sacked)
2573 flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
2575 - if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb)))
2576 + if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb))) {
2578 + WEB100_VAR_INC(tp, ECERcvd);
2581 tcp_ca_event(sk, CA_EVENT_SLOW_ACK);
2583 @@ -4118,6 +4170,8 @@
2585 struct tcp_sock *tp = tcp_sk(sk);
2587 + WEB100_VAR_INC(tp, DupAcksOut);
2589 if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
2590 before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
2591 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
2592 @@ -4371,6 +4425,10 @@
2594 tcp_fast_path_check(sk);
2596 +#ifdef CONFIG_WEB100_STATS
2597 + web100_update_recvq(sk);
2602 else if (!sock_flag(sk, SOCK_DEAD))
2603 @@ -4425,6 +4483,9 @@
2604 SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
2605 tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
2607 +#ifdef CONFIG_WEB100_STATS
2608 + web100_update_recvq(sk);
2610 skb_set_owner_r(skb, sk);
2612 if (!skb_peek(&tp->out_of_order_queue)) {
2613 @@ -4778,6 +4839,8 @@
2614 if (win_used < tp->snd_cwnd) {
2615 tp->snd_ssthresh = tcp_current_ssthresh(sk);
2616 tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1;
2617 + WEB100_VAR_INC(tp, OtherReductions);
2618 + WEB100_VAR_INC(tp, X_OtherReductionsCV);
2620 tp->snd_cwnd_used = 0;
2622 @@ -5308,6 +5371,9 @@
2623 tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
2626 +#ifdef CONFIG_WEB100_STATS
2627 + web100_update_recvq(sk);
2629 tcp_event_data_recv(sk, skb);
2631 if (TCP_SKB_CB(skb)->ack_seq != tp->snd_una) {
2632 @@ -5476,6 +5542,9 @@
2633 tp->copied_seq = tp->rcv_nxt;
2635 tcp_set_state(sk, TCP_ESTABLISHED);
2636 +#ifdef CONFIG_WEB100_STATS
2637 + web100_stats_establish(sk);
2640 security_inet_conn_established(sk, skb);
2642 @@ -5694,6 +5763,9 @@
2644 tcp_set_state(sk, TCP_ESTABLISHED);
2645 sk->sk_state_change(sk);
2646 +#ifdef CONFIG_WEB100_STATS
2647 + web100_stats_establish(sk);
2650 /* Note, that this wakeup is only for marginal
2651 * crossed SYN case. Passively open sockets
2652 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_ipv4.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_ipv4.c
2653 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_ipv4.c 2011-11-16 16:51:07.414470925 -0500
2654 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_ipv4.c 2011-11-16 17:04:35.157317153 -0500
2655 @@ -243,6 +243,10 @@
2659 + WEB100_VAR_SET(tp, SndISS, tp->write_seq);
2660 + WEB100_VAR_SET(tp, SndMax, tp->write_seq);
2661 + WEB100_VAR_SET(tp, SndNxt, tp->write_seq);
2662 + WEB100_VAR_SET(tp, SndUna, tp->write_seq);
2664 inet->id = tp->write_seq ^ jiffies;
2669 case ICMP_SOURCE_QUENCH:
2670 + WEB100_VAR_INC(tp, QuenchRcvd);
2671 /* Just silently ignore these. */
2673 case ICMP_PARAMETERPROB:
2674 @@ -1373,6 +1378,13 @@
2675 newsk = tcp_create_openreq_child(sk, req, skb);
2678 +#ifdef CONFIG_WEB100_STATS
2679 + if (web100_stats_create(newsk)) {
2683 + tcp_sk(newsk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV4;
2686 newsk->sk_gso_type = SKB_GSO_TCPV4;
2687 sk_setup_caps(newsk, dst);
2688 @@ -1626,6 +1638,7 @@
2689 inet_rps_save_rxhash(sk, skb->rxhash);
2691 bh_lock_sock_nested(sk);
2692 + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_segrecv(tcp_sk(sk), skb));
2694 if (!sock_owned_by_user(sk)) {
2695 #ifdef CONFIG_NET_DMA
2696 @@ -1644,6 +1657,7 @@
2698 goto discard_and_relse;
2700 + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_cwnd(tcp_sk(sk)));
2704 @@ -1837,6 +1851,16 @@
2705 sk->sk_sndbuf = sysctl_tcp_wmem[1];
2706 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
2708 +#ifdef CONFIG_WEB100_STATS
2711 + if ((err = web100_stats_create(sk))) {
2714 + tcp_sk(sk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV4;
2719 percpu_counter_inc(&tcp_sockets_allocated);
2721 @@ -1879,6 +1903,10 @@
2722 if (inet_csk(sk)->icsk_bind_hash)
2725 +#ifdef CONFIG_WEB100_STATS
2726 + web100_stats_destroy(tcp_sk(sk)->tcp_stats);
2730 * If sendmsg cached page exists, toss it.
2732 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_minisocks.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_minisocks.c
2733 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_minisocks.c 2011-11-16 16:51:07.414470925 -0500
2734 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_minisocks.c 2011-11-16 16:51:06.109471129 -0500
2739 + WEB100_VAR_SET(tp, State, WC_STATE_TIMEWAIT);
2741 /* Linkage updates. */
2742 __inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
2744 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_output.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_output.c
2745 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_output.c 2011-11-16 16:51:07.409470962 -0500
2746 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_output.c 2011-11-16 16:51:06.104471116 -0500
2749 tcp_advance_send_head(sk, skb);
2750 tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
2751 + WEB100_UPDATE_FUNC(tp, web100_update_snd_nxt(tp));
2753 /* Don't override Nagle indefinately with F-RTO */
2754 if (tp->frto_counter == 2)
2757 tp->rcv_wnd = new_win;
2758 tp->rcv_wup = tp->rcv_nxt;
2759 + WEB100_UPDATE_FUNC(tp, web100_update_rwin_sent(tp));
2761 /* Make sure we do not exceed the maximum possible
2763 @@ -714,11 +716,32 @@
2764 if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
2765 TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS);
2767 +#ifdef CONFIG_WEB100_STATS
2769 + /* If the skb isn't cloned, we can't reference it after
2770 + * calling queue_xmit, so copy everything we need here. */
2771 + int len = skb->len;
2772 + int pcount = tcp_skb_pcount(skb);
2773 + __u32 seq = TCP_SKB_CB(skb)->seq;
2774 + __u32 end_seq = TCP_SKB_CB(skb)->end_seq;
2775 + int flags = TCP_SKB_CB(skb)->flags;
2777 + err = icsk->icsk_af_ops->queue_xmit(skb, 0);
2778 + if (likely(err == 0))
2779 + WEB100_UPDATE_FUNC(tp, web100_update_segsend(sk, len, pcount,
2780 + seq, end_seq, flags));
2783 err = icsk->icsk_af_ops->queue_xmit(skb, 0);
2785 if (likely(err <= 0))
2788 +#ifdef CONFIG_WEB100_NET100
2789 + if (!NET100_WAD(tp, WAD_IFQ, sysctl_WAD_IFQ))
2791 tcp_enter_cwr(sk, 1);
2792 + WEB100_VAR_INC(tp, SendStall);
2794 return net_xmit_eval(err);
2796 @@ -1053,6 +1076,7 @@
2797 if (icsk->icsk_mtup.enabled)
2798 mss_now = min(mss_now, tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low));
2799 tp->mss_cache = mss_now;
2800 + WEB100_UPDATE_FUNC(tp, web100_update_mss(tp));
2804 @@ -1247,20 +1271,22 @@
2805 * should be put on the wire right now. If so, it returns the number of
2806 * packets allowed by the congestion window.
2808 -static unsigned int tcp_snd_test(struct sock *sk, struct sk_buff *skb,
2809 +static int tcp_snd_wait(struct sock *sk, struct sk_buff *skb,
2810 unsigned int cur_mss, int nonagle)
2812 struct tcp_sock *tp = tcp_sk(sk);
2813 - unsigned int cwnd_quota;
2816 tcp_init_tso_segs(sk, skb, cur_mss);
2818 if (!tcp_nagle_test(tp, skb, cur_mss, nonagle))
2820 + return -WC_SNDLIM_SENDER;
2822 cwnd_quota = tcp_cwnd_test(tp, skb);
2823 - if (cwnd_quota && !tcp_snd_wnd_test(tp, skb, cur_mss))
2826 + return -WC_SNDLIM_CWND;
2827 + if (!tcp_snd_wnd_test(tp, skb, cur_mss))
2828 + return -WC_SNDLIM_RWIN;
2832 @@ -1272,9 +1298,9 @@
2833 struct sk_buff *skb = tcp_send_head(sk);
2836 - tcp_snd_test(sk, skb, tcp_current_mss(sk),
2837 + tcp_snd_wait(sk, skb, tcp_current_mss(sk),
2838 (tcp_skb_is_last(sk, skb) ?
2839 - tp->nonagle : TCP_NAGLE_PUSH)));
2840 + tp->nonagle : TCP_NAGLE_PUSH)) > 0);
2843 /* Trim TSO SKB to LEN bytes, put the remaining data into a new packet
2844 @@ -1551,6 +1577,7 @@
2845 unsigned int tso_segs, sent_pkts;
2848 + int why = WC_SNDLIM_NONE;
2852 @@ -1571,20 +1598,29 @@
2855 cwnd_quota = tcp_cwnd_test(tp, skb);
2857 + if (!cwnd_quota) {
2858 + why = WC_SNDLIM_CWND;
2862 - if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))
2863 + if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) {
2864 + why = WC_SNDLIM_RWIN;
2868 if (tso_segs == 1) {
2869 if (unlikely(!tcp_nagle_test(tp, skb, mss_now,
2870 (tcp_skb_is_last(sk, skb) ?
2871 - nonagle : TCP_NAGLE_PUSH))))
2872 + nonagle : TCP_NAGLE_PUSH)))) {
2873 + why = WC_SNDLIM_SENDER;
2877 - if (!push_one && tcp_tso_should_defer(sk, skb))
2878 + if (!push_one && tcp_tso_should_defer(sk, skb)) {
2879 + /* XXX: is this sender or cwnd? */
2880 + why = WC_SNDLIM_SENDER;
2886 @@ -1598,8 +1634,10 @@
2888 TCP_SKB_CB(skb)->when = tcp_time_stamp;
2890 - if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
2891 + if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) {
2892 + why = WC_SNDLIM_SENDER;
2896 /* Advance the send_head. This one is sent out.
2897 * This call will increment packets_out.
2898 @@ -1612,6 +1650,9 @@
2902 + if (why == WC_SNDLIM_NONE)
2903 + why = WC_SNDLIM_SENDER;
2904 + WEB100_UPDATE_FUNC(tp, web100_update_sndlim(tp, why));
2906 if (likely(sent_pkts)) {
2907 tcp_cwnd_validate(sk);
2908 @@ -1769,6 +1810,9 @@
2909 window = free_space;
2912 + WEB100_VAR_SET(tp, X_dbg3, free_space);
2913 + WEB100_VAR_SET(tp, X_dbg2, mss);
2914 + WEB100_VAR_SET(tp, X_dbg1, window);
2918 @@ -2355,6 +2399,7 @@
2921 tp->snd_una = tp->write_seq;
2922 + WEB100_VAR_SET(tp, SndUna, tp->snd_una);
2923 tp->snd_sml = tp->write_seq;
2924 tp->snd_up = tp->write_seq;
2926 @@ -2399,6 +2444,7 @@
2927 * in order to make this packet get counted in tcpOutSegs.
2929 tp->snd_nxt = tp->write_seq;
2930 + WEB100_UPDATE_FUNC(tp, web100_update_snd_nxt(tp));
2931 tp->pushed_seq = tp->write_seq;
2932 TCP_INC_STATS(sock_net(sk), TCP_MIB_ACTIVEOPENS);
2934 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_timer.c linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_timer.c
2935 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/tcp_timer.c 2011-11-16 16:51:07.413470925 -0500
2936 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/tcp_timer.c 2011-11-16 16:51:06.108471039 -0500
2939 NET_INC_STATS_BH(sock_net(sk), mib_idx);
2941 + WEB100_UPDATE_FUNC(tp, web100_update_timeout(sk));
2943 if (tcp_use_frto(sk)) {
2946 * the 120 second clamps though!
2948 icsk->icsk_backoff++;
2949 + WEB100_VAR_SET(tcp_sk(sk), CurTimeoutCount, icsk->icsk_backoff);
2950 icsk->icsk_retransmits++;
2953 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv4/web100_stats.c linux-2.6.32-27.planetlab.i686/net/ipv4/web100_stats.c
2954 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv4/web100_stats.c 1969-12-31 19:00:00.000000000 -0500
2955 +++ linux-2.6.32-27.planetlab.i686/net/ipv4/web100_stats.c 2011-11-16 16:51:06.106470968 -0500
2958 + * net/ipv4/web100_stats.c
2960 + * Copyright (C) 2001 Matt Mathis <mathis@psc.edu>
2961 + * Copyright (C) 2001 John Heffner <jheffner@psc.edu>
2962 + * Copyright (C) 2000 Jeffrey Semke <semke@psc.edu>
2964 + * The Web 100 project. See http://www.web100.org
2966 + * Functions for creating, destroying, and updating the Web100
2967 + * statistics structure.
2969 + * This program is free software; you can redistribute it and/or
2970 + * modify it under the terms of the GNU General Public License
2971 + * as published by the Free Software Foundation; either version
2972 + * 2 of the License, or (at your option) any later version.
2976 +#include <linux/types.h>
2977 +#include <linux/bootmem.h>
2978 +#include <linux/socket.h>
2979 +#include <net/web100.h>
2980 +#include <net/tcp.h>
2981 +#include <linux/string.h>
2982 +#include <linux/proc_fs.h>
2983 +#include <asm/atomic.h>
2985 +#define WC_INF32 0xffffffff
2987 +#define WC_DEATH_SLOTS 8
2988 +#define WC_PERSIST_TIME 60
2990 +/* BEWARE: The release process updates the version string */
2991 +char *web100_version_string = "2.5.27 201001301335"
2992 +#ifdef CONFIG_WEB100_NET100
2997 +static void death_cleanup(unsigned long dummy);
2999 +/* Global stats reader-writer lock */
3000 +rwlock_t web100_linkage_lock = RW_LOCK_UNLOCKED;
3002 +/* Data structures for tying together stats */
3003 +static int web100stats_next_cid;
3004 +static int web100stats_conn_num;
3005 +static int web100stats_htsize;
3006 +struct web100stats **web100stats_ht;
3007 +struct web100stats *web100stats_first = NULL;
3009 +static struct web100stats *death_slots[WC_DEATH_SLOTS];
3010 +static int cur_death_slot;
3011 +static spinlock_t death_lock = SPIN_LOCK_UNLOCKED;
3012 +static struct timer_list stats_persist_timer = TIMER_INITIALIZER(death_cleanup, 0, 0);
3013 +static int ndeaths;
3015 +#ifdef CONFIG_WEB100_NETLINK
3016 +static struct sock *web100_nlsock;
3019 +extern struct proc_dir_entry *proc_web100_dir;
3023 + * Structural maintainance
3026 +static inline int web100stats_hash(int cid)
3028 + return cid % web100stats_htsize;
3031 +struct web100stats *web100stats_lookup(int cid)
3033 + struct web100stats *stats;
3035 + /* Let's ensure safety here. It's not too expensive and may change. */
3036 + if (cid < 0 || cid >= WEB100_MAX_CONNS)
3039 + stats = web100stats_ht[web100stats_hash(cid)];
3040 + while (stats && stats->wc_cid != cid)
3041 + stats = stats->wc_hash_next;
3045 +/* This will get really slow as the cid space fills. This can be done
3046 + * better, but it's just not worth it right now.
3047 + * The caller must hold the lock.
3049 +static int get_next_cid(void)
3053 + if (web100stats_conn_num >= WEB100_MAX_CONNS)
3056 + i = web100stats_next_cid;
3058 + if (web100stats_lookup(i) == NULL)
3060 + i = (i + 1) % WEB100_MAX_CONNS;
3061 + } while (i != web100stats_next_cid);
3062 + web100stats_next_cid = (i + 1) % WEB100_MAX_CONNS;
3067 +static void stats_link(struct web100stats *stats)
3071 + write_lock_bh(&web100_linkage_lock);
3073 + if ((stats->wc_cid = get_next_cid()) < 0) {
3074 + write_unlock_bh(&web100_linkage_lock);
3078 + hash = web100stats_hash(stats->wc_cid);
3079 + stats->wc_hash_next = web100stats_ht[hash];
3080 + stats->wc_hash_prev = NULL;
3081 + if (web100stats_ht[hash])
3082 + web100stats_ht[hash]->wc_hash_prev = stats;
3083 + web100stats_ht[hash] = stats;
3085 + stats->wc_next = web100stats_first;
3086 + stats->wc_prev = NULL;
3087 + if (web100stats_first)
3088 + web100stats_first->wc_prev = stats;
3089 + web100stats_first = stats;
3091 + web100stats_conn_num++;
3092 + proc_web100_dir->nlink = web100stats_conn_num + 2;
3094 + write_unlock_bh(&web100_linkage_lock);
3097 +static void stats_unlink(struct web100stats *stats)
3101 + write_lock_bh(&web100_linkage_lock);
3103 + hash = web100stats_hash(stats->wc_cid);
3104 + if (stats->wc_hash_next)
3105 + stats->wc_hash_next->wc_hash_prev = stats->wc_hash_prev;
3106 + if (stats->wc_hash_prev)
3107 + stats->wc_hash_prev->wc_hash_next = stats->wc_hash_next;
3108 + if (stats == web100stats_ht[hash])
3109 + web100stats_ht[hash] = stats->wc_hash_next ?
3110 + stats->wc_hash_next :
3111 + stats->wc_hash_prev;
3113 + if (stats->wc_next)
3114 + stats->wc_next->wc_prev = stats->wc_prev;
3115 + if (stats->wc_prev)
3116 + stats->wc_prev->wc_next = stats->wc_next;
3117 + if (stats == web100stats_first)
3118 + web100stats_first = stats->wc_next ? stats->wc_next :
3121 + web100stats_conn_num--;
3122 + proc_web100_dir->nlink = web100stats_conn_num + 2;
3124 + write_unlock_bh(&web100_linkage_lock);
3127 +static void stats_persist(struct web100stats *stats)
3129 + spin_lock_bh(&death_lock);
3131 + stats->wc_death_next = death_slots[cur_death_slot];
3132 + death_slots[cur_death_slot] = stats;
3133 + if (ndeaths <= 0) {
3134 + stats_persist_timer.expires = jiffies + WC_PERSIST_TIME * HZ / WC_DEATH_SLOTS;
3135 + add_timer(&stats_persist_timer);
3139 + spin_unlock_bh(&death_lock);
3142 +static void death_cleanup(unsigned long dummy)
3144 + struct web100stats *stats, *next;
3146 + spin_lock_bh(&death_lock);
3148 + cur_death_slot = (cur_death_slot + 1) % WC_DEATH_SLOTS;
3149 + stats = death_slots[cur_death_slot];
3151 + stats->wc_dead = 1;
3153 + next = stats->wc_death_next;
3154 + web100_stats_unuse(stats);
3157 + death_slots[cur_death_slot] = NULL;
3159 + if (ndeaths > 0) {
3160 + stats_persist_timer.expires = jiffies + WC_PERSIST_TIME * HZ / WC_DEATH_SLOTS;
3161 + add_timer(&stats_persist_timer);
3164 + spin_unlock_bh(&death_lock);
3168 +/* Tom Dunigan's (slightly modified) netlink code. Notifies listening apps
3169 + * of Web100 events.
3171 + * NOTE: we are currently squatting on netlink family 10 (NETLINK_WEB100) in
3172 + * include/linux/netlink.h
3175 +#ifdef CONFIG_WEB100_NETLINK
3176 +void web100_netlink_event(int type, int cid)
3178 + struct web100_netlink_msg *msg;
3179 + struct sk_buff *tmpskb;
3181 + if (web100_nlsock == NULL)
3184 + if ((tmpskb = alloc_skb((sizeof (struct web100_netlink_msg)), GFP_ATOMIC)) == NULL) {
3185 + printk(KERN_INFO "web100_netlink_event: alloc_skb failure\n");
3189 + skb_put(tmpskb, sizeof (struct web100_netlink_msg));
3190 + msg = (struct web100_netlink_msg *)tmpskb->data;
3193 + netlink_broadcast(web100_nlsock, tmpskb, 0, ~0, GFP_ATOMIC);
3195 +#endif /* CONFIG_WEB100_NETLINK */
3197 +extern __u32 sysctl_wmem_default;
3198 +extern __u32 sysctl_rmem_default;
3200 +/* Called whenever a TCP/IPv4 sock is created.
3201 + * net/ipv4/tcp_ipv4.c: tcp_v4_syn_recv_sock,
3202 + * tcp_v4_init_sock
3203 + * Allocates a stats structure and initializes values.
3205 +int web100_stats_create(struct sock *sk)
3207 + struct web100stats *stats;
3208 + struct web100directs *vars;
3209 + struct tcp_sock *tp = tcp_sk(sk);
3210 + struct timeval tv;
3212 + if ((stats = kmalloc(sizeof (struct web100stats), gfp_any())) == NULL)
3214 + tp->tcp_stats = stats;
3215 + vars = &stats->wc_vars;
3217 + memset(stats, 0, sizeof (struct web100stats));
3219 + stats->wc_cid = -1;
3220 + stats->wc_sk = sk;
3221 + atomic_set(&stats->wc_users, 0);
3223 + stats->wc_limstate = WC_SNDLIM_STARTUP;
3224 + stats->wc_limstate_time = web100_mono_time();
3226 + vars->NagleEnabled = !(tp->nonagle);
3227 + vars->ActiveOpen = !in_interrupt();
3229 + vars->SndUna = tp->snd_una;
3230 + vars->SndNxt = tp->snd_nxt;
3231 + vars->SndMax = tp->snd_nxt;
3232 + vars->SndISS = tp->snd_nxt;
3234 + do_gettimeofday(&tv);
3235 + vars->StartTime = tv.tv_sec * 10 + tv.tv_usec / 100000;
3236 + vars->StartTimeSec = tv.tv_sec;
3237 + vars->StartTimeUsec = tv.tv_usec;
3238 + stats->wc_start_monotime = web100_mono_time();
3240 + vars->MinRTT = vars->MinRTO = vars->MinMSS = vars->MinRwinRcvd =
3241 + vars->MinRwinSent = vars->MinSsthresh = WC_INF32;
3243 + vars->LimRwin = tp->window_clamp;
3246 + web100_stats_use(stats);
3251 +void web100_stats_destroy(struct web100stats *stats)
3253 + /* Attribute final sndlim time. */
3254 + web100_update_sndlim(tcp_sk(stats->wc_sk), stats->wc_limstate);
3256 + if (stats->wc_cid >= 0) {
3257 +#ifdef CONFIG_WEB100_NETLINK
3258 + web100_netlink_event(WC_NL_TYPE_DISCONNECT, stats->wc_cid);
3260 + stats_persist(stats);
3262 + web100_stats_unuse(stats);
3266 +/* Do not call directly. Called from web100_stats_unuse(). */
3267 +void web100_stats_free(struct web100stats *stats)
3269 + if (stats->wc_cid >= 0) {
3270 + stats_unlink(stats);
3272 + sock_put(stats->wc_sk);
3276 +extern __u32 sysctl_wmem_default;
3277 +extern __u32 sysctl_rmem_default;
3279 +/* Called when a connection enters the ESTABLISHED state, and has all its
3280 + * state initialized.
3281 + * net/ipv4/tcp_input.c: tcp_rcv_state_process,
3282 + * tcp_rcv_synsent_state_process
3283 + * Here we link the statistics structure in so it is visible in the /proc
3284 + * fs, and do some final init.
3286 +void web100_stats_establish(struct sock *sk)
3288 + struct inet_sock *inet = inet_sk(sk);
3289 + struct tcp_sock *tp = tcp_sk(sk);
3290 + struct web100stats *stats = tp->tcp_stats;
3291 + struct web100directs *vars = &stats->wc_vars;
3293 + if (stats == NULL)
3296 + /* Let's set these here, since they can't change once the
3297 + * connection is established.
3299 + vars->LocalPort = inet->num;
3300 + vars->RemPort = ntohs(inet->dport);
3302 + if (vars->LocalAddressType == WC_ADDRTYPE_IPV4) {
3303 + vars->LocalAddress.v4addr = inet->rcv_saddr;
3304 + vars->RemAddress.v4addr = inet->daddr;
3306 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3307 + else if (vars->LocalAddressType == WC_ADDRTYPE_IPV6) {
3308 + memcpy(&vars->LocalAddress.v6addr.addr, &(inet6_sk(sk)->saddr), 16);
3309 + memcpy(&vars->RemAddress.v6addr.addr, &(inet6_sk(sk)->daddr), 16);
3313 + printk(KERN_ERR "Web100: LocalAddressType not valid.\n");
3315 + vars->LocalAddress.v6addr.type = vars->RemAddress.v6addr.type = vars->LocalAddressType;
3317 + vars->SACKEnabled = tp->rx_opt.sack_ok;
3318 + vars->TimestampsEnabled = tp->rx_opt.tstamp_ok;
3319 +#ifdef CONFIG_INET_ECN
3320 + vars->ECNEnabled = tp->ecn_flags & TCP_ECN_OK;
3323 + if (tp->rx_opt.wscale_ok) {
3324 + vars->WinScaleRcvd = tp->rx_opt.snd_wscale;
3325 + vars->WinScaleSent = tp->rx_opt.rcv_wscale;
3327 + vars->WinScaleRcvd = -1;
3328 + vars->WinScaleSent = -1;
3330 + vars->SndWinScale = vars->WinScaleRcvd;
3331 + vars->RcvWinScale = vars->WinScaleSent;
3333 + vars->CurCwnd = tp->snd_cwnd * tp->mss_cache;
3334 + vars->CurSsthresh = tp->snd_ssthresh * tp->mss_cache;
3335 + web100_update_cwnd(tp);
3336 + web100_update_rwin_rcvd(tp);
3337 + web100_update_rwin_sent(tp);
3339 + vars->RecvISS = vars->RcvNxt = tp->rcv_nxt;
3341 + vars->RetranThresh = tp->reordering;
3343 + vars->LimRwin = min_t(__u32, vars->LimRwin, 65355U << tp->rx_opt.rcv_wscale);
3345 + stats_link(stats);
3347 + web100_update_sndlim(tp, WC_SNDLIM_SENDER);
3349 +#ifdef CONFIG_WEB100_NETLINK
3350 + web100_netlink_event(WC_NL_TYPE_CONNECT, stats->wc_cid);
3355 + * Statistics update functions
3358 +void web100_update_snd_nxt(struct tcp_sock *tp)
3360 + struct web100stats *stats = tp->tcp_stats;
3362 + if (after(tp->snd_nxt, stats->wc_vars.SndMax)) {
3363 + if (before(stats->wc_vars.SndMax, stats->wc_vars.SndISS) &&
3364 + after(tp->snd_nxt, stats->wc_vars.SndISS))
3365 + stats->wc_vars.SendWraps++;
3366 + stats->wc_vars.SndMax = tp->snd_nxt;
3368 + stats->wc_vars.SndNxt = tp->snd_nxt;
3371 +void web100_update_snd_una(struct tcp_sock *tp)
3373 + struct web100stats *stats = tp->tcp_stats;
3375 + stats->wc_vars.ThruBytesAcked += (__u32)(tp->snd_una - stats->wc_vars.SndUna);
3376 + stats->wc_vars.SndUna = tp->snd_una;
3379 +void web100_update_rtt(struct sock *sk, unsigned long rtt_sample)
3381 + struct web100stats *stats = tcp_sk(sk)->tcp_stats;
3382 + unsigned long rtt_sample_msec = rtt_sample * 1000 / HZ;
3385 + stats->wc_vars.SampleRTT = rtt_sample_msec;
3387 + if (rtt_sample_msec > stats->wc_vars.MaxRTT)
3388 + stats->wc_vars.MaxRTT = rtt_sample_msec;
3389 + if (rtt_sample_msec < stats->wc_vars.MinRTT)
3390 + stats->wc_vars.MinRTT = rtt_sample_msec;
3392 + stats->wc_vars.CountRTT++;
3393 + stats->wc_vars.SumRTT += rtt_sample_msec;
3395 + if (stats->wc_vars.PreCongCountRTT != stats->wc_vars.PostCongCountRTT) {
3396 + stats->wc_vars.PostCongCountRTT++;
3397 + stats->wc_vars.PostCongSumRTT += rtt_sample_msec;
3400 + /* srtt is stored as 8 * the smoothed estimate */
3401 + stats->wc_vars.SmoothedRTT =
3402 + (tcp_sk(sk)->srtt >> 3) * 1000 / HZ;
3404 + rto = inet_csk(sk)->icsk_rto * 1000 / HZ;
3405 + if (rto > stats->wc_vars.MaxRTO)
3406 + stats->wc_vars.MaxRTO = rto;
3407 + if (rto < stats->wc_vars.MinRTO)
3408 + stats->wc_vars.MinRTO = rto;
3409 + stats->wc_vars.CurRTO = rto;
3411 + stats->wc_vars.CurTimeoutCount = 0;
3413 + stats->wc_vars.RTTVar = (tcp_sk(sk)->rttvar >> 2) * 1000 / HZ;
3416 +void web100_update_timeout(struct sock *sk) {
3417 + struct web100stats *stats = tcp_sk(sk)->tcp_stats;
3419 + stats->wc_vars.CurTimeoutCount++;
3420 + if (inet_csk(sk)->icsk_backoff)
3421 + stats->wc_vars.SubsequentTimeouts++;
3423 + stats->wc_vars.Timeouts++;
3424 + if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open)
3425 + stats->wc_vars.AbruptTimeouts++;
3428 +void web100_update_mss(struct tcp_sock *tp)
3430 + struct web100stats *stats = tp->tcp_stats;
3431 + int mss = tp->mss_cache;
3433 + stats->wc_vars.CurMSS = mss;
3434 + if (mss > stats->wc_vars.MaxMSS)
3435 + stats->wc_vars.MaxMSS = mss;
3436 + if (mss < stats->wc_vars.MinMSS)
3437 + stats->wc_vars.MinMSS = mss;
3440 +void web100_update_cwnd(struct tcp_sock *tp)
3442 + struct web100stats *stats = tp->tcp_stats;
3443 + __u16 mss = tp->mss_cache;
3448 + printk("Web100: web100_update_cwnd: mss == 0\n");
3452 + cwnd = min(WC_INF32 / mss, tp->snd_cwnd) * mss;
3453 + stats->wc_vars.CurCwnd = cwnd;
3454 + if (cwnd > stats->wc_vars.MaxCwnd)
3455 + stats->wc_vars.MaxCwnd = cwnd;
3457 + ssthresh = min(WC_INF32 / mss, tp->snd_ssthresh) * mss;
3458 + stats->wc_vars.CurSsthresh = ssthresh;
3460 + /* Discard initiail ssthresh set at infinity. */
3461 + if (tp->snd_ssthresh >= 0x7ffffff) {
3464 + if (ssthresh > stats->wc_vars.MaxSsthresh)
3465 + stats->wc_vars.MaxSsthresh = ssthresh;
3466 + if (ssthresh < stats->wc_vars.MinSsthresh)
3467 + stats->wc_vars.MinSsthresh = ssthresh;
3470 +void web100_update_rwin_rcvd(struct tcp_sock *tp)
3472 + struct web100stats *stats = tp->tcp_stats;
3473 + __u32 win = tp->snd_wnd;
3475 + stats->wc_vars.CurRwinRcvd = win;
3476 + if (win > stats->wc_vars.MaxRwinRcvd)
3477 + stats->wc_vars.MaxRwinRcvd = win;
3478 + if (win < stats->wc_vars.MinRwinRcvd)
3479 + stats->wc_vars.MinRwinRcvd = win;
3482 +void web100_update_rwin_sent(struct tcp_sock *tp)
3484 + struct web100stats *stats = tp->tcp_stats;
3485 + __u32 win = tp->rcv_wnd;
3487 + /* Update our advertised window. */
3488 + stats->wc_vars.CurRwinSent = win;
3489 + if (win > stats->wc_vars.MaxRwinSent)
3490 + stats->wc_vars.MaxRwinSent = win;
3491 + if (win < stats->wc_vars.MinRwinSent)
3492 + stats->wc_vars.MinRwinSent = win;
3496 +/* TODO: change this to a generic state machine instrument */
3497 +static void web100_state_update(struct tcp_sock *tp, int why, __u64 bytes)
3499 + struct web100stats *stats = tp->tcp_stats;
3502 + now = web100_mono_time();
3503 + stats->wc_vars.SndLimTime[stats->wc_limstate] += now - stats->wc_limstate_time;
3504 + stats->wc_limstate_time = now;
3506 + stats->wc_vars.SndLimBytes[why] += bytes - stats->wc_limstate_bytes;
3507 + stats->wc_limstate_bytes = bytes;
3509 + if (stats->wc_limstate != why) {
3510 + stats->wc_limstate = why;
3511 + stats->wc_vars.SndLimTrans[why]++;
3515 +void web100_update_sndlim(struct tcp_sock *tp, int why)
3517 + struct web100stats *stats = tp->tcp_stats;
3520 + printk("web100_update_sndlim: BUG: why < 0\n");
3524 + web100_state_update(tp, why, stats->wc_vars.DataBytesOut);
3525 + /* future instruments on other sender bottlenecks here... */
3526 + /* if (!why) { why = ??? } */
3527 + /* web100_state_update(tp, why, stats->wc_vars.DataBytesOut); */
3530 +void web100_update_congestion(struct tcp_sock *tp, int why_dummy)
3532 + struct web100stats *stats = tp->tcp_stats;
3534 + stats->wc_vars.CongestionSignals++;
3535 + stats->wc_vars.PreCongSumCwnd += stats->wc_vars.CurCwnd;
3537 + /* This may require more control flags */
3538 + stats->wc_vars.PreCongCountRTT++;
3539 + stats->wc_vars.PreCongSumRTT += stats->wc_vars.SampleRTT;
3542 +/* Called from tcp_transmit_skb, whenever we push a segment onto the wire.
3544 +void web100_update_segsend(struct sock *sk, int len, int pcount,
3545 + __u32 seq, __u32 end_seq, int flags)
3547 + struct web100stats *stats = tcp_sk(sk)->tcp_stats;
3549 + /* We know we're sending a segment. */
3550 + stats->wc_vars.PktsOut += pcount;
3552 + /* We know the ack seq is rcv_nxt. web100_XXX bug compatible*/
3553 + web100_update_rcv_nxt(tcp_sk(sk));
3555 + /* A pure ACK contains no data; everything else is data. */
3557 + stats->wc_vars.DataPktsOut += pcount;
3558 + stats->wc_vars.DataBytesOut += len;
3560 + stats->wc_vars.AckPktsOut++;
3563 + /* Check for retransmission. */
3564 + if (flags & TCPCB_FLAG_SYN) {
3565 + if (inet_csk(sk)->icsk_retransmits)
3566 + stats->wc_vars.PktsRetrans++;
3567 + } else if (before(seq, stats->wc_vars.SndMax)) {
3568 + stats->wc_vars.PktsRetrans += pcount;
3569 + stats->wc_vars.BytesRetrans += end_seq - seq;
3573 +void web100_update_segrecv(struct tcp_sock *tp, struct sk_buff *skb)
3575 + struct web100directs *vars = &tp->tcp_stats->wc_vars;
3576 + struct tcphdr *th = tcp_hdr(skb);
3579 + if (skb->len == th->doff*4) {
3580 + vars->AckPktsIn++;
3581 + if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una)
3582 + vars->DupAcksIn++;
3584 + vars->DataPktsIn++;
3585 + vars->DataBytesIn += skb->len - th->doff*4;
3589 +void web100_update_rcv_nxt(struct tcp_sock *tp)
3591 + struct web100stats *stats = tp->tcp_stats;
3593 + if (before(stats->wc_vars.RcvNxt, stats->wc_vars.RecvISS) &&
3594 + after(tp->rcv_nxt, stats->wc_vars.RecvISS))
3595 + stats->wc_vars.RecvWraps++;
3596 + stats->wc_vars.ThruBytesReceived += (__u32) (tp->rcv_nxt - stats->wc_vars.RcvNxt); /* XXX */
3597 + stats->wc_vars.RcvNxt = tp->rcv_nxt;
3600 +void web100_update_writeq(struct sock *sk)
3602 + struct tcp_sock *tp = tcp_sk(sk);
3603 + struct web100directs *vars = &tp->tcp_stats->wc_vars;
3604 + int len = tp->write_seq - vars->SndMax;
3606 + vars->CurAppWQueue = len;
3607 + if (len > vars->MaxAppWQueue)
3608 + vars->MaxAppWQueue = len;
3611 +void web100_update_recvq(struct sock *sk)
3613 + struct tcp_sock *tp = tcp_sk(sk);
3614 + struct web100directs *vars = &tp->tcp_stats->wc_vars;
3615 + int len1 = tp->rcv_nxt - tp->copied_seq;
3617 + vars->CurAppRQueue = len1;
3618 + if (vars->MaxAppRQueue < len1)
3619 + vars->MaxAppRQueue = len1;
3621 +#if 0 /* FIXME!! */
3622 + vars->CurReasmQueue = len2;
3623 + if (vars->MaxReasmQueue < len2)
3624 + vars->MaxReasmQueue = len2;
3629 +void __init web100_stats_init()
3633 + memset(death_slots, 0, sizeof (death_slots));
3636 + (struct web100stats **)alloc_large_system_hash("TCP ESTATS",
3637 + sizeof (struct web100stats *),
3638 + tcp_hashinfo.ehash_size,
3639 + (num_physpages >= 128 * 1024) ?
3643 + web100stats_htsize = 1 << order;
3644 + memset(web100stats_ht, 0, web100stats_htsize * sizeof (struct web100stats *));
3646 +#ifdef CONFIG_WEB100_NETLINK
3647 + if ((web100_nlsock = netlink_kernel_create(&init_net, NETLINK_WEB100, 0, NULL, NULL, NULL)) == NULL)
3648 + printk(KERN_ERR "web100_stats_init(): cannot initialize netlink socket\n");
3651 + printk("Web100 %s: Initialization successful\n", web100_version_string);
3654 +#ifdef CONFIG_IPV6_MODULE
3655 +EXPORT_SYMBOL(web100_stats_create);
3656 +EXPORT_SYMBOL(web100_stats_destroy);
3657 +EXPORT_SYMBOL(web100_update_segrecv);
3658 +EXPORT_SYMBOL(web100_update_cwnd);
3659 +EXPORT_SYMBOL(web100_update_writeq);
3661 diff -Naur linux-2.6.32-27.planetlab.i686.orig/net/ipv6/tcp_ipv6.c linux-2.6.32-27.planetlab.i686/net/ipv6/tcp_ipv6.c
3662 --- linux-2.6.32-27.planetlab.i686.orig/net/ipv6/tcp_ipv6.c 2011-11-16 16:51:07.402470961 -0500
3663 +++ linux-2.6.32-27.planetlab.i686/net/ipv6/tcp_ipv6.c 2011-11-16 17:06:57.467410360 -0500
3664 @@ -309,6 +309,11 @@
3668 + WEB100_VAR_SET(tp, SndISS, tp->write_seq);
3669 + WEB100_VAR_SET(tp, SndMax, tp->write_seq);
3670 + WEB100_VAR_SET(tp, SndNxt, tp->write_seq);
3671 + WEB100_VAR_SET(tp, SndUna, tp->write_seq);
3673 err = tcp_connect(sk);
3676 @@ -1370,6 +1375,13 @@
3677 newsk = tcp_create_openreq_child(sk, req, skb);
3680 +#ifdef CONFIG_WEB100_STATS
3681 + if (web100_stats_create(newsk)) {
3685 + tcp_sk(newsk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV6;
3689 * No need to charge this sock to the relevant IPv6 refcnt debug socks
3690 @@ -1683,6 +1695,7 @@
3693 bh_lock_sock_nested(sk);
3694 + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_segrecv(tcp_sk(sk), skb));
3696 if (!sock_owned_by_user(sk)) {
3697 #ifdef CONFIG_NET_DMA
3698 @@ -1701,6 +1714,7 @@
3700 goto discard_and_relse;
3702 + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_cwnd(tcp_sk(sk)));
3706 @@ -1881,6 +1895,16 @@
3707 sk->sk_sndbuf = sysctl_tcp_wmem[1];
3708 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
3710 +#ifdef CONFIG_WEB100_STATS
3713 + if ((err = web100_stats_create(sk))) {
3716 + tcp_sk(sk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV6;
3721 percpu_counter_inc(&tcp_sockets_allocated);