[SOLUTION] Avaya CM SIP TCP trunk: connection drops after ~6s idle — CRLF keepalive causes immediate FIN, fix with pjsip transport tcp_keepalive

Environment

  • Asterisk 22.8.2 (chan_pjsip / res_pjsip)
  • Avaya Communication Manager (SIP trunk over TCP, port 5062)
  • Asterisk acts as SIP proxy between Avaya CM and local SIP endpoints
  • TCP transport mandatory (customer requirement, UDP not acceptable)

Problem

Intermittent call failures on inbound calls from Avaya CM. Roughly 1 in 8–10 calls would fail silently: Asterisk stopped responding to Avaya SIP packets mid-ringing, the channel would be marked as CONGESTION, and Dial() would return non-zero. Avaya would eventually send CANCEL and receive a 481 Call/Transaction Does Not Exist.

Asterisk logs showed:

Spawn extension (users, s, N) exited non-zero on 'PJSIP/trunk-120-XXXXXXXX'

No obvious errors — the failure was silent from the dialplan perspective.


Root Cause — TCP Idle Timer on Avaya CM

A tcpdump capture during a failing call revealed the issue. After the SIP 180 Ringing was sent to Avaya and while waiting for the called party to answer, approximately 6 seconds of SIP silence elapsed. Avaya CM then sent a TCP FIN+ACK, closing the connection:

# tcpdump on the Asterisk server, filtered to Avaya IP

11:19:17.924  Asterisk → Avaya  [P.] length 438   ← SIP OPTIONS (qualify)
11:19:17.926  Avaya → Asterisk  [P.] length 348   ← SIP 200 OK
...
[~6 seconds of silence — call is ringing, no SIP traffic]
...
11:19:24.272  Avaya → Asterisk  [F.] length 0     ← TCP FIN  ← ROOT CAUSE
11:19:24.273  Asterisk → Avaya  [.] ack            ← Asterisk acknowledges
11:19:24.274  Asterisk → Avaya  [F.] length 0     ← Asterisk closes its side

Avaya CM has a TCP idle timer of approximately 6 seconds. After this period with no TCP data on the connection, it sends FIN+ACK regardless of active SIP dialogs. Asterisk’s pjsip detects the TCP close, marks the channel as unavailable, and Dial() exits non-zero — the post-Dial DIALSTATUS handlers become unreachable.


First Attempt — qualify_frequency=5 (partial fix)

Raising qualify_frequency to 5 seconds on the trunk AOR generates SIP OPTIONS every 5 seconds, resetting Avaya’s idle timer. This reduced the failure rate significantly (~2 months of reduced incidents), but did not eliminate the problem.

The margin between the 5s OPTIONS interval and the ~6s timer is only 1 second — too thin to survive scheduling jitter, especially during calls where the OPTIONS timing can slip relative to last SIP dialog traffic.

[trunk-120](default_trunk_aor)
type=aor
contact=sip:172.26.7.35:5062
qualify_frequency=5   ; helps but not sufficient alone

Second Attempt — keep_alive_interval in [global] — DO NOT USE WITH AVAYA

Based on Asterisk documentation, keep_alive_interval in the [global] section sends lightweight CRLF packets (\r\n\r\n, 4 bytes, per RFC 5626) on idle TCP connections to keep them alive.

Avaya CM does NOT support RFC 5626 CRLF keepalives.

When Avaya receives the 4-byte CRLF packet, it immediately responds with TCP FIN+ACK — the keepalive attempt actively causes the disconnect. The tcpdump evidence:

# Every CRLF keepalive packet immediately triggers FIN from Avaya

15:04:53.835  Asterisk → Avaya  [P.] length 4     ← CRLF keepalive (\r\n\r\n)
15:04:53.840  Avaya → Asterisk  [.] ack
15:04:53.840  Avaya → Asterisk  [F.] length 0     ← IMMEDIATE FIN
15:04:53.841  Asterisk → Avaya  [F.] length 0     ← connection closed
15:04:53.841  Avaya → Asterisk  [.] ack

15:04:53.999  Asterisk → Avaya  [S]               ← Asterisk immediately reconnects
...
15:04:56.835  Asterisk → Avaya  [P.] length 4     ← next CRLF keepalive
15:04:56.836  Avaya → Asterisk  [F.] length 0     ← IMMEDIATE FIN again

With keep_alive_interval=3, Asterisk was reconnecting every 3 seconds. The connection was never stable. Do not use this setting with Avaya CM.


Solution — Per-socket TCP keepalive on the pjsip transport

The correct fix uses OS-level TCP keepalive probes configured per-socket directly on the pjsip transport. These are pure TCP protocol-level ACK frames with no SIP payload — they pass through the Avaya SIP stack invisibly and reset the TCP idle timer at the OS/network level.

Unlike keep_alive_interval (which sends SIP application data that Avaya rejects), TCP keepalive probes ([.], length 0) are accepted by Avaya without issue:

# With tcp_keepalive_enable=yes on the transport:

15:14:43.072  Asterisk → Avaya  [.] length 0     ← TCP keepalive probe
15:14:43.072  Avaya → Asterisk  [.] ack           ← acknowledged, NO FIN ✓

15:14:46.080  Asterisk → Avaya  [.] length 0     ← probe (+3s)
15:14:46.080  Avaya → Asterisk  [.] ack           ← acknowledged, NO FIN ✓

15:14:49.088  Asterisk → Avaya  [.] length 0     ← probe (+3s)
15:14:49.088  Avaya → Asterisk  [.] ack           ← acknowledged, NO FIN ✓

The TCP connection remains stable indefinitely. No FINs, no reconnects.

Final working configuration

pjsip_transports.conf (or wherever your transport is defined):

[transport-tcp]
type=transport
protocol=tcp
bind=<your_asterisk_ip>:5062
tcp_keepalive_enable=yes
tcp_keepalive_idle_time=3      ; send first probe after 3s idle (< Avaya's ~6s timer)
tcp_keepalive_interval_time=3  ; subsequent probes every 3s
tcp_keepalive_probe_count=3    ; declare dead after 3 failed probes

pjsip_trunks.conf (Avaya trunk AOR):

[trunk-avaya](default_trunk_aor)
type=aor
contact=sip:<avaya_ip_address>:5062
qualify_frequency=5   ; keep as secondary safety net for monitoring + SIP-level keepalive

pjsip.conf [global] section — ensure keep_alive_interval is NOT set (or set to 0):

[global]
keep_alive_interval=0   ; DO NOT enable — Avaya rejects CRLF keepalives with TCP FIN

Apply with:

asterisk -rx "pjsip reload"

Key findings summary

Mechanism Result with Avaya CM
keep_alive_interval (CRLF, RFC 5626) Breaks connection — Avaya responds with immediate TCP FIN
qualify_frequency=5 (SIP OPTIONS) Reduces failures but insufficient — 1s margin on ~6s timer
tcp_keepalive_enable=yes (TCP probe) Works — Avaya accepts TCP ACK probes, no FIN triggered
tcp_keepalive_enable + qualify_frequency=5 Optimal — TCP keepalive keeps connection alive, OPTIONS provides SIP-level monitoring

The tcp_keepalive_* parameters operate at the socket level via SO_KEEPALIVE + TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT and apply only to connections using that specific transport — no system-wide sysctl changes required.

Hope this helps others hitting the same wall with Avaya CM over TCP.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.