: [IPV4/6]: Netfilter IPsec input hooks
Subsystems (8)
Hello.
In article <[email protected]> (at Tue, 22 Nov 2005 02:14:26 +0100), Patrick McHardy <[email protected]> says:
Quoted 3 lines
The easiest way would be to store nhoff somewhere in the skb and use it to continue at the next header. But I still hope there is a way without keeping data in the skb.
We've coded up this.
Though we have still another issue (call chain issue) to resolve, we're getting closer to the goal.
i.e. we should continue the loop for common case.
include/linux/skbuff.h +3 -0
@@ -272,6 +272,9 @@ struct sk_buff {void (*destructor)(struct sk_buff *skb);#ifdef CONFIG_NETFILTER __u32 nfmark; +#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE ) +unsigned int nf_nhoff; +#endif struct nf_conntrack *nfct;#if defined(CONFIG_NF_CONNTRACK ) || defined(CONFIG_NF_CONNTRACK_MODULE )struct sk_buff *nfct_reasm;
include/net/ipv6.h +2 -0
@@ -463,6 +463,8 @@ extern int ip6_dst_lookup(struct sockextern int ip6_output (struct sk_buff *skb);extern int ip6_forward (struct sk_buff *skb);extern int ip6_input (struct sk_buff *skb); +extern int ip6_input_finish2 (struct sk_buff *skb, +unsigned int nhoff);extern int ip6_mc_input (struct sk_buff *skb);/*
net/ipv6/ip6_input.c +22 -20
59 lines not on this page · raw message
net/ipv6/ipv6_syms.c +1 -0
@@ -15,6 +15,7 @@ EXPORT_SYMBOL(ndisc_mc_map);EXPORT_SYMBOL (register_inet6addr_notifier);EXPORT_SYMBOL (unregister_inet6addr_notifier);EXPORT_SYMBOL (ip6_route_output); +EXPORT_SYMBOL (ip6_input_finish2);EXPORT_SYMBOL (addrconf_lock);EXPORT_SYMBOL (ipv6_setsockopt);EXPORT_SYMBOL (ipv6_getsockopt);
net/ipv6/xfrm6_input.c +23 -1
@@ -9,6 +9,7 @@* IPv6 support */ +#include <linux/config.h> #include <linux/module.h> #include <linux/string.h> #include <linux/netfilter.h>
@@ -17,6 +18,7 @@#include <net/inet_ecn.h> #include <net/ip.h> #include <net/ipv6.h> +#include <net/ip6_route.h> #include <net/xfrm.h> static inline void ipip6_ecn_decapsulate (struct sk_buff *skb)
@@ -28,6 +30,25 @@ static inline void ipip6_ecn_decapsulateIP6_ECN_set_ce (inner_iph); } +#ifdef CONFIG_NETFILTER +static inline int xfrm6_rcv_spi_finish2 (struct sk_buff *skb) +{ +__skb_pull (skb, skb->h.raw - skb->nh.raw); +return ip6_input_finish2 (skb, skb->nf_nhoff); +} + +static inline int xfrm6_rcv_spi_finish (struct sk_buff *skb) +{ +if (skb->dst ==NULL ) { +ip6_route_input (skb); +return dst_input (skb); + } + +return NF_HOOK (PF_INET6 ,NF_IP6_LOCAL_IN , skb, skb->dev,NULL , + xfrm6_rcv_spi_finish2); +} +#endif +int xfrm6_rcv_spi (struct sk_buff **pskb,unsigned int *nhoffp,u32 spi) {struct sk_buff *skb = *pskb;
@@ -136,9 +157,10 @@ int xfrm6_rcv_spi(struct sk_buff **pskb,#ifdef CONFIG_NETFILTER skb->nh.ipv6h->payload_len =htons (skb->len);__skb_push (skb, skb->data - skb->nh.raw); + skb->nf_nhoff = nhoff;NF_HOOK (PF_INET6 ,NF_IP6_PRE_ROUTING , skb, skb->dev,NULL , - ip6_rcv_finish); + xfrm6_rcv_spi_finish);return -1 ;#else return 1 ;
Signature · 2 lines
YOSHIFUJI Hideaki @ USAGI Project <[email protected]> GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
Quoted 9 lines · YOSHIFUJI Hideaki / $B5HF#1QL@ wrote:
In article <[email protected]> (at Tue, 22 Nov 2005 02:14:26 +0100), Patrick McHardy <[email protected]> says:
Quoted 3 lines
The easiest way would be to store nhoff somewhere in the skb and use it to continue at the next header. But I still hope there is a way without keeping data in the skb.
We've coded up this.
How about this patch instead? It eliminates the nhoffp argument to IPv6 protocol handlers by storing it in the IP6CB, which allows to call ip6_input_finish a second time and have it skip already parsed headers and also gets rid of the manual hopopts skipping.
Quoted 3 lines
Though we have still another issue (call chain issue) to resolve, we're getting closer to the goal.
i.e. we should continue the loop for common case.
I'll look into this now.
[IPv6]: Move nextheader offset to the IP6CB
Move nextheader offset to the IP6CB to make it possible to pass a packet to ip6_input_finish multiple times and have it skip already parsed headers. As a nice side-effect this gets rid of the manual hopopts skipping.
---
commit 6678dcab480a4c410fe7984c43a9d1830c9b9912
tree 5eb3a8f6f5379c5f2b91af6d37dab9ca880681ae
parent 4cd76cb0703ffcb89d6c49e4d9171d7b6a116cd9
author Patrick McHardy <[email protected]> Sun, 18 Dec 2005 06:52:02 +0100 committer Patrick McHardy <[email protected]> Sun, 18 Dec 2005 06:52:02 +0100
include/linux/ipv6.h | 1 + include/net/protocol.h | 2 +- include/net/xfrm.h | 6 +++--- net/dccp/ipv6.c | 2 +- net/ipv6/exthdrs.c | 19 ++++++++++++------- net/ipv6/icmp.c | 4 ++-- net/ipv6/ip6_input.c | 21 ++++++--------------- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/reassembly.c | 11 +++++------ net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/udp.c | 2 +- net/ipv6/xfrm6_input.c | 8 ++++---- net/ipv6/xfrm6_tunnel.c | 6 +++--- net/sctp/ipv6.c | 2 +- 14 files changed, 42 insertions(+), 46 deletions(-)
include/linux/ipv6.h +1 -0
@@ -190,6 +190,7 @@ struct inet6_skb_parm {__u16 srcrt;__u16 dst1;__u16 lastopt; +__u32 nhoff; };#define IP6CB (skb) ((struct inet6_skb_parm*)((skb)->cb))
include/net/protocol.h +1 -1
@@ -43,7 +43,7 @@ struct net_protocol { #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_protocol { - int (*handler)(struct sk_buff **skb, unsigned int *nhoffp); + int (*handler)(struct sk_buff **skb); void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
include/net/xfrm.h +3 -3
@@ -830,7 +830,7 @@ struct xfrm_tunnel { };struct xfrm6_tunnel { -int (*handler)(struct sk_buff **pskb,unsigned int *nhoffp); +int (*handler)(struct sk_buff **pskb);void (*err_handler)(struct sk_buff *skb,struct inet6_skb_parm *opt,int type,int code,int offset,__u32 info); };
@@ -867,8 +867,8 @@ extern int xfrm4_rcv(struct sk_buff *skbextern int xfrm4_output (struct sk_buff *skb);extern int xfrm4_tunnel_register (struct xfrm_tunnel *handler);extern int xfrm4_tunnel_deregister (struct xfrm_tunnel *handler); -extern int xfrm6_rcv_spi (struct sk_buff **pskb,unsigned int *nhoffp,u32 spi); -extern int xfrm6_rcv (struct sk_buff **pskb,unsigned int *nhoffp); +extern int xfrm6_rcv_spi (struct sk_buff **pskb,u32 spi); +extern int xfrm6_rcv (struct sk_buff **pskb);extern int xfrm6_tunnel_register (struct xfrm6_tunnel *handler);extern int xfrm6_tunnel_deregister (struct xfrm6_tunnel *handler);extern u32 xfrm6_tunnel_alloc_spi (xfrm_address_t *saddr);
net/dccp/ipv6.c +1 -1
@@ -1027,7 +1027,7 @@ discard:return 0 ; } -static int dccp_v6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +static int dccp_v6_rcv (struct sk_buff **pskb) {const struct dccp_hdr *dh;struct sk_buff *skb = *pskb;
net/ipv6/exthdrs.c +12 -7
@@ -152,7 +152,7 @@ static struct tlvtype_proc tlvprocdestop {-1, NULL} }; -static int ipv6_destopt_rcv (struct sk_buff **skbp,unsigned int *nhoffp) +static int ipv6_destopt_rcv (struct sk_buff **skbp) {struct sk_buff *skb = *skbp;struct inet6_skb_parm *opt =IP6CB (skb);
@@ -169,7 +169,7 @@ static int ipv6_destopt_rcv(struct sk_buif (ip6_parse_tlv (tlvprocdestopt_lst, skb)) { skb->h.raw += ((skb->h.raw[1 ]+1 )<<3 ); - *nhoffp = opt->dst1; + opt->nhoff = opt->dst1;return 1 ; }
@@ -192,7 +192,7 @@ void __init ipv6_destopt_init(void)NONE header. No data in packet. ********************************/ -static int ipv6_nodata_rcv (struct sk_buff **skbp,unsigned int *nhoffp) +static int ipv6_nodata_rcv (struct sk_buff **skbp) {struct sk_buff *skb = *skbp;
@@ -215,7 +215,7 @@ void __init ipv6_nodata_init(void)Routing header. ********************************/ -static int ipv6_rthdr_rcv (struct sk_buff **skbp,unsigned int *nhoffp) +static int ipv6_rthdr_rcv (struct sk_buff **skbp) {struct sk_buff *skb = *skbp;struct inet6_skb_parm *opt =IP6CB (skb);
@@ -249,7 +249,7 @@ looped_back: skb->h.raw += (hdr->hdrlen +1 ) <<3 ; opt->dst0 = opt->dst1; opt->dst1 =0 ; - *nhoffp = (&hdr->nexthdr) - skb->nh.raw; + opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;return 1 ; }
@@ -487,9 +487,14 @@ static struct tlvtype_proc tlvprochopoptint ipv6_parse_hopopts (struct sk_buff *skb,int nhoff) { -IP6CB (skb)->hop =sizeof (struct ipv6hdr ); -if (ip6_parse_tlv (tlvprochopopt_lst, skb)) +struct inet6_skb_parm *opt =IP6CB (skb); + + opt->hop =sizeof (struct ipv6hdr ); +if (ip6_parse_tlv (tlvprochopopt_lst, skb)) { + skb->h.raw += (skb->h.raw[1 ]+1 )<<3 ; + opt->nhoff =sizeof (struct ipv6hdr );return sizeof (struct ipv6hdr ); + }return -1 ; }
net/ipv6/icmp.c +2 -2
@@ -79,7 +79,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmp static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;#define icmpv6_socket __get_cpu_var(__icmpv6_socket) -static int icmpv6_rcv (struct sk_buff **pskb,unsigned int *nhoffp); +static int icmpv6_rcv (struct sk_buff **pskb);static struct inet6_protocol icmpv6_protocol = { .handler = icmpv6_rcv,
@@ -569,7 +569,7 @@ static void icmpv6_notify(struct sk_buff* Handle icmp messages */ -static int icmpv6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +static int icmpv6_rcv (struct sk_buff **pskb) {struct sk_buff *skb = *pskb;struct net_device *dev = skb->dev;
net/ipv6/ip6_input.c +6 -15
@@ -97,6 +97,9 @@ int ipv6_rcv(struct sk_buff *skb, structif (hdr->version !=6 ) goto err; + skb->h.raw = (u8 *)(hdr +1 ); +IP6CB (skb)->nhoff = offsetof(struct ipv6hdr , nexthdr); + pkt_len =ntohs (hdr->payload_len);/* pkt_len may be zero if Jumbo payload option is present */
@@ -111,8 +114,7 @@ int ipv6_rcv(struct sk_buff *skb, struct }if (hdr->nexthdr ==NEXTHDR_HOP ) { - skb->h.raw = (u8 *)(hdr+1 ); -if (ipv6_parse_hopopts (skb, offsetof(struct ipv6hdr , nexthdr)) <0 ) { +if (ipv6_parse_hopopts (skb,IP6CB (skb)->nhoff) <0 ) {IP6_INC_STATS_BH (IPSTATS_MIB_INHDRERRORS );return 0 ; }
@@ -143,26 +145,15 @@ static inline int ip6_input_finish(strucint nexthdr;u8 hash; - skb->h.raw = skb->nh.raw +sizeof (struct ipv6hdr ); -/* * Parse extension headers */ - nexthdr = skb->nh.ipv6h->nexthdr; - nhoff = offsetof(struct ipv6hdr , nexthdr); - -/* Skip hop-by-hop options, they are already parsed. */ -if (nexthdr ==NEXTHDR_HOP ) { - nhoff =sizeof (struct ipv6hdr ); - nexthdr = skb->h.raw[0 ]; - skb->h.raw += (skb->h.raw[1 ]+1 )<<3 ; - } -rcu_read_lock (); resubmit:if (!pskb_pull (skb, skb->h.raw - skb->data)) goto discard; + nhoff =IP6CB (skb)->nhoff; nexthdr = skb->nh.raw[nhoff]; raw_sk =sk_head (&raw_v6_htable[nexthdr & (MAX_INET_PROTOS -1 )]);
@@ -194,7 +185,7 @@ resubmit: !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) goto discard; - ret = ipprot->handler (&skb, &nhoff); + ret = ipprot->handler (&skb);if (ret >0 ) goto resubmit;else if (ret ==0 )
net/ipv6/ip6_tunnel.c +1 -1
@@ -510,7 +510,7 @@ static inline void ip6ip6_ecn_decapsulat**/ static int -ip6ip6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +ip6ip6_rcv (struct sk_buff **pskb) {struct sk_buff *skb = *pskb;struct ipv6hdr *ipv6h;
net/ipv6/reassembly.c +5 -6
@@ -581,7 +581,6 @@ err:* the last and the first frames arrived and all the bits are here. */ static int ip6_frag_reasm (struct frag_queue *fq,struct sk_buff **skb_in, -unsigned int *nhoffp,struct net_device *dev) {struct sk_buff *fp, *head = fq->fragments;
@@ -654,6 +653,7 @@ static int ip6_frag_reasm(struct frag_qu head->dev = dev;skb_set_timestamp (head, &fq->stamp); head->nh.ipv6h->payload_len =htons (payload_len); +IP6CB (head)->nhoff = nhoff; *skb_in = head;
@@ -663,7 +663,6 @@ static int ip6_frag_reasm(struct frag_quIP6_INC_STATS_BH (IPSTATS_MIB_REASMOKS ); fq->fragments =NULL ; - *nhoffp = nhoff;return 1 ; out_oversize:
@@ -678,7 +677,7 @@ out_fail:return -1 ; } -static int ipv6_frag_rcv (struct sk_buff **skbp,unsigned int *nhoffp) +static int ipv6_frag_rcv (struct sk_buff **skbp) {struct sk_buff *skb = *skbp;struct net_device *dev = skb->dev;
@@ -710,7 +709,7 @@ static int ipv6_frag_rcv(struct sk_buff skb->h.raw +=sizeof (struct frag_hdr );IP6_INC_STATS_BH (IPSTATS_MIB_REASMOKS ); - *nhoffp = (u8 *)fhdr - skb->nh.raw; +IP6CB (skb)->nhoff = (u8 *)fhdr - skb->nh.raw;return 1 ; }
@@ -722,11 +721,11 @@ static int ipv6_frag_rcv(struct sk_buffspin_lock (&fq->lock); -ip6_frag_queue (fq, skb, fhdr, *nhoffp); +ip6_frag_queue (fq, skb, fhdr,IP6CB (skb)->nhoff);if (fq->last_in == (FIRST_IN |LAST_IN ) && fq->meat == fq->len) - ret =ip6_frag_reasm (fq, skbp, nhoffp, dev); + ret =ip6_frag_reasm (fq, skbp, dev);spin_unlock (&fq->lock);fq_put (fq,NULL );
net/ipv6/tcp_ipv6.c +1 -1
@@ -1153,7 +1153,7 @@ ipv6_pktoptions:return 0 ; } -static int tcp_v6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +static int tcp_v6_rcv (struct sk_buff **pskb) {struct sk_buff *skb = *pskb;struct tcphdr *th;
net/ipv6/udp.c +1 -1
@@ -435,7 +435,7 @@ out:read_unlock (&udp_hash_lock); } -static int udpv6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +static int udpv6_rcv (struct sk_buff **pskb) {struct sk_buff *skb = *pskb;struct sock *sk;
net/ipv6/xfrm6_input.c +4 -4
@@ -26,7 +26,7 @@ static inline void ipip6_ecn_decapsulateIP6_ECN_set_ce (inner_iph); } -int xfrm6_rcv_spi (struct sk_buff **pskb,unsigned int *nhoffp,u32 spi) +int xfrm6_rcv_spi (struct sk_buff **pskb,u32 spi) {struct sk_buff *skb = *pskb;int err;
@@ -38,7 +38,7 @@ int xfrm6_rcv_spi(struct sk_buff **pskb,int nexthdr;unsigned int nhoff; - nhoff = *nhoffp; + nhoff =IP6CB (skb)->nhoff; nexthdr = skb->nh.raw[nhoff]; seq =0 ;
@@ -144,7 +144,7 @@ drop:EXPORT_SYMBOL (xfrm6_rcv_spi); -int xfrm6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +int xfrm6_rcv (struct sk_buff **pskb) { -return xfrm6_rcv_spi (pskb, nhoffp,0 ); +return xfrm6_rcv_spi (pskb,0 ); }
net/ipv6/xfrm6_tunnel.c +3 -3
@@ -397,7 +397,7 @@ int xfrm6_tunnel_deregister(struct xfrm6EXPORT_SYMBOL (xfrm6_tunnel_deregister); -static int xfrm6_tunnel_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +static int xfrm6_tunnel_rcv (struct sk_buff **pskb) {struct sk_buff *skb = *pskb;struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
@@ -405,11 +405,11 @@ static int xfrm6_tunnel_rcv(struct sk_buu32 spi;/* device-like_ip6ip6_handler() */ -if (handler && handler->handler (pskb, nhoffp) ==0 ) +if (handler && handler->handler (pskb) ==0 )return 0 ; spi =xfrm6_tunnel_spi_lookup ((xfrm_address_t *)&iph->saddr); -return xfrm6_rcv_spi (pskb, nhoffp, spi); +return xfrm6_rcv_spi (pskb, spi); } static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
net/sctp/ipv6.c +1 -1
@@ -905,7 +905,7 @@ static struct inet_protosw sctpv6_stream .flags = SCTP_PROTOSW_FLAG, }; -static int sctp6_rcv (struct sk_buff **pskb,unsigned int *nhoffp) +static int sctp6_rcv (struct sk_buff **pskb) {return sctp_rcv (*pskb) ?-1 :0 ; }
In article <[email protected]> (at Sun, 18 Dec 2005 15:27:01 +0100), Patrick McHardy <[email protected]> says:
Quoted 9 lines
Quoted 8 lines · YOSHIFUJI Hideaki
In article <[email protected]> (at Tue, 22 Nov 2005 02:14:26 +0100), Patrick McHardy <[email protected]> says:
Quoted 3 lines
The easiest way would be to store nhoff somewhere in the skb and use it to continue at the next header. But I still hope there is a way without keeping data in the skb.
Quoted 6 lines
Quoted 1 line
We've coded up this.
How about this patch instead? It eliminates the nhoffp argument to IPv6 protocol handlers by storing it in the IP6CB, which allows to call
ip6_input_finisha second time and have it skip already parsed headers and also gets rid of the manual hopopts skipping.
The idea to store IP6CB itself seems sane to me.
BTW, we're now using full of skb->cb
(and we are even exceeding it w/ mobile-ipv6 extensions)...
--yoshfuji
Quoted 8 lines · YOSHIFUJI Hideaki / $B5HF#1QL@ wrote:
In article <[email protected]> (at Sun, 18 Dec 2005 15:27:01 +0100), Patrick McHardy <[email protected]> says:
Quoted 4 lines
How about this patch instead? It eliminates the nhoffp argument to IPv6 protocol handlers by storing it in the IP6CB, which allows to call
ip6_input_finisha second time and have it skip already parsed headers and also gets rid of the manual hopopts skipping.
Quoted 4 lines
The idea to store IP6CB itself seems sane to me.
BTW, we're now using full of
skb->cb
(and we are even exceeding it w/ mobile-ipv6 extensions)...
Not in mainline so far, so maybe we can fit your extensions and my patches without the mobile extensions, that apparently exceed the CB anyway, in there for now. Can I look at those patches somewhere? BTW, other fields in the IP6CB seem to store offsets in u16 fields, is this OK for nhoff too? I thought with jumbo options I need to use a u32 field.
In article <[email protected]> (at Sun, 18 Dec 2005 23:59:35 +0100), Patrick McHardy <[email protected]> says:
Quoted 1 line
YOSHIFUJI Hideaki wrote:
:
Quoted 9 lines
Quoted 2 lines
BTW, we're now using full of
skb->cb
(and we are even exceeding it w/ mobile-ipv6 extensions)...Not in mainline so far, so maybe we can fit your extensions and my patches without the mobile extensions, that apparently exceed the CB anyway, in there for now. Can I look at those patches somewhere? BTW, other fields in the IP6CB seem to store offsets in u16 fields, is this OK for nhoff too? I thought with jumbo options I need to use a u32 field.
Well, don't mind too much.
I just wanted to note that we're about to exceed skb->cb. I will probably enlarge skb->cb if needed.
And, yes, good point.
I think nhoff should be u32 because it is critical. In theory, u32 is definitely needed for others as well...
--yoshfuji