cregit-Linux how code gets into the kernel

Release 4.8 net/netfilter/ipvs/ip_vs_dh.c

/*
 * IPVS:        Destination Hashing scheduling module
 *
 * Authors:     Wensong Zhang <wensong@gnuchina.org>
 *
 *              Inspired by the consistent hashing scheduler patch from
 *              Thomas Proell <proellt@gmx.de>
 *
 *              This program is free software; you can redistribute it and/or
 *              modify it under the terms of the GNU General Public License
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 *
 * Changes:
 *
 */

/*
 * The dh algorithm is to select server by the hash key of destination IP
 * address. The pseudo code is as follows:
 *
 *       n <- servernode[dest_ip];
 *       if (n is dead) OR
 *          (n is overloaded) OR (n.weight <= 0) then
 *                 return NULL;
 *
 *       return n;
 *
 * Notes that servernode is a 256-bucket hash table that maps the hash
 * index derived from packet destination IP address to the current server
 * array. If the dh scheduler is used in cache cluster, it is good to
 * combine it with cache_bypass feature. When the statically assigned
 * server is dead or overloaded, the load balancer can bypass the cache
 * server and send requests to the original server directly.
 *
 */


#define KMSG_COMPONENT "IPVS"

#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

#include <linux/ip.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>

#include <net/ip_vs.h>


/*
 *      IPVS DH bucket
 */

struct ip_vs_dh_bucket {
	
struct ip_vs_dest __rcu	*dest;	/* real server (cache) */
};

/*
 *     for IPVS DH entry hash table
 */
#ifndef CONFIG_IP_VS_DH_TAB_BITS

#define CONFIG_IP_VS_DH_TAB_BITS        8
#endif

#define IP_VS_DH_TAB_BITS               CONFIG_IP_VS_DH_TAB_BITS

#define IP_VS_DH_TAB_SIZE               (1 << IP_VS_DH_TAB_BITS)

#define IP_VS_DH_TAB_MASK               (IP_VS_DH_TAB_SIZE - 1)


struct ip_vs_dh_state {
	
struct ip_vs_dh_bucket		buckets[IP_VS_DH_TAB_SIZE];
	
struct rcu_head			rcu_head;
};

/*
 *      Returns hash value for IPVS DH entry
 */

