X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv4%2Fipvs%2Fip_vs_sync.c;h=69c56663cc9a90645cdcfab47495261f01e70e99;hb=03414e57ad9875d0c8bfa5a4a65813cb2157372e;hp=3b0d32291d5ec66c2dc2f3bc432bed4c453d928d;hpb=ba25f9dcc4ea6e30839fcab5a5516f2176d5bfed;p=linux-2.6 diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 3b0d32291d..69c56663cc 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -72,7 +72,6 @@ struct ip_vs_sync_thread_data { int state; }; -#define IP_VS_SYNC_CONN_TIMEOUT (3*60*HZ) #define SIMPLE_CONN_SIZE (sizeof(struct ip_vs_sync_conn)) #define FULL_CONN_SIZE \ (sizeof(struct ip_vs_sync_conn) + sizeof(struct ip_vs_sync_conn_options)) @@ -284,6 +283,8 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) struct ip_vs_sync_conn *s; struct ip_vs_sync_conn_options *opt; struct ip_vs_conn *cp; + struct ip_vs_protocol *pp; + struct ip_vs_dest *dest; char *p; int i; @@ -304,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; inr_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, @@ -317,22 +319,57 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) s->caddr, s->cport, s->vaddr, s->vport); if (!cp) { + /* + * Find the appropriate destination for the connection. + * If it is not found the connection will remain unbound + * but still handled. + */ + 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, s->daddr, s->dport, - flags, NULL); + flags, dest); + if (dest) + atomic_dec(&dest->refcnt); if (!cp) { IP_VS_ERR("ip_vs_conn_new failed\n"); return; } - cp->state = ntohs(s->state); + cp->state = state; } else if (!cp->dest) { - /* it is an entry created by the synchronization */ - cp->state = ntohs(s->state); - cp->flags = flags | IP_VS_CONN_F_HASHED; - } /* Note that we don't touch its state and flags - if it is a normal entry. */ + dest = ip_vs_try_bind_dest(cp); + if (!dest) { + /* it is an unbound entry created by + * synchronization */ + cp->flags = flags | IP_VS_CONN_F_HASHED; + } else + atomic_dec(&dest->refcnt); + } 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]; @@ -342,7 +379,9 @@ 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->timeout = IP_VS_SYNC_CONN_TIMEOUT; + cp->state = state; + pp = ip_vs_proto_get(s->protocol); + cp->timeout = pp->timeout_table[cp->state]; ip_vs_conn_put(cp); if (p > buffer+buflen) { @@ -794,7 +833,7 @@ static int sync_thread(void *startup) add_wait_queue(&sync_wait, &wait); - set_sync_pid(state, current->pid); + set_sync_pid(state, task_pid_nr(current)); complete(tinfo->startup); /* @@ -877,7 +916,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid) if (!tinfo) return -ENOMEM; - IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current)); + IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current)); IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n", sizeof(struct ip_vs_sync_conn)); @@ -917,7 +956,7 @@ int stop_sync_thread(int state) (state == IP_VS_STATE_BACKUP && !sync_backup_pid)) return -ESRCH; - IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, task_pid_nr(current)); + IP_VS_DBG(7, "%s: pid %d\n", __func__, task_pid_nr(current)); IP_VS_INFO("stopping sync thread %d ...\n", (state == IP_VS_STATE_MASTER) ? sync_master_pid : sync_backup_pid);