The logic in the EmberZNet stack (3.1 and later) for determining the next hop of a Unicast delivery based on the various routing options is as follows:
•Call emberAppendSourceRouteHandler() [in EZN API] or examine current source route [in EZSP] to try to obtain source route from internal source route table (where entries are managed per-destination by SetSourceRoute in EZSP). See the FAQ on Source Routing Logic for more details.
After this preparation, try each of the following steps (in this order) until something succeeds:
•If destination is our own node ID, send message using local loopback (no packets emitted).
•If we are an end device, just pass the message to our parent as the first hop.
•If destination is one of our end device children, deliver it directly to the child (holding it in the MAC indirect queue until next poll from child if the destination is a sleepy [RxOffWhenIdle] end device).
•If a source route was found earlier (first step), use that.
•If we already have a route table entry giving us the next hop (which could have come from a prior AODV route discovery or a prior Many To One Route Request [MTORR] event by the concentrator), just use that.
•If ENABLE_ROUTE_DISCOVERY or FORCE_ROUTE_DISCOVERY is enabled for the delivery, initiate an AODV route discovery and wait for the results to resolve next hop.
•If the destination is in our neighbor table, just send directly to him (assuming an implicit 1-hop route).
•If still no next hop, fail delivery.
Hopefully, this makes it clear what will happen in certain cases. The general summary is that the source route will take precedence over the AODV route discoveries, but in the case where you accidentally try to send to some destination to whom you have no source route (or MTOR on the other side), it's possible for the AODV route discovery to be initiated, which defeats the purpose of using the source routes.
Note that the logic above all occurs after the destination node ID has been resolved (either provided in the API if sending with EMBER_OUTGOING_DIRECT, or provided via the Address Table or Binding Table, including any network address discovery that might be necessary). If the destination node ID is not available via these methods and EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY is omitted from the EmberApsOptions bitmask, the delivery will fail and none of the logic above will be processed.