lkml.org 
[lkml]   [2000]   [Sep]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectnetworking todo, was Re: Linux-2.4.0-test9-pre2
On Tue, Sep 19, 2000 at 05:14:39PM -0700, David S. Miller wrote:
> And hey, guess what, as a result of this right now my "non-driver
> caused" core/ipv4/ipv6 networking bug list is pretty much empty right
> now. Only a few netfilter glitches appear to remain.

Some items for your list:

The ipid handling is still fishy, it will break when you talk to more
destinations than the inetpeer cache can take (I fixed it in my local
tree with the appended patch)

Receiver side SMP reordering is still there, but I'm not sure if it is
fixable (but it'll surely hit people that cannot use Linux senders, I
just see the reports)

The TCP connect running out of ports problem is still there (I fixed it
locally, but the changes are probably far too extensive for 2.4.x now)

The TCP ISN computation is not SMP safe.

include/linux/snmp.h is probably still not properly aligned for all
cache line sizes.

UDP recvmsg error handling for csum errors is bogus (fix pending)

net/ipv6/route.c:struct rt6_info ip6_null_entry initialisation seems
to be out of date (fix pending)

I also would like to remove the inetpeer cache code before 2.4.0, now
that nobody managed to salvage tw recycling and ipid can do without it.


-Andi


Index: drivers/char/random.c
===================================================================
RCS file: /cvs/linux/drivers/char/random.c,v
retrieving revision 1.47
diff -u -u -d -r1.47 random.c
--- drivers/char/random.c 2000/07/26 01:03:56 1.47
+++ drivers/char/random.c 2000/09/17 11:55:03
@@ -1994,6 +1994,13 @@
#define REKEY_INTERVAL 300
#define HASH_BITS 24

+/* Most of the following procedures have SMP races, which are mostly harmless
+ (it is possible that you get duplicated ISNs/or non monotonic IDs with some bad
+ luck)
+ You should definitely make sure that only start sending packets _after_
+ the random pool has been restored from disk.
+*/
+
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
__u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
__u16 sport, __u16 dport)
@@ -2099,24 +2106,22 @@
#endif
return seq;
}
+__u16 ip_id_counter;

/* The code below is shamelessly stolen from secure_tcp_sequence_number().
* All blames to Andrey V. Savochkin <saw@msu.ru>.
+ * Changed by Andi Kleen to never rekey (blames to him now)
+ * Should be inlined.
*/
__u32 secure_ip_id(__u32 daddr)
{
- static time_t rekey_time = 0;
- static __u32 secret[12];
- time_t t;
-
- /*
- * Pick a random secret every REKEY_INTERVAL seconds.
- */
- t = CURRENT_TIME;
- if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
- rekey_time = t;
- /* First word is overwritten below. */
- get_random_bytes(secret+1, sizeof(secret)-4);
+ static __u32 ip_id_secret[12];
+ static int init;
+
+ if (!init) {
+ get_random_bytes(ip_id_secret+1, sizeof(ip_id_secret)-4);
+ get_random_bytes(&ip_id_counter, 2);
+ init = 1;
}

/*
@@ -2127,9 +2132,9 @@
* hashing fixed data into it isn't going to improve anything,
* so we should get started with the variable data.
*/
- secret[0]=daddr;
+ ip_id_secret[0]=daddr;

- return halfMD4Transform(secret+8, secret);
+ return halfMD4Transform(ip_id_secret+8, ip_id_secret);
}

#ifdef CONFIG_SYN_COOKIES
Index: include/linux/random.h
===================================================================
RCS file: /cvs/linux/include/linux/random.h,v
retrieving revision 1.12
diff -u -u -d -r1.12 random.h
--- include/linux/random.h 2000/01/29 07:39:40 1.12
+++ include/linux/random.h 2000/09/17 11:55:09
@@ -56,6 +56,8 @@
extern void get_random_bytes(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);

+extern __u16 ip_id_counter;
+
extern __u32 secure_ip_id(__u32 daddr);
extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport);
Index: include/net/dst.h
===================================================================
RCS file: /cvs/linux/include/net/dst.h,v
retrieving revision 1.20
diff -u -u -d -r1.20 dst.h
--- include/net/dst.h 2000/08/09 11:59:03 1.20
+++ include/net/dst.h 2000/09/17 11:55:09
@@ -45,6 +45,7 @@
unsigned cwnd;
unsigned advmss;
unsigned reordering;
+ unsigned idbase;

unsigned long rate_last; /* rate limiting for ICMP */
unsigned long rate_tokens;
Index: include/net/ip.h
===================================================================
RCS file: /cvs/linux/include/net/ip.h,v
retrieving revision 1.38
diff -u -u -d -r1.38 ip.h
--- include/net/ip.h 2000/07/07 22:29:42 1.38
+++ include/net/ip.h 2000/09/17 11:55:10
@@ -5,7 +5,7 @@
*
* Definitions for the IP module.
*
- * Version: @(#)ip.h 1.0.2 05/07/93
+ * Version: $Id$
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -67,6 +67,19 @@
extern struct ip_ra_chain *ip_ra_chain;
extern rwlock_t ip_ra_lock;

+#define IPID_CPU_GRAB 32
+#define IPID_GRAB_EXPIRE (HZ/50)
+
+struct ip_local_data {
+ unsigned long ipid_grab_time;
+ int ipid_left;
+ __u16 ipid;
+} ____cacheline_aligned;
+
+extern struct ip_local_data ip_local_data[NR_CPUS];
+
+#define IP_LOCAL_DATA (&ip_local_data[smp_processor_id()])
+
/* IP flags. */
#define IP_CE 0x8000 /* Flag: "Congestion" */
#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
@@ -186,14 +199,13 @@
!(dst->mxlock&(1<<RTAX_MTU))));
}

-extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst);
+void __ip_select_ident(struct iphdr *, struct dst_entry *);

-extern __inline__ void ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
+static __inline__ void ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
{
- if (iph->frag_off&__constant_htons(IP_DF))
- iph->id = 0;
- else
- __ip_select_ident(iph, dst);
+ iph->id = 0;
+ if ((iph->frag_off&__constant_htons(IP_DF)) == 0)
+ __ip_select_ident(iph,dst);
}

/*
===================================================================
RCS file: /cvs/linux/net/ipv4/ip_output.c,v
retrieving revision 1.85
diff -u -u -d -r1.85 ip_output.c
--- net/ipv4/ip_output.c 2000/08/31 23:39:12 1.85
+++ net/ipv4/ip_output.c 2000/09/17 11:55:16
@@ -76,6 +76,12 @@
#include <linux/netfilter_ipv4.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
+#include <linux/random.h>
+
+/*
+ * Per CPU local data of IP. Wasteful, should be merged with other fields.
+ */
+struct ip_local_data ip_local_data[NR_CPUS];

/*
* Shall we try to damage output packets if routing dev changes?
@@ -83,6 +89,38 @@

int sysctl_ip_dynaddr = 0;
int sysctl_ip_default_ttl = IPDEFTTL;
+
+void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
+{
+ if (!dst->idbase)
+ dst->idbase = secure_ip_id(iph->daddr);
+
+ local_bh_disable();
+
+#ifdef __SMP__
+ {
+ static spinlock_t ip_id_lock = SPIN_LOCK_UNLOCKED;
+ struct ip_local_data *ipl = IP_LOCAL_DATA;
+
+ if (ipl->ipid_left == 0 || time_before(ipl->ipid_grab_time, jiffies-IPID_GRAB_EXPIRE)) {
+ /* Fetch some new cookies for the local lair. */
+ spin_lock(&ip_id_lock);
+ ipl->ipid = ip_id_counter;
+ ip_id_counter += IPID_CPU_GRAB;
+ spin_unlock(&ip_id_lock);
+ ipl->ipid_left = IPID_CPU_GRAB;
+ ipl->ipid_grab_time = jiffies;
+ }
+ iph->id = htons(dst->idbase + ipl->ipid);
+ ipl->ipid++;
+ ipl->ipid_left--;
+ }
+#else
+ iph->id = dst->idbase + ip_id_counter++;
+#endif
+
+ local_bh_enable();
+}

/* Generate a checksum for an outgoing IP datagram. */
__inline__ void ip_send_check(struct iphdr *iph)
Index: net/ipv4/route.c
===================================================================
RCS file: /cvs/linux/net/ipv4/route.c,v
retrieving revision 1.90
diff -u -u -d -r1.90 route.c
--- net/ipv4/route.c 2000/08/31 23:39:12 1.90
+++ net/ipv4/route.c 2000/09/17 11:55:18
@@ -83,7 +83,6 @@
#include <linux/pkt_sched.h>
#include <linux/mroute.h>
#include <linux/netfilter_ipv4.h>
-#include <linux/random.h>
#include <net/protocol.h>
#include <net/ip.h>
#include <net/route.h>
@@ -650,48 +649,6 @@
spin_unlock_bh(&rt_peer_lock);
if (peer)
inet_putpeer(peer);
-}
-
-/*
- * Peer allocation may fail only in serious out-of-memory conditions. However
- * we still can generate some output.
- * Random ID selection looks a bit dangerous because we have no chances to
- * select ID being unique in a reasonable period of time.
- * But broken packet identifier may be better than no packet at all.
- */
-static void ip_select_fb_ident(struct iphdr *iph)
-{
- static spinlock_t ip_fb_id_lock = SPIN_LOCK_UNLOCKED;
- static u32 ip_fallback_id;
- u32 salt;
-
- spin_lock_bh(&ip_fb_id_lock);
- salt = secure_ip_id(ip_fallback_id ^ iph->daddr);
- iph->id = salt & 0xFFFF;
- ip_fallback_id = salt;
- spin_unlock_bh(&ip_fb_id_lock);
-}
-
-void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
-{
- struct rtable *rt = (struct rtable *) dst;
-
- if (rt) {
- if (rt->peer == NULL)
- rt_bind_peer(rt, 1);
-
- /* If peer is attached to destination, it is never detached,
- so that we need not to grab a lock to dereference it.
- */
- if (rt->peer) {
- iph->id = inet_getid(rt->peer);
- return;
- }
- } else {
- printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", NET_CALLER(iph));
- }
-
- ip_select_fb_ident(iph);
}

static void rt_del(unsigned hash, struct rtable *rt)
--- net/ipv6/route.c 2000/08/10 01:17:13 1.48
+++ net/ipv6/route.c 2000/09/17 11:55:32
@@ -92,23 +92,26 @@
};

struct rt6_info ip6_null_entry = {
- {{NULL, ATOMIC_INIT(1), 1, &loopback_dev,
- -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- -ENETUNREACH, NULL, NULL,
- ip6_pkt_discard, ip6_pkt_discard,
-#ifdef CONFIG_NET_CLS_ROUTE
- 0,
-#endif
- &ip6_dst_ops}},
- NULL, {{{0}}}, RTF_REJECT|RTF_NONEXTHOP, ~0U,
- 255, ATOMIC_INIT(1), {NULL}, {{{{0}}}, 0}, {{{{0}}}, 0}
-};
-
-struct fib6_node ip6_routing_table = {
- NULL, NULL, NULL, NULL,
- &ip6_null_entry,
- 0, RTN_ROOT|RTN_TL_ROOT|RTN_RTINFO, 0
-};
+ u: { dst: {
+ __refcnt: ATOMIC_INIT(1),
+ __use: 1,
+ dev: &loopback_dev,
+ lastuse: -1,
+ error: -ENETUNREACH,
+ input: ip6_pkt_discard,
+ output: ip6_pkt_discard,
+ ops: &ip6_dst_ops
+ }},
+ rt6i_flags: RTF_REJECT|RTF_NONEXTHOP,
+ rt6i_metric: ~0U,
+ rt6i_hoplimit: 255,
+ rt6i_ref: ATOMIC_INIT(1)
+};
+
+struct fib6_node ip6_routing_table = {
+ leaf: &ip6_null_entry,
+ fn_flags: RTN_ROOT|RTN_TL_ROOT|RTN_RTINFO
+};

#ifdef CONFIG_RT6_POLICY
int ip6_rt_policy = 0;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 12:45    [W:0.256 / U:0.764 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site