static inline unsigned int ip_vs_dh_hashkey(int af, const union nf_inet_addr *addr) { __be32 addr_fold = addr->ip; #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) addr_fold = addr->ip6[0]^addr->ip6[1]^ addr->ip6[2]^addr->ip6[3]; #endif return (ntohl(addr_fold)*2654435761UL) & IP_VS_DH_TAB_MASK; }

Contributors

PersonTokensPropCommitsCommitProp
julius volzjulius volz5875.32%250.00%
wensong zhangwensong zhang1823.38%125.00%
eric dumazeteric dumazet11.30%125.00%
Total77100.00%4100.00%

/* * Get ip_vs_dest associated with supplied parameters. */
static inline struct ip_vs_dest * ip_vs_dh_get(int af, struct ip_vs_dh_state *s, const union nf_inet_addr *addr) { return rcu_dereference(s->buckets[ip_vs_dh_hashkey(af, addr)].dest); }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang2253.66%125.00%
julius volzjulius volz1126.83%250.00%
julian anastasovjulian anastasov819.51%125.00%
Total41100.00%4100.00%

/* * Assign all the hash buckets of the specified table with the service. */
static int ip_vs_dh_reassign(struct ip_vs_dh_state *s, struct ip_vs_service *svc) { int i; struct ip_vs_dh_bucket *b; struct list_head *p; struct ip_vs_dest *dest; bool empty; b = &s->buckets[0]; p = &svc->destinations; empty = list_empty(p); for (i=0; i<IP_VS_DH_TAB_SIZE; i++) { dest = rcu_dereference_protected(b->dest, 1); if (dest) ip_vs_dest_put(dest); if (empty) RCU_INIT_POINTER(b->dest, NULL); else { if (p == &svc->destinations) p = p->next; dest = list_entry(p, struct ip_vs_dest, n_list); ip_vs_dest_hold(dest); RCU_INIT_POINTER(b->dest, dest); p = p->next; } b++; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang11569.70%133.33%
julian anastasovjulian anastasov4829.09%133.33%
julius volzjulius volz21.21%133.33%
Total165100.00%3100.00%

/* * Flush all the hash buckets of the specified table. */
static void ip_vs_dh_flush(struct ip_vs_dh_state *s) { int i; struct ip_vs_dh_bucket *b; struct ip_vs_dest *dest; b = &s->buckets[0]; for (i=0; i<IP_VS_DH_TAB_SIZE; i++) { dest = rcu_dereference_protected(b->dest, 1); if (dest) { ip_vs_dest_put(dest); RCU_INIT_POINTER(b->dest, NULL); } b++; } }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang5060.24%133.33%
julian anastasovjulian anastasov3036.14%133.33%
julius volzjulius volz33.61%133.33%
Total83100.00%3100.00%


static int ip_vs_dh_init_svc(struct ip_vs_service *svc) { struct ip_vs_dh_state *s; /* allocate the DH table for this service */ s = kzalloc(sizeof(struct ip_vs_dh_state), GFP_KERNEL); if (s == NULL) return -ENOMEM; svc->sched_data = s; IP_VS_DBG(6, "DH hash table (memory=%Zdbytes) allocated for " "current service\n", sizeof(struct ip_vs_dh_bucket)*IP_VS_DH_TAB_SIZE); /* assign the hash buckets with current dests */ ip_vs_dh_reassign(s, svc); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang5778.08%125.00%
julian anastasovjulian anastasov1115.07%250.00%
julius volzjulius volz56.85%125.00%
Total73100.00%4100.00%


static void ip_vs_dh_done_svc(struct ip_vs_service *svc) { struct ip_vs_dh_state *s = svc->sched_data; /* got to clean up hash buckets here */ ip_vs_dh_flush(s); /* release the table itself */ kfree_rcu(s, rcu_head); IP_VS_DBG(6, "DH hash table (memory=%Zdbytes) released\n", sizeof(struct ip_vs_dh_bucket)*IP_VS_DH_TAB_SIZE); }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang3673.47%125.00%
julian anastasovjulian anastasov816.33%250.00%
julius volzjulius volz510.20%125.00%
Total49100.00%4100.00%


static int ip_vs_dh_dest_changed(struct ip_vs_service *svc, struct ip_vs_dest *dest) { struct ip_vs_dh_state *s = svc->sched_data; /* assign the hash buckets with the updated service */ ip_vs_dh_reassign(s, svc); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang2672.22%150.00%
julian anastasovjulian anastasov1027.78%150.00%
Total36100.00%2100.00%

/* * If the dest flags is set with IP_VS_DEST_F_OVERLOAD, * consider that the server is overloaded here. */
static inline int is_overloaded(struct ip_vs_dest *dest) { return dest->flags & IP_VS_DEST_F_OVERLOAD; }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang19100.00%1100.00%
Total19100.00%1100.00%

/* * Destination hashing scheduling */
static struct ip_vs_dest * ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest; struct ip_vs_dh_state *s; IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); s = (struct ip_vs_dh_state *) svc->sched_data; dest = ip_vs_dh_get(svc->af, s, &iph->daddr); if (!dest || !(dest->flags & IP_VS_DEST_F_AVAILABLE) || atomic_read(&dest->weight) <= 0 || is_overloaded(dest)) { ip_vs_scheduler_err(svc, "no destination available"); return NULL; } IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n", IP_VS_DBG_ADDR(svc->af, &iph->daddr), IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port)); return dest; }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang10065.79%111.11%
julius volzjulius volz2415.79%222.22%
julian anastasovjulian anastasov2315.13%444.44%
hannes ederhannes eder31.97%111.11%
harvey harrisonharvey harrison21.32%111.11%
Total152100.00%9100.00%

/* * IPVS DH Scheduler structure */ static struct ip_vs_scheduler ip_vs_dh_scheduler = { .name = "dh", .refcnt = ATOMIC_INIT(0), .module = THIS_MODULE, .n_list = LIST_HEAD_INIT(ip_vs_dh_scheduler.n_list), .init_service = ip_vs_dh_init_svc, .done_service = ip_vs_dh_done_svc, .add_dest = ip_vs_dh_dest_changed, .del_dest = ip_vs_dh_dest_changed, .schedule = ip_vs_dh_schedule, };
static int __init ip_vs_dh_init(void) { return register_ip_vs_scheduler(&ip_vs_dh_scheduler); }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang1487.50%150.00%
julius volzjulius volz212.50%150.00%
Total16100.00%2100.00%


static void __exit ip_vs_dh_cleanup(void) { unregister_ip_vs_scheduler(&ip_vs_dh_scheduler); synchronize_rcu(); }

Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang1372.22%133.33%
julian anastasovjulian anastasov316.67%133.33%
julius volzjulius volz211.11%133.33%
Total18100.00%3100.00%

module_init(ip_vs_dh_init); module_exit(ip_vs_dh_cleanup); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
wensong zhangwensong zhang55762.37%15.88%
julian anastasovjulian anastasov16518.48%741.18%
julius volzjulius volz13615.23%211.76%
hannes ederhannes eder141.57%211.76%
sven wegenersven wegener91.01%15.88%
arnaldo carvalho de meloarnaldo carvalho de melo60.67%15.88%
tejun heotejun heo30.34%15.88%
harvey harrisonharvey harrison20.22%15.88%
eric dumazeteric dumazet10.11%15.88%
Total893100.00%17100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.