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. )
  15. func configureIface(ifname string, ipn pkg.IP4Net, mtu int) error {
  16. iface, err := net.InterfaceByName(ifname)
  17. if err != nil {
  18. log.Error("Failed to lookup interface ", ifname)
  19. return err
  20. }
  21. n := ipn.ToIPNet()
  22. err = netlink.NetworkLinkAddIp(iface, n.IP, n)
  23. if err != nil {
  24. log.Errorf("Failed to add IP address %s to %s: %s", n.IP, ifname, err)
  25. return err
  26. }
  27. err = netlink.NetworkSetMTU(iface, mtu)
  28. if err != nil {
  29. log.Errorf("Failed to set MTU for %s: ", ifname, err)
  30. return err
  31. }
  32. err = netlink.NetworkLinkUp(iface)
  33. if err != nil {
  34. log.Errorf("Failed set interface %s to UP state: %s", ifname, err)
  35. return err
  36. }
  37. return nil
  38. }
  39. func acquireLease(sm *subnet.SubnetManager, pubIP net.IP) (pkg.IP4Net, error) {
  40. attrs := subnet.BaseAttrs{
  41. PublicIP: pkg.FromIP(pubIP),
  42. }
  43. data, err := json.Marshal(&attrs)
  44. if err != nil {
  45. return pkg.IP4Net{}, err
  46. }
  47. var sn pkg.IP4Net
  48. for {
  49. sn, err = sm.AcquireLease(attrs.PublicIP, string(data))
  50. if err == nil {
  51. log.Info("Subnet lease acquired: ", sn)
  52. break
  53. }
  54. log.Error("Failed to acquire subnet: ", err)
  55. time.Sleep(time.Second)
  56. }
  57. return sn, nil
  58. }
  59. func Run(sm *subnet.SubnetManager, iface *net.Interface, ip net.IP, port int, fast bool, ready backend.ReadyFunc) {
  60. sn, err := acquireLease(sm, ip)
  61. if err != nil {
  62. log.Error("Failed to acquire lease: ", err)
  63. return
  64. }
  65. tun, tunName, err := pkg.OpenTun("kolach%d")
  66. if err != nil {
  67. log.Error("Failed to open TUN device: ", err)
  68. return
  69. }
  70. localAddr := net.UDPAddr{
  71. Port: port,
  72. }
  73. conn, err := net.ListenUDP("udp4", &localAddr)
  74. if err != nil {
  75. log.Error("Failed to start listening on UDP socket: ", err)
  76. return
  77. }
  78. // Interface's subnet is that of the whole overlay network (e.g. /16)
  79. // and not that of the individual host (e.g. /24)
  80. ipn := pkg.IP4Net{
  81. IP: sn.IP,
  82. PrefixLen: sm.GetConfig().Network.PrefixLen,
  83. }
  84. // TUN MTU will be smaller b/c of encap (IP+UDP hdrs)
  85. var mtu int
  86. if iface.MTU > 0 {
  87. mtu = iface.MTU - encapOverhead
  88. } else {
  89. log.Errorf("Failed to determine MTU for %s interface", ip)
  90. return
  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, uint(mtu), port)
  101. } else {
  102. proxy(sm, tun, conn, uint(mtu), port)
  103. }
  104. }