summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-04-08 21:23:58 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-04-08 21:23:58 -0700
commitfaedca65dfd1abf0097d1dabf45030560828a8ae (patch)
tree7cb4544e35a32f3ab39af24d0dcde9caaf877362
parentda220b091670cdc32f59d24575cf23d4dce397bb (diff)
parent75552d6863c17d8d138ae2ff21868f0d5bc96390 (diff)
Merge bk://kernel.bkbits.net/davem/net-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/acenic.c2
-rw-r--r--drivers/net/e100/e100_main.c4
-rw-r--r--drivers/net/sungem.c2
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/tg3.c12
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--include/linux/irda.h2
-rw-r--r--include/linux/net.h5
-rw-r--r--include/linux/netlink.h2
-rw-r--r--include/net/tcp.h15
-rw-r--r--include/net/xfrm.h1
-rw-r--r--net/8021q/vlan.c18
-rw-r--r--net/8021q/vlan_dev.c1
-rw-r--r--net/core/datagram.c4
-rw-r--r--net/core/skbuff.c10
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/ah.c3
-rw-r--r--net/ipv4/esp.c2
-rw-r--r--net/ipv4/proc.c12
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv6/ah6.c4
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/xfrm/xfrm_algo.c4
-rw-r--r--net/xfrm/xfrm_policy.c2
-rw-r--r--net/xfrm/xfrm_state.c88
26 files changed, 136 insertions, 70 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 838eea92f8f2..5bc9fe749d83 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -826,7 +826,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
* Otherwise we could race with the device.
*/
first_eor = eor;
- first_len = skb->len - skb->data_len;
+ first_len = skb_headlen(skb);
first_mapping = pci_map_single(cp->pdev, skb->data,
first_len, PCI_DMA_TODEVICE);
cp->tx_skb[entry].skb = skb;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index e05a28c98a94..502e1f0414ba 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -2829,7 +2829,7 @@ restart:
int i, len = 0;
mapping = ace_map_tx_skb(ap, skb, NULL, idx);
- flagsize = ((skb->len - skb->data_len) << 16);
+ flagsize = (skb_headlen(skb) << 16);
if (skb->ip_summed == CHECKSUM_HW)
flagsize |= BD_FLG_TCP_UDP_SUM;
#if ACENIC_DO_VLAN
diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
index d241eaa64e2e..2f3f6f6b1e8d 100644
--- a/drivers/net/e100/e100_main.c
+++ b/drivers/net/e100/e100_main.c
@@ -2199,10 +2199,10 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
(tcb->tbd_ptr)->tbd_buf_addr =
cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
- (skb->len - skb->data_len),
+ skb_headlen(skb),
PCI_DMA_TODEVICE));
(tcb->tbd_ptr)->tbd_buf_cnt =
- cpu_to_le16(skb->len - skb->data_len);
+ cpu_to_le16(skb_headlen(skb));
for (i = 0; i < skb_shinfo(skb)->nr_frags;
i++, tbd_arr_ptr++, frag++) {
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 7c139fdafea6..daeb1f39e9c8 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -894,7 +894,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* We must give this initial chunk to the device last.
* Otherwise we could race with the device.
*/
- first_len = skb->len - skb->data_len;
+ first_len = skb_headlen(skb);
first_mapping = pci_map_page(gp->pdev, virt_to_page(skb->data),
((unsigned long) skb->data & ~PAGE_MASK),
first_len, PCI_DMA_TODEVICE);
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 5b34d6ecb03b..631d07021d81 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2319,7 +2319,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* We must give this initial chunk to the device last.
* Otherwise we could race with the device.
*/
- first_len = skb->len - skb->data_len;
+ first_len = skb_headlen(skb);
first_mapping = hme_dma_map(hp, skb->data, first_len, DMA_TODEVICE);
entry = NEXT_TX(entry);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ea4082646fde..07a311b66d3c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1751,7 +1751,7 @@ static void tg3_tx(struct tg3 *tp)
pci_unmap_single(tp->pdev,
pci_unmap_addr(ri, mapping),
- (skb->len - skb->data_len),
+ skb_headlen(skb),
PCI_DMA_TODEVICE);
ri->skb = NULL;
@@ -2316,7 +2316,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
int len;
if (i == 0)
- len = skb->len - skb->data_len;
+ len = skb_headlen(skb);
else
len = skb_shinfo(skb)->frags[i-1].size;
pci_unmap_single(tp->pdev,
@@ -2401,7 +2401,7 @@ static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev)
int would_hit_hwbug;
unsigned long flags;
- len = (skb->len - skb->data_len);
+ len = skb_headlen(skb);
/* No BH disabling for tx_lock here. We are running in BH disabled
* context and TX reclaim runs via tp->poll inside of a software
@@ -2520,7 +2520,7 @@ static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev)
i = 0;
while (entry != last_plus_one) {
if (i == 0)
- len = skb->len - skb->data_len;
+ len = skb_headlen(skb);
else
len = skb_shinfo(skb)->frags[i-1].size;
@@ -2593,7 +2593,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 len, entry, base_flags, mss;
unsigned long flags;
- len = (skb->len - skb->data_len);
+ len = skb_headlen(skb);
/* No BH disabling for tx_lock here. We are running in BH disabled
* context and TX reclaim runs via tp->poll inside of a software
@@ -2829,7 +2829,7 @@ static void tg3_free_rings(struct tg3 *tp)
pci_unmap_single(tp->pdev,
pci_unmap_addr(txp, mapping),
- (skb->len - skb->data_len),
+ skb_headlen(skb),
PCI_DMA_TODEVICE);
txp->skb = NULL;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index e6c46f2f41a0..6a6a8eb72c10 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -844,7 +844,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
} else {
int i, len;
- len = skb->len - skb->data_len;
+ len = skb_headlen(skb);
skb_dma = pci_map_single(tp->tx_pdev, skb->data, len,
PCI_DMA_TODEVICE);
txd->flags = TYPHOON_FRAG_DESC | TYPHOON_DESC_VALID;
diff --git a/include/linux/irda.h b/include/linux/irda.h
index bdf23baa5483..948488ece2a8 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -25,6 +25,8 @@
#ifndef KERNEL_IRDA_H
#define KERNEL_IRDA_H
+#include <linux/socket.h> /* only for sa_family_t */
+
/* Hint bit positions for first hint byte */
#define HINT_PNP 0x01
#define HINT_PDA 0x02
diff --git a/include/linux/net.h b/include/linux/net.h
index 55083c938298..6ba6e1038521 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -19,7 +19,6 @@
#define _LINUX_NET_H
#include <linux/config.h>
-#include <linux/socket.h>
#include <linux/wait.h>
struct poll_table_struct;
@@ -88,6 +87,8 @@ struct socket {
struct vm_area_struct;
struct page;
struct kiocb;
+struct sockaddr;
+struct msghdr;
struct proto_ops {
int family;
@@ -136,6 +137,8 @@ struct net_proto_family {
short encrypt_net;
};
+struct iovec;
+
extern int sock_wake_async(struct socket *sk, int how, int band);
extern int sock_register(struct net_proto_family *fam);
extern int sock_unregister(int family);
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 69346c394563..30de192de7a9 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -1,6 +1,8 @@
#ifndef __LINUX_NETLINK_H
#define __LINUX_NETLINK_H
+#include <linux/socket.h> /* for sa_family_t */
+
#define NETLINK_ROUTE 0 /* Routing/device hook */
#define NETLINK_SKIP 1 /* Reserved for ENskip */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index b652650286fe..8844d3f3d8f9 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -31,6 +31,7 @@
#include <linux/percpu.h>
#include <net/checksum.h>
#include <net/sock.h>
+#include <net/snmp.h>
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
#include <linux/ipv6.h>
#endif
@@ -639,6 +640,8 @@ DECLARE_SNMP_STAT(struct tcp_mib, tcp_statistics);
#define TCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(tcp_statistics, field)
#define TCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(tcp_statistics, field)
#define TCP_DEC_STATS(field) SNMP_DEC_STATS(tcp_statistics, field)
+#define TCP_ADD_STATS_BH(field, val) SNMP_ADD_STATS_BH(tcp_statistics, field, val)
+#define TCP_ADD_STATS_USER(field, val) SNMP_ADD_STATS_USER(tcp_statistics, field, val)
extern __inline__ void tcp_put_port(struct sock *sk);
extern void tcp_inherit_port(struct sock *sk, struct sock *child);
@@ -1398,6 +1401,9 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
break;
case TCP_CLOSE:
+ if (oldstate == TCP_CLOSE_WAIT || oldstate == TCP_ESTABLISHED)
+ TCP_INC_STATS(TcpEstabResets);
+
sk->prot->unhash(sk);
if (sk->prev && !(sk->userlocks&SOCK_BINDPORT_LOCK))
tcp_put_port(sk);
@@ -1878,4 +1884,13 @@ static inline int tcp_use_frto(const struct sock *sk)
tp->snd_una + tp->snd_wnd));
}
+static inline void tcp_mib_init(void)
+{
+ /* See RFC 2012 */
+ TCP_ADD_STATS_USER(TcpRtoAlgorithm, 1);
+ TCP_ADD_STATS_USER(TcpRtoMin, TCP_RTO_MIN*1000/HZ);
+ TCP_ADD_STATS_USER(TcpRtoMax, TCP_RTO_MAX*1000/HZ);
+ TCP_ADD_STATS_USER(TcpMaxConn, -1);
+}
+
#endif /* _TCP_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index fe32e5c32354..b75d2651adf0 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -84,6 +84,7 @@ extern struct semaphore xfrm_cfg_sem;
/* Full description of state of transformer. */
struct xfrm_state
{
+ /* Note: bydst is re-used during gc */
struct list_head bydst;
struct list_head byspi;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 25562366d4c0..fc59bfc7a8bb 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -29,7 +29,6 @@
#include <net/p8022.h>
#include <net/arp.h>
#include <linux/rtnetlink.h>
-#include <linux/brlock.h>
#include <linux/notifier.h>
#include <linux/if_vlan.h>
@@ -68,7 +67,6 @@ static struct packet_type vlan_packet_type = {
.dev =NULL,
.func = vlan_skb_recv, /* VLAN receive method */
.data = (void *)(-1), /* Set here '(void *)1' when this code can SHARE SKBs */
- .next = NULL
};
/* End of global variables definitions. */
@@ -231,9 +229,8 @@ static int unregister_vlan_dev(struct net_device *real_dev,
real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
}
- br_write_lock(BR_NETPROTO_LOCK);
grp->vlan_devices[vlan_id] = NULL;
- br_write_unlock(BR_NETPROTO_LOCK);
+ synchronize_net();
/* Caller unregisters (and if necessary, puts)
@@ -266,7 +263,7 @@ static int unregister_vlan_dev(struct net_device *real_dev,
ret = 1;
}
- MOD_DEC_USE_COUNT;
+ module_put(THIS_MODULE);
}
}
@@ -433,6 +430,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
/* set up method calls */
new_dev->init = vlan_dev_init;
new_dev->destructor = vlan_dev_destruct;
+ new_dev->owner = THIS_MODULE;
/* new_dev->ifindex = 0; it will be set when added to
* the global list.
@@ -540,16 +538,22 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
register_netdevice(new_dev);
rtnl_unlock();
-
+
/* NOTE: We have a reference to the real device,
* so hold on to the reference.
*/
- MOD_INC_USE_COUNT; /* Add was a success!! */
+ if (!try_module_get(THIS_MODULE))
+ goto out_module_dying;
+
#ifdef VLAN_DEBUG
printk(VLAN_DBG "Allocated new device successfully, returning.\n");
#endif
return new_dev;
+out_module_dying:
+ rtnl_lock();
+ unregister_netdevice(new_dev);
+
out_free_newdev_priv:
kfree(new_dev->priv);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 907073996bc7..24a4462cc152 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -31,7 +31,6 @@
#include <net/datalink.h>
#include <net/p8022.h>
#include <net/arp.h>
-#include <linux/brlock.h>
#include "vlan.h"
#include "vlanproc.h"
diff --git a/net/core/datagram.c b/net/core/datagram.c
index f83189e52b13..7474e087fa12 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -220,7 +220,7 @@ int skb_copy_datagram(const struct sk_buff *skb, int offset, char *to, int size)
int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
struct iovec *to, int len)
{
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
int i, copy = start - offset;
/* Copy header. */
@@ -295,7 +295,7 @@ fault:
int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
u8 *to, int len, unsigned int *csump)
{
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
int pos = 0;
int i, copy = start - offset;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c909a7d3f00a..bb68b12b0047 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -932,7 +932,7 @@ pull_pages:
int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
{
int i, copy;
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
if (offset > (int)skb->len - len)
goto fault;
@@ -1009,7 +1009,7 @@ fault:
unsigned int skb_checksum(const struct sk_buff *skb, int offset,
int len, unsigned int csum)
{
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
int i, copy = start - offset;
int pos = 0;
@@ -1085,7 +1085,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset,
unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
u8 *to, int len, unsigned int csum)
{
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
int i, copy = start - offset;
int pos = 0;
@@ -1170,9 +1170,9 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
if (skb->ip_summed == CHECKSUM_HW)
csstart = skb->h.raw - skb->data;
else
- csstart = skb->len - skb->data_len;
+ csstart = skb_headlen(skb);
- if (csstart > skb->len - skb->data_len)
+ if (csstart > skb_headlen(skb))
BUG();
memcpy(to, skb->data, csstart);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 2082abcdc2d3..390c24c2a45b 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1108,6 +1108,8 @@ static int __init init_ipv4_mibs(void)
}
}
+ (void) tcp_mib_init();
+
return 0;
}
diff --git a/net/ipv4/ah.c b/net/ipv4/ah.c
index 1f4830a94319..02f08aa24437 100644
--- a/net/ipv4/ah.c
+++ b/net/ipv4/ah.c
@@ -314,12 +314,14 @@ static void ah_destroy(struct xfrm_state *x)
crypto_free_tfm(ahp->tfm);
ahp->tfm = NULL;
}
+ kfree(ahp);
}
static struct xfrm_type ah_type =
{
.description = "AH4",
+ .owner = THIS_MODULE,
.proto = IPPROTO_AH,
.init_state = ah_init_state,
.destructor = ah_destroy,
@@ -335,7 +337,6 @@ static struct inet_protocol ah4_protocol = {
static int __init ah4_init(void)
{
- SET_MODULE_OWNER(&ah_type);
if (xfrm_register_type(&ah_type, AF_INET) < 0) {
printk(KERN_INFO "ip ah init: can't add xfrm type\n");
return -EAGAIN;
diff --git a/net/ipv4/esp.c b/net/ipv4/esp.c
index 2fe10539c371..db29b32b118e 100644
--- a/net/ipv4/esp.c
+++ b/net/ipv4/esp.c
@@ -452,6 +452,7 @@ void esp_destroy(struct xfrm_state *x)
kfree(esp->auth.work_icv);
esp->auth.work_icv = NULL;
}
+ kfree(esp);
}
int esp_init_state(struct xfrm_state *x, void *args)
@@ -552,6 +553,7 @@ error:
static struct xfrm_type esp_type =
{
.description = "ESP4",
+ .owner = THIS_MODULE,
.proto = IPPROTO_ESP,
.init_state = esp_init_state,
.destructor = esp_destroy,
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index c78c0ac544b6..d07556385a0b 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -143,9 +143,15 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
"InSegs OutSegs RetransSegs InErrs OutRsts\nTcp:");
for (i = 0;
- i < offsetof(struct tcp_mib, __pad) / sizeof(unsigned long); i++)
- seq_printf(seq, " %lu",
- fold_field((void **) tcp_statistics, i));
+ i < offsetof(struct tcp_mib, __pad) / sizeof(unsigned long); i++) {
+ if (i == (offsetof(struct tcp_mib, TcpMaxConn) / sizeof(unsigned long)))
+ /* MaxConn field is negative, RFC 2012 */
+ seq_printf(seq, " %ld",
+ fold_field((void **) tcp_statistics, i));
+ else
+ seq_printf(seq, " %lu",
+ fold_field((void **) tcp_statistics, i));
+ }
seq_printf(seq, "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
"Udp:");
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index fd3baeb58b8f..344353ac7a6f 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -354,7 +354,7 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss)
static void skb_split(struct sk_buff *skb, struct sk_buff *skb1, u32 len)
{
int i;
- int pos = skb->len - skb->data_len;
+ int pos = skb_headlen(skb);
if (len < pos) {
/* Split line is inside header. */
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 0130c3b7889b..746dc9697b15 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -313,11 +313,13 @@ static void ah6_destroy(struct xfrm_state *x)
crypto_free_tfm(ahp->tfm);
ahp->tfm = NULL;
}
+ kfree(ahp);
}
static struct xfrm_type ah6_type =
{
.description = "AH6",
+ .owner = THIS_MODULE,
.proto = IPPROTO_AH,
.init_state = ah6_init_state,
.destructor = ah6_destroy,
@@ -333,8 +335,6 @@ static struct inet6_protocol ah6_protocol = {
int __init ah6_init(void)
{
- SET_MODULE_OWNER(&ah6_type);
-
if (xfrm_register_type(&ah6_type, AF_INET6) < 0) {
printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n");
return -EAGAIN;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 5f9275aabf0f..764a5d8ac1ea 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -406,6 +406,7 @@ void esp6_destroy(struct xfrm_state *x)
kfree(esp->auth.work_icv);
esp->auth.work_icv = NULL;
}
+ kfree(esp);
}
int esp6_init_state(struct xfrm_state *x, void *args)
@@ -488,6 +489,7 @@ error:
static struct xfrm_type esp6_type =
{
.description = "ESP6",
+ .owner = THIS_MODULE,
.proto = IPPROTO_ESP,
.init_state = esp6_init_state,
.destructor = esp6_destroy,
@@ -504,7 +506,6 @@ static struct inet6_protocol esp6_protocol = {
int __init esp6_init(void)
{
- SET_MODULE_OWNER(&esp6_type);
if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
return -EAGAIN;
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index d01a6fd02456..b850f0285cf2 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -445,7 +445,7 @@ int xfrm_count_enc_supported(void)
void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
int offset, int len, icv_update_fn_t icv_update)
{
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
int i, copy = start - offset;
struct scatterlist sg;
@@ -521,7 +521,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
int
skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
{
- int start = skb->len - skb->data_len;
+ int start = skb_headlen(skb);
int i, copy = start - offset;
int elt = 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b0460abbde2d..321858bf3af2 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -963,6 +963,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* are implied between each two transformations.
*/
for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
+ if (pol->xfrm_vec[i].optional)
+ continue;
k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
if (k < 0)
goto reject;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 162fa975f050..8f435d8e51fa 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -13,6 +13,7 @@
*
*/
+#include <linux/workqueue.h>
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
@@ -41,8 +42,48 @@ DECLARE_WAIT_QUEUE_HEAD(km_waitq);
static rwlock_t xfrm_state_afinfo_lock = RW_LOCK_UNLOCKED;
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
+static struct work_struct xfrm_state_gc_work;
+static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list);
+static spinlock_t xfrm_state_gc_lock = SPIN_LOCK_UNLOCKED;
+
static void __xfrm_state_delete(struct xfrm_state *x);
+static void xfrm_state_gc_destroy(struct xfrm_state *x)
+{
+ if (del_timer(&x->timer))
+ BUG();
+ if (x->aalg)
+ kfree(x->aalg);
+ if (x->ealg)
+ kfree(x->ealg);
+ if (x->calg)
+ kfree(x->calg);
+ if (x->encap)
+ kfree(x->encap);
+ if (x->type) {
+ x->type->destructor(x);
+ xfrm_put_type(x->type);
+ }
+ kfree(x);
+ wake_up(&km_waitq);
+}
+
+static void xfrm_state_gc_task(void *data)
+{
+ struct xfrm_state *x;
+ struct list_head *entry, *tmp;
+ struct list_head gc_list = LIST_HEAD_INIT(gc_list);
+
+ spin_lock_bh(&xfrm_state_gc_lock);
+ list_splice_init(&xfrm_state_gc_list, &gc_list);
+ spin_unlock_bh(&xfrm_state_gc_lock);
+
+ list_for_each_safe(entry, tmp, &gc_list) {
+ x = list_entry(entry, struct xfrm_state, bydst);
+ xfrm_state_gc_destroy(x);
+ }
+}
+
static inline unsigned long make_jiffies(long secs)
{
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
@@ -149,28 +190,17 @@ struct xfrm_state *xfrm_state_alloc(void)
void __xfrm_state_destroy(struct xfrm_state *x)
{
BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
- if (del_timer(&x->timer))
- BUG();
- if (x->aalg)
- kfree(x->aalg);
- if (x->ealg)
- kfree(x->ealg);
- if (x->calg)
- kfree(x->calg);
- if (x->encap)
- kfree(x->encap);
- if (x->type)
- xfrm_put_type(x->type);
- kfree(x);
+
+ spin_lock_bh(&xfrm_state_gc_lock);
+ list_add(&x->bydst, &xfrm_state_gc_list);
+ spin_unlock_bh(&xfrm_state_gc_lock);
+ schedule_work(&xfrm_state_gc_work);
}
static void __xfrm_state_delete(struct xfrm_state *x)
{
- int kill = 0;
-
if (x->km.state != XFRM_STATE_DEAD) {
x->km.state = XFRM_STATE_DEAD;
- kill = 1;
spin_lock(&xfrm_state_lock);
list_del(&x->bydst);
atomic_dec(&x->refcnt);
@@ -189,22 +219,17 @@ static void __xfrm_state_delete(struct xfrm_state *x)
*/
if (atomic_read(&x->refcnt) > 2)
xfrm_flush_bundles(x);
- }
- /* All xfrm_state objects are created by one of two possible
- * paths:
- *
- * 1) xfrm_state_alloc --> xfrm_state_insert
- * 2) xfrm_state_lookup --> xfrm_state_insert
- *
- * The xfrm_state_lookup or xfrm_state_alloc call gives a
- * reference, and that is what we are dropping here.
- */
- atomic_dec(&x->refcnt);
-
- if (kill && x->type)
- x->type->destructor(x);
- wake_up(&km_waitq);
+ /* All xfrm_state objects are created by one of two possible
+ * paths:
+ *
+ * 2) xfrm_state_lookup --> xfrm_state_insert
+ *
+ * The xfrm_state_lookup or xfrm_state_alloc call gives a
+ * reference, and that is what we are dropping here.
+ */
+ atomic_dec(&x->refcnt);
+ }
}
void xfrm_state_delete(struct xfrm_state *x)
@@ -773,5 +798,6 @@ void __init xfrm_state_init(void)
INIT_LIST_HEAD(&xfrm_state_bydst[i]);
INIT_LIST_HEAD(&xfrm_state_byspi[i]);
}
+ INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
}