Commit fcfa8f49 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

Merge branch 'ipvs-next'

Simon Horman says:

====================
This pull requests makes the following changes:

* Add simple weighted fail-over scheduler.
  - Unlike other IPVS schedulers this offers fail-over rather than load
    balancing. Connections are directed to the appropriate server based
    solely on highest weight value and server availability.
  - Thanks to Kenny Mathis

* Support IPv6 real servers in IPv4 virtual-services and vice versa
  - This feature is supported in conjunction with the tunnel (IPIP)
    forwarding mechanism. That is, IPv4 may be forwarded in IPv6 and
    vice versa.
  - The motivation for this is to allow more flexibility in the
    choice of IP version offered by both virtual-servers and
    real-servers as they no longer need to match: An IPv4 connection from an
    end-user may be forwarded to a real-server using IPv6 and vice versa.
  - Further work need to be done to support this feature in conjunction
    with connection synchronisation. For now such configurations are
    not allowed.
  - This change includes update to netlink protocol, adding a new
    destination address family attribute. And the necessary changes
    to plumb this information throughout IPVS.
  - Thanks to Alex Gartrell and Julian Anastasov
====================
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parents 07034aea bc18d37f
...@@ -535,6 +535,7 @@ struct ip_vs_conn { ...@@ -535,6 +535,7 @@ struct ip_vs_conn {
union nf_inet_addr daddr; /* destination address */ union nf_inet_addr daddr; /* destination address */
volatile __u32 flags; /* status flags */ volatile __u32 flags; /* status flags */
__u16 protocol; /* Which protocol (TCP/UDP) */ __u16 protocol; /* Which protocol (TCP/UDP) */
__u16 daf; /* Address family of the dest */
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
struct net *net; /* Name space */ struct net *net; /* Name space */
#endif #endif
...@@ -648,6 +649,9 @@ struct ip_vs_dest_user_kern { ...@@ -648,6 +649,9 @@ struct ip_vs_dest_user_kern {
/* thresholds for active connections */ /* thresholds for active connections */
u32 u_threshold; /* upper threshold */ u32 u_threshold; /* upper threshold */
u32 l_threshold; /* lower threshold */ u32 l_threshold; /* lower threshold */
/* Address family of addr */
u16 af;
}; };
...@@ -986,6 +990,10 @@ struct netns_ipvs { ...@@ -986,6 +990,10 @@ struct netns_ipvs {
char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
/* net name space ptr */ /* net name space ptr */
struct net *net; /* Needed by timer routines */ struct net *net; /* Needed by timer routines */
/* Number of heterogeneous destinations, needed because
* heterogeneous are not supported when synchronization is
* enabled */
unsigned int mixed_address_family_dests;
}; };
#define DEFAULT_SYNC_THRESHOLD 3 #define DEFAULT_SYNC_THRESHOLD 3
...@@ -1210,7 +1218,7 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp) ...@@ -1210,7 +1218,7 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
void ip_vs_conn_put(struct ip_vs_conn *cp); void ip_vs_conn_put(struct ip_vs_conn *cp);
void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
const union nf_inet_addr *daddr, const union nf_inet_addr *daddr,
__be16 dport, unsigned int flags, __be16 dport, unsigned int flags,
struct ip_vs_dest *dest, __u32 fwmark); struct ip_vs_dest *dest, __u32 fwmark);
...@@ -1396,8 +1404,9 @@ void ip_vs_unregister_nl_ioctl(void); ...@@ -1396,8 +1404,9 @@ void ip_vs_unregister_nl_ioctl(void);
int ip_vs_control_init(void); int ip_vs_control_init(void);
void ip_vs_control_cleanup(void); void ip_vs_control_cleanup(void);
struct ip_vs_dest * struct ip_vs_dest *
ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr, ip_vs_find_dest(struct net *net, int svc_af, int dest_af,
__be16 dport, const union nf_inet_addr *vaddr, __be16 vport, const union nf_inet_addr *daddr, __be16 dport,
const union nf_inet_addr *vaddr, __be16 vport,
__u16 protocol, __u32 fwmark, __u32 flags); __u16 protocol, __u32 fwmark, __u32 flags);
void ip_vs_try_bind_dest(struct ip_vs_conn *cp); void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
......
...@@ -384,6 +384,9 @@ enum { ...@@ -384,6 +384,9 @@ enum {
IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */ IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */
IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */ IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */
IPVS_DEST_ATTR_ADDR_FAMILY, /* Address family of address */
__IPVS_DEST_ATTR_MAX, __IPVS_DEST_ATTR_MAX,
}; };
......
...@@ -152,6 +152,16 @@ config IP_VS_WLC ...@@ -152,6 +152,16 @@ config IP_VS_WLC
If you want to compile it in kernel, say Y. To compile it as a If you want to compile it in kernel, say Y. To compile it as a
module, choose M here. If unsure, say N. module, choose M here. If unsure, say N.
config IP_VS_FO
tristate "weighted failover scheduling"
---help---
The weighted failover scheduling algorithm directs network
connections to the server with the highest weight that is
currently available.
If you want to compile it in kernel, say Y. To compile it as a
module, choose M here. If unsure, say N.
config IP_VS_LBLC config IP_VS_LBLC
tristate "locality-based least-connection scheduling" tristate "locality-based least-connection scheduling"
---help--- ---help---
......
...@@ -26,6 +26,7 @@ obj-$(CONFIG_IP_VS_RR) += ip_vs_rr.o ...@@ -26,6 +26,7 @@ obj-$(CONFIG_IP_VS_RR) += ip_vs_rr.o
obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o
obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o
obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o
obj-$(CONFIG_IP_VS_FO) += ip_vs_fo.o
obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o
obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o
obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/inet.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -77,6 +78,13 @@ static unsigned int ip_vs_conn_rnd __read_mostly; ...@@ -77,6 +78,13 @@ static unsigned int ip_vs_conn_rnd __read_mostly;
#define CT_LOCKARRAY_SIZE (1<<CT_LOCKARRAY_BITS) #define CT_LOCKARRAY_SIZE (1<<CT_LOCKARRAY_BITS)
#define CT_LOCKARRAY_MASK (CT_LOCKARRAY_SIZE-1) #define CT_LOCKARRAY_MASK (CT_LOCKARRAY_SIZE-1)
/* We need an addrstrlen that works with or without v6 */
#ifdef CONFIG_IP_VS_IPV6
#define IP_VS_ADDRSTRLEN INET6_ADDRSTRLEN
#else
#define IP_VS_ADDRSTRLEN (8+1)
#endif
struct ip_vs_aligned_lock struct ip_vs_aligned_lock
{ {
spinlock_t l; spinlock_t l;
...@@ -488,6 +496,11 @@ static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp) ...@@ -488,6 +496,11 @@ static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp)
break; break;
case IP_VS_CONN_F_TUNNEL: case IP_VS_CONN_F_TUNNEL:
#ifdef CONFIG_IP_VS_IPV6
if (cp->daf == AF_INET6)
cp->packet_xmit = ip_vs_tunnel_xmit_v6;
else
#endif
cp->packet_xmit = ip_vs_tunnel_xmit; cp->packet_xmit = ip_vs_tunnel_xmit;
break; break;
...@@ -514,7 +527,10 @@ static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp) ...@@ -514,7 +527,10 @@ static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp)
break; break;
case IP_VS_CONN_F_TUNNEL: case IP_VS_CONN_F_TUNNEL:
if (cp->daf == AF_INET6)
cp->packet_xmit = ip_vs_tunnel_xmit_v6; cp->packet_xmit = ip_vs_tunnel_xmit_v6;
else
cp->packet_xmit = ip_vs_tunnel_xmit;
break; break;
case IP_VS_CONN_F_DROUTE: case IP_VS_CONN_F_DROUTE:
...@@ -580,7 +596,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) ...@@ -580,7 +596,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
ip_vs_proto_name(cp->protocol), ip_vs_proto_name(cp->protocol),
IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport), IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport), IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport), IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
ip_vs_fwd_tag(cp), cp->state, ip_vs_fwd_tag(cp), cp->state,
cp->flags, atomic_read(&cp->refcnt), cp->flags, atomic_read(&cp->refcnt),
atomic_read(&dest->refcnt)); atomic_read(&dest->refcnt));
...@@ -616,7 +632,13 @@ void ip_vs_try_bind_dest(struct ip_vs_conn *cp) ...@@ -616,7 +632,13 @@ void ip_vs_try_bind_dest(struct ip_vs_conn *cp)
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
rcu_read_lock(); rcu_read_lock();
dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, &cp->daddr,
/* This function is only invoked by the synchronization code. We do
* not currently support heterogeneous pools with synchronization,
* so we can make the assumption that the svc_af is the same as the
* dest_af
*/
dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, cp->af, &cp->daddr,
cp->dport, &cp->vaddr, cp->vport, cp->dport, &cp->vaddr, cp->vport,
cp->protocol, cp->fwmark, cp->flags); cp->protocol, cp->fwmark, cp->flags);
if (dest) { if (dest) {
...@@ -671,7 +693,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) ...@@ -671,7 +693,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
ip_vs_proto_name(cp->protocol), ip_vs_proto_name(cp->protocol),
IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport), IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport), IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport), IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
ip_vs_fwd_tag(cp), cp->state, ip_vs_fwd_tag(cp), cp->state,
cp->flags, atomic_read(&cp->refcnt), cp->flags, atomic_read(&cp->refcnt),
atomic_read(&dest->refcnt)); atomic_read(&dest->refcnt));
...@@ -740,7 +762,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct) ...@@ -740,7 +762,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
ntohs(ct->cport), ntohs(ct->cport),
IP_VS_DBG_ADDR(ct->af, &ct->vaddr), IP_VS_DBG_ADDR(ct->af, &ct->vaddr),
ntohs(ct->vport), ntohs(ct->vport),
IP_VS_DBG_ADDR(ct->af, &ct->daddr), IP_VS_DBG_ADDR(ct->daf, &ct->daddr),
ntohs(ct->dport)); ntohs(ct->dport));
/* /*
...@@ -848,7 +870,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp) ...@@ -848,7 +870,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
* Create a new connection entry and hash it into the ip_vs_conn_tab * Create a new connection entry and hash it into the ip_vs_conn_tab
*/ */
struct ip_vs_conn * struct ip_vs_conn *
ip_vs_conn_new(const struct ip_vs_conn_param *p, ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
const union nf_inet_addr *daddr, __be16 dport, unsigned int flags, const union nf_inet_addr *daddr, __be16 dport, unsigned int flags,
struct ip_vs_dest *dest, __u32 fwmark) struct ip_vs_dest *dest, __u32 fwmark)
{ {
...@@ -867,6 +889,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, ...@@ -867,6 +889,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp); setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
ip_vs_conn_net_set(cp, p->net); ip_vs_conn_net_set(cp, p->net);
cp->af = p->af; cp->af = p->af;
cp->daf = dest_af;
cp->protocol = p->protocol; cp->protocol = p->protocol;
ip_vs_addr_set(p->af, &cp->caddr, p->caddr); ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
cp->cport = p->cport; cp->cport = p->cport;
...@@ -874,7 +897,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, ...@@ -874,7 +897,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
&cp->vaddr, p->vaddr); &cp->vaddr, p->vaddr);
cp->vport = p->vport; cp->vport = p->vport;
ip_vs_addr_set(p->af, &cp->daddr, daddr); ip_vs_addr_set(cp->daf, &cp->daddr, daddr);
cp->dport = dport; cp->dport = dport;
cp->flags = flags; cp->flags = flags;
cp->fwmark = fwmark; cp->fwmark = fwmark;
...@@ -1036,6 +1059,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) ...@@ -1036,6 +1059,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
struct net *net = seq_file_net(seq); struct net *net = seq_file_net(seq);
char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3]; char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3];
size_t len = 0; size_t len = 0;
char dbuf[IP_VS_ADDRSTRLEN];
if (!ip_vs_conn_net_eq(cp, net)) if (!ip_vs_conn_net_eq(cp, net))
return 0; return 0;
...@@ -1049,25 +1073,33 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) ...@@ -1049,25 +1073,33 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
} }
pe_data[len] = '\0'; pe_data[len] = '\0';
#ifdef CONFIG_IP_VS_IPV6
if (cp->daf == AF_INET6)
snprintf(dbuf, sizeof(dbuf), "%pI6", &cp->daddr.in6);
else
#endif
snprintf(dbuf, sizeof(dbuf), "%08X",
ntohl(cp->daddr.ip));
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
if (cp->af == AF_INET6) if (cp->af == AF_INET6)
seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X " seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
"%pI6 %04X %-11s %7lu%s\n", "%s %04X %-11s %7lu%s\n",
ip_vs_proto_name(cp->protocol), ip_vs_proto_name(cp->protocol),
&cp->caddr.in6, ntohs(cp->cport), &cp->caddr.in6, ntohs(cp->cport),
&cp->vaddr.in6, ntohs(cp->vport), &cp->vaddr.in6, ntohs(cp->vport),
&cp->daddr.in6, ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp->protocol, cp->state),
(cp->timer.expires-jiffies)/HZ, pe_data); (cp->timer.expires-jiffies)/HZ, pe_data);
else else
#endif #endif
seq_printf(seq, seq_printf(seq,
"%-3s %08X %04X %08X %04X" "%-3s %08X %04X %08X %04X"
" %08X %04X %-11s %7lu%s\n", " %s %04X %-11s %7lu%s\n",
ip_vs_proto_name(cp->protocol), ip_vs_proto_name(cp->protocol),
ntohl(cp->caddr.ip), ntohs(cp->cport), ntohl(cp->caddr.ip), ntohs(cp->cport),
ntohl(cp->vaddr.ip), ntohs(cp->vport), ntohl(cp->vaddr.ip), ntohs(cp->vport),
ntohl(cp->daddr.ip), ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp->protocol, cp->state),
(cp->timer.expires-jiffies)/HZ, pe_data); (cp->timer.expires-jiffies)/HZ, pe_data);
} }
...@@ -1105,6 +1137,7 @@ static const char *ip_vs_origin_name(unsigned int flags) ...@@ -1105,6 +1137,7 @@ static const char *ip_vs_origin_name(unsigned int flags)
static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
{ {
char dbuf[IP_VS_ADDRSTRLEN];
if (v == SEQ_START_TOKEN) if (v == SEQ_START_TOKEN)
seq_puts(seq, seq_puts(seq,
...@@ -1116,13 +1149,22 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) ...@@ -1116,13 +1149,22 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
if (!ip_vs_conn_net_eq(cp, net)) if (!ip_vs_conn_net_eq(cp, net))
return 0; return 0;
#ifdef CONFIG_IP_VS_IPV6
if (cp->daf == AF_INET6)
snprintf(dbuf, sizeof(dbuf), "%pI6", &cp->daddr.in6);
else
#endif
snprintf(dbuf, sizeof(dbuf), "%08X",
ntohl(cp->daddr.ip));
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
if (cp->af == AF_INET6) if (cp->af == AF_INET6)
seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X %pI6 %04X %-11s %-6s %7lu\n", seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
"%s %04X %-11s %-6s %7lu\n",
ip_vs_proto_name(cp->protocol), ip_vs_proto_name(cp->protocol),
&cp->caddr.in6, ntohs(cp->cport), &cp->caddr.in6, ntohs(cp->cport),
&cp->vaddr.in6, ntohs(cp->vport), &cp->vaddr.in6, ntohs(cp->vport),
&cp->daddr.in6, ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp->protocol, cp->state),
ip_vs_origin_name(cp->flags), ip_vs_origin_name(cp->flags),
(cp->timer.expires-jiffies)/HZ); (cp->timer.expires-jiffies)/HZ);
...@@ -1130,11 +1172,11 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) ...@@ -1130,11 +1172,11 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
#endif #endif
seq_printf(seq, seq_printf(seq,
"%-3s %08X %04X %08X %04X " "%-3s %08X %04X %08X %04X "
"%08X %04X %-11s %-6s %7lu\n", "%s %04X %-11s %-6s %7lu\n",
ip_vs_proto_name(cp->protocol), ip_vs_proto_name(cp->protocol),
ntohl(cp->caddr.ip), ntohs(cp->cport), ntohl(cp->caddr.ip), ntohs(cp->cport),
ntohl(cp->vaddr.ip), ntohs(cp->vport), ntohl(cp->vaddr.ip), ntohs(cp->vport),
ntohl(cp->daddr.ip), ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp->protocol, cp->state),
ip_vs_origin_name(cp->flags), ip_vs_origin_name(cp->flags),
(cp->timer.expires-jiffies)/HZ); (cp->timer.expires-jiffies)/HZ);
......
...@@ -328,7 +328,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc, ...@@ -328,7 +328,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
* This adds param.pe_data to the template, * This adds param.pe_data to the template,
* and thus param.pe_data will be destroyed * and thus param.pe_data will be destroyed
* when the template expires */ * when the template expires */
ct = ip_vs_conn_new(&param, &dest->addr, dport, ct = ip_vs_conn_new(&param, dest->af, &dest->addr, dport,
IP_VS_CONN_F_TEMPLATE, dest, skb->mark); IP_VS_CONN_F_TEMPLATE, dest, skb->mark);
if (ct == NULL) { if (ct == NULL) {
kfree(param.pe_data); kfree(param.pe_data);
...@@ -357,7 +357,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc, ...@@ -357,7 +357,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr, ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr,
src_port, &iph->daddr, dst_port, &param); src_port, &iph->daddr, dst_port, &param);
cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest, skb->mark); cp = ip_vs_conn_new(&param, dest->af, &dest->addr, dport, flags, dest,
skb->mark);
if (cp == NULL) { if (cp == NULL) {
ip_vs_conn_put(ct); ip_vs_conn_put(ct);
*ignored = -1; *ignored = -1;
...@@ -479,7 +480,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -479,7 +480,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
&iph->saddr, pptr[0], &iph->daddr, &iph->saddr, pptr[0], &iph->daddr,
pptr[1], &p); pptr[1], &p);
cp = ip_vs_conn_new(&p, &dest->addr, cp = ip_vs_conn_new(&p, dest->af, &dest->addr,
dest->port ? dest->port : pptr[1], dest->port ? dest->port : pptr[1],
flags, dest, skb->mark); flags, dest, skb->mark);
if (!cp) { if (!cp) {
...@@ -491,9 +492,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -491,9 +492,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u " IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
"d:%s:%u conn->flags:%X conn->refcnt:%d\n", "d:%s:%u conn->flags:%X conn->refcnt:%d\n",
ip_vs_fwd_tag(cp), ip_vs_fwd_tag(cp),
IP_VS_DBG_ADDR(svc->af, &cp->caddr), ntohs(cp->cport), IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
IP_VS_DBG_ADDR(svc->af, &cp->vaddr), ntohs(cp->vport), IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
IP_VS_DBG_ADDR(svc->af, &cp->daddr), ntohs(cp->dport), IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
cp->flags, atomic_read(&cp->refcnt)); cp->flags, atomic_read(&cp->refcnt));
ip_vs_conn_stats(cp, svc); ip_vs_conn_stats(cp, svc);
...@@ -550,7 +551,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -550,7 +551,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
&iph->saddr, pptr[0], &iph->saddr, pptr[0],
&iph->daddr, pptr[1], &p); &iph->daddr, pptr[1], &p);
cp = ip_vs_conn_new(&p, &daddr, 0, cp = ip_vs_conn_new(&p, svc->af, &daddr, 0,
IP_VS_CONN_F_BYPASS | flags, IP_VS_CONN_F_BYPASS | flags,
NULL, skb->mark); NULL, skb->mark);
if (!cp) if (!cp)
......
This diff is collapsed.
...@@ -234,7 +234,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -234,7 +234,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n", 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(svc->af, &iph->daddr),
IP_VS_DBG_ADDR(svc->af, &dest->addr), IP_VS_DBG_ADDR(dest->af, &dest->addr),
ntohs(dest->port)); ntohs(dest->port));
return dest; return dest;
......
/*
* IPVS: Weighted Fail Over module
*
* Authors: Kenny Mathis <kmathis@chokepoint.net>
*
* 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:
* Kenny Mathis : added initial functionality based on weight
*
*/
#define KMSG_COMPONENT "IPVS"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <net/ip_vs.h>
/* Weighted Fail Over Module */
static struct ip_vs_dest *
ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
struct ip_vs_iphdr *iph)
{
struct ip_vs_dest *dest, *hweight = NULL;
int hw = 0; /* Track highest weight */
IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n");
/* Basic failover functionality
* Find virtual server with highest weight and send it traffic
*/
list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
atomic_read(&dest->weight) > hw) {
hweight = dest;
hw = atomic_read(&dest->weight);
}
}
if (hweight) {
IP_VS_DBG_BUF(6, "FO: server %s:%u activeconns %d weight %d\n",
IP_VS_DBG_ADDR(hweight->af, &hweight->addr),
ntohs(hweight->port),
atomic_read(&hweight->activeconns),
atomic_read(&hweight->weight));
return hweight;
}
ip_vs_scheduler_err(svc, "no destination available");
return NULL;
}
static struct ip_vs_scheduler ip_vs_fo_scheduler = {
.name = "fo",
.refcnt = ATOMIC_INIT(0),
.module = THIS_MODULE,
.n_list = LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list),
.schedule = ip_vs_fo_schedule,
};
static int __init ip_vs_fo_init(void)
{
return register_ip_vs_scheduler(&ip_vs_fo_scheduler);
}
static void __exit ip_vs_fo_cleanup(void)
{
unregister_ip_vs_scheduler(&ip_vs_fo_scheduler);
synchronize_rcu();
}
module_init(ip_vs_fo_init);
module_exit(ip_vs_fo_cleanup);
MODULE_LICENSE("GPL");
...@@ -233,7 +233,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, ...@@ -233,7 +233,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
ip_vs_conn_fill_param(ip_vs_conn_net(cp), ip_vs_conn_fill_param(ip_vs_conn_net(cp),
AF_INET, IPPROTO_TCP, &cp->caddr, AF_INET, IPPROTO_TCP, &cp->caddr,
0, &cp->vaddr, port, &p); 0, &cp->vaddr, port, &p);
n_cp = ip_vs_conn_new(&p, &from, port, /* As above, this is ipv4 only */
n_cp = ip_vs_conn_new(&p, AF_INET, &from, port,
IP_VS_CONN_F_NO_CPORT | IP_VS_CONN_F_NO_CPORT |
IP_VS_CONN_F_NFCT, IP_VS_CONN_F_NFCT,
cp->dest, skb->mark); cp->dest, skb->mark);
...@@ -396,7 +397,8 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, ...@@ -396,7 +397,8 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
htons(ntohs(cp->vport)-1), &p); htons(ntohs(cp->vport)-1), &p);
n_cp = ip_vs_conn_in_get(&p); n_cp = ip_vs_conn_in_get(&p);
if (!n_cp) { if (!n_cp) {
n_cp = ip_vs_conn_new(&p, &cp->daddr, /* This is ipv4 only */
n_cp = ip_vs_conn_new(&p, AF_INET, &cp->daddr,
htons(ntohs(cp->dport)-1), htons(ntohs(cp->dport)-1),
IP_VS_CONN_F_NFCT, cp->dest, IP_VS_CONN_F_NFCT, cp->dest,
skb->mark); skb->mark);
......
...@@ -199,11 +199,11 @@ ip_vs_lblc_get(int af, struct ip_vs_lblc_table *tbl, ...@@ -199,11 +199,11 @@ ip_vs_lblc_get(int af, struct ip_vs_lblc_table *tbl,
*/ */
static inline struct ip_vs_lblc_entry * static inline struct ip_vs_lblc_entry *
ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr, ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
struct ip_vs_dest *dest) u16 af, struct ip_vs_dest *dest)
{ {
struct ip_vs_lblc_entry *en; struct ip_vs_lblc_entry *en;
en = ip_vs_lblc_get(dest->af, tbl, daddr); en = ip_vs_lblc_get(af, tbl, daddr);
if (en) { if (en) {
if (en->dest == dest) if (en->dest == dest)
return en; return en;
...@@ -213,8 +213,8 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr, ...@@ -213,8 +213,8 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
if (!en) if (!en)
return NULL; return NULL;
en->af = dest->af; en->af = af;
ip_vs_addr_copy(dest->af, &en->addr, daddr); ip_vs_addr_copy(af, &en->addr, daddr);
en->lastuse = jiffies; en->lastuse = jiffies;
ip_vs_dest_hold(dest); ip_vs_dest_hold(dest);
...@@ -521,13 +521,13 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -521,13 +521,13 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
/* If we fail to create a cache entry, we'll just use the valid dest */ /* If we fail to create a cache entry, we'll just use the valid dest */
spin_lock_bh(&svc->sched_lock); spin_lock_bh(&svc->sched_lock);
if (!tbl->dead) if (!tbl->dead)
ip_vs_lblc_new(tbl, &iph->daddr, dest); ip_vs_lblc_new(tbl, &iph->daddr, svc->af, dest);
spin_unlock_bh(&svc->sched_lock); spin_unlock_bh(&svc->sched_lock);
out: out:
IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n", IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n",
IP_VS_DBG_ADDR(svc->af, &iph->daddr), IP_VS_DBG_ADDR(svc->af, &iph->daddr),
IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port));
return dest; return dest;
} }
......
...@@ -362,18 +362,18 @@ ip_vs_lblcr_get(int af, struct ip_vs_lblcr_table *tbl, ...@@ -362,18 +362,18 @@ ip_vs_lblcr_get(int af, struct ip_vs_lblcr_table *tbl,
*/ */
static inline struct ip_vs_lblcr_entry * static inline struct ip_vs_lblcr_entry *
ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr,
struct ip_vs_dest *dest) u16 af, struct ip_vs_dest *dest)
{ {
struct ip_vs_lblcr_entry *en; struct ip_vs_lblcr_entry *en;
en = ip_vs_lblcr_get(dest->af, tbl, daddr); en = ip_vs_lblcr_get(af, tbl, daddr);
if (!en) { if (!en) {
en = kmalloc(sizeof(*en), GFP_ATOMIC); en = kmalloc(sizeof(*en), GFP_ATOMIC);
if (!en) if (!en)
return NULL; return NULL;
en->af = dest->af; en->af = af;
ip_vs_addr_copy(dest->af, &en->addr, daddr); ip_vs_addr_copy(af, &en->addr, daddr);
en->lastuse = jiffies; en->lastuse = jiffies;
/* initialize its dest set */ /* initialize its dest set */
...@@ -706,13 +706,13 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -706,13 +706,13 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
/* If we fail to create a cache entry, we'll just use the valid dest */ /* If we fail to create a cache entry, we'll just use the valid dest */
spin_lock_bh(&svc->sched_lock); spin_lock_bh(&svc->sched_lock);
if (!tbl->dead) if (!tbl->dead)
ip_vs_lblcr_new(tbl, &iph->daddr, dest); ip_vs_lblcr_new(tbl, &iph->daddr, svc->af, dest);
spin_unlock_bh(&svc->sched_lock); spin_unlock_bh(&svc->sched_lock);
out: out:
IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n", IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n",
IP_VS_DBG_ADDR(svc->af, &iph->daddr), IP_VS_DBG_ADDR(svc->af, &iph->daddr),
IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port));
return dest; return dest;
} }
......
...@@ -59,7 +59,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -59,7 +59,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
else else
IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d " IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
"inactconns %d\n", "inactconns %d\n",
IP_VS_DBG_ADDR(svc->af, &least->addr), IP_VS_DBG_ADDR(least->af, &least->addr),
ntohs(least->port), ntohs(least->port),
atomic_read(&least->activeconns), atomic_read(&least->activeconns),
atomic_read(&least->inactconns)); atomic_read(&least->inactconns));
......
...@@ -107,7 +107,8 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -107,7 +107,8 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
out: out:
IP_VS_DBG_BUF(6, "NQ: server %s:%u " IP_VS_DBG_BUF(6, "NQ: server %s:%u "
"activeconns %d refcnt %d weight %d overhead %d\n", "activeconns %d refcnt %d weight %d overhead %d\n",
IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), IP_VS_DBG_ADDR(least->af, &least->addr),
ntohs(least->port),
atomic_read(&least->activeconns), atomic_read(&least->activeconns),
atomic_read(&least->refcnt), atomic_read(&least->refcnt),
atomic_read(&least->weight), loh); atomic_read(&least->weight), loh);
......
...@@ -432,7 +432,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, ...@@ -432,7 +432,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
pd->pp->name, pd->pp->name,
((direction == IP_VS_DIR_OUTPUT) ? ((direction == IP_VS_DIR_OUTPUT) ?
"output " : "input "), "output " : "input "),
IP_VS_DBG_ADDR(cp->af, &cp->daddr), IP_VS_DBG_ADDR(cp->daf, &cp->daddr),
ntohs(cp->dport), ntohs(cp->dport),
IP_VS_DBG_ADDR(cp->af, &cp->caddr), IP_VS_DBG_ADDR(cp->af, &cp->caddr),
ntohs(cp->cport), ntohs(cp->cport),
......
...@@ -510,7 +510,7 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, ...@@ -510,7 +510,7 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
th->fin ? 'F' : '.', th->fin ? 'F' : '.',
th->ack ? 'A' : '.', th->ack ? 'A' : '.',
th->rst ? 'R' : '.', th->rst ? 'R' : '.',
IP_VS_DBG_ADDR(cp->af, &cp->daddr), IP_VS_DBG_ADDR(cp->daf, &cp->daddr),
ntohs(cp->dport), ntohs(cp->dport),
IP_VS_DBG_ADDR(cp->af, &cp->caddr), IP_VS_DBG_ADDR(cp->af, &cp->caddr),
ntohs(cp->cport), ntohs(cp->cport),
......
...@@ -95,7 +95,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -95,7 +95,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
spin_unlock_bh(&svc->sched_lock); spin_unlock_bh(&svc->sched_lock);
IP_VS_DBG_BUF(6, "RR: server %s:%u " IP_VS_DBG_BUF(6, "RR: server %s:%u "
"activeconns %d refcnt %d weight %d\n", "activeconns %d refcnt %d weight %d\n",
IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
atomic_read(&dest->activeconns), atomic_read(&dest->activeconns),
atomic_read(&dest->refcnt), atomic_read(&dest->weight)); atomic_read(&dest->refcnt), atomic_read(&dest->weight));
......
...@@ -108,7 +108,8 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -108,7 +108,8 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
IP_VS_DBG_BUF(6, "SED: server %s:%u " IP_VS_DBG_BUF(6, "SED: server %s:%u "
"activeconns %d refcnt %d weight %d overhead %d\n", "activeconns %d refcnt %d weight %d overhead %d\n",
IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), IP_VS_DBG_ADDR(least->af, &least->addr),
ntohs(least->port),
atomic_read(&least->activeconns), atomic_read(&least->activeconns),
atomic_read(&least->refcnt), atomic_read(&least->refcnt),
atomic_read(&least->weight), loh); atomic_read(&least->weight), loh);
......
...@@ -138,7 +138,7 @@ ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s, ...@@ -138,7 +138,7 @@ ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s,
return dest; return dest;
IP_VS_DBG_BUF(6, "SH: selected unavailable server %s:%d, reselecting", IP_VS_DBG_BUF(6, "SH: selected unavailable server %s:%d, reselecting",
IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port));
/* if the original dest is unavailable, loop around the table /* if the original dest is unavailable, loop around the table
* starting from ihash to find a new dest * starting from ihash to find a new dest
...@@ -153,7 +153,7 @@ ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s, ...@@ -153,7 +153,7 @@ ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s,
return dest; return dest;
IP_VS_DBG_BUF(6, "SH: selected unavailable " IP_VS_DBG_BUF(6, "SH: selected unavailable "
"server %s:%d (offset %d), reselecting", "server %s:%d (offset %d), reselecting",
IP_VS_DBG_ADDR(svc->af, &dest->addr), IP_VS_DBG_ADDR(dest->af, &dest->addr),
ntohs(dest->port), roffset); ntohs(dest->port), roffset);
} }
...@@ -192,7 +192,7 @@ ip_vs_sh_reassign(struct ip_vs_sh_state *s, struct ip_vs_service *svc) ...@@ -192,7 +192,7 @@ ip_vs_sh_reassign(struct ip_vs_sh_state *s, struct ip_vs_service *svc)
RCU_INIT_POINTER(b->dest, dest); RCU_INIT_POINTER(b->dest, dest);
IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n", IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n",
i, IP_VS_DBG_ADDR(svc->af, &dest->addr), i, IP_VS_DBG_ADDR(dest->af, &dest->addr),
atomic_read(&dest->weight)); atomic_read(&dest->weight));
/* Don't move to next dest until filling weight */ /* Don't move to next dest until filling weight */
...@@ -342,7 +342,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -342,7 +342,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n", IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n",
IP_VS_DBG_ADDR(svc->af, &iph->saddr), IP_VS_DBG_ADDR(svc->af, &iph->saddr),
IP_VS_DBG_ADDR(svc->af, &dest->addr), IP_VS_DBG_ADDR(dest->af, &dest->addr),
ntohs(dest->port)); ntohs(dest->port));
return dest; return dest;
......
...@@ -880,10 +880,17 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, ...@@ -880,10 +880,17 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
* but still handled. * but still handled.
*/ */
rcu_read_lock(); rcu_read_lock();
dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr, /* This function is only invoked by the synchronization
param->vport, protocol, fwmark, flags); * code. We do not currently support heterogeneous pools
* with synchronization, so we can make the assumption that
* the svc_af is the same as the dest_af
*/
dest = ip_vs_find_dest(net, type, type, daddr, dport,
param->vaddr, param->vport, protocol,
fwmark, flags);
cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); cp = ip_vs_conn_new(param, type, daddr, dport, flags, dest,
fwmark);
rcu_read_unlock(); rcu_read_unlock();
if (!cp) { if (!cp) {
kfree(param->pe_data); kfree(param->pe_data);
......
...@@ -80,7 +80,8 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -80,7 +80,8 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
IP_VS_DBG_BUF(6, "WLC: server %s:%u " IP_VS_DBG_BUF(6, "WLC: server %s:%u "
"activeconns %d refcnt %d weight %d overhead %d\n", "activeconns %d refcnt %d weight %d overhead %d\n",
IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), IP_VS_DBG_ADDR(least->af, &least->addr),
ntohs(least->port),
atomic_read(&least->activeconns), atomic_read(&least->activeconns),
atomic_read(&least->refcnt), atomic_read(&least->refcnt),
atomic_read(&least->weight), loh); atomic_read(&least->weight), loh);
......
...@@ -216,7 +216,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, ...@@ -216,7 +216,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
found: found:
IP_VS_DBG_BUF(6, "WRR: server %s:%u " IP_VS_DBG_BUF(6, "WRR: server %s:%u "
"activeconns %d refcnt %d weight %d\n", "activeconns %d refcnt %d weight %d\n",
IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
atomic_read(&dest->activeconns), atomic_read(&dest->activeconns),
atomic_read(&dest->refcnt), atomic_read(&dest->refcnt),
atomic_read(&dest->weight)); atomic_read(&dest->weight));
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment