Commit 0b38c676 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/disk1/davem/BK/net-2.6.1

into nuts.ninka.net:/disk1/davem/BK/net-2.6
parents 2c663d3f c869560d
......@@ -90,7 +90,6 @@
#include <net/snmp.h>
#include <net/sctp/structs.h>
#include <net/sctp/constants.h>
#include <net/sctp/sm.h>
/* Set SCTP_DEBUG flag via config if not already set. */
......
......@@ -860,7 +860,7 @@ extern void xfrm_policy_flush(void);
extern void xfrm_policy_kill(struct xfrm_policy *);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl);
extern int xfrm_flush_bundles(struct xfrm_state *x);
extern int xfrm_flush_bundles(void);
extern wait_queue_head_t km_waitq;
extern void km_state_expired(struct xfrm_state *x, int hard);
......
......@@ -91,8 +91,10 @@ static struct recent_ip_tables *r_tables = NULL;
*/
static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
#ifdef CONFIG_PROC_FS
/* Our /proc/net/ipt_recent entry */
static struct proc_dir_entry *proc_net_ipt_recent = NULL;
#endif
/* Function declaration for later. */
static int
......@@ -959,8 +961,10 @@ static int __init init(void)
int count;
printk(version);
#ifdef CONFIG_PROC_FS
proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
if(!proc_net_ipt_recent) return -ENOMEM;
#endif
if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
......
......@@ -75,6 +75,9 @@
#include <net/checksum.h>
#include <linux/proc_fs.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
static struct socket *ndisc_socket;
static u32 ndisc_hash(const void *pkey, const struct net_device *dev);
......@@ -497,10 +500,11 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
skb->dst = dst;
idev = in6_dev_get(dst->dev);
dst_output(skb);
ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutNeighborAdvertisements);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
}
if (likely(idev != NULL))
in6_dev_put(idev);
......@@ -576,10 +580,11 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
/* send it! */
skb->dst = dst;
idev = in6_dev_get(dst->dev);
dst_output(skb);
ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutNeighborSolicits);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
}
if (likely(idev != NULL))
in6_dev_put(idev);
......@@ -644,10 +649,11 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
/* send it! */
skb->dst = dst;
idev = in6_dev_get(dst->dev);
dst_output(skb);
ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutRouterSolicits);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
}
if (likely(idev != NULL))
in6_dev_put(idev);
......@@ -1404,10 +1410,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
buff->dst = dst;
idev = in6_dev_get(dst->dev);
dst_output(buff);
ICMP6_INC_STATS(idev, Icmp6OutRedirects);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
if (!err) {
ICMP6_INC_STATS(idev, Icmp6OutRedirects);
ICMP6_INC_STATS(idev, Icmp6OutMsgs);
}
if (likely(idev != NULL))
in6_dev_put(idev);
......
......@@ -58,6 +58,7 @@
#include <linux/in.h>
#include <net/ipv6.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Forward declarations for internal functions. */
static void sctp_assoc_bh_rcv(struct sctp_association *asoc);
......
......@@ -53,6 +53,7 @@
#include <net/sock.h> /* For skb_set_owner_w */
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Declare internal functions here. */
static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
......
......@@ -77,6 +77,7 @@
#include <linux/socket.h> /* for sa_family_t */
#include <net/sock.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* WARNING: Please do not remove the SCTP_STATIC attribute to
* any of the functions below as they are used to export functions
......
......@@ -50,6 +50,7 @@
#include <linux/types.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* 1st Level Abstractions. */
......
......@@ -19,6 +19,8 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
#include <net/xfrm.h>
#include <net/ip.h>
......@@ -690,6 +692,8 @@ static inline int policy_to_flow_dir(int dir)
};
}
static int stale_bundle(struct dst_entry *dst);
/* Main function: finds/creates a bundle for given flow.
*
* At the moment we eat a raw IP route. Mostly to speed up lookups
......@@ -814,10 +818,11 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
}
write_lock_bh(&policy->lock);
if (unlikely(policy->dead)) {
if (unlikely(policy->dead || stale_bundle(dst))) {
/* Wow! While we worked on resolving, this
* policy has gone. Retry. It is not paranoia,
* we just cannot enlist new bundle to dead object.
* We can't enlist stable bundles either.
*/
write_unlock_bh(&policy->lock);
......@@ -984,19 +989,28 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
/* Optimize later using cookies and generation ids. */
static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
{
if (!stale_bundle(dst))
return dst;
dst_release(dst);
return NULL;
}
static int stale_bundle(struct dst_entry *dst)
{
struct dst_entry *child = dst;
while (child) {
if (child->obsolete > 0 ||
(child->dev && !netif_running(child->dev)) ||
(child->xfrm && child->xfrm->km.state != XFRM_STATE_VALID)) {
dst_release(dst);
return NULL;
return 1;
}
child = child->child;
}
return dst;
return 0;
}
static void xfrm_dst_destroy(struct dst_entry *dst)
......@@ -1022,7 +1036,7 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst)
return dst;
}
static void __xfrm_garbage_collect(void)
static void xfrm_prune_bundles(int (*func)(struct dst_entry *))
{
int i;
struct xfrm_policy *pol;
......@@ -1034,7 +1048,7 @@ static void __xfrm_garbage_collect(void)
write_lock(&pol->lock);
dstp = &pol->bundles;
while ((dst=*dstp) != NULL) {
if (atomic_read(&dst->__refcnt) == 0) {
if (func(dst)) {
*dstp = dst->next;
dst->next = gc_list;
gc_list = dst;
......@@ -1054,46 +1068,19 @@ static void __xfrm_garbage_collect(void)
}
}
static int bundle_depends_on(struct dst_entry *dst, struct xfrm_state *x)
static int unused_bundle(struct dst_entry *dst)
{
do {
if (dst->xfrm == x)
return 1;
} while ((dst = dst->child) != NULL);
return 0;
return !atomic_read(&dst->__refcnt);
}
int xfrm_flush_bundles(struct xfrm_state *x)
static void __xfrm_garbage_collect(void)
{
int i;
struct xfrm_policy *pol;
struct dst_entry *dst, **dstp, *gc_list = NULL;
read_lock_bh(&xfrm_policy_lock);
for (i=0; i<2*XFRM_POLICY_MAX; i++) {
for (pol = xfrm_policy_list[i]; pol; pol = pol->next) {
write_lock(&pol->lock);
dstp = &pol->bundles;
while ((dst=*dstp) != NULL) {
if (bundle_depends_on(dst, x)) {
*dstp = dst->next;
dst->next = gc_list;
gc_list = dst;
} else {
dstp = &dst->next;
}
}
write_unlock(&pol->lock);
}
}
read_unlock_bh(&xfrm_policy_lock);
while (gc_list) {
dst = gc_list;
gc_list = dst->next;
dst_free(dst);
}
xfrm_prune_bundles(unused_bundle);
}
int xfrm_flush_bundles(void)
{
xfrm_prune_bundles(stale_bundle);
return 0;
}
......@@ -1216,6 +1203,21 @@ void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
read_unlock(&afinfo->lock);
}
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
switch (event) {
case NETDEV_DOWN:
xfrm_flush_bundles();
}
return NOTIFY_DONE;
}
struct notifier_block xfrm_dev_notifier = {
xfrm_dev_event,
NULL,
0
};
void __init xfrm_policy_init(void)
{
xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
......@@ -1226,6 +1228,7 @@ void __init xfrm_policy_init(void)
panic("XFRM: failed to allocate xfrm_dst_cache\n");
INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL);
register_netdevice_notifier(&xfrm_dev_notifier);
}
void __init xfrm_init(void)
......
......@@ -219,7 +219,7 @@ static void __xfrm_state_delete(struct xfrm_state *x)
* there are DSTs attached to this xfrm_state.
*/
if (atomic_read(&x->refcnt) > 2)
xfrm_flush_bundles(x);
xfrm_flush_bundles();
/* All xfrm_state objects are created by one of two possible
* paths:
......
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