Hello,
On Mon, 16 May 2016, Marco Angaroni wrote:
> Previous patch that introduced handling of outgoing packets in SIP
> persistent-engine did not call ip_vs_check_template() in case packet was
> matching a connection template. Assumption was that real-server was
> healthy, since it was sending a packet just in that moment.
>
> There are however real-server fault conditions requiring that association
> between call-id and real-server (represented by connection template)
> gets updated. Here is an example of the sequence of events:
> 1) RS1 is a back2back user agent that handled call-id1 and call-id2
> 2) RS1 is down and was marked as unavailable
> 3) new message from outside comes to IPVS with call-id1
> 4) IPVS reschedules the message to RS2, which becomes new call handler
> 5) RS2 forwards the message outside, translating call-id1 to call-id2
> 6) inside pe->conn_out() IPVS matches call-id2 with existing template
> 7) IPVS does not change association call-id2 <-> RS1
> 8) new message comes from client with call-id2
> 9) IPVS reschedules the message to a real-server potentially different
> from RS2, which is now the correct destination
>
> This patch introduces ip_vs_check_template() call in the handling of
> outgoing packets for SIP-pe. And also introduces a second optional
> argument for ip_vs_check_template() that allows to check if dest
> associated to a connection template is the same dest that was identified
> as the source of the packet. This is to change the real-server bound to a
> particular call-id independently from its availability status: the idea
> is that it's more reliable, for in->out direction (where internal
> network can be considered trusted), to always associate a call-id with
> the last real-server that used it in one of its messages. Think about
> above sequence of events where, just after step 5, RS1 returns instead
> to be available.
>
> Comparison of dests is done by simply comparing pointers to struct
> ip_vs_dest; there should be no cases where struct ip_vs_dest keeps its
> memory address, but represent a different real-server in terms of
> ip-address / port.
>
> Signed-off-by: Marco Angaroni <marcoangaroni@xxxxxxxxx>
Looks good to me.
Acked-by: Julian Anastasov <ja@xxxxxx>
> ---
> include/net/ip_vs.h | 2 +-
> net/netfilter/ipvs/ip_vs_conn.c | 5 +++--
> net/netfilter/ipvs/ip_vs_core.c | 5 +++--
> 3 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index 7eff508..290595e 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -1232,7 +1232,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
> const char *ip_vs_state_name(__u16 proto, int state);
>
> void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp);
> -int ip_vs_check_template(struct ip_vs_conn *ct);
> +int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest);
> void ip_vs_random_dropentry(struct netns_ipvs *ipvs);
> int ip_vs_conn_init(void);
> void ip_vs_conn_cleanup(void);
> diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
> index 2cb3c62..096a451 100644
> --- a/net/netfilter/ipvs/ip_vs_conn.c
> +++ b/net/netfilter/ipvs/ip_vs_conn.c
> @@ -762,7 +762,7 @@ static int expire_quiescent_template(struct netns_ipvs
> *ipvs,
> * If available, return 1, otherwise invalidate this connection
> * template and return 0.
> */
> -int ip_vs_check_template(struct ip_vs_conn *ct)
> +int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest)
> {
> struct ip_vs_dest *dest = ct->dest;
> struct netns_ipvs *ipvs = ct->ipvs;
> @@ -772,7 +772,8 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
> */
> if ((dest == NULL) ||
> !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
> - expire_quiescent_template(ipvs, dest)) {
> + expire_quiescent_template(ipvs, dest) ||
> + (cdest && (dest != cdest))) {
> IP_VS_DBG_BUF(9, "check_template: dest not available for "
> "protocol %s s:%s:%d v:%s:%d "
> "-> d:%s:%d\n",
> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> index a97de51..ad99837 100644
> --- a/net/netfilter/ipvs/ip_vs_core.c
> +++ b/net/netfilter/ipvs/ip_vs_core.c
> @@ -321,7 +321,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
>
> /* Check if a template already exists */
> ct = ip_vs_ct_in_get(¶m);
> - if (!ct || !ip_vs_check_template(ct)) {
> + if (!ct || !ip_vs_check_template(ct, NULL)) {
> struct ip_vs_scheduler *sched;
>
> /*
> @@ -1153,7 +1153,8 @@ struct ip_vs_conn *ip_vs_new_conn_out(struct
> ip_vs_service *svc,
> vport, ¶m) < 0)
> return NULL;
> ct = ip_vs_ct_in_get(¶m);
> - if (!ct) {
> + /* check if template exists and points to the same dest */
> + if (!ct || !ip_vs_check_template(ct, dest)) {
> ct = ip_vs_conn_new(¶m, dest->af, daddr, dport,
> IP_VS_CONN_F_TEMPLATE, dest, 0);
> if (!ct) {
> --
> 1.8.3.1
Regards
--
Julian Anastasov <ja@xxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
|