GRE tunnels can incapsulate IPv4/IPv6 unicast/multicast traffic, so it is de-facto tunnel standard for dynamic routed networks. You can setup up to 64K tunnels for an unique tunnel endpoints pair. It can work with FreeBSD and cisco IOS. Kernel module is 'ip_gre'.
The following setup will configure a GRE tunnel between Node 1 (having 10.20.30.40 as public IP) and Node 2 (having 50.60.70.80 as public IP). The GRE tunnel subnet used will be 192.168.1.0/30 since we only need 2 IPs. We'll also route 2 other subnets from Node 1 to Node 2 and from Node 2 to Node 1 using the newly created GRE interfaces.
Node 1
$ modprobe ip_gre
$ ip tunnel add gre1 mode gre local 10.20.30.40 remote 50.60.70.80
$ ip address add dev gre1 192.168.1.1 peer 192.168.1.2/30
$ ip link set dev gre1 up
$ ip route add 172.16.10.0/24 via 192.168.1.2
$ ip link show gre1
$ ifconfig gre1
Node 2
$ modprobe ip_gre
$ ip tunnel add gre1 mode gre local 50.60.70.80 remote 10.20.30.40
$ ip address add dev gre1 192.168.1.2 peer 192.168.1.1/30
$ ip link set dev gre1 up
$ ip route add 172.16.20.0/24 via 192.168.1.1
$ ip link show gre1
$ ifconfig gre1
$ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=201 ms
Cleanup
$ ip tunnel del gre1
$ rmmod ip_gre
Ubuntu Networking: http://onvox.net/linux/how-to-create-ipv4-gre-tunnels-in-ubuntu