diff options
author | David S. Miller <davem@nuts.davemloft.net> | 2004-07-29 23:00:42 -0700 |
---|---|---|
committer | David S. Miller <davem@nuts.davemloft.net> | 2004-07-29 23:00:42 -0700 |
commit | e71f71031d296e866086e574bd9448e1f496149f (patch) | |
tree | 07b82239d39c26edb7e74a1b6d96c5ccdcef746e /net | |
parent | 99202312a6e44bbe29355c5706064fb71dd33db9 (diff) | |
parent | bb9a9e6e2e102ee416da9383b24024b3ed23ca94 (diff) | |
download | history-e71f71031d296e866086e574bd9448e1f496149f.tar.gz |
Merge nuts.davemloft.net:/disk1/BK/network-2.6
into nuts.davemloft.net:/disk1/BK/net-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/Kconfig | 2 | ||||
-rw-r--r-- | net/bridge/br_device.c | 35 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 72 | ||||
-rw-r--r-- | net/bridge/br_if.c | 8 | ||||
-rw-r--r-- | net/bridge/br_input.c | 4 | ||||
-rw-r--r-- | net/bridge/br_notify.c | 47 | ||||
-rw-r--r-- | net/bridge/br_private.h | 11 | ||||
-rw-r--r-- | net/bridge/br_stp_if.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 7 | ||||
-rw-r--r-- | net/ipv6/Kconfig | 2 | ||||
-rw-r--r-- | net/ipv6/Makefile | 2 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 158 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 87 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 2 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 76 | ||||
-rw-r--r-- | net/ipv6/xfrm6_output.c | 123 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 2 | ||||
-rw-r--r-- | net/ipv6/xfrm6_tunnel.c | 42 | ||||
-rw-r--r-- | net/netrom/af_netrom.c | 4 | ||||
-rw-r--r-- | net/rose/af_rose.c | 5 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 113 | ||||
-rw-r--r-- | net/sctp/Kconfig | 10 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 30 |
24 files changed, 435 insertions, 411 deletions
diff --git a/net/Kconfig b/net/Kconfig index 6b033215e64949..a558582251c249 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -109,6 +109,8 @@ source "net/ipv4/Kconfig" config IPV6 tristate "The IPv6 protocol (EXPERIMENTAL)" depends on INET && EXPERIMENTAL + select CRYPTO if IPV6_PRIVACY + select CRYPTO_MD5 if IPV6_PRIVACY ---help--- This is experimental support for the IP version 6 (formerly called IPng "IP next generation"). You will still be able to do diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index e91f80f972ff3f..44a976221318f4 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -28,43 +28,28 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev) return &br->statistics; } -static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev) +int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_bridge *br; - unsigned char *dest; + struct net_bridge *br = netdev_priv(dev); + const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; - br = dev->priv; br->statistics.tx_packets++; br->statistics.tx_bytes += skb->len; - dest = skb->mac.raw = skb->data; + skb->mac.raw = skb->data; skb_pull(skb, ETH_HLEN); - if (dest[0] & 1) { + rcu_read_lock(); + if (dest[0] & 1) br_flood_deliver(br, skb, 0); - return 0; - } - - if ((dst = br_fdb_get(br, dest)) != NULL) { + else if ((dst = __br_fdb_get(br, dest)) != NULL) br_deliver(dst->dst, skb); - br_fdb_put(dst); - return 0; - } - - br_flood_deliver(br, skb, 0); - return 0; -} - -int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) -{ - int ret; + else + br_flood_deliver(br, skb, 0); - rcu_read_lock(); - ret = __br_dev_xmit(skb, dev); rcu_read_unlock(); - - return ret; + return 0; } static int br_dev_open(struct net_device *dev) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 324489dda89a5c..373c05d78d0fe5 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -73,7 +73,7 @@ static __inline__ int br_mac_hash(const unsigned char *mac) static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f) { - hlist_del(&f->hlist); + hlist_del_rcu(&f->hlist); if (!f->is_static) list_del(&f->age_list); @@ -85,7 +85,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) struct net_bridge *br = p->br; int i; - write_lock_bh(&br->hash_lock); + spin_lock_bh(&br->hash_lock); /* Search all chains since old address/hash is unknown */ for (i = 0; i < BR_HASH_SIZE; i++) { @@ -117,7 +117,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) fdb_insert(br, p, newaddr, 1); - write_unlock_bh(&br->hash_lock); + spin_unlock_bh(&br->hash_lock); } void br_fdb_cleanup(unsigned long _data) @@ -126,7 +126,7 @@ void br_fdb_cleanup(unsigned long _data) struct list_head *l, *n; unsigned long delay; - write_lock_bh(&br->hash_lock); + spin_lock_bh(&br->hash_lock); delay = hold_time(br); list_for_each_safe(l, n, &br->age_list) { @@ -144,14 +144,14 @@ void br_fdb_cleanup(unsigned long _data) break; } } - write_unlock_bh(&br->hash_lock); + spin_unlock_bh(&br->hash_lock); } void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) { int i; - write_lock_bh(&br->hash_lock); + spin_lock_bh(&br->hash_lock); for (i = 0; i < BR_HASH_SIZE; i++) { struct hlist_node *h, *g; @@ -182,37 +182,53 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) skip_delete: ; } } - write_unlock_bh(&br->hash_lock); + spin_unlock_bh(&br->hash_lock); } -struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, unsigned char *addr) +/* No locking or refcounting, assumes caller has no preempt (rcu_read_lock) */ +struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, + const unsigned char *addr) { struct hlist_node *h; + struct net_bridge_fdb_entry *fdb; - read_lock_bh(&br->hash_lock); - - hlist_for_each(h, &br->hash[br_mac_hash(addr)]) { - struct net_bridge_fdb_entry *fdb - = hlist_entry(h, struct net_bridge_fdb_entry, hlist); - + hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) { - if (has_expired(br, fdb)) - goto ret_null; - - atomic_inc(&fdb->use_count); - read_unlock_bh(&br->hash_lock); + if (unlikely(has_expired(br, fdb))) + break; return fdb; } } - ret_null: - read_unlock_bh(&br->hash_lock); + return NULL; } +/* Interface used by ATM hook that keeps a ref count */ +struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, + unsigned char *addr) +{ + struct net_bridge_fdb_entry *fdb; + + rcu_read_lock(); + fdb = __br_fdb_get(br, addr); + if (fdb) + atomic_inc(&fdb->use_count); + rcu_read_unlock(); + return fdb; +} + +static void fdb_rcu_free(struct rcu_head *head) +{ + struct net_bridge_fdb_entry *ent + = container_of(head, struct net_bridge_fdb_entry, rcu); + kmem_cache_free(br_fdb_cache, ent); +} + +/* Set entry up for deletion with RCU */ void br_fdb_put(struct net_bridge_fdb_entry *ent) { if (atomic_dec_and_test(&ent->use_count)) - kmem_cache_free(br_fdb_cache, ent); + call_rcu(&ent->rcu, fdb_rcu_free); } /* @@ -229,9 +245,9 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, memset(buf, 0, maxnum*sizeof(struct __fdb_entry)); - read_lock_bh(&br->hash_lock); + rcu_read_lock(); for (i = 0; i < BR_HASH_SIZE; i++) { - hlist_for_each_entry(f, h, &br->hash[i], hlist) { + hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { if (num >= maxnum) goto out; @@ -255,7 +271,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, } out: - read_unlock_bh(&br->hash_lock); + rcu_read_unlock(); return num; } @@ -309,7 +325,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, memcpy(fdb->addr.addr, addr, ETH_ALEN); atomic_set(&fdb->use_count, 1); - hlist_add_head(&fdb->hlist, &br->hash[hash]); + hlist_add_head_rcu(&fdb->hlist, &br->hash[hash]); if (!timer_pending(&br->gc_timer)) { br->gc_timer.expires = jiffies + hold_time(br); @@ -332,8 +348,8 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, { int ret; - write_lock_bh(&br->hash_lock); + spin_lock_bh(&br->hash_lock); ret = fdb_insert(br, source, addr, is_local); - write_unlock_bh(&br->hash_lock); + spin_unlock_bh(&br->hash_lock); return ret; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 092d4516364492..43d03734e48b2b 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -149,7 +149,7 @@ static struct net_device *new_bridge_dev(const char *name) br->lock = SPIN_LOCK_UNLOCKED; INIT_LIST_HEAD(&br->port_list); - br->hash_lock = RW_LOCK_UNLOCKED; + br->hash_lock = SPIN_LOCK_UNLOCKED; br->bridge_id.prio[0] = 0x80; br->bridge_id.prio[1] = 0x00; @@ -295,6 +295,7 @@ int br_del_bridge(const char *name) return ret; } +/* Mtu of the bridge pseudo-device 1500 or the minimum of the ports */ int br_min_mtu(const struct net_bridge *br) { const struct net_bridge_port *p; @@ -343,11 +344,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); - if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP)) + if ((br->dev->flags & IFF_UP) + && (dev->flags & IFF_UP) && netif_carrier_ok(dev)) br_stp_enable_port(p); spin_unlock_bh(&br->lock); - br->dev->mtu = br_min_mtu(br); + dev_set_mtu(br->dev, br_min_mtu(br)); } return err; diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 1c714c6860e759..fdf8f9eb6554e0 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -83,19 +83,17 @@ int br_handle_frame_finish(struct sk_buff *skb) goto out; } - dst = br_fdb_get(br, dest); + dst = __br_fdb_get(br, dest); if (dst != NULL && dst->is_local) { if (!passedup) br_pass_frame_up(br, skb); else kfree_skb(skb); - br_fdb_put(dst); goto out; } if (dst != NULL) { br_forward(dst->dst, skb); - br_fdb_put(dst); goto out; } diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 5c88a71b85e3cf..70dc21f0c5ec50 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -19,58 +19,59 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr); -struct notifier_block br_device_notifier = -{ +struct notifier_block br_device_notifier = { .notifier_call = br_device_event }; static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev; - struct net_bridge_port *p; + struct net_device *dev = ptr; + struct net_bridge_port *p = dev->br_port; struct net_bridge *br; - dev = ptr; - p = dev->br_port; - if (p == NULL) return NOTIFY_DONE; br = p->br; + if ( !(br->dev->flags & IFF_UP)) + return NOTIFY_DONE; + + if (event == NETDEV_CHANGEMTU) { + dev_set_mtu(br->dev, br_min_mtu(br)); + return NOTIFY_DONE; + } + spin_lock_bh(&br->lock); switch (event) { case NETDEV_CHANGEADDR: - spin_lock_bh(&br->lock); br_fdb_changeaddr(p, dev->dev_addr); - if (br->dev->flags & IFF_UP) - br_stp_recalculate_bridge_id(br); - spin_unlock_bh(&br->lock); + br_stp_recalculate_bridge_id(br); break; - case NETDEV_CHANGEMTU: - br->dev->mtu = br_min_mtu(br); + case NETDEV_CHANGE: /* device is up but carrier changed */ + if (netif_carrier_ok(dev)) { + if (p->state == BR_STATE_DISABLED) + br_stp_enable_port(p); + } else { + if (p->state != BR_STATE_DISABLED) + br_stp_disable_port(p); + } break; case NETDEV_DOWN: - if (br->dev->flags & IFF_UP) { - spin_lock_bh(&br->lock); - br_stp_disable_port(p); - spin_unlock_bh(&br->lock); - } + br_stp_disable_port(p); break; case NETDEV_UP: - if (br->dev->flags & IFF_UP) { - spin_lock_bh(&br->lock); + if (netif_carrier_ok(dev)) br_stp_enable_port(p); - spin_unlock_bh(&br->lock); - } break; case NETDEV_UNREGISTER: br_del_if(br, dev); break; - } + } + spin_unlock_bh(&br->lock); return NOTIFY_DONE; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1064d4c68c2412..6cd11410711cbf 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -46,7 +46,10 @@ struct net_bridge_fdb_entry { struct hlist_node hlist; struct net_bridge_port *dst; - struct list_head age_list; + union { + struct list_head age_list; + struct rcu_head rcu; + }; atomic_t use_count; unsigned long ageing_timer; mac_addr addr; @@ -86,7 +89,7 @@ struct net_bridge struct list_head port_list; struct net_device *dev; struct net_device_stats statistics; - rwlock_t hash_lock; + spinlock_t hash_lock; struct hlist_head hash[BR_HASH_SIZE]; struct list_head age_list; @@ -136,8 +139,10 @@ extern void br_fdb_changeaddr(struct net_bridge_port *p, extern void br_fdb_cleanup(unsigned long arg); extern void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p); +extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, + const unsigned char *addr); extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, - unsigned char *addr); + unsigned char *addr); extern void br_fdb_put(struct net_bridge_fdb_entry *ent); extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count, unsigned long off); diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 9e1d296b6e95b4..6c08fefcc75d55 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -52,7 +52,7 @@ void br_stp_enable_bridge(struct net_bridge *br) br_config_bpdu_generation(br); list_for_each_entry(p, &br->port_list, list) { - if (p->dev->flags & IFF_UP) + if ((p->dev->flags & IFF_UP) && netif_carrier_ok(p->dev)) br_stp_enable_port(p); } diff --git a/net/core/dev.c b/net/core/dev.c index 3bead55e88a634..93a145c4d9ab65 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3431,6 +3431,8 @@ EXPORT_SYMBOL(dev_queue_xmit_nit); EXPORT_SYMBOL(dev_remove_pack); EXPORT_SYMBOL(dev_set_allmulti); EXPORT_SYMBOL(dev_set_promiscuity); +EXPORT_SYMBOL(dev_change_flags); +EXPORT_SYMBOL(dev_set_mtu); EXPORT_SYMBOL(free_netdev); EXPORT_SYMBOL(netdev_boot_setup_check); EXPORT_SYMBOL(netdev_set_master); @@ -3448,10 +3450,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier); #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) EXPORT_SYMBOL(br_handle_frame_hook); #endif -/* for 801q VLAN support */ -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -EXPORT_SYMBOL(dev_change_flags); -#endif + #ifdef CONFIG_KMOD EXPORT_SYMBOL(dev_load); #endif diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index f5b568867e08ea..23c5759c022d9b 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -4,8 +4,6 @@ config IPV6_PRIVACY bool "IPv6: Privacy Extensions (RFC 3041) support" depends on IPV6 - select CRYPTO - select CRYPTO_MD5 ---help--- Privacy Extensions for Stateless Address Autoconfiguration in IPv6 support. With this option, additional periodically-alter diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 31afc9cfc0a647..d9e309fe84905a 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -11,7 +11,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ ip6_flowlabel.o ipv6_syms.o ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ - xfrm6_tunnel.o + xfrm6_tunnel.o xfrm6_output.o ipv6-objs += $(ipv6-y) obj-$(CONFIG_INET6_AH) += ah6.o diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index ca1e0fb576acba..f7674431ff1b8c 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -31,6 +31,7 @@ #include <net/ah.h> #include <linux/crypto.h> #include <linux/pfkeyv2.h> +#include <linux/string.h> #include <net/icmp.h> #include <net/ipv6.h> #include <net/xfrm.h> @@ -74,6 +75,45 @@ bad: return 0; } +/** + * ipv6_rearrange_rthdr - rearrange IPv6 routing header + * @iph: IPv6 header + * @rthdr: routing header + * + * Rearrange the destination address in @iph and the addresses in @rthdr + * so that they appear in the order they will at the final destination. + * See Appendix A2 of RFC 2402 for details. + */ +static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) +{ + int segments, segments_left; + struct in6_addr *addrs; + struct in6_addr final_addr; + + segments_left = rthdr->segments_left; + if (segments_left == 0) + return; + rthdr->segments_left = 0; + + /* The value of rthdr->hdrlen has been verified either by the system + * call if it is locally generated, or by ipv6_rthdr_rcv() for incoming + * packets. So we can assume that it is even and that segments is + * greater than or equal to segments_left. + * + * For the same reason we can assume that this option is of type 0. + */ + segments = rthdr->hdrlen >> 1; + + addrs = ((struct rt0_hdr *)rthdr)->addr; + ipv6_addr_copy(&final_addr, addrs + segments - 1); + + addrs += segments - segments_left; + memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs)); + + ipv6_addr_copy(addrs, &iph->daddr); + ipv6_addr_copy(&iph->daddr, &final_addr); +} + static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) { union { @@ -101,7 +141,7 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) break; case NEXTHDR_ROUTING: - exthdr.rth->segments_left = 0; + ipv6_rearrange_rthdr(iph, exthdr.rth); break; default : @@ -118,70 +158,55 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) int ah6_output(struct sk_buff **pskb) { int err; - int hdr_len = sizeof(struct ipv6hdr); + int extlen; struct dst_entry *dst = (*pskb)->dst; struct xfrm_state *x = dst->xfrm; - struct ipv6hdr *iph = NULL; + struct ipv6hdr *top_iph; struct ip_auth_hdr *ah; struct ah_data *ahp; u8 nexthdr; + char tmp_base[8]; + struct { + struct in6_addr daddr; + char hdrs[0]; + } *tmp_ext; - if ((*pskb)->ip_summed == CHECKSUM_HW) { - err = skb_checksum_help(pskb, 0); - if (err) - goto error_nolock; - } + top_iph = (struct ipv6hdr *)(*pskb)->data; + top_iph->payload_len = htons((*pskb)->len - sizeof(*top_iph)); - spin_lock_bh(&x->lock); - err = xfrm_state_check(x, *pskb); - if (err) - goto error; + nexthdr = *(*pskb)->nh.raw; + *(*pskb)->nh.raw = IPPROTO_AH; - if (x->props.mode) { - err = xfrm6_tunnel_check_size(*pskb); - if (err) - goto error; - - iph = (*pskb)->nh.ipv6h; - (*pskb)->nh.ipv6h = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); - (*pskb)->nh.ipv6h->version = 6; - (*pskb)->nh.ipv6h->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); - (*pskb)->nh.ipv6h->nexthdr = IPPROTO_AH; - ipv6_addr_copy(&(*pskb)->nh.ipv6h->saddr, - (struct in6_addr *) &x->props.saddr); - ipv6_addr_copy(&(*pskb)->nh.ipv6h->daddr, - (struct in6_addr *) &x->id.daddr); - ah = (struct ip_auth_hdr*)((*pskb)->nh.ipv6h+1); - ah->nexthdr = IPPROTO_IPV6; - } else { - u8 *prevhdr; - - hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr); - nexthdr = *prevhdr; - *prevhdr = IPPROTO_AH; - iph = kmalloc(hdr_len, GFP_ATOMIC); - if (!iph) { + /* When there are no extension headers, we only need to save the first + * 8 bytes of the base IP header. + */ + memcpy(tmp_base, top_iph, sizeof(tmp_base)); + + tmp_ext = NULL; + extlen = (*pskb)->h.raw - (unsigned char *)(top_iph + 1); + if (extlen) { + extlen += sizeof(*tmp_ext); + tmp_ext = kmalloc(extlen, GFP_ATOMIC); + if (!tmp_ext) { err = -ENOMEM; goto error; } - memcpy(iph, (*pskb)->data, hdr_len); - (*pskb)->nh.ipv6h = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); - iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); - memcpy((*pskb)->nh.ipv6h, iph, hdr_len); - err = ipv6_clear_mutable_options((*pskb)->nh.ipv6h, hdr_len); + memcpy(tmp_ext, &top_iph->daddr, extlen); + err = ipv6_clear_mutable_options(top_iph, + extlen - sizeof(*tmp_ext) + + sizeof(*top_iph)); if (err) goto error_free_iph; - - ah = (struct ip_auth_hdr*)((*pskb)->nh.raw+hdr_len); - (*pskb)->h.raw = (unsigned char*) ah; - ah->nexthdr = nexthdr; } - (*pskb)->nh.ipv6h->priority = 0; - (*pskb)->nh.ipv6h->flow_lbl[0] = 0; - (*pskb)->nh.ipv6h->flow_lbl[1] = 0; - (*pskb)->nh.ipv6h->flow_lbl[2] = 0; - (*pskb)->nh.ipv6h->hop_limit = 0; + ah = (struct ip_auth_hdr *)(*pskb)->h.raw; + ah->nexthdr = nexthdr; + + top_iph->priority = 0; + top_iph->flow_lbl[0] = 0; + top_iph->flow_lbl[1] = 0; + top_iph->flow_lbl[2] = 0; + top_iph->hop_limit = 0; ahp = x->data; ah->hdrlen = (XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + @@ -192,35 +217,16 @@ int ah6_output(struct sk_buff **pskb) ah->seq_no = htonl(++x->replay.oseq); ahp->icv(ahp, *pskb, ah->auth_data); - if (x->props.mode) { - (*pskb)->nh.ipv6h->hop_limit = iph->hop_limit; - (*pskb)->nh.ipv6h->priority = iph->priority; - (*pskb)->nh.ipv6h->flow_lbl[0] = iph->flow_lbl[0]; - (*pskb)->nh.ipv6h->flow_lbl[1] = iph->flow_lbl[1]; - (*pskb)->nh.ipv6h->flow_lbl[2] = iph->flow_lbl[2]; - if (x->props.flags & XFRM_STATE_NOECN) - IP6_ECN_clear((*pskb)->nh.ipv6h); - } else { - memcpy((*pskb)->nh.ipv6h, iph, hdr_len); - kfree (iph); - } - - (*pskb)->nh.raw = (*pskb)->data; + err = 0; - x->curlft.bytes += (*pskb)->len; - x->curlft.packets++; - spin_unlock_bh(&x->lock); - if (((*pskb)->dst = dst_pop(dst)) == NULL) { - err = -EHOSTUNREACH; - goto error_nolock; - } - return NET_XMIT_BYPASS; + memcpy(top_iph, tmp_base, sizeof(tmp_base)); + if (tmp_ext) { + memcpy(&top_iph->daddr, tmp_ext, extlen); error_free_iph: - kfree(iph); + kfree(tmp_ext); + } + error: - spin_unlock_bh(&x->lock); -error_nolock: - kfree_skb(*pskb); return err; } diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 0763c9fc50bb7b..2403f8bd6f731c 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -41,10 +41,10 @@ int esp6_output(struct sk_buff **pskb) { int err; - int hdr_len = 0; + int hdr_len; struct dst_entry *dst = (*pskb)->dst; struct xfrm_state *x = dst->xfrm; - struct ipv6hdr *iph = NULL, *top_iph; + struct ipv6hdr *top_iph; struct ipv6_esp_hdr *esph; struct crypto_tfm *tfm; struct esp_data *esp; @@ -53,37 +53,13 @@ int esp6_output(struct sk_buff **pskb) int clen; int alen; int nfrags; - u8 *prevhdr; - u8 nexthdr = 0; - if ((*pskb)->ip_summed == CHECKSUM_HW) { - err = skb_checksum_help(pskb, 0); - if (err) - goto error_nolock; - } + esp = x->data; + hdr_len = (*pskb)->h.raw - (*pskb)->data + + sizeof(*esph) + esp->conf.ivlen; - spin_lock_bh(&x->lock); - err = xfrm_state_check(x, *pskb); - if (err) - goto error; - - if (x->props.mode) { - err = xfrm6_tunnel_check_size(*pskb); - if (err) - goto error; - } else { - /* Strip IP header in transport mode. Save it. */ - hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr); - nexthdr = *prevhdr; - *prevhdr = IPPROTO_ESP; - iph = kmalloc(hdr_len, GFP_ATOMIC); - if (!iph) { - err = -ENOMEM; - goto error; - } - memcpy(iph, (*pskb)->nh.raw, hdr_len); - __skb_pull(*pskb, hdr_len); - } + /* Strip IP+ESP header. */ + __skb_pull(*pskb, hdr_len); /* Now skb is pure payload to encrypt */ err = -ENOMEM; @@ -91,7 +67,6 @@ int esp6_output(struct sk_buff **pskb) /* Round to block size */ clen = (*pskb)->len; - esp = x->data; alen = esp->auth.icv_trunc_len; tfm = esp->conf.tfm; blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3; @@ -100,7 +75,6 @@ int esp6_output(struct sk_buff **pskb) clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0) { - if (!x->props.mode && iph) kfree(iph); goto error; } @@ -113,34 +87,11 @@ int esp6_output(struct sk_buff **pskb) *(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2; pskb_put(*pskb, trailer, clen - (*pskb)->len); - if (x->props.mode) { - iph = (*pskb)->nh.ipv6h; - top_iph = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); - esph = (struct ipv6_esp_hdr*)(top_iph+1); - *(u8*)(trailer->tail - 1) = IPPROTO_IPV6; - top_iph->version = 6; - top_iph->priority = iph->priority; - top_iph->flow_lbl[0] = iph->flow_lbl[0]; - top_iph->flow_lbl[1] = iph->flow_lbl[1]; - top_iph->flow_lbl[2] = iph->flow_lbl[2]; - if (x->props.flags & XFRM_STATE_NOECN) - IP6_ECN_clear(top_iph); - top_iph->nexthdr = IPPROTO_ESP; - top_iph->payload_len = htons((*pskb)->len + alen - sizeof(struct ipv6hdr)); - top_iph->hop_limit = iph->hop_limit; - ipv6_addr_copy(&top_iph->saddr, - (struct in6_addr *)&x->props.saddr); - ipv6_addr_copy(&top_iph->daddr, - (struct in6_addr *)&x->id.daddr); - } else { - esph = (struct ipv6_esp_hdr*)skb_push(*pskb, x->props.header_len); - (*pskb)->h.raw = (unsigned char*)esph; - top_iph = (struct ipv6hdr*)skb_push(*pskb, hdr_len); - memcpy(top_iph, iph, hdr_len); - kfree(iph); - top_iph->payload_len = htons((*pskb)->len + alen - sizeof(struct ipv6hdr)); - *(u8*)(trailer->tail - 1) = nexthdr; - } + top_iph = (struct ipv6hdr *)__skb_push(*pskb, hdr_len); + esph = (struct ipv6_esp_hdr *)(*pskb)->h.raw; + top_iph->payload_len = htons((*pskb)->len + alen - sizeof(*top_iph)); + *(u8*)(trailer->tail - 1) = *(*pskb)->nh.raw; + *(*pskb)->nh.raw = IPPROTO_ESP; esph->spi = x->id.spi; esph->seq_no = htonl(++x->replay.oseq); @@ -173,21 +124,9 @@ int esp6_output(struct sk_buff **pskb) pskb_put(*pskb, trailer, alen); } - (*pskb)->nh.raw = (*pskb)->data; - - x->curlft.bytes += (*pskb)->len; - x->curlft.packets++; - spin_unlock_bh(&x->lock); - if (((*pskb)->dst = dst_pop(dst)) == NULL) { - err = -EHOSTUNREACH; - goto error_nolock; - } - return NET_XMIT_BYPASS; + err = 0; error: - spin_unlock_bh(&x->lock); -error_nolock: - kfree_skb(*pskb); return err; } diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 5d51e9706d7dc2..65a137241777e6 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -94,7 +94,7 @@ static __u32 rt_sernum; static struct timer_list ip6_fib_timer = TIMER_INITIALIZER(fib6_run_gc, 0, 0); -static struct fib6_walker_t fib6_walker_list = { +struct fib6_walker_t fib6_walker_list = { .prev = &fib6_walker_list, .next = &fib6_walker_list, }; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 9f2dfa1607c4d3..a531614f39c7ba 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -120,52 +120,14 @@ static int ipcomp6_output(struct sk_buff **pskb) int err; struct dst_entry *dst = (*pskb)->dst; struct xfrm_state *x = dst->xfrm; - struct ipv6hdr *iph, *top_iph; - int hdr_len = 0; + struct ipv6hdr *top_iph; + int hdr_len; struct ipv6_comp_hdr *ipch; struct ipcomp_data *ipcd = x->data; - u8 *prevhdr; - u8 nexthdr = 0; int plen, dlen; u8 *start, *scratch = ipcd->scratch; - if ((*pskb)->ip_summed == CHECKSUM_HW) { - err = skb_checksum_help(pskb, 0); - if (err) - goto error_nolock; - } - - spin_lock_bh(&x->lock); - - err = xfrm_state_check(x, *pskb); - if (err) - goto error; - - if (x->props.mode) { - err = xfrm6_tunnel_check_size(*pskb); - if (err) - goto error; - - hdr_len = sizeof(struct ipv6hdr); - nexthdr = IPPROTO_IPV6; - iph = (*pskb)->nh.ipv6h; - top_iph = (struct ipv6hdr *)skb_push(*pskb, sizeof(struct ipv6hdr)); - top_iph->version = 6; - top_iph->priority = iph->priority; - top_iph->flow_lbl[0] = iph->flow_lbl[0]; - top_iph->flow_lbl[1] = iph->flow_lbl[1]; - top_iph->flow_lbl[2] = iph->flow_lbl[2]; - top_iph->nexthdr = IPPROTO_IPV6; /* initial */ - top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); - top_iph->hop_limit = iph->hop_limit; - memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr)); - memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr)); - (*pskb)->nh.raw = (*pskb)->data; /* == top_iph */ - (*pskb)->h.raw = (*pskb)->nh.raw + hdr_len; - } else { - hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr); - nexthdr = *prevhdr; - } + hdr_len = (*pskb)->h.raw - (*pskb)->data; /* check whether datagram len is larger than threshold */ if (((*pskb)->len - hdr_len) < ipcd->threshold) { @@ -181,7 +143,7 @@ static int ipcomp6_output(struct sk_buff **pskb) /* compression */ plen = (*pskb)->len - hdr_len; dlen = IPCOMP_SCRATCH_SIZE; - start = (*pskb)->data + hdr_len; + start = (*pskb)->h.raw; err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen); if (err) { @@ -194,39 +156,21 @@ static int ipcomp6_output(struct sk_buff **pskb) pskb_trim(*pskb, hdr_len + dlen + sizeof(struct ip_comp_hdr)); /* insert ipcomp header and replace datagram */ - top_iph = (*pskb)->nh.ipv6h; + top_iph = (struct ipv6hdr *)(*pskb)->data; - if (x->props.mode && (x->props.flags & XFRM_STATE_NOECN)) - IP6_ECN_clear(top_iph); top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); - (*pskb)->nh.raw = (*pskb)->data; /* top_iph */ - ip6_find_1stfragopt(*pskb, &prevhdr); - *prevhdr = IPPROTO_COMP; - ipch = (struct ipv6_comp_hdr *)((unsigned char *)top_iph + hdr_len); - ipch->nexthdr = nexthdr; + ipch = (struct ipv6_comp_hdr *)start; + ipch->nexthdr = *(*pskb)->nh.raw; ipch->flags = 0; ipch->cpi = htons((u16 )ntohl(x->id.spi)); + *(*pskb)->nh.raw = IPPROTO_COMP; - (*pskb)->h.raw = (unsigned char*)ipch; out_ok: - x->curlft.bytes += (*pskb)->len; - x->curlft.packets++; - spin_unlock_bh(&x->lock); - - if (((*pskb)->dst = dst_pop(dst)) == NULL) { - err = -EHOSTUNREACH; - goto error_nolock; - } - err = NET_XMIT_BYPASS; + err = 0; -out_exit: - return err; error: - spin_unlock_bh(&x->lock); -error_nolock: - kfree_skb(*pskb); - goto out_exit; + return err; } static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c new file mode 100644 index 00000000000000..028c9dd96bebe5 --- /dev/null +++ b/net/ipv6/xfrm6_output.c @@ -0,0 +1,123 @@ +/* + * xfrm6_output.c - Common IPsec encapsulation code for IPv6. + * Copyright (C) 2002 USAGI/WIDE Project + * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <net/inet_ecn.h> +#include <net/ipv6.h> +#include <net/xfrm.h> + +/* Add encapsulation header. + * + * In transport mode, the IP header and mutable extension headers will be moved + * forward to make space for the encapsulation header. + * + * In tunnel mode, the top IP header will be constructed per RFC 2401. + * The following fields in it shall be filled in by x->type->output: + * payload_len + * + * On exit, skb->h will be set to the start of the encapsulation header to be + * filled in by x->type->output and skb->nh will be set to the nextheader field + * of the extension header directly preceding the encapsulation header, or in + * its absence, that of the top IP header. The value of skb->data will always + * point to the top IP header. + */ +static void xfrm6_encap(struct sk_buff *skb) +{ + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + struct ipv6hdr *iph, *top_iph; + + skb_push(skb, x->props.header_len); + iph = skb->nh.ipv6h; + + if (!x->props.mode) { + u8 *prevhdr; + int hdr_len; + + hdr_len = ip6_find_1stfragopt(skb, &prevhdr); + skb->nh.raw = prevhdr - x->props.header_len; + skb->h.raw = skb->data + hdr_len; + memmove(skb->data, iph, hdr_len); + return; + } + + skb->nh.raw = skb->data; + top_iph = skb->nh.ipv6h; + skb->nh.raw = &top_iph->nexthdr; + skb->h.ipv6h = top_iph + 1; + + top_iph->version = 6; + top_iph->priority = iph->priority; + if (x->props.flags & XFRM_STATE_NOECN) + IP6_ECN_clear(top_iph); + top_iph->flow_lbl[0] = iph->flow_lbl[0]; + top_iph->flow_lbl[1] = iph->flow_lbl[1]; + top_iph->flow_lbl[2] = iph->flow_lbl[2]; + top_iph->nexthdr = IPPROTO_IPV6; + top_iph->hop_limit = iph->hop_limit; + ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); +} + +int xfrm6_output(struct sk_buff **pskb) +{ + struct sk_buff *skb = *pskb; + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + int err; + + if (skb->ip_summed == CHECKSUM_HW) { + err = skb_checksum_help(pskb, 0); + skb = *pskb; + if (err) + goto error_nolock; + } + + spin_lock_bh(&x->lock); + err = xfrm_state_check(x, skb); + if (err) + goto error; + + if (x->props.mode) { + err = xfrm6_tunnel_check_size(skb); + if (err) + goto error; + } + + xfrm6_encap(skb); + + err = x->type->output(pskb); + skb = *pskb; + if (err) + goto error; + + x->curlft.bytes += skb->len; + x->curlft.packets++; + + spin_unlock_bh(&x->lock); + + skb->nh.raw = skb->data; + + if (!(skb->dst = dst_pop(dst))) { + err = -EHOSTUNREACH; + goto error_nolock; + } + err = NET_XMIT_BYPASS; + +out_exit: + return err; +error: + spin_unlock_bh(&x->lock); +error_nolock: + kfree_skb(skb); + goto out_exit; +} diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index b5a3bdb440e4be..ab4e40b0ab766e 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -157,7 +157,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int /* Copy neighbour for reachability confirmation */ dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); dst_prev->input = rt->u.dst.input; - dst_prev->output = dst_prev->xfrm->type->output; + dst_prev->output = xfrm6_output; /* Sheit... I remember I did this right. Apparently, * it was magically lost, so this code needs audit */ x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index c72cf83d465fae..29c4b28fa0b5c5 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -16,7 +16,7 @@ #include <linux/ipsec.h> #include <net/ipv6.h> -extern struct xfrm_state_afinfo xfrm6_state_afinfo; +static struct xfrm_state_afinfo xfrm6_state_afinfo; static void __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index f5a06546d301e1..d35c87ff83ddff 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -365,46 +365,12 @@ EXPORT_SYMBOL(xfrm6_tunnel_check_size); static int xfrm6_tunnel_output(struct sk_buff **pskb) { struct sk_buff *skb = *pskb; - struct dst_entry *dst = skb->dst; - struct xfrm_state *x = dst->xfrm; - struct ipv6hdr *iph, *top_iph; - int err; - - if ((err = xfrm6_tunnel_check_size(skb)) != 0) - goto error_nolock; - - iph = skb->nh.ipv6h; - - top_iph = (struct ipv6hdr *)skb_push(skb, x->props.header_len); - top_iph->version = 6; - top_iph->priority = iph->priority; - top_iph->flow_lbl[0] = iph->flow_lbl[0]; - top_iph->flow_lbl[1] = iph->flow_lbl[1]; - top_iph->flow_lbl[2] = iph->flow_lbl[2]; - top_iph->nexthdr = IPPROTO_IPV6; - top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); - top_iph->hop_limit = iph->hop_limit; - memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr)); - memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr)); - skb->nh.raw = skb->data; - skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr); - - x->curlft.bytes += skb->len; - x->curlft.packets++; - - spin_unlock_bh(&x->lock); + struct ipv6hdr *top_iph; - if ((skb->dst = dst_pop(dst)) == NULL) { - kfree_skb(skb); - err = -EHOSTUNREACH; - goto error_nolock; - } - - return NET_XMIT_BYPASS; + top_iph = (struct ipv6hdr *)skb->data; + top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); -error_nolock: - kfree_skb(skb); - return err; + return 0; } static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index fbb97bf3797e06..6774669bb212c9 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -10,6 +10,7 @@ */ #include <linux/config.h> #include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> @@ -1451,8 +1452,7 @@ static int __init nr_proto_init(void) module_init(nr_proto_init); - -MODULE_PARM(nr_ndevs, "i"); +module_param(nr_ndevs, int, 0); MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices"); MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index a5555c3280dd90..31c4ab77efe795 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -11,6 +11,7 @@ */ #include <linux/config.h> #include <linux/module.h> +#include <linux/moduleparam.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/types.h> @@ -57,7 +58,7 @@ int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT; int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC; int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE; -HLIST_HEAD(rose_list); +static HLIST_HEAD(rose_list); spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED; static struct proto_ops rose_proto_ops; @@ -1550,7 +1551,7 @@ fail: } module_init(rose_proto_init); -MODULE_PARM(rose_ndevs, "i"); +module_param(rose_ndevs, int, 0); MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices"); MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index e2d7c0e252c906..30d26d4fe34a90 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -64,17 +64,20 @@ struct tc_u_knode struct tc_u_hnode *ht_up; #ifdef CONFIG_NET_CLS_ACT struct tc_action *action; -#ifdef CONFIG_NET_CLS_IND - char indev[IFNAMSIZ]; -#endif #else #ifdef CONFIG_NET_CLS_POLICE struct tcf_police *police; #endif #endif +#ifdef CONFIG_NET_CLS_IND + char indev[IFNAMSIZ]; +#endif u8 fshift; struct tcf_result res; struct tc_u_hnode *ht_down; +#ifdef CONFIG_CLS_U32_PERF + struct tc_u32_pcnt *pf; +#endif struct tc_u32_sel sel; }; @@ -120,6 +123,9 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re int sdepth = 0; int off2 = 0; int sel = 0; +#ifdef CONFIG_CLS_U32_PERF + int j; +#endif int i; next_ht: @@ -130,7 +136,8 @@ next_knode: struct tc_u32_key *key = n->sel.keys; #ifdef CONFIG_CLS_U32_PERF - n->sel.rcnt +=1; + n->pf->rcnt +=1; + j = 0; #endif for (i = n->sel.nkeys; i>0; i--, key++) { @@ -139,7 +146,8 @@ next_knode: goto next_knode; } #ifdef CONFIG_CLS_U32_PERF - key->kcnt +=1; + n->pf->kcnts[j] +=1; + j++; #endif } if (n->ht_down == NULL) { @@ -147,7 +155,6 @@ check_terminal: if (n->sel.flags&TC_U32_TERMINAL) { *res = n->res; -#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_IND /* yes, i know it sucks but the feature is ** optional dammit! - JHS */ @@ -164,8 +171,9 @@ check_terminal: } #endif #ifdef CONFIG_CLS_U32_PERF - n->sel.rhit +=1; + n->pf->rhit +=1; #endif +#ifdef CONFIG_NET_CLS_ACT if (n->action) { int pol_res = tcf_action_exec(skb, n->action); if (skb->tc_classid > 0) { @@ -358,6 +366,10 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n) #endif if (n->ht_down) n->ht_down->refcnt--; +#ifdef CONFIG_CLS_U32_PERF + if (n && (NULL != n->pf)) + kfree(n->pf); +#endif kfree(n); return 0; } @@ -571,18 +583,6 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base, tcf_action_destroy(act, TCA_ACT_UNBIND); } -#ifdef CONFIG_NET_CLS_IND - n->indev[0] = 0; - if(tb[TCA_U32_INDEV-1]) { - struct rtattr *input_dev = tb[TCA_U32_INDEV-1]; - if (RTA_PAYLOAD(input_dev) >= IFNAMSIZ) { - printk("cls_u32: bad indev name %s\n",(char*)RTA_DATA(input_dev)); - /* should we clear state first? */ - return -EINVAL; - } - sprintf(n->indev, "%s", (char*)RTA_DATA(input_dev)); - } -#endif #else #ifdef CONFIG_NET_CLS_POLICE @@ -595,6 +595,19 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base, } #endif #endif +#ifdef CONFIG_NET_CLS_IND + n->indev[0] = 0; + if(tb[TCA_U32_INDEV-1]) { + struct rtattr *input_dev = tb[TCA_U32_INDEV-1]; + if (RTA_PAYLOAD(input_dev) >= IFNAMSIZ) { + printk("cls_u32: bad indev name %s\n",(char*)RTA_DATA(input_dev)); + /* should we clear state first? */ + return -EINVAL; + } + sprintf(n->indev, "%s", (char*)RTA_DATA(input_dev)); + printk("got IND %s\n",n->indev); + } +#endif return 0; } @@ -682,17 +695,20 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, s = RTA_DATA(tb[TCA_U32_SEL-1]); -#ifdef CONFIG_CLS_U32_PERF - if (RTA_PAYLOAD(tb[TCA_U32_SEL-1]) < - (s->nkeys*sizeof(struct tc_u32_key)) + sizeof(struct tc_u32_sel)) { - printk("Please upgrade your iproute2 tools or compile proper options in!\n"); - return -EINVAL; -} -#endif n = kmalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL); if (n == NULL) return -ENOBUFS; + memset(n, 0, sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key)); +#ifdef CONFIG_CLS_U32_PERF + n->pf = kmalloc(sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(__u64), GFP_KERNEL); + if (n->pf == NULL) { + kfree(n); + return -ENOBUFS; + } + memset(n->pf, 0, sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(__u64)); +#endif + memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key)); n->ht_up = ht; n->handle = handle; @@ -721,6 +737,10 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, *arg = (unsigned long)n; return 0; } +#ifdef CONFIG_CLS_U32_PERF + if (n && (NULL != n->pf)) + kfree(n->pf); +#endif kfree(n); return err; } @@ -812,13 +832,6 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, p_rta->rta_len = skb->tail - (u8*)p_rta; } -#ifdef CONFIG_NET_CLS_IND - if(strlen(n->indev)) { - struct rtattr * p_rta = (struct rtattr*)skb->tail; - RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev); - p_rta->rta_len = skb->tail - (u8*)p_rta; - } -#endif #else #ifdef CONFIG_NET_CLS_POLICE @@ -834,13 +847,28 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, } #endif #endif + +#ifdef CONFIG_NET_CLS_IND + if(strlen(n->indev)) { + struct rtattr * p_rta = (struct rtattr*)skb->tail; + RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev); + p_rta->rta_len = skb->tail - (u8*)p_rta; + } +#endif +#ifdef CONFIG_CLS_U32_PERF + RTA_PUT(skb, TCA_U32_PCNT, + sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(__u64), + n->pf); +#endif } rta->rta_len = skb->tail - b; #ifdef CONFIG_NET_CLS_ACT - if (TC_U32_KEY(n->handle) && n->action && n->action->type == TCA_OLD_COMPAT) { - if (tcf_action_copy_stats(skb,n->action)) - goto rtattr_failure; + if (TC_U32_KEY(n->handle) != 0) { + if (TC_U32_KEY(n->handle) && n->action && n->action->type == TCA_OLD_COMPAT) { + if (tcf_action_copy_stats(skb,n->action)) + goto rtattr_failure; + } } #else #ifdef CONFIG_NET_CLS_POLICE @@ -875,6 +903,19 @@ static struct tcf_proto_ops cls_u32_ops = { static int __init init_u32(void) { + printk("u32 classifier\n"); +#ifdef CONFIG_CLS_U32_PERF + printk(" Perfomance counters on\n"); +#endif +#ifdef CONFIG_NET_CLS_POLICE + printk(" OLD policer on \n"); +#endif +#ifdef CONFIG_NET_CLS_IND + printk(" input device check on \n"); +#endif +#ifdef CONFIG_NET_CLS_ACT + printk(" Actions configured \n"); +#endif return register_tcf_proto_ops(&cls_u32_ops); } diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index d7757c951c38b2..9cba49e2ad4318 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -8,6 +8,10 @@ menu "SCTP Configuration (EXPERIMENTAL)" config IP_SCTP tristate "The SCTP Protocol (EXPERIMENTAL)" depends on IPV6 || IPV6=n + select CRYPTO if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5 + select CRYPTO_HMAC if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5 + select CRYPTO_SHA1 if SCTP_HMAC_SHA1 + select CRYPTO_MD5 if SCTP_HMAC_MD5 ---help--- Stream Control Transmission Protocol @@ -71,18 +75,12 @@ config SCTP_HMAC_NONE config SCTP_HMAC_SHA1 bool "HMAC-SHA1" - select CRYPTO - select CRYPTO_HMAC - select CRYPTO_SHA1 help Enable the use of HMAC-SHA1 during association establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1. config SCTP_HMAC_MD5 bool "HMAC-MD5" - select CRYPTO - select CRYPTO_HMAC - select CRYPTO_MD5 help Enable the use of HMAC-MD5 during association establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1. diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 5fbbe608b14f5c..a7ab07fe5cc04d 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1296,21 +1296,6 @@ xprt_transmit(struct rpc_task *task) /* * Reserve an RPC call slot. */ -void -xprt_reserve(struct rpc_task *task) -{ - struct rpc_xprt *xprt = task->tk_xprt; - - task->tk_status = -EIO; - if (!xprt->shutdown) { - spin_lock(&xprt->xprt_lock); - do_xprt_reserve(task); - spin_unlock(&xprt->xprt_lock); - if (task->tk_rqstp) - del_timer_sync(&xprt->timer); - } -} - static inline void do_xprt_reserve(struct rpc_task *task) { @@ -1332,6 +1317,21 @@ do_xprt_reserve(struct rpc_task *task) rpc_sleep_on(&xprt->backlog, task, NULL, NULL); } +void +xprt_reserve(struct rpc_task *task) +{ + struct rpc_xprt *xprt = task->tk_xprt; + + task->tk_status = -EIO; + if (!xprt->shutdown) { + spin_lock(&xprt->xprt_lock); + do_xprt_reserve(task); + spin_unlock(&xprt->xprt_lock); + if (task->tk_rqstp) + del_timer_sync(&xprt->timer); + } +} + /* * Allocate a 'unique' XID */ |