The client says it authenticated, the IKE status looks healthy, and the packet counters stay at zero. That combination is not a contradiction: IKEv2 keeps a control relationship and a data relationship separate, and the first can succeed while the second never comes up. The parent handles negotiation; the child handles traffic. Read the two layers separately before you call the tunnel down.

What the two SAs do

The IKE SA is the control relationship: it authenticates the peers and carries the exchanges that negotiate, replace and remove protection. It never carries your application packets. A healthy parent therefore proves that the two ends can agree on security policy, and nothing more.

A CHILD SA is the data relationship, created under the parent, with traffic selectors and keying material for one protected set. It is directional, so status output lists an inbound and an outbound association with separate identifiers, and usually separate counters for each direction. That pairing is why one direction can work while the other drops, and why the phrase the tunnel is up says nothing about traffic. One parent can also hold several children, which is how a single connection label hides the one you need.

Read the child entries, not the connection label

Open the parent status and the child list together, and find the child whose selectors match the flow you are testing. Note its traffic selectors, the negotiated algorithms, its lifetime, and the counters in both directions. If several children exist, match on selectors rather than on position, because position changes after a rekey. Write the identifiers down before you change anything.

If the parent lists a different traffic set from the one you are testing, you are reading the wrong child. That is a selector problem, not a broken tunnel.

Record timestamps as well. Rekeying can replace one layer while the other stays established, and a child that looks new may be the replacement for the one you were watching. Compare identifiers before concluding that a child disappeared.

When no child exists

Authentication can succeed while the data proposal or the selectors fail, which leaves a parent with no child at all. The usual cause is an algorithm mismatch or a traffic-selector mismatch, and both peers log the refused proposal. Read both ends, because the side you can reach may show only the rejection. Fix the mismatch instead of bouncing the parent, which repeats the same failed negotiation and adds an outage to the evidence.

A parent that keeps re-establishing is a different failure from a parent that stays up without a child. In the second case the logs name the proposal that was refused, so collect that proposal from both ends before editing a policy.

When the child exists but counters stay at zero

Send a fresh request that matches the child selectors. A request to a destination outside that policy will not move its counters, however successful it looks.

Check the route that should push the flow into the tunnel, because a child with no traffic is often a child nothing is routed to. Counters that move in one direction only point at a selector or policy mismatch on the return path. Look at the remote peer's return selectors before touching the local side. A fresh request also gives you a timestamp to correlate against both ends' status output.

Name the layer in the report

Report the failure as three fields rather than a verdict: the layer that failed, the exchange or child you inspected, and the evidence you hold. The layer is one of three: the parent never established, the child negotiation was refused, or a child exists and traffic is not reaching it. The evidence is the child identifier with its selectors and counters, or the refused proposal quoted from both logs. Anyone reading that can go straight to the exchange that matters instead of asking which VPN you mean.

The strongSwan IKEv2 documentation shows how those layers appear in status output. Attach the child output you tested, not only the parent summary.

Qillqakuna t'inkisqa