Why does this routing setup not working

Solution 1:

First of all, supplying IP address & interface with -I parameter to the ping aren't synonyms. First tells which source IP to pick. It will route it according the net flow, including local addresses & routing tables. Second tells to directly pick the interface to send packet to (and it will pick first assigned IP as the source).

Next what are you doing has nothing to do with packet forwarding. Forwarding means that the packet has to actually arrive from the "outside". As you are generating a packet from this host there is no forwarding involved. It's a locally generated packet. As your destination IP are one of the locally assigned addresses when you aren't forcing ping to send packet to a specific interface "outside" (with -I interface option) kernel will process this packet flow internally. It just won't try to output it to a real interface as it's destination are "already here". So this is what happens and why it works in one case and not in another.

PS: Also check out the -r option of the ping tool in case you know that you're doing and both interfaces are attached to a same broadcast domain (I doubt this with the TAP interface).