run.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package udp
  2. import (
  3. "encoding/json"
  4. "net"
  5. "time"
  6. "github.com/coreos-inc/kolach/Godeps/_workspace/src/github.com/docker/libcontainer/netlink"
  7. log "github.com/coreos-inc/kolach/Godeps/_workspace/src/github.com/golang/glog"
  8. "github.com/coreos-inc/kolach/backend"
  9. "github.com/coreos-inc/kolach/pkg"
  10. "github.com/coreos-inc/kolach/subnet"
  11. )
  12. const (
  13. encapOverhead = 28 // 20 bytes IP hdr + 8 bytes UDP hdr
  14. defaultMTU = 1500 - encapOverhead
  15. )
  16. func configureIface(ifname string, ipn pkg.IP4Net, mtu int) error {
  17. iface, err := net.InterfaceByName(ifname)
  18. if err != nil {
  19. log.Error("Failed to lookup interface ", ifname)
  20. return err
  21. }
  22. n := ipn.ToIPNet()
  23. err = netlink.NetworkLinkAddIp(iface, n.IP, n)
  24. if err != nil {
  25. log.Errorf("Failed to add IP address %s to %s: %s", n.IP, ifname, err)
  26. return err
  27. }
  28. err = netlink.NetworkSetMTU(iface, mtu)
  29. if err != nil {
  30. log.Errorf("Failed to set MTU for %s: ", ifname, err)
  31. return err
  32. }
  33. err = netlink.NetworkLinkUp(iface)
  34. if err != nil {
  35. log.Errorf("Failed set interface %s to UP state: %s", ifname, err)
  36. return err
  37. }
  38. return nil
  39. }
  40. func acquireLease(sm *subnet.SubnetManager, pubIP net.IP) (pkg.IP4Net, error) {
  41. attrs := subnet.BaseAttrs{
  42. PublicIP: pkg.FromIP(pubIP),
  43. }
  44. data, err := json.Marshal(&attrs)
  45. if err != nil {
  46. return pkg.IP4Net{}, err
  47. }
  48. var sn pkg.IP4Net
  49. for {
  50. sn, err = sm.AcquireLease(attrs.PublicIP, string(data))
  51. if err == nil {
  52. log.Info("Subnet lease acquired: ", sn)
  53. break
  54. }
  55. log.Error("Failed to acquire subnet: ", err)
  56. time.Sleep(time.Second)
  57. }
  58. return sn, nil
  59. }
  60. func Run(sm *subnet.SubnetManager, iface *net.Interface, ip net.IP, port int, fast bool, ready backend.ReadyFunc) {
  61. sn, err := acquireLease(sm, ip)
  62. if err != nil {
  63. log.Error("Failed to acquire lease: ", err)
  64. return
  65. }
  66. tun, tunName, err := pkg.OpenTun("kolach%d")
  67. if err != nil {
  68. log.Error("Failed to open TUN device: ", err)
  69. return
  70. }
  71. localAddr := net.UDPAddr{
  72. Port: port,
  73. }
  74. conn, err := net.ListenUDP("udp4", &localAddr)
  75. if err != nil {
  76. log.Error("Failed to start listening on UDP socket: ", err)
  77. return
  78. }
  79. // Interface's subnet is that of the whole overlay network (e.g. /16)
  80. // and not that of the individual host (e.g. /24)
  81. ipn := pkg.IP4Net{
  82. IP: sn.IP,
  83. PrefixLen: sm.GetConfig().Network.PrefixLen,
  84. }
  85. // TUN MTU will be smaller b/c of encap (IP+UDP hdrs)
  86. var mtu int
  87. if iface.MTU > 0 {
  88. mtu = iface.MTU - encapOverhead
  89. } else {
  90. mtu = defaultMTU
  91. }
  92. err = configureIface(tunName, ipn, mtu)
  93. if err != nil {
  94. return
  95. }
  96. // all initialized and ready for business
  97. log.Info("UDP encapsulation initialized")
  98. ready(sn, mtu)
  99. if fast {
  100. fastProxy(sm, tun, conn, ipn.IP, port)
  101. } else {
  102. proxy(sm, tun, conn, port)
  103. }
  104. }