diff options
Diffstat (limited to 'net/ipv4/ipvs')
-rw-r--r-- | net/ipv4/ipvs/ip_vs_app.c | 9 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_conn.c | 73 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_core.c | 116 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_ctl.c | 39 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_est.c | 4 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_lblc.c | 36 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_lblcr.c | 36 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_proto.c | 2 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_proto_esp.c | 16 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_sched.c | 1 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_sync.c | 34 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_xmit.c | 16 |
12 files changed, 177 insertions, 205 deletions
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index 664cb8e97c1..535abe0c45e 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c @@ -51,18 +51,13 @@ static DEFINE_MUTEX(__ip_vs_app_mutex); */ static inline int ip_vs_app_get(struct ip_vs_app *app) { - /* test and get the module atomically */ - if (app->module) - return try_module_get(app->module); - else - return 1; + return try_module_get(app->module); } static inline void ip_vs_app_put(struct ip_vs_app *app) { - if (app->module) - module_put(app->module); + module_put(app->module); } diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 0a9f3c37e18..65f1ba11275 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c @@ -393,7 +393,15 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) atomic_inc(&dest->refcnt); /* Bind with the destination and its corresponding transmitter */ - cp->flags |= atomic_read(&dest->conn_flags); + if ((cp->flags & IP_VS_CONN_F_SYNC) && + (!(cp->flags & IP_VS_CONN_F_TEMPLATE))) + /* if the connection is not template and is created + * by sync, preserve the activity flag. + */ + cp->flags |= atomic_read(&dest->conn_flags) & + (~IP_VS_CONN_F_INACTIVE); + else + cp->flags |= atomic_read(&dest->conn_flags); cp->dest = dest; IP_VS_DBG(7, "Bind-dest %s c:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d " @@ -412,7 +420,11 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) /* It is a normal connection, so increase the inactive connection counter because it is in TCP SYNRECV state (inactive) or other protocol inacive state */ - atomic_inc(&dest->inactconns); + if ((cp->flags & IP_VS_CONN_F_SYNC) && + (!(cp->flags & IP_VS_CONN_F_INACTIVE))) + atomic_inc(&dest->activeconns); + else + atomic_inc(&dest->inactconns); } else { /* It is a persistent connection/template, so increase the peristent connection counter */ @@ -629,9 +641,7 @@ ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport } INIT_LIST_HEAD(&cp->c_list); - init_timer(&cp->timer); - cp->timer.data = (unsigned long)cp; - cp->timer.function = ip_vs_conn_expire; + setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp); cp->protocol = proto; cp->caddr = caddr; cp->cport = cport; @@ -783,6 +793,57 @@ static const struct file_operations ip_vs_conn_fops = { .llseek = seq_lseek, .release = seq_release, }; + +static const char *ip_vs_origin_name(unsigned flags) +{ + if (flags & IP_VS_CONN_F_SYNC) + return "SYNC"; + else + return "LOCAL"; +} + +static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) +{ + + if (v == SEQ_START_TOKEN) + seq_puts(seq, + "Pro FromIP FPrt ToIP TPrt DestIP DPrt State Origin Expires\n"); + else { + const struct ip_vs_conn *cp = v; + + seq_printf(seq, + "%-3s %08X %04X %08X %04X %08X %04X %-11s %-6s %7lu\n", + ip_vs_proto_name(cp->protocol), + ntohl(cp->caddr), ntohs(cp->cport), + ntohl(cp->vaddr), ntohs(cp->vport), + ntohl(cp->daddr), ntohs(cp->dport), + ip_vs_state_name(cp->protocol, cp->state), + ip_vs_origin_name(cp->flags), + (cp->timer.expires-jiffies)/HZ); + } + return 0; +} + +static const struct seq_operations ip_vs_conn_sync_seq_ops = { + .start = ip_vs_conn_seq_start, + .next = ip_vs_conn_seq_next, + .stop = ip_vs_conn_seq_stop, + .show = ip_vs_conn_sync_seq_show, +}; + +static int ip_vs_conn_sync_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &ip_vs_conn_sync_seq_ops); +} + +static const struct file_operations ip_vs_conn_sync_fops = { + .owner = THIS_MODULE, + .open = ip_vs_conn_sync_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + #endif @@ -942,6 +1003,7 @@ int ip_vs_conn_init(void) } proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops); + proc_net_fops_create(&init_net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops); /* calculate the random value for connection hash */ get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); @@ -958,5 +1020,6 @@ void ip_vs_conn_cleanup(void) /* Release the empty cache */ kmem_cache_destroy(ip_vs_conn_cachep); proc_net_remove(&init_net, "ip_vs_conn"); + proc_net_remove(&init_net, "ip_vs_conn_sync"); vfree(ip_vs_conn_tab); } diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 8fba20256f5..963981a9d50 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -423,7 +423,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, and the destination is RTN_UNICAST (and not local), then create a cache_bypass connection entry */ if (sysctl_ip_vs_cache_bypass && svc->fwmark - && (inet_addr_type(iph->daddr) == RTN_UNICAST)) { + && (inet_addr_type(&init_net, iph->daddr) == RTN_UNICAST)) { int ret, cs; struct ip_vs_conn *cp; @@ -481,7 +481,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, /* - * It is hooked before NF_IP_PRI_NAT_SRC at the NF_IP_POST_ROUTING + * It is hooked before NF_IP_PRI_NAT_SRC at the NF_INET_POST_ROUTING * chain, and is used for VS/NAT. * It detects packets for VS/NAT connections and sends the packets * immediately. This can avoid that iptable_nat mangles the packets @@ -679,7 +679,7 @@ static inline int is_tcp_reset(const struct sk_buff *skb) } /* - * It is hooked at the NF_IP_FORWARD chain, used only for VS/NAT. + * It is hooked at the NF_INET_FORWARD chain, used only for VS/NAT. * Check if outgoing packet belongs to the established ip_vs_conn, * rewrite addresses of the packet and send it on its way... */ @@ -814,7 +814,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) /* reassemble IP fragments */ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { - if (ip_vs_gather_frags(skb, hooknum == NF_IP_LOCAL_IN ? + if (ip_vs_gather_frags(skb, hooknum == NF_INET_LOCAL_IN ? IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD)) return NF_STOLEN; } @@ -1003,12 +1003,12 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, /* - * It is hooked at the NF_IP_FORWARD chain, in order to catch ICMP + * It is hooked at the NF_INET_FORWARD chain, in order to catch ICMP * related packets destined for 0.0.0.0/0. * When fwmark-based virtual service is used, such as transparent * cache cluster, TCP packets can be marked and routed to ip_vs_in, * but ICMP destined for 0.0.0.0/0 cannot not be easily marked and - * sent to ip_vs_in_icmp. So, catch them at the NF_IP_FORWARD chain + * sent to ip_vs_in_icmp. So, catch them at the NF_INET_FORWARD chain * and send them to ip_vs_in_icmp. */ static unsigned int @@ -1025,43 +1025,42 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, } -/* After packet filtering, forward packet through VS/DR, VS/TUN, - or VS/NAT(change destination), so that filtering rules can be - applied to IPVS. */ -static struct nf_hook_ops ip_vs_in_ops = { - .hook = ip_vs_in, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_LOCAL_IN, - .priority = 100, -}; - -/* After packet filtering, change source only for VS/NAT */ -static struct nf_hook_ops ip_vs_out_ops = { - .hook = ip_vs_out, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_FORWARD, - .priority = 100, -}; - -/* After packet filtering (but before ip_vs_out_icmp), catch icmp - destined for 0.0.0.0/0, which is for incoming IPVS connections */ -static struct nf_hook_ops ip_vs_forward_icmp_ops = { - .hook = ip_vs_forward_icmp, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_FORWARD, - .priority = 99, -}; - -/* Before the netfilter connection tracking, exit from POST_ROUTING */ -static struct nf_hook_ops ip_vs_post_routing_ops = { - .hook = ip_vs_post_routing, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_IP_POST_ROUTING, - .priority = NF_IP_PRI_NAT_SRC-1, +static struct nf_hook_ops ip_vs_ops[] __read_mostly = { + /* After packet filtering, forward packet through VS/DR, VS/TUN, + * or VS/NAT(change destination), so that filtering rules can be + * applied to IPVS. */ + { + .hook = ip_vs_in, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_LOCAL_IN, + .priority = 100, + }, + /* After packet filtering, change source only for VS/NAT */ + { + .hook = ip_vs_out, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_FORWARD, + .priority = 100, + }, + /* After packet filtering (but before ip_vs_out_icmp), catch icmp + * destined for 0.0.0.0/0, which is for incoming IPVS connections */ + { + .hook = ip_vs_forward_icmp, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_FORWARD, + .priority = 99, + }, + /* Before the netfilter connection tracking, exit from POST_ROUTING */ + { + .hook = ip_vs_post_routing, + .owner = THIS_MODULE, + .pf = PF_INET, + .hooknum = NF_INET_POST_ROUTING, + .priority = NF_IP_PRI_NAT_SRC-1, + }, }; @@ -1092,37 +1091,15 @@ static int __init ip_vs_init(void) goto cleanup_app; } - ret = nf_register_hook(&ip_vs_in_ops); + ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); if (ret < 0) { - IP_VS_ERR("can't register in hook.\n"); + IP_VS_ERR("can't register hooks.\n"); goto cleanup_conn; } - ret = nf_register_hook(&ip_vs_out_ops); - if (ret < 0) { - IP_VS_ERR("can't register out hook.\n"); - goto cleanup_inops; - } - ret = nf_register_hook(&ip_vs_post_routing_ops); - if (ret < 0) { - IP_VS_ERR("can't register post_routing hook.\n"); - goto cleanup_outops; - } - ret = nf_register_hook(&ip_vs_forward_icmp_ops); - if (ret < 0) { - IP_VS_ERR("can't register forward_icmp hook.\n"); - goto cleanup_postroutingops; - } - IP_VS_INFO("ipvs loaded.\n"); return ret; - cleanup_postroutingops: - nf_unregister_hook(&ip_vs_post_routing_ops); - cleanup_outops: - nf_unregister_hook(&ip_vs_out_ops); - cleanup_inops: - nf_unregister_hook(&ip_vs_in_ops); cleanup_conn: ip_vs_conn_cleanup(); cleanup_app: @@ -1136,10 +1113,7 @@ static int __init ip_vs_init(void) static void __exit ip_vs_cleanup(void) { - nf_unregister_hook(&ip_vs_forward_icmp_ops); - nf_unregister_hook(&ip_vs_post_routing_ops); - nf_unregister_hook(&ip_vs_out_ops); - nf_unregister_hook(&ip_vs_in_ops); + nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); ip_vs_conn_cleanup(); ip_vs_app_cleanup(); ip_vs_protocol_cleanup(); diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 693d92490c1..94c5767c8e0 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -704,7 +704,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE; /* check if local node and update the flags */ - if (inet_addr_type(udest->addr) == RTN_LOCAL) { + if (inet_addr_type(&init_net, udest->addr) == RTN_LOCAL) { conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK) | IP_VS_CONN_F_LOCALNODE; } @@ -756,7 +756,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest, EnterFunction(2); - atype = inet_addr_type(udest->addr); + atype = inet_addr_type(&init_net, udest->addr); if (atype != RTN_LOCAL && atype != RTN_UNICAST) return -EINVAL; @@ -1591,34 +1591,13 @@ static struct ctl_table vs_vars[] = { { .ctl_name = 0 } }; -static ctl_table vs_table[] = { - { - .procname = "vs", - .mode = 0555, - .child = vs_vars - }, - { .ctl_name = 0 } -}; - -static ctl_table ipvs_ipv4_table[] = { - { - .ctl_name = NET_IPV4, - .procname = "ipv4", - .mode = 0555, - .child = vs_table, - }, - { .ctl_name = 0 } -}; - -static ctl_table vs_root_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .mode = 0555, - .child = ipvs_ipv4_table, - }, - { .ctl_name = 0 } +struct ctl_path net_vs_ctl_path[] = { + { .procname = "net", .ctl_name = CTL_NET, }, + { .procname = "ipv4", .ctl_name = NET_IPV4, }, + { .procname = "vs", }, + { } }; +EXPORT_SYMBOL_GPL(net_vs_ctl_path); static struct ctl_table_header * sysctl_header; @@ -2345,7 +2324,7 @@ int ip_vs_control_init(void) proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops); proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops); - sysctl_header = register_sysctl_table(vs_root_table); + sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars); /* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */ for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c index 7d68b80c4c1..dfa0d713c80 100644 --- a/net/ipv4/ipvs/ip_vs_est.c +++ b/net/ipv4/ipvs/ip_vs_est.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/interrupt.h> +#include <linux/sysctl.h> #include <net/ip_vs.h> @@ -146,9 +147,8 @@ int ip_vs_new_estimator(struct ip_vs_stats *stats) write_lock_bh(&est_lock); est->next = est_list; if (est->next == NULL) { - init_timer(&est_timer); + setup_timer(&est_timer, estimation_timer, 0); est_timer.expires = jiffies + 2*HZ; - est_timer.function = estimation_timer; add_timer(&est_timer); } est_list = est; diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index ad89644ef5d..3888642706a 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c @@ -123,35 +123,6 @@ static ctl_table vs_vars_table[] = { { .ctl_name = 0 } }; -static ctl_table vs_table[] = { - { - .procname = "vs", - .mode = 0555, - .child = vs_vars_table - }, - { .ctl_name = 0 } -}; - -static ctl_table ipvs_ipv4_table[] = { - { - .ctl_name = NET_IPV4, - .procname = "ipv4", - .mode = 0555, - .child = vs_table - }, - { .ctl_name = 0 } -}; - -static ctl_table lblc_root_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .mode = 0555, - .child = ipvs_ipv4_table - }, - { .ctl_name = 0 } -}; - static struct ctl_table_header * sysctl_header; /* @@ -391,9 +362,8 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc) /* * Hook periodic timer for garbage collection */ - init_timer(&tbl->periodic_timer); - tbl->periodic_timer.data = (unsigned long)tbl; - tbl->periodic_timer.function = ip_vs_lblc_check_expire; + setup_timer(&tbl->periodic_timer, ip_vs_lblc_check_expire, + (unsigned long)tbl); tbl->periodic_timer.expires = jiffies+CHECK_EXPIRE_INTERVAL; add_timer(&tbl->periodic_timer); @@ -583,7 +553,7 @@ static int __init ip_vs_lblc_init(void) int ret; INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list); - sysctl_header = register_sysctl_table(lblc_root_table); + sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table); ret = register_ip_vs_scheduler(&ip_vs_lblc_scheduler); if (ret) unregister_sysctl_table(sysctl_header); diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index 2a5ed85a335..daa260eb21c 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c @@ -311,35 +311,6 @@ static ctl_table vs_vars_table[] = { { .ctl_name = 0 } }; -static ctl_table vs_table[] = { - { - .procname = "vs", - .mode = 0555, - .child = vs_vars_table - }, - { .ctl_name = 0 } -}; - -static ctl_table ipvs_ipv4_table[] = { - { - .ctl_name = NET_IPV4, - .procname = "ipv4", - .mode = 0555, - .child = vs_table - }, - { .ctl_name = 0 } -}; - -static ctl_table lblcr_root_table[] = { - { - .ctl_name = CTL_NET, - .procname = "net", - .mode = 0555, - .child = ipvs_ipv4_table - }, - { .ctl_name = 0 } -}; - static struct ctl_table_header * sysctl_header; /* @@ -575,9 +546,8 @@ static int ip_vs_lblcr_init_svc(struct ip_vs_service *svc) /* * Hook periodic timer for garbage collection */ - init_timer(&tbl->periodic_timer); - tbl->periodic_timer.data = (unsigned long)tbl; - tbl->periodic_timer.function = ip_vs_lblcr_check_expire; + setup_timer(&tbl->periodic_timer, ip_vs_lblcr_check_expire, + (unsigned long)tbl); tbl->periodic_timer.expires = jiffies+CHECK_EXPIRE_INTERVAL; add_timer(&tbl->periodic_timer); @@ -772,7 +742,7 @@ static int __init ip_vs_lblcr_init(void) int ret; INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list); - sysctl_header = register_sysctl_table(lblcr_root_table); + sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table); ret = register_ip_vs_scheduler(&ip_vs_lblcr_scheduler); if (ret) unregister_sysctl_table(sysctl_header); diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c index c0e11ec8f0f..dde28a250d9 100644 --- a/net/ipv4/ipvs/ip_vs_proto.c +++ b/net/ipv4/ipvs/ip_vs_proto.c @@ -165,7 +165,7 @@ ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp, ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); if (ih == NULL) sprintf(buf, "%s TRUNCATED", pp->name); - else if (ih->frag_off & __constant_htons(IP_OFFSET)) + else if (ih->frag_off & htons(IP_OFFSET)) sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag", pp->name, NIPQUAD(ih->saddr), NIPQUAD(ih->daddr)); diff --git a/net/ipv4/ipvs/ip_vs_proto_esp.c b/net/ipv4/ipvs/ip_vs_proto_esp.c index c36ccf057a1..aef0d3ee8e4 100644 --- a/net/ipv4/ipvs/ip_vs_proto_esp.c +++ b/net/ipv4/ipvs/ip_vs_proto_esp.c @@ -52,15 +52,15 @@ esp_conn_in_get(const struct sk_buff *skb, if (likely(!inverse)) { cp = ip_vs_conn_in_get(IPPROTO_UDP, iph->saddr, - __constant_htons(PORT_ISAKMP), + htons(PORT_ISAKMP), iph->daddr, - __constant_htons(PORT_ISAKMP)); + htons(PORT_ISAKMP)); } else { cp = ip_vs_conn_in_get(IPPROTO_UDP, iph->daddr, - __constant_htons(PORT_ISAKMP), + htons(PORT_ISAKMP), iph->saddr, - __constant_htons(PORT_ISAKMP)); + htons(PORT_ISAKMP)); } if (!cp) { @@ -89,15 +89,15 @@ esp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, if (likely(!inverse)) { cp = ip_vs_conn_out_get(IPPROTO_UDP, iph->saddr, - __constant_htons(PORT_ISAKMP), + htons(PORT_ISAKMP), iph->daddr, - __constant_htons(PORT_ISAKMP)); + htons(PORT_ISAKMP)); } else { cp = ip_vs_conn_out_get(IPPROTO_UDP, iph->daddr, - __constant_htons(PORT_ISAKMP), + htons(PORT_ISAKMP), iph->saddr, - __constant_htons(PORT_ISAKMP)); + htons(PORT_ISAKMP)); } if (!cp) { diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c index 43223586190..121a32b1b75 100644 --- a/net/ipv4/ipvs/ip_vs_sched.c +++ b/net/ipv4/ipvs/ip_vs_sched.c @@ -24,6 +24,7 @@ #include <linux/interrupt.h> #include <asm/string.h> #include <linux/kmod.h> +#include <linux/sysctl.h> #include <net/ip_vs.h> diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index bd930efc18d..948378d0a75 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -305,10 +305,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); for (i=0; i<m->nr_conns; i++) { - unsigned flags; + unsigned flags, state; s = (struct ip_vs_sync_conn *)p; - flags = ntohs(s->flags); + flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC; + state = ntohs(s->state); if (!(flags & IP_VS_CONN_F_TEMPLATE)) cp = ip_vs_conn_in_get(s->protocol, s->caddr, s->cport, @@ -326,6 +327,13 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) dest = ip_vs_find_dest(s->daddr, s->dport, s->vaddr, s->vport, s->protocol); + /* Set the approprite ativity flag */ + if (s->protocol == IPPROTO_TCP) { + if (state != IP_VS_TCP_S_ESTABLISHED) + flags |= IP_VS_CONN_F_INACTIVE; + else + flags &= ~IP_VS_CONN_F_INACTIVE; + } cp = ip_vs_conn_new(s->protocol, s->caddr, s->cport, s->vaddr, s->vport, @@ -337,7 +345,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) IP_VS_ERR("ip_vs_conn_new failed\n"); return; } - cp->state = ntohs(s->state); + cp->state = state; } else if (!cp->dest) { dest = ip_vs_try_bind_dest(cp); if (!dest) { @@ -346,8 +354,22 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) cp->flags = flags | IP_VS_CONN_F_HASHED; } else atomic_dec(&dest->refcnt); - } /* Note that we don't touch its state and flags - if it is a normal entry. */ + } else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) && + (cp->state != state)) { + /* update active/inactive flag for the connection */ + dest = cp->dest; + if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && + (state != IP_VS_TCP_S_ESTABLISHED)) { + atomic_dec(&dest->activeconns); + atomic_inc(&dest->inactconns); + cp->flags |= IP_VS_CONN_F_INACTIVE; + } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) && + (state == IP_VS_TCP_S_ESTABLISHED)) { + atomic_inc(&dest->activeconns); + atomic_dec(&dest->inactconns); + cp->flags &= ~IP_VS_CONN_F_INACTIVE; + } + } if (flags & IP_VS_CONN_F_SEQ_MASK) { opt = (struct ip_vs_sync_conn_options *)&s[1]; @@ -357,7 +379,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) p += SIMPLE_CONN_SIZE; atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]); - cp->state = ntohs(s->state); + cp->state = state; pp = ip_vs_proto_get(s->protocol); cp->timeout = pp->timeout_table[cp->state]; ip_vs_conn_put(cp); diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index 7c074e386c1..f63006caea0 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c @@ -16,8 +16,8 @@ */ #include <linux/kernel.h> -#include <linux/ip.h> #include <linux/tcp.h> /* for tcphdr */ +#include <net/ip.h> #include <net/tcp.h> /* for csum_tcpudp_magic */ #include <net/udp.h> #include <net/icmp.h> /* for icmp_send */ @@ -59,7 +59,7 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos, u32 cookie) return dst; } -static inline struct rtable * +static struct rtable * __ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) { struct rtable *rt; /* Route to the other host */ @@ -78,7 +78,7 @@ __ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) .tos = rtos, } }, }; - if (ip_route_output_key(&rt, &fl)) { + if (ip_route_output_key(&init_net, &rt, &fl)) { spin_unlock(&dest->dst_lock); IP_VS_DBG_RL("ip_route_output error, " "dest: %u.%u.%u.%u\n", @@ -101,7 +101,7 @@ __ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) .tos = rtos, } }, }; - if (ip_route_output_key(&rt, &fl)) { + if (ip_route_output_key(&init_net, &rt, &fl)) { IP_VS_DBG_RL("ip_route_output error, dest: " "%u.%u.%u.%u\n", NIPQUAD(cp->daddr)); return NULL; @@ -129,7 +129,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) do { \ (skb)->ipvs_property = 1; \ skb_forward_csum(skb); \ - NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \ + NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, (skb), NULL, \ (rt)->u.dst.dev, dst_output); \ } while (0) @@ -170,7 +170,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, EnterFunction(10); - if (ip_route_output_key(&rt, &fl)) { + if (ip_route_output_key(&init_net, &rt, &fl)) { IP_VS_DBG_RL("ip_vs_bypass_xmit(): ip_route_output error, " "dest: %u.%u.%u.%u\n", NIPQUAD(iph->daddr)); goto tx_error_icmp; @@ -406,14 +406,12 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, iph->daddr = rt->rt_dst; iph->saddr = rt->rt_src; iph->ttl = old_iph->ttl; - iph->tot_len = htons(skb->len); ip_select_ident(iph, &rt->u.dst, NULL); - ip_send_check(iph); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; - IP_VS_XMIT(skb, rt); + ip_local_out(skb); LeaveFunction(10); |