|
@@ -89,6 +89,7 @@
|
|
|
#include <linux/rcupdate.h>
|
|
|
#include <linux/times.h>
|
|
|
#include <linux/slab.h>
|
|
|
+#include <linux/jhash.h>
|
|
|
#include <net/dst.h>
|
|
|
#include <net/net_namespace.h>
|
|
|
#include <net/protocol.h>
|
|
@@ -456,39 +457,19 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
|
|
|
return neigh_create(&arp_tbl, pkey, dev);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * 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 DEFINE_SPINLOCK(ip_fb_id_lock);
|
|
|
- static u32 ip_fallback_id;
|
|
|
- u32 salt;
|
|
|
+atomic_t *ip_idents __read_mostly;
|
|
|
+EXPORT_SYMBOL(ip_idents);
|
|
|
|
|
|
- spin_lock_bh(&ip_fb_id_lock);
|
|
|
- salt = secure_ip_id((__force __be32)ip_fallback_id ^ iph->daddr);
|
|
|
- iph->id = htons(salt & 0xFFFF);
|
|
|
- ip_fallback_id = salt;
|
|
|
- spin_unlock_bh(&ip_fb_id_lock);
|
|
|
-}
|
|
|
-
|
|
|
-void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
|
|
|
+void __ip_select_ident(struct iphdr *iph, int segs)
|
|
|
{
|
|
|
- struct net *net = dev_net(dst->dev);
|
|
|
- struct inet_peer *peer;
|
|
|
+ static u32 ip_idents_hashrnd __read_mostly;
|
|
|
+ u32 hash, id;
|
|
|
|
|
|
- peer = inet_getpeer_v4(net->ipv4.peers, iph->daddr, 1);
|
|
|
- if (peer) {
|
|
|
- iph->id = htons(inet_getid(peer, more));
|
|
|
- inet_putpeer(peer);
|
|
|
- return;
|
|
|
- }
|
|
|
+ net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
|
|
|
|
|
|
- ip_select_fb_ident(iph);
|
|
|
+ hash = jhash_1word((__force u32)iph->daddr, ip_idents_hashrnd);
|
|
|
+ id = ip_idents_reserve(hash, segs);
|
|
|
+ iph->id = htons(id);
|
|
|
}
|
|
|
EXPORT_SYMBOL(__ip_select_ident);
|
|
|
|
|
@@ -2711,6 +2692,12 @@ int __init ip_rt_init(void)
|
|
|
{
|
|
|
int rc = 0;
|
|
|
|
|
|
+ ip_idents = kmalloc(IP_IDENTS_SZ * sizeof(*ip_idents), GFP_KERNEL);
|
|
|
+ if (!ip_idents)
|
|
|
+ panic("IP: failed to allocate ip_idents\n");
|
|
|
+
|
|
|
+ prandom_bytes(ip_idents, IP_IDENTS_SZ * sizeof(*ip_idents));
|
|
|
+
|
|
|
#ifdef CONFIG_IP_ROUTE_CLASSID
|
|
|
ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct));
|
|
|
if (!ip_rt_acct)
|