diff options
author | Rumen G. Bogdanovski <rumen@voicecho.com> | 2007-11-20 00:53:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:54:21 -0500 |
commit | b209639e8a91aaabedf8bf3716710e6d9ae942e3 (patch) | |
tree | 53614de391f67fab8fdbaf13d7d05306c17e9c76 /net/ipv4/ipvs | |
parent | 7a4fbb1fa46e1a84c246e7bcd99bff45935bf114 (diff) |
[IPVS]: Create synced connections with their real state
With this patch the synced connections are created with their real state,
which can be changed on the next synchronizations if necessary. This way
on fail-over all the connections will be treated according to their actual
state, causing no scheduling problems (the active and the nonactive
connections have different weights in the schedulers).
The backwards compatibility is preserved and the existing tools will show
the true connection states even on the backup director.
Signed-off-by: Rumen G. Bogdanovski <rumen@voicecho.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipvs')
-rw-r--r-- | net/ipv4/ipvs/ip_vs_conn.c | 16 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_sync.c | 32 |
2 files changed, 41 insertions, 7 deletions
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 45a642edb93b..65f1ba112752 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) | |||
393 | atomic_inc(&dest->refcnt); | 393 | atomic_inc(&dest->refcnt); |
394 | 394 | ||
395 | /* Bind with the destination and its corresponding transmitter */ | 395 | /* Bind with the destination and its corresponding transmitter */ |
396 | cp->flags |= atomic_read(&dest->conn_flags); | 396 | if ((cp->flags & IP_VS_CONN_F_SYNC) && |
397 | (!(cp->flags & IP_VS_CONN_F_TEMPLATE))) | ||
398 | /* if the connection is not template and is created | ||
399 | * by sync, preserve the activity flag. | ||
400 | */ | ||
401 | cp->flags |= atomic_read(&dest->conn_flags) & | ||
402 | (~IP_VS_CONN_F_INACTIVE); | ||
403 | else | ||
404 | cp->flags |= atomic_read(&dest->conn_flags); | ||
397 | cp->dest = dest; | 405 | cp->dest = dest; |
398 | 406 | ||
399 | IP_VS_DBG(7, "Bind-dest %s c:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d " | 407 | 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) | |||
412 | /* It is a normal connection, so increase the inactive | 420 | /* It is a normal connection, so increase the inactive |
413 | connection counter because it is in TCP SYNRECV | 421 | connection counter because it is in TCP SYNRECV |
414 | state (inactive) or other protocol inacive state */ | 422 | state (inactive) or other protocol inacive state */ |
415 | atomic_inc(&dest->inactconns); | 423 | if ((cp->flags & IP_VS_CONN_F_SYNC) && |
424 | (!(cp->flags & IP_VS_CONN_F_INACTIVE))) | ||
425 | atomic_inc(&dest->activeconns); | ||
426 | else | ||
427 | atomic_inc(&dest->inactconns); | ||
416 | } else { | 428 | } else { |
417 | /* It is a persistent connection/template, so increase | 429 | /* It is a persistent connection/template, so increase |
418 | the peristent connection counter */ | 430 | the peristent connection counter */ |
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 47b7f8f3ae79..948378d0a755 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) | |||
305 | 305 | ||
306 | p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); | 306 | p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); |
307 | for (i=0; i<m->nr_conns; i++) { | 307 | for (i=0; i<m->nr_conns; i++) { |
308 | unsigned flags; | 308 | unsigned flags, state; |
309 | 309 | ||
310 | s = (struct ip_vs_sync_conn *)p; | 310 | s = (struct ip_vs_sync_conn *)p; |
311 | flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC; | 311 | flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC; |
312 | state = ntohs(s->state); | ||
312 | if (!(flags & IP_VS_CONN_F_TEMPLATE)) | 313 | if (!(flags & IP_VS_CONN_F_TEMPLATE)) |
313 | cp = ip_vs_conn_in_get(s->protocol, | 314 | cp = ip_vs_conn_in_get(s->protocol, |
314 | s->caddr, s->cport, | 315 | s->caddr, s->cport, |
@@ -326,6 +327,13 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) | |||
326 | dest = ip_vs_find_dest(s->daddr, s->dport, | 327 | dest = ip_vs_find_dest(s->daddr, s->dport, |
327 | s->vaddr, s->vport, | 328 | s->vaddr, s->vport, |
328 | s->protocol); | 329 | s->protocol); |
330 | /* Set the approprite ativity flag */ | ||
331 | if (s->protocol == IPPROTO_TCP) { | ||
332 | if (state != IP_VS_TCP_S_ESTABLISHED) | ||
333 | flags |= IP_VS_CONN_F_INACTIVE; | ||
334 | else | ||
335 | flags &= ~IP_VS_CONN_F_INACTIVE; | ||
336 | } | ||
329 | cp = ip_vs_conn_new(s->protocol, | 337 | cp = ip_vs_conn_new(s->protocol, |
330 | s->caddr, s->cport, | 338 | s->caddr, s->cport, |
331 | s->vaddr, s->vport, | 339 | s->vaddr, s->vport, |
@@ -337,7 +345,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) | |||
337 | IP_VS_ERR("ip_vs_conn_new failed\n"); | 345 | IP_VS_ERR("ip_vs_conn_new failed\n"); |
338 | return; | 346 | return; |
339 | } | 347 | } |
340 | cp->state = ntohs(s->state); | 348 | cp->state = state; |
341 | } else if (!cp->dest) { | 349 | } else if (!cp->dest) { |
342 | dest = ip_vs_try_bind_dest(cp); | 350 | dest = ip_vs_try_bind_dest(cp); |
343 | if (!dest) { | 351 | if (!dest) { |
@@ -346,8 +354,22 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) | |||
346 | cp->flags = flags | IP_VS_CONN_F_HASHED; | 354 | cp->flags = flags | IP_VS_CONN_F_HASHED; |
347 | } else | 355 | } else |
348 | atomic_dec(&dest->refcnt); | 356 | atomic_dec(&dest->refcnt); |
349 | } /* Note that we don't touch its state and flags | 357 | } else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) && |
350 | if it is a normal entry. */ | 358 | (cp->state != state)) { |
359 | /* update active/inactive flag for the connection */ | ||
360 | dest = cp->dest; | ||
361 | if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && | ||
362 | (state != IP_VS_TCP_S_ESTABLISHED)) { | ||
363 | atomic_dec(&dest->activeconns); | ||
364 | atomic_inc(&dest->inactconns); | ||
365 | cp->flags |= IP_VS_CONN_F_INACTIVE; | ||
366 | } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) && | ||
367 | (state == IP_VS_TCP_S_ESTABLISHED)) { | ||
368 | atomic_inc(&dest->activeconns); | ||
369 | atomic_dec(&dest->inactconns); | ||
370 | cp->flags &= ~IP_VS_CONN_F_INACTIVE; | ||
371 | } | ||
372 | } | ||
351 | 373 | ||
352 | if (flags & IP_VS_CONN_F_SEQ_MASK) { | 374 | if (flags & IP_VS_CONN_F_SEQ_MASK) { |
353 | opt = (struct ip_vs_sync_conn_options *)&s[1]; | 375 | 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) | |||
357 | p += SIMPLE_CONN_SIZE; | 379 | p += SIMPLE_CONN_SIZE; |
358 | 380 | ||
359 | atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]); | 381 | atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]); |
360 | cp->state = ntohs(s->state); | 382 | cp->state = state; |
361 | pp = ip_vs_proto_get(s->protocol); | 383 | pp = ip_vs_proto_get(s->protocol); |
362 | cp->timeout = pp->timeout_table[cp->state]; | 384 | cp->timeout = pp->timeout_table[cp->state]; |
363 | ip_vs_conn_put(cp); | 385 | ip_vs_conn_put(cp); |