diff options
author | Julian Anastasov <ja@ssi.bg> | 2012-04-24 16:46:38 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-05-08 13:38:31 -0400 |
commit | cdcc5e905d59026fbf2e7f74f9cc834203b6207b (patch) | |
tree | 3f8c6440384a2d0e753d35f51e344269953a986a | |
parent | 882a844bd5b3ffa35e059f21ee920cc113985a89 (diff) |
ipvs: always update some of the flags bits in backup
As the goal is to mirror the inactconns/activeconns
counters in the backup server, make sure the cp->flags are
updated even if cp is still not bound to dest. If cp->flags
are not updated ip_vs_bind_dest will rely only on the initial
flags when updating the counters. To avoid mistakes and
complicated checks for protocol state rely only on the
IP_VS_CONN_F_INACTIVE bit when updating the counters.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Tested-by: Aleksey Chudov <aleksey.chudov@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r-- | include/linux/ip_vs.h | 5 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 65 |
2 files changed, 28 insertions, 42 deletions
diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h index be0ef3df4acb..8a2d438dc499 100644 --- a/include/linux/ip_vs.h +++ b/include/linux/ip_vs.h | |||
@@ -89,6 +89,7 @@ | |||
89 | #define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ | 89 | #define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ |
90 | #define IP_VS_CONN_F_ONE_PACKET 0x2000 /* forward only one packet */ | 90 | #define IP_VS_CONN_F_ONE_PACKET 0x2000 /* forward only one packet */ |
91 | 91 | ||
92 | /* Initial bits allowed in backup server */ | ||
92 | #define IP_VS_CONN_F_BACKUP_MASK (IP_VS_CONN_F_FWD_MASK | \ | 93 | #define IP_VS_CONN_F_BACKUP_MASK (IP_VS_CONN_F_FWD_MASK | \ |
93 | IP_VS_CONN_F_NOOUTPUT | \ | 94 | IP_VS_CONN_F_NOOUTPUT | \ |
94 | IP_VS_CONN_F_INACTIVE | \ | 95 | IP_VS_CONN_F_INACTIVE | \ |
@@ -97,6 +98,10 @@ | |||
97 | IP_VS_CONN_F_TEMPLATE \ | 98 | IP_VS_CONN_F_TEMPLATE \ |
98 | ) | 99 | ) |
99 | 100 | ||
101 | /* Bits allowed to update in backup server */ | ||
102 | #define IP_VS_CONN_F_BACKUP_UPD_MASK (IP_VS_CONN_F_INACTIVE | \ | ||
103 | IP_VS_CONN_F_SEQ_MASK) | ||
104 | |||
100 | /* Flags that are not sent to backup server start from bit 16 */ | 105 | /* Flags that are not sent to backup server start from bit 16 */ |
101 | #define IP_VS_CONN_F_NFCT (1 << 16) /* use netfilter conntrack */ | 106 | #define IP_VS_CONN_F_NFCT (1 << 16) /* use netfilter conntrack */ |
102 | 107 | ||
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index bf5e538af67b..d2df694405f1 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -731,9 +731,30 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, | |||
731 | else | 731 | else |
732 | cp = ip_vs_ct_in_get(param); | 732 | cp = ip_vs_ct_in_get(param); |
733 | 733 | ||
734 | if (cp && param->pe_data) /* Free pe_data */ | 734 | if (cp) { |
735 | /* Free pe_data */ | ||
735 | kfree(param->pe_data); | 736 | kfree(param->pe_data); |
736 | if (!cp) { | 737 | |
738 | dest = cp->dest; | ||
739 | if ((cp->flags ^ flags) & IP_VS_CONN_F_INACTIVE && | ||
740 | !(flags & IP_VS_CONN_F_TEMPLATE) && dest) { | ||
741 | if (flags & IP_VS_CONN_F_INACTIVE) { | ||
742 | atomic_dec(&dest->activeconns); | ||
743 | atomic_inc(&dest->inactconns); | ||
744 | } else { | ||
745 | atomic_inc(&dest->activeconns); | ||
746 | atomic_dec(&dest->inactconns); | ||
747 | } | ||
748 | } | ||
749 | flags &= IP_VS_CONN_F_BACKUP_UPD_MASK; | ||
750 | flags |= cp->flags & ~IP_VS_CONN_F_BACKUP_UPD_MASK; | ||
751 | cp->flags = flags; | ||
752 | if (!dest) { | ||
753 | dest = ip_vs_try_bind_dest(cp); | ||
754 | if (dest) | ||
755 | atomic_dec(&dest->refcnt); | ||
756 | } | ||
757 | } else { | ||
737 | /* | 758 | /* |
738 | * Find the appropriate destination for the connection. | 759 | * Find the appropriate destination for the connection. |
739 | * If it is not found the connection will remain unbound | 760 | * If it is not found the connection will remain unbound |
@@ -742,18 +763,6 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, | |||
742 | dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr, | 763 | dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr, |
743 | param->vport, protocol, fwmark, flags); | 764 | param->vport, protocol, fwmark, flags); |
744 | 765 | ||
745 | /* Set the approprite ativity flag */ | ||
746 | if (protocol == IPPROTO_TCP) { | ||
747 | if (state != IP_VS_TCP_S_ESTABLISHED) | ||
748 | flags |= IP_VS_CONN_F_INACTIVE; | ||
749 | else | ||
750 | flags &= ~IP_VS_CONN_F_INACTIVE; | ||
751 | } else if (protocol == IPPROTO_SCTP) { | ||
752 | if (state != IP_VS_SCTP_S_ESTABLISHED) | ||
753 | flags |= IP_VS_CONN_F_INACTIVE; | ||
754 | else | ||
755 | flags &= ~IP_VS_CONN_F_INACTIVE; | ||
756 | } | ||
757 | cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); | 766 | cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); |
758 | if (dest) | 767 | if (dest) |
759 | atomic_dec(&dest->refcnt); | 768 | atomic_dec(&dest->refcnt); |
@@ -763,34 +772,6 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, | |||
763 | IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); | 772 | IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); |
764 | return; | 773 | return; |
765 | } | 774 | } |
766 | } else if (!cp->dest) { | ||
767 | dest = ip_vs_try_bind_dest(cp); | ||
768 | if (dest) | ||
769 | atomic_dec(&dest->refcnt); | ||
770 | } else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) && | ||
771 | (cp->state != state)) { | ||
772 | /* update active/inactive flag for the connection */ | ||
773 | dest = cp->dest; | ||
774 | if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && | ||
775 | (state != IP_VS_TCP_S_ESTABLISHED)) { | ||
776 | atomic_dec(&dest->activeconns); | ||
777 | atomic_inc(&dest->inactconns); | ||
778 | cp->flags |= IP_VS_CONN_F_INACTIVE; | ||
779 | } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) && | ||
780 | (state == IP_VS_TCP_S_ESTABLISHED)) { | ||
781 | atomic_inc(&dest->activeconns); | ||
782 | atomic_dec(&dest->inactconns); | ||
783 | cp->flags &= ~IP_VS_CONN_F_INACTIVE; | ||
784 | } | ||
785 | } else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) && | ||
786 | (cp->state != state)) { | ||
787 | dest = cp->dest; | ||
788 | if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && | ||
789 | (state != IP_VS_SCTP_S_ESTABLISHED)) { | ||
790 | atomic_dec(&dest->activeconns); | ||
791 | atomic_inc(&dest->inactconns); | ||
792 | cp->flags &= ~IP_VS_CONN_F_INACTIVE; | ||
793 | } | ||
794 | } | 775 | } |
795 | 776 | ||
796 | if (opt) | 777 | if (opt) |