Commit 83902db6 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5

into kernel.bkbits.net:/home/davem/net-2.5
parents 0dd22e54 44389abb
...@@ -316,6 +316,15 @@ M: marcel@holtmann.org ...@@ -316,6 +316,15 @@ M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/ W: http://www.holtmann.org/linux/bluetooth/
S: Maintained S: Maintained
BONDING DRIVER
P: Chad Tindel
M: ctindel@users.sourceforge.net
P: Jay Vosburgh
M: fubar@us.ibm.com
L: bonding-devel@lists.sourceforge.net
W: http://sourceforge.net/projects/bonding/
S: Supported
BTTV VIDEO4LINUX DRIVER BTTV VIDEO4LINUX DRIVER
P: Gerd Knorr P: Gerd Knorr
M: kraxel@bytesex.org M: kraxel@bytesex.org
......
...@@ -1102,7 +1102,7 @@ static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) ...@@ -1102,7 +1102,7 @@ static inline int skb_cow(struct sk_buff *skb, unsigned int headroom)
static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len) static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len)
{ {
unsigned int size = skb->len + skb->data_len; unsigned int size = skb->len;
if (likely(size >= len)) if (likely(size >= len))
return skb; return skb;
return skb_pad(skb, len-size); return skb_pad(skb, len-size);
......
...@@ -122,7 +122,7 @@ static inline void dn_nsp_send(struct sk_buff *skb) ...@@ -122,7 +122,7 @@ static inline void dn_nsp_send(struct sk_buff *skb)
if ((dst = sk->dst_cache) && !dst->obsolete) { if ((dst = sk->dst_cache) && !dst->obsolete) {
try_again: try_again:
skb->dst = dst_clone(dst); skb->dst = dst_clone(dst);
dst->output(skb); dst_output(skb);
return; return;
} }
......
...@@ -593,7 +593,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, ...@@ -593,7 +593,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
* associations. * associations.
*/ */
skb->dst = dst_clone(dst); skb->dst = dst_clone(dst);
skb->dst->output(skb); dst_output(skb);
} }
......
...@@ -389,7 +389,7 @@ static int dn_route_rx_packet(struct sk_buff *skb) ...@@ -389,7 +389,7 @@ static int dn_route_rx_packet(struct sk_buff *skb)
int err; int err;
if ((err = dn_route_input(skb)) == 0) if ((err = dn_route_input(skb)) == 0)
return skb->dst->input(skb); return dst_input(skb);
if (decnet_debug_level & 4) { if (decnet_debug_level & 4) {
char *devname = skb->dev ? skb->dev->name : "???"; char *devname = skb->dev ? skb->dev->name : "???";
......
...@@ -184,14 +184,6 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) ...@@ -184,14 +184,6 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
#define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4) #define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook
changes route */
static inline int
output_maybe_reroute(struct sk_buff *skb)
{
return skb->dst->output(skb);
}
static int igmp_send_report(struct net_device *dev, u32 group, int type) static int igmp_send_report(struct net_device *dev, u32 group, int type)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -255,7 +247,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) ...@@ -255,7 +247,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr)); ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
output_maybe_reroute); dst_output);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Bill Hawes : Frag accounting and evictor fixes. * Bill Hawes : Frag accounting and evictor fixes.
* John McDonald : 0 length frag bug. * John McDonald : 0 length frag bug.
* Alexey Kuznetsov: SMP races, threading, cleanup. * Alexey Kuznetsov: SMP races, threading, cleanup.
* Patrick McHardy : LRU queue of frag heads for evictor.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/list.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/icmp.h> #include <linux/icmp.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
...@@ -67,6 +69,7 @@ struct ipfrag_skb_cb ...@@ -67,6 +69,7 @@ struct ipfrag_skb_cb
/* Describe an entry in the "incomplete datagrams" queue. */ /* Describe an entry in the "incomplete datagrams" queue. */
struct ipq { struct ipq {
struct ipq *next; /* linked list pointers */ struct ipq *next; /* linked list pointers */
struct list_head lru_list; /* lru list member */
u32 saddr; u32 saddr;
u32 daddr; u32 daddr;
u16 id; u16 id;
...@@ -94,6 +97,7 @@ struct ipq { ...@@ -94,6 +97,7 @@ struct ipq {
/* Per-bucket lock is easy to add now. */ /* Per-bucket lock is easy to add now. */
static struct ipq *ipq_hash[IPQ_HASHSZ]; static struct ipq *ipq_hash[IPQ_HASHSZ];
static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED; static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
static LIST_HEAD(ipq_lru_list);
int ip_frag_nqueues = 0; int ip_frag_nqueues = 0;
static __inline__ void __ipq_unlink(struct ipq *qp) static __inline__ void __ipq_unlink(struct ipq *qp)
...@@ -101,6 +105,7 @@ static __inline__ void __ipq_unlink(struct ipq *qp) ...@@ -101,6 +105,7 @@ static __inline__ void __ipq_unlink(struct ipq *qp)
if(qp->next) if(qp->next)
qp->next->pprev = qp->pprev; qp->next->pprev = qp->pprev;
*qp->pprev = qp->next; *qp->pprev = qp->next;
list_del(&qp->lru_list);
ip_frag_nqueues--; ip_frag_nqueues--;
} }
...@@ -202,39 +207,30 @@ static void ipq_kill(struct ipq *ipq) ...@@ -202,39 +207,30 @@ static void ipq_kill(struct ipq *ipq)
*/ */
static void ip_evictor(void) static void ip_evictor(void)
{ {
int i, progress; struct ipq *qp;
struct list_head *tmp;
do { for(;;) {
if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh) if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
return; return;
progress = 0; read_lock(&ipfrag_lock);
/* FIXME: Make LRU queue of frag heads. -DaveM */ if (list_empty(&ipq_lru_list)) {
for (i = 0; i < IPQ_HASHSZ; i++) {
struct ipq *qp;
if (ipq_hash[i] == NULL)
continue;
read_lock(&ipfrag_lock);
if ((qp = ipq_hash[i]) != NULL) {
/* find the oldest queue for this hash bucket */
while (qp->next)
qp = qp->next;
atomic_inc(&qp->refcnt);
read_unlock(&ipfrag_lock);
spin_lock(&qp->lock);
if (!(qp->last_in&COMPLETE))
ipq_kill(qp);
spin_unlock(&qp->lock);
ipq_put(qp);
IP_INC_STATS_BH(IpReasmFails);
progress = 1;
continue;
}
read_unlock(&ipfrag_lock); read_unlock(&ipfrag_lock);
return;
} }
} while (progress); tmp = ipq_lru_list.next;
qp = list_entry(tmp, struct ipq, lru_list);
atomic_inc(&qp->refcnt);
read_unlock(&ipfrag_lock);
spin_lock(&qp->lock);
if (!(qp->last_in&COMPLETE))
ipq_kill(qp);
spin_unlock(&qp->lock);
ipq_put(qp);
IP_INC_STATS_BH(IpReasmFails);
}
} }
/* /*
...@@ -302,6 +298,8 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) ...@@ -302,6 +298,8 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
qp->next->pprev = &qp->next; qp->next->pprev = &qp->next;
ipq_hash[hash] = qp; ipq_hash[hash] = qp;
qp->pprev = &ipq_hash[hash]; qp->pprev = &ipq_hash[hash];
INIT_LIST_HEAD(&qp->lru_list);
list_add_tail(&qp->lru_list, &ipq_lru_list);
ip_frag_nqueues++; ip_frag_nqueues++;
write_unlock(&ipfrag_lock); write_unlock(&ipfrag_lock);
return qp; return qp;
...@@ -496,6 +494,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb) ...@@ -496,6 +494,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (offset == 0) if (offset == 0)
qp->last_in |= FIRST_IN; qp->last_in |= FIRST_IN;
write_lock(&ipfrag_lock);
list_move_tail(&qp->lru_list, &ipq_lru_list);
write_unlock(&ipfrag_lock);
return; return;
err: err:
......
...@@ -344,7 +344,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb) ...@@ -344,7 +344,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
} }
} }
return skb->dst->input(skb); return dst_input(skb);
inhdr_error: inhdr_error:
IP_INC_STATS_BH(IpInHdrErrors); IP_INC_STATS_BH(IpInHdrErrors);
......
...@@ -1112,9 +1112,9 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) ...@@ -1112,9 +1112,9 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
struct dst_entry *dst = skb->dst; struct dst_entry *dst = skb->dst;
if (skb->len <= dst_pmtu(dst)) if (skb->len <= dst_pmtu(dst))
return dst->output(skb); return dst_output(skb);
else else
return ip_fragment(skb, dst->output); return ip_fragment(skb, dst_output);
} }
/* /*
......
...@@ -2409,149 +2409,149 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name, ...@@ -2409,149 +2409,149 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name,
ctl_table ipv4_route_table[] = { ctl_table ipv4_route_table[] = {
{ {
.ctl_name = NET_IPV4_ROUTE_FLUSH, .ctl_name = NET_IPV4_ROUTE_FLUSH,
.procname = "flush", .procname = "flush",
.data = &flush_delay, .data = &flush_delay,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&ipv4_sysctl_rtcache_flush, .proc_handler = &ipv4_sysctl_rtcache_flush,
.strategy = &ipv4_sysctl_rtcache_flush_strategy, .strategy = &ipv4_sysctl_rtcache_flush_strategy,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_MIN_DELAY, .ctl_name = NET_IPV4_ROUTE_MIN_DELAY,
.procname = "min_delay", .procname = "min_delay",
.data = &ip_rt_min_delay, .data = &ip_rt_min_delay,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies, .strategy = &sysctl_jiffies,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_MAX_DELAY, .ctl_name = NET_IPV4_ROUTE_MAX_DELAY,
.procname = "max_delay", .procname = "max_delay",
.data = &ip_rt_max_delay, .data = &ip_rt_max_delay,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies, .strategy = &sysctl_jiffies,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_GC_THRESH, .ctl_name = NET_IPV4_ROUTE_GC_THRESH,
.procname = "gc_thresh", .procname = "gc_thresh",
.data = &ipv4_dst_ops.gc_thresh, .data = &ipv4_dst_ops.gc_thresh,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_MAX_SIZE, .ctl_name = NET_IPV4_ROUTE_MAX_SIZE,
.procname = "max_size", .procname = "max_size",
.data = &ip_rt_max_size, .data = &ip_rt_max_size,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL, .ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL,
.procname = "gc_min_interval", .procname = "gc_min_interval",
.data = &ip_rt_gc_min_interval, .data = &ip_rt_gc_min_interval,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies, .strategy = &sysctl_jiffies,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT, .ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT,
.procname = "gc_timeout", .procname = "gc_timeout",
.data = &ip_rt_gc_timeout, .data = &ip_rt_gc_timeout,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies, .strategy = &sysctl_jiffies,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_GC_INTERVAL, .ctl_name = NET_IPV4_ROUTE_GC_INTERVAL,
.procname = "gc_interval", .procname = "gc_interval",
.data = &ip_rt_gc_interval, .data = &ip_rt_gc_interval,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies, .strategy = &sysctl_jiffies,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_REDIRECT_LOAD, .ctl_name = NET_IPV4_ROUTE_REDIRECT_LOAD,
.procname = "redirect_load", .procname = "redirect_load",
.data = &ip_rt_redirect_load, .data = &ip_rt_redirect_load,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_REDIRECT_NUMBER, .ctl_name = NET_IPV4_ROUTE_REDIRECT_NUMBER,
.procname = "redirect_number", .procname = "redirect_number",
.data = &ip_rt_redirect_number, .data = &ip_rt_redirect_number,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_REDIRECT_SILENCE, .ctl_name = NET_IPV4_ROUTE_REDIRECT_SILENCE,
.procname = "redirect_silence", .procname = "redirect_silence",
.data = &ip_rt_redirect_silence, .data = &ip_rt_redirect_silence,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_ERROR_COST, .ctl_name = NET_IPV4_ROUTE_ERROR_COST,
.procname = "error_cost", .procname = "error_cost",
.data = &ip_rt_error_cost, .data = &ip_rt_error_cost,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_ERROR_BURST, .ctl_name = NET_IPV4_ROUTE_ERROR_BURST,
.procname = "error_burst", .procname = "error_burst",
.data = &ip_rt_error_burst, .data = &ip_rt_error_burst,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_GC_ELASTICITY, .ctl_name = NET_IPV4_ROUTE_GC_ELASTICITY,
.procname = "gc_elasticity", .procname = "gc_elasticity",
.data = &ip_rt_gc_elasticity, .data = &ip_rt_gc_elasticity,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_MTU_EXPIRES, .ctl_name = NET_IPV4_ROUTE_MTU_EXPIRES,
.procname = "mtu_expires", .procname = "mtu_expires",
.data = &ip_rt_mtu_expires, .data = &ip_rt_mtu_expires,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec_jiffies, .proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies, .strategy = &sysctl_jiffies,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_MIN_PMTU, .ctl_name = NET_IPV4_ROUTE_MIN_PMTU,
.procname = "min_pmtu", .procname = "min_pmtu",
.data = &ip_rt_min_pmtu, .data = &ip_rt_min_pmtu,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ {
.ctl_name = NET_IPV4_ROUTE_MIN_ADVMSS, .ctl_name = NET_IPV4_ROUTE_MIN_ADVMSS,
.procname = "min_adv_mss", .procname = "min_adv_mss",
.data = &ip_rt_min_advmss, .data = &ip_rt_min_advmss,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler =&proc_dointvec, .proc_handler = &proc_dointvec,
}, },
{ 0 } { .ctl_name = 0 }
}; };
#endif #endif
......
#include <linux/config.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <net/ip.h> #include <net/ip.h>
...@@ -198,6 +199,49 @@ struct xfrm_type *xfrm_get_type(u8 proto) ...@@ -198,6 +199,49 @@ struct xfrm_type *xfrm_get_type(u8 proto)
return type; return type;
} }
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct xfrm_type *xfrm6_type_map[256];
static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
int xfrm6_register_type(struct xfrm_type *type)
{
int err = 0;
write_lock(&xfrm6_type_lock);
if (xfrm6_type_map[type->proto] == NULL)
xfrm6_type_map[type->proto] = type;
else
err = -EEXIST;
write_unlock(&xfrm6_type_lock);
return err;
}
int xfrm6_unregister_type(struct xfrm_type *type)
{
int err = 0;
write_lock(&xfrm6_type_lock);
if (xfrm6_type_map[type->proto] != type)
err = -ENOENT;
else
xfrm6_type_map[type->proto] = NULL;
write_unlock(&xfrm6_type_lock);
return err;
}
struct xfrm_type *xfrm6_get_type(u8 proto)
{
struct xfrm_type *type;
read_lock(&xfrm6_type_lock);
type = xfrm6_type_map[proto];
if (type && !try_module_get(type->owner))
type = NULL;
read_unlock(&xfrm6_type_lock);
return type;
}
#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
void xfrm_put_type(struct xfrm_type *type) void xfrm_put_type(struct xfrm_type *type)
{ {
module_put(type->owner); module_put(type->owner);
......
/* xfrm_user.c: User interface to configure xfrm engine. /* xfrm_user.c: User interface to configure xfrm engine.
* *
* Copyright (C) 2002 David S. Miller (davem@redhat.com) * Copyright (C) 2002 David S. Miller (davem@redhat.com)
*
* Changes
*
* Mitsuru KANDA @USAGI : IPv6 Support
* Kazunori MIYAZAWA @USAGI :
* Kunihiro Ishiguro :
*
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -17,6 +24,9 @@ ...@@ -17,6 +24,9 @@
#include <linux/ipsec.h> #include <linux/ipsec.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/security.h> #include <linux/security.h>
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#include <linux/in6.h>
#endif
#include <net/sock.h> #include <net/sock.h>
#include <net/xfrm.h> #include <net/xfrm.h>
...@@ -63,10 +73,14 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, ...@@ -63,10 +73,14 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
case AF_INET: case AF_INET:
break; break;
case AF_INET6: /* XXX */ case AF_INET6:
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
break;
#else
err = -EAFNOSUPPORT; err = -EAFNOSUPPORT;
goto out;
#endif
/* fallthru */
default: default:
goto out; goto out;
}; };
...@@ -171,7 +185,19 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, ...@@ -171,7 +185,19 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
goto error; goto error;
err = -ENOENT; err = -ENOENT;
x->type = xfrm_get_type(x->id.proto); switch (x->props.family) {
case AF_INET:
x->type = xfrm_get_type(x->id.proto);
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
x->type = xfrm6_get_type(x->id.proto);
break;
#endif
default:
x->type = NULL;
break;
}
if (x->type == NULL) if (x->type == NULL)
goto error; goto error;
...@@ -206,8 +232,21 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) ...@@ -206,8 +232,21 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
if (!x) if (!x)
return err; return err;
x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr, switch (x->props.family) {
x->id.spi, x->id.proto); case AF_INET:
x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
x->id.spi, x->id.proto);
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
x1 = xfrm6_state_lookup((struct in6_addr*)x->props.saddr.a6,
x->id.spi, x->id.proto);
break;
#endif
default:
x1 = NULL;
break;
}
if (x1) { if (x1) {
xfrm_state_put(x); xfrm_state_put(x);
xfrm_state_put(x1); xfrm_state_put(x1);
...@@ -224,7 +263,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) ...@@ -224,7 +263,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
struct xfrm_state *x; struct xfrm_state *x;
struct xfrm_usersa_id *p = NLMSG_DATA(nlh); struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto); switch (p->family) {
case AF_INET:
x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
x = xfrm6_state_lookup((struct in6_addr*)p->saddr.a6, p->spi, p->proto);
break;
#endif
default:
x = NULL;
break;
}
if (x == NULL) if (x == NULL)
return -ESRCH; return -ESRCH;
...@@ -342,7 +393,19 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) ...@@ -342,7 +393,19 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
struct sk_buff *resp_skb; struct sk_buff *resp_skb;
int err; int err;
x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto); switch (p->family) {
case AF_INET:
x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
x = xfrm6_state_lookup((struct in6_addr*)p->saddr.a6, p->spi, p->proto);
break;
#endif
default:
x = NULL;
break;
}
err = -ESRCH; err = -ESRCH;
if (x == NULL) if (x == NULL)
goto out_noput; goto out_noput;
...@@ -393,9 +456,23 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, void ** ...@@ -393,9 +456,23 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, void **
err = verify_userspi_info(p); err = verify_userspi_info(p);
if (err) if (err)
goto out_noput; goto out_noput;
x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto, switch (p->info.family) {
p->info.sel.daddr.xfrm4_addr, case AF_INET:
p->info.sel.saddr.xfrm4_addr, 1); x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
p->info.sel.daddr.xfrm4_addr,
p->info.sel.saddr.xfrm4_addr, 1);
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
x = xfrm6_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
(struct in6_addr*)p->info.sel.daddr.a6,
(struct in6_addr*)p->info.sel.saddr.a6, 1);
break;
#endif
default:
x = NULL;
break;
}
err = -ENOENT; err = -ENOENT;
if (x == NULL) if (x == NULL)
goto out_noput; goto out_noput;
......
...@@ -11,5 +11,3 @@ ipv6-objs := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \ ...@@ -11,5 +11,3 @@ ipv6-objs := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \
ip6_flowlabel.o ipv6_syms.o ip6_flowlabel.o ipv6_syms.o
obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_NETFILTER) += netfilter/
obj-y += xfrm_policy.o
...@@ -288,7 +288,7 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff) ...@@ -288,7 +288,7 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
dst_release(xchg(&skb->dst, NULL)); dst_release(xchg(&skb->dst, NULL));
ip6_route_input(skb); ip6_route_input(skb);
if (skb->dst->error) { if (skb->dst->error) {
skb->dst->input(skb); dst_input(skb);
return -1; return -1;
} }
if (skb->dst->dev->flags&IFF_LOOPBACK) { if (skb->dst->dev->flags&IFF_LOOPBACK) {
...@@ -302,7 +302,7 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff) ...@@ -302,7 +302,7 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
goto looped_back; goto looped_back;
} }
skb->dst->input(skb); dst_input(skb);
return -1; return -1;
} }
......
...@@ -47,7 +47,7 @@ static inline int ip6_rcv_finish( struct sk_buff *skb) ...@@ -47,7 +47,7 @@ static inline int ip6_rcv_finish( struct sk_buff *skb)
if (skb->dst == NULL) if (skb->dst == NULL)
ip6_route_input(skb); ip6_route_input(skb);
return skb->dst->input(skb); return dst_input(skb);
} }
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
...@@ -235,7 +235,7 @@ int ip6_mc_input(struct sk_buff *skb) ...@@ -235,7 +235,7 @@ int ip6_mc_input(struct sk_buff *skb)
skb2 = skb; skb2 = skb;
} }
dst->output(skb2); dst_output(skb2);
} }
} }
#endif #endif
......
...@@ -174,7 +174,7 @@ static inline int ip6_maybe_reroute(struct sk_buff *skb) ...@@ -174,7 +174,7 @@ static inline int ip6_maybe_reroute(struct sk_buff *skb)
} }
} }
#endif /* CONFIG_NETFILTER */ #endif /* CONFIG_NETFILTER */
return skb->dst->output(skb); return dst_output(skb);
} }
/* /*
...@@ -722,7 +722,7 @@ int ip6_call_ra_chain(struct sk_buff *skb, int sel) ...@@ -722,7 +722,7 @@ int ip6_call_ra_chain(struct sk_buff *skb, int sel)
static inline int ip6_forward_finish(struct sk_buff *skb) static inline int ip6_forward_finish(struct sk_buff *skb)
{ {
return skb->dst->output(skb); return dst_output(skb);
} }
int ip6_forward(struct sk_buff *skb) int ip6_forward(struct sk_buff *skb)
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/ip6_route.h> #include <net/ip6_route.h>
#include <net/xfrm.h>
EXPORT_SYMBOL(ipv6_addr_type); EXPORT_SYMBOL(ipv6_addr_type);
EXPORT_SYMBOL(icmpv6_send); EXPORT_SYMBOL(icmpv6_send);
...@@ -26,6 +25,3 @@ EXPORT_SYMBOL(inet6_getname); ...@@ -26,6 +25,3 @@ EXPORT_SYMBOL(inet6_getname);
EXPORT_SYMBOL(inet6_ioctl); EXPORT_SYMBOL(inet6_ioctl);
EXPORT_SYMBOL(ipv6_get_saddr); EXPORT_SYMBOL(ipv6_get_saddr);
EXPORT_SYMBOL(ipv6_chk_addr); EXPORT_SYMBOL(ipv6_chk_addr);
EXPORT_SYMBOL(xfrm6_register_type);
EXPORT_SYMBOL(xfrm6_unregister_type);
EXPORT_SYMBOL(xfrm6_get_type);
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* *
* Horst von Brand Add missing #include <linux/string.h> * Horst von Brand Add missing #include <linux/string.h>
* Alexey Kuznetsov SMP races, threading, cleanup. * Alexey Kuznetsov SMP races, threading, cleanup.
* Patrick McHardy LRU queue of frag heads for evictor.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/list.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/in6.h> #include <linux/in6.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
...@@ -67,6 +69,7 @@ struct ip6frag_skb_cb ...@@ -67,6 +69,7 @@ struct ip6frag_skb_cb
struct frag_queue struct frag_queue
{ {
struct frag_queue *next; struct frag_queue *next;
struct list_head lru_list; /* lru list member */
__u32 id; /* fragment id */ __u32 id; /* fragment id */
struct in6_addr saddr; struct in6_addr saddr;
...@@ -95,6 +98,7 @@ struct frag_queue ...@@ -95,6 +98,7 @@ struct frag_queue
static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ]; static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED; static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
static LIST_HEAD(ip6_frag_lru_list);
int ip6_frag_nqueues = 0; int ip6_frag_nqueues = 0;
static __inline__ void __fq_unlink(struct frag_queue *fq) static __inline__ void __fq_unlink(struct frag_queue *fq)
...@@ -102,6 +106,7 @@ static __inline__ void __fq_unlink(struct frag_queue *fq) ...@@ -102,6 +106,7 @@ static __inline__ void __fq_unlink(struct frag_queue *fq)
if(fq->next) if(fq->next)
fq->next->pprev = fq->pprev; fq->next->pprev = fq->pprev;
*fq->pprev = fq->next; *fq->pprev = fq->next;
list_del(&fq->lru_list);
ip6_frag_nqueues--; ip6_frag_nqueues--;
} }
...@@ -193,38 +198,30 @@ static __inline__ void fq_kill(struct frag_queue *fq) ...@@ -193,38 +198,30 @@ static __inline__ void fq_kill(struct frag_queue *fq)
static void ip6_evictor(void) static void ip6_evictor(void)
{ {
int i, progress; struct frag_queue *fq;
struct list_head *tmp;
do { for(;;) {
if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh) if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
return; return;
progress = 0; read_lock(&ip6_frag_lock);
for (i = 0; i < IP6Q_HASHSZ; i++) { if (list_empty(&ip6_frag_lru_list)) {
struct frag_queue *fq;
if (ip6_frag_hash[i] == NULL)
continue;
read_lock(&ip6_frag_lock);
if ((fq = ip6_frag_hash[i]) != NULL) {
/* find the oldest queue for this hash bucket */
while (fq->next)
fq = fq->next;
atomic_inc(&fq->refcnt);
read_unlock(&ip6_frag_lock);
spin_lock(&fq->lock);
if (!(fq->last_in&COMPLETE))
fq_kill(fq);
spin_unlock(&fq->lock);
fq_put(fq);
IP6_INC_STATS_BH(Ip6ReasmFails);
progress = 1;
continue;
}
read_unlock(&ip6_frag_lock); read_unlock(&ip6_frag_lock);
return;
} }
} while (progress); tmp = ip6_frag_lru_list.next;
fq = list_entry(tmp, struct frag_queue, lru_list);
atomic_inc(&fq->refcnt);
read_unlock(&ip6_frag_lock);
spin_lock(&fq->lock);
if (!(fq->last_in&COMPLETE))
fq_kill(fq);
spin_unlock(&fq->lock);
fq_put(fq);
IP6_INC_STATS_BH(Ip6ReasmFails);
}
} }
static void ip6_frag_expire(unsigned long data) static void ip6_frag_expire(unsigned long data)
...@@ -294,6 +291,8 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash, ...@@ -294,6 +291,8 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
fq->next->pprev = &fq->next; fq->next->pprev = &fq->next;
ip6_frag_hash[hash] = fq; ip6_frag_hash[hash] = fq;
fq->pprev = &ip6_frag_hash[hash]; fq->pprev = &ip6_frag_hash[hash];
INIT_LIST_HEAD(&fq->lru_list);
list_add_tail(&fq->lru_list, &ip6_frag_lru_list);
ip6_frag_nqueues++; ip6_frag_nqueues++;
write_unlock(&ip6_frag_lock); write_unlock(&ip6_frag_lock);
return fq; return fq;
...@@ -501,6 +500,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -501,6 +500,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
fq->nhoffset = nhoff; fq->nhoffset = nhoff;
fq->last_in |= FIRST_IN; fq->last_in |= FIRST_IN;
} }
write_lock(&ip6_frag_lock);
list_move_tail(&fq->lru_list, &ip6_frag_lru_list);
write_unlock(&ip6_frag_lock);
return; return;
err: err:
......
#include <net/xfrm.h>
#include <net/ip.h>
static struct xfrm_type *xfrm6_type_map[256];
static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
int xfrm6_register_type(struct xfrm_type *type)
{
int err = 0;
write_lock(&xfrm6_type_lock);
if (xfrm6_type_map[type->proto] == NULL)
xfrm6_type_map[type->proto] = type;
else
err = -EEXIST;
write_unlock(&xfrm6_type_lock);
return err;
}
int xfrm6_unregister_type(struct xfrm_type *type)
{
int err = 0;
write_lock(&xfrm6_type_lock);
if (xfrm6_type_map[type->proto] != type)
err = -ENOENT;
else
xfrm6_type_map[type->proto] = NULL;
write_unlock(&xfrm6_type_lock);
return err;
}
struct xfrm_type *xfrm6_get_type(u8 proto)
{
struct xfrm_type *type;
read_lock(&xfrm6_type_lock);
type = xfrm6_type_map[proto];
if (type && !try_module_get(type->owner))
type = NULL;
read_unlock(&xfrm6_type_lock);
return type;
}
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* David S. Miller <davem@redhat.com> * David S. Miller <davem@redhat.com>
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
* Kunihiro Ishiguro <kunihiro@ipinfusion.com> * Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* Kazunori MIYAZAWA / USAGI Project <miyazawa@linux-ipv6.org>
*/ */
#include <linux/config.h> #include <linux/config.h>
......
...@@ -328,6 +328,9 @@ EXPORT_SYMBOL(xfrm_policy_list); ...@@ -328,6 +328,9 @@ EXPORT_SYMBOL(xfrm_policy_list);
EXPORT_SYMBOL(xfrm6_state_lookup); EXPORT_SYMBOL(xfrm6_state_lookup);
EXPORT_SYMBOL(xfrm6_find_acq); EXPORT_SYMBOL(xfrm6_find_acq);
EXPORT_SYMBOL(xfrm6_alloc_spi); EXPORT_SYMBOL(xfrm6_alloc_spi);
EXPORT_SYMBOL(xfrm6_register_type);
EXPORT_SYMBOL(xfrm6_unregister_type);
EXPORT_SYMBOL(xfrm6_get_type);
#endif #endif
EXPORT_SYMBOL_GPL(xfrm_probe_algs); EXPORT_SYMBOL_GPL(xfrm_probe_algs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment