aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipvs
diff options
context:
space:
mode:
authorJulius Volz <juliusv@google.com>2008-09-02 09:55:37 -0400
committerSimon Horman <horms@verge.net.au>2008-09-04 21:17:05 -0400
commitb18610de9ec2728159f723a9b864ca78a5774193 (patch)
tree0e433de080cd5bbfc0d2c24c5d80c5904d2b238c /net/ipv4/ipvs
parentc860c6b1479992440e4962e9c95d258bfdce4fca (diff)
IPVS: Convert __ip_vs_svc_get() and __ip_vs_fwm_get()
Add support for getting services based on their address family to __ip_vs_service_get(), __ip_vs_fwm_get() and the helper hash function ip_vs_svc_hashkey(). Adjust the callers. Signed-off-by: Julius Volz <juliusv@google.com> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net/ipv4/ipvs')
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c79
1 files changed, 47 insertions, 32 deletions
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index a0c8b7bb5530..a2d69b2ce6a1 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -282,11 +282,19 @@ static atomic_t ip_vs_nullsvc_counter = ATOMIC_INIT(0);
282 * Returns hash value for virtual service 282 * Returns hash value for virtual service
283 */ 283 */
284static __inline__ unsigned 284static __inline__ unsigned
285ip_vs_svc_hashkey(unsigned proto, __be32 addr, __be16 port) 285ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
286 __be16 port)
286{ 287{
287 register unsigned porth = ntohs(port); 288 register unsigned porth = ntohs(port);
289 __be32 addr_fold = addr->ip;
288 290
289 return (proto^ntohl(addr)^(porth>>IP_VS_SVC_TAB_BITS)^porth) 291#ifdef CONFIG_IP_VS_IPV6
292 if (af == AF_INET6)
293 addr_fold = addr->ip6[0]^addr->ip6[1]^
294 addr->ip6[2]^addr->ip6[3];
295#endif
296
297 return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth)
290 & IP_VS_SVC_TAB_MASK; 298 & IP_VS_SVC_TAB_MASK;
291} 299}
292 300
@@ -317,7 +325,7 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
317 /* 325 /*
318 * Hash it by <protocol,addr,port> in ip_vs_svc_table 326 * Hash it by <protocol,addr,port> in ip_vs_svc_table
319 */ 327 */
320 hash = ip_vs_svc_hashkey(svc->protocol, svc->addr.ip, 328 hash = ip_vs_svc_hashkey(svc->af, svc->protocol, &svc->addr,
321 svc->port); 329 svc->port);
322 list_add(&svc->s_list, &ip_vs_svc_table[hash]); 330 list_add(&svc->s_list, &ip_vs_svc_table[hash]);
323 } else { 331 } else {
@@ -364,17 +372,19 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
364/* 372/*
365 * Get service by {proto,addr,port} in the service table. 373 * Get service by {proto,addr,port} in the service table.
366 */ 374 */
367static __inline__ struct ip_vs_service * 375static inline struct ip_vs_service *
368__ip_vs_service_get(__u16 protocol, __be32 vaddr, __be16 vport) 376__ip_vs_service_get(int af, __u16 protocol, const union nf_inet_addr *vaddr,
377 __be16 vport)
369{ 378{
370 unsigned hash; 379 unsigned hash;
371 struct ip_vs_service *svc; 380 struct ip_vs_service *svc;
372 381
373 /* Check for "full" addressed entries */ 382 /* Check for "full" addressed entries */
374 hash = ip_vs_svc_hashkey(protocol, vaddr, vport); 383 hash = ip_vs_svc_hashkey(af, protocol, vaddr, vport);
375 384
376 list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){ 385 list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){
377 if ((svc->addr.ip == vaddr) 386 if ((svc->af == af)
387 && ip_vs_addr_equal(af, &svc->addr, vaddr)
378 && (svc->port == vport) 388 && (svc->port == vport)
379 && (svc->protocol == protocol)) { 389 && (svc->protocol == protocol)) {
380 /* HIT */ 390 /* HIT */
@@ -390,7 +400,8 @@ __ip_vs_service_get(__u16 protocol, __be32 vaddr, __be16 vport)
390/* 400/*
391 * Get service by {fwmark} in the service table. 401 * Get service by {fwmark} in the service table.
392 */ 402 */
393static __inline__ struct ip_vs_service *__ip_vs_svc_fwm_get(__u32 fwmark) 403static inline struct ip_vs_service *
404__ip_vs_svc_fwm_get(int af, __u32 fwmark)
394{ 405{
395 unsigned hash; 406 unsigned hash;
396 struct ip_vs_service *svc; 407 struct ip_vs_service *svc;
@@ -399,7 +410,7 @@ static __inline__ struct ip_vs_service *__ip_vs_svc_fwm_get(__u32 fwmark)
399 hash = ip_vs_svc_fwm_hashkey(fwmark); 410 hash = ip_vs_svc_fwm_hashkey(fwmark);
400 411
401 list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) { 412 list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) {
402 if (svc->fwmark == fwmark) { 413 if (svc->fwmark == fwmark && svc->af == af) {
403 /* HIT */ 414 /* HIT */
404 atomic_inc(&svc->usecnt); 415 atomic_inc(&svc->usecnt);
405 return svc; 416 return svc;
@@ -413,20 +424,20 @@ struct ip_vs_service *
413ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport) 424ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
414{ 425{
415 struct ip_vs_service *svc; 426 struct ip_vs_service *svc;
416 427 union nf_inet_addr _vaddr = { .ip = vaddr };
417 read_lock(&__ip_vs_svc_lock); 428 read_lock(&__ip_vs_svc_lock);
418 429
419 /* 430 /*
420 * Check the table hashed by fwmark first 431 * Check the table hashed by fwmark first
421 */ 432 */
422 if (fwmark && (svc = __ip_vs_svc_fwm_get(fwmark))) 433 if (fwmark && (svc = __ip_vs_svc_fwm_get(AF_INET, fwmark)))
423 goto out; 434 goto out;
424 435
425 /* 436 /*
426 * Check the table hashed by <protocol,addr,port> 437 * Check the table hashed by <protocol,addr,port>
427 * for "full" addressed entries 438 * for "full" addressed entries
428 */ 439 */
429 svc = __ip_vs_service_get(protocol, vaddr, vport); 440 svc = __ip_vs_service_get(AF_INET, protocol, &_vaddr, vport);
430 441
431 if (svc == NULL 442 if (svc == NULL
432 && protocol == IPPROTO_TCP 443 && protocol == IPPROTO_TCP
@@ -436,7 +447,7 @@ ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
436 * Check if ftp service entry exists, the packet 447 * Check if ftp service entry exists, the packet
437 * might belong to FTP data connections. 448 * might belong to FTP data connections.
438 */ 449 */
439 svc = __ip_vs_service_get(protocol, vaddr, FTPPORT); 450 svc = __ip_vs_service_get(AF_INET, protocol, &_vaddr, FTPPORT);
440 } 451 }
441 452
442 if (svc == NULL 453 if (svc == NULL
@@ -444,7 +455,7 @@ ip_vs_service_get(__u32 fwmark, __u16 protocol, __be32 vaddr, __be16 vport)
444 /* 455 /*
445 * Check if the catch-all port (port zero) exists 456 * Check if the catch-all port (port zero) exists
446 */ 457 */
447 svc = __ip_vs_service_get(protocol, vaddr, 0); 458 svc = __ip_vs_service_get(AF_INET, protocol, &_vaddr, 0);
448 } 459 }
449 460
450 out: 461 out:
@@ -2016,10 +2027,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2016 2027
2017 /* Lookup the exact service by <protocol, addr, port> or fwmark */ 2028 /* Lookup the exact service by <protocol, addr, port> or fwmark */
2018 if (usvc.fwmark == 0) 2029 if (usvc.fwmark == 0)
2019 svc = __ip_vs_service_get(usvc.protocol, 2030 svc = __ip_vs_service_get(usvc.af, usvc.protocol,
2020 usvc.addr.ip, usvc.port); 2031 &usvc.addr, usvc.port);
2021 else 2032 else
2022 svc = __ip_vs_svc_fwm_get(usvc.fwmark); 2033 svc = __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
2023 2034
2024 if (cmd != IP_VS_SO_SET_ADD 2035 if (cmd != IP_VS_SO_SET_ADD
2025 && (svc == NULL || svc->protocol != usvc.protocol)) { 2036 && (svc == NULL || svc->protocol != usvc.protocol)) {
@@ -2141,13 +2152,15 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
2141 struct ip_vs_get_dests __user *uptr) 2152 struct ip_vs_get_dests __user *uptr)
2142{ 2153{
2143 struct ip_vs_service *svc; 2154 struct ip_vs_service *svc;
2155 union nf_inet_addr addr = { .ip = get->addr };
2144 int ret = 0; 2156 int ret = 0;
2145 2157
2146 if (get->fwmark) 2158 if (get->fwmark)
2147 svc = __ip_vs_svc_fwm_get(get->fwmark); 2159 svc = __ip_vs_svc_fwm_get(AF_INET, get->fwmark);
2148 else 2160 else
2149 svc = __ip_vs_service_get(get->protocol, 2161 svc = __ip_vs_service_get(AF_INET, get->protocol, &addr,
2150 get->addr, get->port); 2162 get->port);
2163
2151 if (svc) { 2164 if (svc) {
2152 int count = 0; 2165 int count = 0;
2153 struct ip_vs_dest *dest; 2166 struct ip_vs_dest *dest;
@@ -2282,13 +2295,15 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2282 { 2295 {
2283 struct ip_vs_service_entry *entry; 2296 struct ip_vs_service_entry *entry;
2284 struct ip_vs_service *svc; 2297 struct ip_vs_service *svc;
2298 union nf_inet_addr addr;
2285 2299
2286 entry = (struct ip_vs_service_entry *)arg; 2300 entry = (struct ip_vs_service_entry *)arg;
2301 addr.ip = entry->addr;
2287 if (entry->fwmark) 2302 if (entry->fwmark)
2288 svc = __ip_vs_svc_fwm_get(entry->fwmark); 2303 svc = __ip_vs_svc_fwm_get(AF_INET, entry->fwmark);
2289 else 2304 else
2290 svc = __ip_vs_service_get(entry->protocol, 2305 svc = __ip_vs_service_get(AF_INET, entry->protocol,
2291 entry->addr, entry->port); 2306 &addr, entry->port);
2292 if (svc) { 2307 if (svc) {
2293 ip_vs_copy_service(entry, svc); 2308 ip_vs_copy_service(entry, svc);
2294 if (copy_to_user(user, entry, sizeof(*entry)) != 0) 2309 if (copy_to_user(user, entry, sizeof(*entry)) != 0)
@@ -2613,10 +2628,10 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
2613 2628
2614 /* prefill flags from service if it already exists */ 2629 /* prefill flags from service if it already exists */
2615 if (usvc->fwmark) 2630 if (usvc->fwmark)
2616 svc = __ip_vs_svc_fwm_get(usvc->fwmark); 2631 svc = __ip_vs_svc_fwm_get(usvc->af, usvc->fwmark);
2617 else 2632 else
2618 svc = __ip_vs_service_get(usvc->protocol, usvc->addr.ip, 2633 svc = __ip_vs_service_get(usvc->af, usvc->protocol,
2619 usvc->port); 2634 &usvc->addr, usvc->port);
2620 if (svc) { 2635 if (svc) {
2621 usvc->flags = svc->flags; 2636 usvc->flags = svc->flags;
2622 ip_vs_service_put(svc); 2637 ip_vs_service_put(svc);
@@ -2644,10 +2659,10 @@ static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla)
2644 return ERR_PTR(ret); 2659 return ERR_PTR(ret);
2645 2660
2646 if (usvc.fwmark) 2661 if (usvc.fwmark)
2647 return __ip_vs_svc_fwm_get(usvc.fwmark); 2662 return __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
2648 else 2663 else
2649 return __ip_vs_service_get(usvc.protocol, usvc.addr.ip, 2664 return __ip_vs_service_get(usvc.af, usvc.protocol,
2650 usvc.port); 2665 &usvc.addr, usvc.port);
2651} 2666}
2652 2667
2653static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest) 2668static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
@@ -2955,10 +2970,10 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
2955 2970
2956 /* Lookup the exact service by <protocol, addr, port> or fwmark */ 2971 /* Lookup the exact service by <protocol, addr, port> or fwmark */
2957 if (usvc.fwmark == 0) 2972 if (usvc.fwmark == 0)
2958 svc = __ip_vs_service_get(usvc.protocol, usvc.addr.ip, 2973 svc = __ip_vs_service_get(usvc.af, usvc.protocol,
2959 usvc.port); 2974 &usvc.addr, usvc.port);
2960 else 2975 else
2961 svc = __ip_vs_svc_fwm_get(usvc.fwmark); 2976 svc = __ip_vs_svc_fwm_get(usvc.af, usvc.fwmark);
2962 2977
2963 /* Unless we're adding a new service, the service must already exist */ 2978 /* Unless we're adding a new service, the service must already exist */
2964 if ((cmd != IPVS_CMD_NEW_SERVICE) && (svc == NULL)) { 2979 if ((cmd != IPVS_CMD_NEW_SERVICE) && (svc == NULL)) {