X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fipvs%2Fip_vs_proto_tcp.c;h=16a9ebee2fe67f28708fc1ece8cb15a77b04ccda;hb=refs%2Fheads%2Fvserver;hp=46c346e807211876640cc337ae2b0e8b6e14a079;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c index 46c346e80..16a9ebee2 100644 --- a/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -29,19 +29,20 @@ static struct ip_vs_conn * tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, const struct iphdr *iph, unsigned int proto_off, int inverse) { - __u16 ports[2]; + __be16 _ports[2], *pptr; - if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0) + pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); + if (pptr == NULL) return NULL; if (likely(!inverse)) { return ip_vs_conn_in_get(iph->protocol, - iph->saddr, ports[0], - iph->daddr, ports[1]); + iph->saddr, pptr[0], + iph->daddr, pptr[1]); } else { return ip_vs_conn_in_get(iph->protocol, - iph->daddr, ports[1], - iph->saddr, ports[0]); + iph->daddr, pptr[1], + iph->saddr, pptr[0]); } } @@ -49,19 +50,20 @@ static struct ip_vs_conn * tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, const struct iphdr *iph, unsigned int proto_off, int inverse) { - __u16 ports[2]; + __be16 _ports[2], *pptr; - if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0) + pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); + if (pptr == NULL) return NULL; if (likely(!inverse)) { return ip_vs_conn_out_get(iph->protocol, - iph->saddr, ports[0], - iph->daddr, ports[1]); + iph->saddr, pptr[0], + iph->daddr, pptr[1]); } else { return ip_vs_conn_out_get(iph->protocol, - iph->daddr, ports[1], - iph->saddr, ports[0]); + iph->daddr, pptr[1], + iph->saddr, pptr[0]); } } @@ -72,16 +74,18 @@ tcp_conn_schedule(struct sk_buff *skb, int *verdict, struct ip_vs_conn **cpp) { struct ip_vs_service *svc; - struct tcphdr tcph; + struct tcphdr _tcph, *th; - if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) { + th = skb_header_pointer(skb, skb->nh.iph->ihl*4, + sizeof(_tcph), &_tcph); + if (th == NULL) { *verdict = NF_DROP; return 0; } - if (tcph.syn && - (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, - skb->nh.iph->daddr, tcph.dest))) { + if (th->syn && + (svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol, + skb->nh.iph->daddr, th->dest))) { if (ip_vs_todrop()) { /* * It seems that we are very loaded. @@ -108,13 +112,13 @@ tcp_conn_schedule(struct sk_buff *skb, static inline void -tcp_fast_csum_update(struct tcphdr *tcph, u32 oldip, u32 newip, - u16 oldport, u16 newport) +tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip, + __be16 oldport, __be16 newport) { tcph->check = - ip_vs_check_diff(~oldip, newip, - ip_vs_check_diff(oldport ^ 0xFFFF, - newport, tcph->check)); + csum_fold(ip_vs_check_diff4(oldip, newip, + ip_vs_check_diff2(oldport, newport, + ~csum_unfold(tcph->check)))); } @@ -147,7 +151,7 @@ tcp_snat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr, cp->dport, cp->vport); - if ((*pskb)->ip_summed == CHECKSUM_HW) + if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) (*pskb)->ip_summed = CHECKSUM_NONE; } else { /* full checksum calculation */ @@ -158,7 +162,7 @@ tcp_snat_handler(struct sk_buff **pskb, (*pskb)->len - tcphoff, cp->protocol, (*pskb)->csum); - IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%d)\n", + IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", pp->name, tcph->check, (char*)&(tcph->check) - (char*)tcph); } @@ -200,7 +204,7 @@ tcp_dnat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr, cp->vport, cp->dport); - if ((*pskb)->ip_summed == CHECKSUM_HW) + if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) (*pskb)->ip_summed = CHECKSUM_NONE; } else { /* full checksum calculation */ @@ -225,7 +229,7 @@ tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) switch (skb->ip_summed) { case CHECKSUM_NONE: skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); - case CHECKSUM_HW: + case CHECKSUM_COMPLETE: if (csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, skb->len - tcphoff, skb->nh.iph->protocol, skb->csum)) { @@ -235,7 +239,7 @@ tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) } break; default: - /* CHECKSUM_UNNECESSARY */ + /* No need to checksum. */ break; } @@ -247,7 +251,7 @@ tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) #define TCP_DIR_OUTPUT 4 #define TCP_DIR_INPUT_ONLY 8 -static int tcp_state_off[IP_VS_DIR_LAST] = { +static const int tcp_state_off[IP_VS_DIR_LAST] = { [IP_VS_DIR_INPUT] = TCP_DIR_INPUT, [IP_VS_DIR_OUTPUT] = TCP_DIR_OUTPUT, [IP_VS_DIR_INPUT_ONLY] = TCP_DIR_INPUT_ONLY, @@ -271,28 +275,6 @@ static int tcp_timeouts[IP_VS_TCP_S_LAST+1] = { [IP_VS_TCP_S_LAST] = 2*HZ, }; - -#if 0 - -/* FIXME: This is going to die */ - -static int tcp_timeouts_dos[IP_VS_TCP_S_LAST+1] = { - [IP_VS_TCP_S_NONE] = 2*HZ, - [IP_VS_TCP_S_ESTABLISHED] = 8*60*HZ, - [IP_VS_TCP_S_SYN_SENT] = 60*HZ, - [IP_VS_TCP_S_SYN_RECV] = 10*HZ, - [IP_VS_TCP_S_FIN_WAIT] = 60*HZ, - [IP_VS_TCP_S_TIME_WAIT] = 60*HZ, - [IP_VS_TCP_S_CLOSE] = 10*HZ, - [IP_VS_TCP_S_CLOSE_WAIT] = 60*HZ, - [IP_VS_TCP_S_LAST_ACK] = 30*HZ, - [IP_VS_TCP_S_LISTEN] = 2*60*HZ, - [IP_VS_TCP_S_SYNACK] = 100*HZ, - [IP_VS_TCP_S_LAST] = 2*HZ, -}; - -#endif - static char * tcp_state_name_table[IP_VS_TCP_S_LAST+1] = { [IP_VS_TCP_S_NONE] = "NONE", [IP_VS_TCP_S_ESTABLISHED] = "ESTABLISHED", @@ -444,7 +426,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, struct ip_vs_dest *dest = cp->dest; IP_VS_DBG(8, "%s %s [%c%c%c%c] %u.%u.%u.%u:%d->" - "%u.%u.%u.%u:%d state: %s->%s cnt:%d\n", + "%u.%u.%u.%u:%d state: %s->%s conn->refcnt:%d\n", pp->name, (state_off==TCP_DIR_OUTPUT)?"output ":"input ", th->syn? 'S' : '.', @@ -483,13 +465,15 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction, const struct sk_buff *skb, struct ip_vs_protocol *pp) { - struct tcphdr tcph; + struct tcphdr _tcph, *th; - if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) + th = skb_header_pointer(skb, skb->nh.iph->ihl*4, + sizeof(_tcph), &_tcph); + if (th == NULL) return 0; spin_lock(&cp->lock); - set_tcp_state(pp, cp, direction, &tcph); + set_tcp_state(pp, cp, direction, th); spin_unlock(&cp->lock); return 1; @@ -504,18 +488,20 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction, #define TCP_APP_TAB_MASK (TCP_APP_TAB_SIZE - 1) static struct list_head tcp_apps[TCP_APP_TAB_SIZE]; -static spinlock_t tcp_app_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(tcp_app_lock); -static inline __u16 tcp_app_hashkey(__u16 port) +static inline __u16 tcp_app_hashkey(__be16 port) { - return ((port >> TCP_APP_TAB_BITS) ^ port) & TCP_APP_TAB_MASK; + return (((__force u16)port >> TCP_APP_TAB_BITS) ^ (__force u16)port) + & TCP_APP_TAB_MASK; } static int tcp_register_app(struct ip_vs_app *inc) { struct ip_vs_app *i; - __u16 hash, port = inc->port; + __u16 hash; + __be16 port = inc->port; int ret = 0; hash = tcp_app_hashkey(port); @@ -598,14 +584,14 @@ void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp) } -static void tcp_init(struct ip_vs_protocol *pp) +static void ip_vs_tcp_init(struct ip_vs_protocol *pp) { IP_VS_INIT_HASH_TABLE(tcp_apps); pp->timeout_table = tcp_timeouts; } -static void tcp_exit(struct ip_vs_protocol *pp) +static void ip_vs_tcp_exit(struct ip_vs_protocol *pp) { } @@ -615,8 +601,8 @@ struct ip_vs_protocol ip_vs_protocol_tcp = { .protocol = IPPROTO_TCP, .dont_defrag = 0, .appcnt = ATOMIC_INIT(0), - .init = tcp_init, - .exit = tcp_exit, + .init = ip_vs_tcp_init, + .exit = ip_vs_tcp_exit, .register_app = tcp_register_app, .unregister_app = tcp_unregister_app, .conn_schedule = tcp_conn_schedule,