diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-30 07:11:50 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-30 07:11:50 -0800 |
| commit | 37e19a489ded6daeb46cc8f55f24b284db981cc4 (patch) | |
| tree | 1c11da21ad04885778f9ce8fd25ef47cdd9dee3e | |
| parent | f812d833cc90d19590a24ceeb03cff08f6a74d5b (diff) | |
| parent | d3f58c34c2a49bc9691f052ceb524a88ee46eadd (diff) | |
Merge bk://kernel.bkbits.net/davem/net-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
| -rw-r--r-- | Documentation/DocBook/kernel-api.tmpl | 5 | ||||
| -rw-r--r-- | include/linux/gen_stats.h | 5 | ||||
| -rw-r--r-- | include/net/udp.h | 2 | ||||
| -rw-r--r-- | net/compat.c | 4 | ||||
| -rw-r--r-- | net/core/gen_estimator.c | 35 | ||||
| -rw-r--r-- | net/core/gen_stats.c | 90 | ||||
| -rw-r--r-- | net/core/pktgen.c | 1 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 2 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 47 | ||||
| -rw-r--r-- | net/ipv6/af_inet6.c | 2 |
10 files changed, 190 insertions, 3 deletions
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 5f11984a04f3..ef66fdda129f 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -133,6 +133,11 @@ KAO --> <sect1><title>Socket Filter</title> !Enet/core/filter.c </sect1> + <sect1><title>Generic Network Statistics</title> +!Iinclude/linux/gen_stats.h +!Enet/core/gen_stats.c +!Enet/core/gen_estimator.c + </sect1> </chapter> <chapter id="netdev"> diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h index ab631c3571ce..13f4e74609ac 100644 --- a/include/linux/gen_stats.h +++ b/include/linux/gen_stats.h @@ -14,6 +14,7 @@ enum { #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) /** + * struct gnet_stats_basic - byte/packet throughput statistics * @bytes: number of seen bytes * @packets: number of seen packets */ @@ -24,6 +25,7 @@ struct gnet_stats_basic }; /** + * struct gnet_stats_rate_est - rate estimator * @bps: current byte rate * @pps: current packet rate */ @@ -34,10 +36,12 @@ struct gnet_stats_rate_est }; /** + * struct gnet_stats_queue - queuing statistics * @qlen: queue length * @backlog: backlog size of queue * @drops: number of dropped packets * @requeues: number of requeues + * @overlimits: number of enqueues over the limit */ struct gnet_stats_queue { @@ -49,6 +53,7 @@ struct gnet_stats_queue }; /** + * struct gnet_estimator - rate estimator configuration * @interval: sampling period * @ewma_log: the log of measurement window weight */ diff --git a/include/net/udp.h b/include/net/udp.h index 2ef99a71bc30..c496d10101db 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -71,6 +71,8 @@ extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, extern int udp_rcv(struct sk_buff *skb); extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int udp_disconnect(struct sock *sk, int flags); +extern unsigned int udp_poll(struct file *file, struct socket *sock, + poll_table *wait); DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field) diff --git a/net/compat.c b/net/compat.c index 6080b6439b96..69524b497f01 100644 --- a/net/compat.c +++ b/net/compat.c @@ -22,6 +22,7 @@ #include <linux/filter.h> #include <linux/compat.h> #include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/security.h> #include <net/scm.h> #include <net/sock.h> @@ -264,6 +265,9 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) for (i = 0, cmfptr = (int __user *) CMSG_COMPAT_DATA(cm); i < fdmax; i++, cmfptr++) { int new_fd; + err = security_file_receive(fp[i]); + if (err) + break; err = get_unused_fd(); if (err < 0) break; diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 00e167827dd7..c9c70c6d0cfb 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -132,6 +132,21 @@ static void est_timer(unsigned long arg) read_unlock(&est_lock); } +/** + * gen_new_estimator - create a new rate estimator + * @bstats: basic statistics + * @rate_est: rate estimator statistics + * @stats_lock: statistics lock + * @opt: rate estimator configuration TLV + * + * Creates a new rate estimator with &bstats as source and &rate_est + * as destination. A new timer with the interval specified in the + * configuration TLV is created. Upon each interval, the latest statistics + * will be read from &bstats and the estimated rate will be stored in + * &rate_est with the statistics lock grabed during this period. + * + * Returns 0 on success or a negative error code. + */ int gen_new_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct rtattr *opt) { @@ -173,6 +188,14 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, return 0; } +/** + * gen_kill_estimator - remove a rate estimator + * @bstats: basic statistics + * @rate_est: rate estimator statistics + * + * Removes the rate estimator specified by &bstats and &rate_est + * and deletes the timer. + */ void gen_kill_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est) { @@ -200,6 +223,18 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats, } } +/** + * gen_replace_estimator - replace rate estimator configruation + * @bstats: basic statistics + * @rate_est: rate estimator statistics + * @stats_lock: statistics lock + * @opt: rate estimator configuration TLV + * + * Replaces the configuration of a rate estimator by calling + * gen_kill_estimator() and gen_new_estimator(). + * + * Returns 0 on success or a negative error code. + */ int gen_replace_estimator(struct gnet_stats_basic *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index a35e97b5ad8a..86cd889d0e2b 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -34,6 +34,24 @@ rtattr_failure: return -1; } +/** + * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode + * @skb: socket buffer to put statistics TLVs into + * @type: TLV type for top level statistic TLV + * @tc_stats_type: TLV type for backward compatibility struct tc_stats TLV + * @xstats_type: TLV type for backward compatibility xstats TLV + * @lock: statistics lock + * @d: dumping handle + * + * Initializes the dumping handle, grabs the statistic lock and appends + * an empty TLV header to the socket buffer for use a container for all + * other statistic TLVS. + * + * The dumping handle is marked to be in backward compatibility mode telling + * all gnet_stats_copy_XXX() functions to fill a local copy of struct tc_stats. + * + * Returns 0 on success or -1 if the room in the socket buffer was not sufficient. + */ int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, int xstats_type, spinlock_t *lock, struct gnet_dump *d) @@ -52,6 +70,19 @@ gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type, return gnet_stats_copy(d, type, NULL, 0); } +/** + * gnet_stats_start_copy_compat - start dumping procedure in compatibility mode + * @skb: socket buffer to put statistics TLVs into + * @type: TLV type for top level statistic TLV + * @lock: statistics lock + * @d: dumping handle + * + * Initializes the dumping handle, grabs the statistic lock and appends + * an empty TLV header to the socket buffer for use a container for all + * other statistic TLVS. + * + * Returns 0 on success or -1 if the room in the socket buffer was not sufficient. + */ int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, struct gnet_dump *d) @@ -59,7 +90,17 @@ gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, return gnet_stats_start_copy_compat(skb, type, 0, 0, lock, d); } - +/** + * gnet_stats_copy_basic - copy basic statistics into statistic TLV + * @d: dumping handle + * @b: basic statistics + * + * Appends the basic statistics to the top level TLV created by + * gnet_stats_start_copy(). + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b) { @@ -71,6 +112,17 @@ gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b) return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b)); } +/** + * gnet_stats_copy_rate_est - copy rate estimator statistics into statistics TLV + * @d: dumping handle + * @r: rate estimator statistics + * + * Appends the rate estimator statistics to the top level TLV created by + * gnet_stats_start_copy(). + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r) { @@ -82,6 +134,17 @@ gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r) return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r)); } +/** + * gnet_stats_copy_queue - copy queue statistics into statistics TLV + * @d: dumping handle + * @q: queue statistics + * + * Appends the queue statistics to the top level TLV created by + * gnet_stats_start_copy(). + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q) { @@ -95,6 +158,19 @@ gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q) return gnet_stats_copy(d, TCA_STATS_QUEUE, q, sizeof(*q)); } +/** + * gnet_stats_copy_app - copy application specific statistics into statistics TLV + * @d: dumping handle + * @st: application specific statistics data + * @len: length of data + * + * Appends the application sepecific statistics to the top level TLV created by + * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping + * handle is in backward compatibility mode. + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) { @@ -103,6 +179,18 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) return gnet_stats_copy(d, TCA_STATS_APP, st, len); } +/** + * gnet_stats_finish_copy - finish dumping procedure + * @d: dumping handle + * + * Corrects the length of the top level TLV to include all TLVs added + * by gnet_stats_copy_XXX() calls. Adds the backward compatibility TLVs + * if gnet_stats_start_copy_compat() was used and releases the statistics + * lock. + * + * Returns 0 on success or -1 with the statistic lock released + * if the room in the socket buffer was not sufficient. + */ int gnet_stats_finish_copy(struct gnet_dump *d) { diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 0e4a6f9f6d87..f57db05b4341 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -647,6 +647,7 @@ static void inject(struct pktgen_info* info) info->do_run_run = 1; /* Cranke yeself! */ info->idle_acc = 0; info->sofar = 0; + info->errors = 0; lcount = info->count; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f9cacafdb511..d127c16746bf 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -809,7 +809,7 @@ struct proto_ops inet_dgram_ops = { .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = inet_getname, - .poll = datagram_poll, + .poll = udp_poll, .ioctl = inet_ioctl, .listen = sock_no_listen, .shutdown = inet_shutdown, diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d38f2b2579dd..4a1bfb39c4b0 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1303,6 +1303,52 @@ static int udp_getsockopt(struct sock *sk, int level, int optname, return 0; } +/** + * udp_poll - wait for a UDP event. + * @file - file struct + * @sock - socket + * @wait - poll table + * + * This is same as datagram poll, except for the special case of + * blocking sockets. If application is using a blocking fd + * and a packet with checksum error is in the queue; + * then it could get return from select indicating data available + * but then block when reading it. Add special case code + * to work around these arguably broken applications. + */ +unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) +{ + unsigned int mask = datagram_poll(file, sock, wait); + struct sock *sk = sock->sk; + + /* Check for false positives due to checksum errors */ + if ( (mask & POLLRDNORM) && + !(file->f_flags & O_NONBLOCK) && + !(sk->sk_shutdown & RCV_SHUTDOWN)){ + struct sk_buff_head *rcvq = &sk->sk_receive_queue; + struct sk_buff *skb; + + spin_lock_irq(&rcvq->lock); + while ((skb = skb_peek(rcvq)) != NULL) { + if (udp_checksum_complete(skb)) { + UDP_INC_STATS_BH(UDP_MIB_INERRORS); + __skb_unlink(skb, rcvq); + kfree_skb(skb); + } else { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + } + spin_unlock_irq(&rcvq->lock); + + /* nothing to see, move along */ + if (skb == NULL) + mask &= ~(POLLIN | POLLRDNORM); + } + + return mask; + +} struct proto udp_prot = { .name = "UDP", @@ -1517,6 +1563,7 @@ EXPORT_SYMBOL(udp_ioctl); EXPORT_SYMBOL(udp_port_rover); EXPORT_SYMBOL(udp_prot); EXPORT_SYMBOL(udp_sendmsg); +EXPORT_SYMBOL(udp_poll); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(udp_proc_register); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 0190359a2b31..1d10fb1409f8 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -501,7 +501,7 @@ struct proto_ops inet6_dgram_ops = { .socketpair = sock_no_socketpair, /* a do nothing */ .accept = sock_no_accept, /* a do nothing */ .getname = inet6_getname, - .poll = datagram_poll, /* ok */ + .poll = udp_poll, /* ok */ .ioctl = inet6_ioctl, /* must change */ .listen = sock_no_listen, /* ok */ .shutdown = inet_shutdown, /* ok */ |
