Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Julian Anastasov and committed by
Pablo Neira Ayuso
cdcc5e90 882a844b

+28 -42
+5
include/linux/ip_vs.h
··· 89 89 #define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ 90 90 #define IP_VS_CONN_F_ONE_PACKET 0x2000 /* forward only one packet */ 91 91 92 + /* Initial bits allowed in backup server */ 92 93 #define IP_VS_CONN_F_BACKUP_MASK (IP_VS_CONN_F_FWD_MASK | \ 93 94 IP_VS_CONN_F_NOOUTPUT | \ 94 95 IP_VS_CONN_F_INACTIVE | \ ··· 97 96 IP_VS_CONN_F_NO_CPORT | \ 98 97 IP_VS_CONN_F_TEMPLATE \ 99 98 ) 99 + 100 + /* Bits allowed to update in backup server */ 101 + #define IP_VS_CONN_F_BACKUP_UPD_MASK (IP_VS_CONN_F_INACTIVE | \ 102 + IP_VS_CONN_F_SEQ_MASK) 100 103 101 104 /* Flags that are not sent to backup server start from bit 16 */ 102 105 #define IP_VS_CONN_F_NFCT (1 << 16) /* use netfilter conntrack */
+23 -42
net/netfilter/ipvs/ip_vs_sync.c
··· 731 731 else 732 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 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 759 * Find the appropriate destination for the connection. 739 760 * If it is not found the connection will remain unbound ··· 763 742 dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr, 764 743 param->vport, protocol, fwmark, flags); 765 744 766 - /* Set the approprite ativity flag */ 767 - if (protocol == IPPROTO_TCP) { 768 - if (state != IP_VS_TCP_S_ESTABLISHED) 769 - flags |= IP_VS_CONN_F_INACTIVE; 770 - else 771 - flags &= ~IP_VS_CONN_F_INACTIVE; 772 - } else if (protocol == IPPROTO_SCTP) { 773 - if (state != IP_VS_SCTP_S_ESTABLISHED) 774 - flags |= IP_VS_CONN_F_INACTIVE; 775 - else 776 - flags &= ~IP_VS_CONN_F_INACTIVE; 777 - } 778 745 cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); 779 746 if (dest) 780 747 atomic_dec(&dest->refcnt); ··· 771 762 kfree(param->pe_data); 772 763 IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); 773 764 return; 774 - } 775 - } else if (!cp->dest) { 776 - dest = ip_vs_try_bind_dest(cp); 777 - if (dest) 778 - atomic_dec(&dest->refcnt); 779 - } else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) && 780 - (cp->state != state)) { 781 - /* update active/inactive flag for the connection */ 782 - dest = cp->dest; 783 - if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && 784 - (state != IP_VS_TCP_S_ESTABLISHED)) { 785 - atomic_dec(&dest->activeconns); 786 - atomic_inc(&dest->inactconns); 787 - cp->flags |= IP_VS_CONN_F_INACTIVE; 788 - } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) && 789 - (state == IP_VS_TCP_S_ESTABLISHED)) { 790 - atomic_inc(&dest->activeconns); 791 - atomic_dec(&dest->inactconns); 792 - cp->flags &= ~IP_VS_CONN_F_INACTIVE; 793 - } 794 - } else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) && 795 - (cp->state != state)) { 796 - dest = cp->dest; 797 - if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && 798 - (state != IP_VS_SCTP_S_ESTABLISHED)) { 799 - atomic_dec(&dest->activeconns); 800 - atomic_inc(&dest->inactconns); 801 - cp->flags &= ~IP_VS_CONN_F_INACTIVE; 802 765 } 803 766 } 804 767