* IPv6 support
*/
+#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/xfrm.h>
-static kmem_cache_t *secpath_cachep;
+static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph,
+ struct sk_buff *skb)
+{
+ if (INET_ECN_is_ce(ip6_get_dsfield(iph)) &&
+ INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+ IP6_ECN_set_ce(skb->nh.ipv6h);
+}
int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{
if (nexthdr != IPPROTO_IPV6)
goto drop;
skb->nh.raw = skb->data;
+ if (!(x->props.flags & XFRM_STATE_NOECN))
+ ipip6_ecn_decapsulate(iph, skb);
iph = skb->nh.ipv6h;
decaps = 1;
break;
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
- kmem_cache_t *pool = skb->sp ? skb->sp->pool : secpath_cachep;
struct sec_path *sp;
- sp = kmem_cache_alloc(pool, SLAB_ATOMIC);
+ sp = secpath_dup(skb->sp);
if (!sp)
goto drop;
- if (skb->sp) {
- memcpy(sp, skb->sp, sizeof(struct sec_path));
+ if (skb->sp)
secpath_put(skb->sp);
- } else {
- sp->pool = pool;
- sp->len = 0;
- }
- atomic_set(&sp->refcnt, 1);
skb->sp = sp;
}
kfree_skb(skb);
return -1;
}
-
-void __init xfrm6_input_init(void)
-{
- secpath_cachep = kmem_cache_create("secpath6_cache",
- sizeof(struct sec_path),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
- if (!secpath_cachep)
- panic("IPv6: failed to allocate secpath6_cache\n");
-}
-