run.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package udp
  2. import (
  3. "encoding/json"
  4. "net"
  5. "syscall"
  6. "time"
  7. "github.com/coreos-inc/rudder/Godeps/_workspace/src/github.com/docker/libcontainer/netlink"
  8. log "github.com/coreos-inc/rudder/Godeps/_workspace/src/github.com/golang/glog"
  9. "github.com/coreos-inc/rudder/backend"
  10. "github.com/coreos-inc/rudder/pkg"
  11. "github.com/coreos-inc/rudder/subnet"
  12. )
  13. const (
  14. encapOverhead = 28 // 20 bytes IP hdr + 8 bytes UDP hdr
  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 to set interface %s to UP state: %s", ifname, err)
  36. return err
  37. }
  38. // explicitly add a route since there might be a route for a subnet already
  39. // installed by Docker and then it won't get auto added
  40. err = netlink.AddRoute(ipn.Network().String(), "", "", ifname)
  41. if err != nil && err != syscall.EEXIST {
  42. log.Errorf("Failed to add route (%s -> %s): ", ipn.Network().String(), ifname, err)
  43. return err
  44. }
  45. return nil
  46. }
  47. func acquireLease(sm *subnet.SubnetManager, pubIP net.IP) (pkg.IP4Net, error) {
  48. attrs := subnet.BaseAttrs{
  49. PublicIP: pkg.FromIP(pubIP),
  50. }
  51. data, err := json.Marshal(&attrs)
  52. if err != nil {
  53. return pkg.IP4Net{}, err
  54. }
  55. var sn pkg.IP4Net
  56. for {
  57. sn, err = sm.AcquireLease(attrs.PublicIP, string(data))
  58. if err == nil {
  59. log.Info("Subnet lease acquired: ", sn)
  60. break
  61. }
  62. log.Error("Failed to acquire subnet: ", err)
  63. time.Sleep(time.Second)
  64. }
  65. return sn, nil
  66. }
  67. func Run(sm *subnet.SubnetManager, iface *net.Interface, ip net.IP, port int, fast bool, ready backend.ReadyFunc) {
  68. sn, err := acquireLease(sm, ip)
  69. if err != nil {
  70. log.Error("Failed to acquire lease: ", err)
  71. return
  72. }
  73. tun, tunName, err := pkg.OpenTun("rudder%d")
  74. if err != nil {
  75. log.Error("Failed to open TUN device: ", err)
  76. return
  77. }
  78. localAddr := net.UDPAddr{
  79. Port: port,
  80. }
  81. conn, err := net.ListenUDP("udp4", &localAddr)
  82. if err != nil {
  83. log.Error("Failed to start listening on UDP socket: ", err)
  84. return
  85. }
  86. // Interface's subnet is that of the whole overlay network (e.g. /16)
  87. // and not that of the individual host (e.g. /24)
  88. ipn := pkg.IP4Net{
  89. IP: sn.IP,
  90. PrefixLen: sm.GetConfig().Network.PrefixLen,
  91. }
  92. // TUN MTU will be smaller b/c of encap (IP+UDP hdrs)
  93. var mtu int
  94. if iface.MTU > 0 {
  95. mtu = iface.MTU - encapOverhead
  96. } else {
  97. log.Errorf("Failed to determine MTU for %s interface", ip)
  98. return
  99. }
  100. err = configureIface(tunName, ipn, mtu)
  101. if err != nil {
  102. return
  103. }
  104. // all initialized and ready for business
  105. log.Info("UDP encapsulation initialized")
  106. ready(sn, mtu)
  107. if fast {
  108. fastProxy(sm, tun, conn, ipn.IP, uint(mtu), port)
  109. } else {
  110. proxy(sm, tun, conn, uint(mtu), port)
  111. }
  112. }