X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fipvs%2Fip_vs_proto_udp.c;h=03f0a414cfa406bce2505c269d6a9b1d24a5bed5;hb=refs%2Fheads%2Fvserver;hp=740d8d92c2fcbaf276649c0e0e89ac1d3eefdb23;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c index 740d8d92c..03f0a414c 100644 --- a/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -15,8 +15,11 @@ * */ +#include +#include #include #include +#include #include @@ -26,19 +29,20 @@ udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, const struct iphdr *iph, unsigned int proto_off, int inverse) { struct ip_vs_conn *cp; - __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)) { cp = ip_vs_conn_in_get(iph->protocol, - iph->saddr, ports[0], - iph->daddr, ports[1]); + iph->saddr, pptr[0], + iph->daddr, pptr[1]); } else { cp = ip_vs_conn_in_get(iph->protocol, - iph->daddr, ports[1], - iph->saddr, ports[0]); + iph->daddr, pptr[1], + iph->saddr, pptr[0]); } return cp; @@ -50,19 +54,21 @@ udp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, const struct iphdr *iph, unsigned int proto_off, int inverse) { struct ip_vs_conn *cp; - __u16 ports[2]; + __be16 _ports[2], *pptr; - if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) + pptr = skb_header_pointer(skb, skb->nh.iph->ihl*4, + sizeof(_ports), _ports); + if (pptr == NULL) return NULL; if (likely(!inverse)) { cp = ip_vs_conn_out_get(iph->protocol, - iph->saddr, ports[0], - iph->daddr, ports[1]); + iph->saddr, pptr[0], + iph->daddr, pptr[1]); } else { cp = ip_vs_conn_out_get(iph->protocol, - iph->daddr, ports[1], - iph->saddr, ports[0]); + iph->daddr, pptr[1], + iph->saddr, pptr[0]); } return cp; @@ -74,15 +80,17 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, int *verdict, struct ip_vs_conn **cpp) { struct ip_vs_service *svc; - struct udphdr udph; + struct udphdr _udph, *uh; - if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) { + uh = skb_header_pointer(skb, skb->nh.iph->ihl*4, + sizeof(_udph), &_udph); + if (uh == NULL) { *verdict = NF_DROP; return 0; } - if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, - skb->nh.iph->daddr, udph.dest))) { + if ((svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol, + skb->nh.iph->daddr, uh->dest))) { if (ip_vs_todrop()) { /* * It seems that we are very loaded. @@ -109,15 +117,15 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, static inline void -udp_fast_csum_update(struct udphdr *uhdr, u32 oldip, u32 newip, - u16 oldport, u16 newport) +udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip, + __be16 oldport, __be16 newport) { uhdr->check = - ip_vs_check_diff(~oldip, newip, - ip_vs_check_diff(oldport ^ 0xFFFF, - newport, uhdr->check)); + csum_fold(ip_vs_check_diff4(oldip, newip, + ip_vs_check_diff2(oldport, newport, + ~csum_unfold(uhdr->check)))); if (!uhdr->check) - uhdr->check = 0xFFFF; + uhdr->check = CSUM_MANGLED_0; } static int @@ -153,7 +161,7 @@ udp_snat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ udp_fast_csum_update(udph, 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 */ @@ -165,8 +173,8 @@ udp_snat_handler(struct sk_buff **pskb, cp->protocol, (*pskb)->csum); if (udph->check == 0) - udph->check = 0xFFFF; - IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%d)\n", + udph->check = CSUM_MANGLED_0; + IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", pp->name, udph->check, (char*)&(udph->check) - (char*)udph); } @@ -208,7 +216,7 @@ udp_dnat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ udp_fast_csum_update(udph, 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 */ @@ -220,7 +228,7 @@ udp_dnat_handler(struct sk_buff **pskb, cp->protocol, (*pskb)->csum); if (udph->check == 0) - udph->check = 0xFFFF; + udph->check = CSUM_MANGLED_0; (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; } return 1; @@ -230,18 +238,19 @@ udp_dnat_handler(struct sk_buff **pskb, static int udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) { - struct udphdr udph; + struct udphdr _udph, *uh; unsigned int udphoff = skb->nh.iph->ihl*4; - if (skb_copy_bits(skb, udphoff, &udph, sizeof(udph)) < 0) + uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph); + if (uh == NULL) return 0; - if (udph.check != 0) { + if (uh->check != 0) { switch (skb->ip_summed) { case CHECKSUM_NONE: skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); - case CHECKSUM_HW: + case CHECKSUM_COMPLETE: if (csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, skb->len - udphoff, @@ -253,7 +262,7 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) } break; default: - /* CHECKSUM_UNNECESSARY */ + /* No need to checksum. */ break; } } @@ -271,18 +280,20 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) #define UDP_APP_TAB_MASK (UDP_APP_TAB_SIZE - 1) static struct list_head udp_apps[UDP_APP_TAB_SIZE]; -static spinlock_t udp_app_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(udp_app_lock); -static inline __u16 udp_app_hashkey(__u16 port) +static inline __u16 udp_app_hashkey(__be16 port) { - return ((port >> UDP_APP_TAB_BITS) ^ port) & UDP_APP_TAB_MASK; + return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port) + & UDP_APP_TAB_MASK; } static int udp_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 = udp_app_hashkey(port);