udp_network_amd64.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // +build !windows
  2. // Copyright 2015 flannel authors
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. // +build !windows
  16. package udp
  17. import (
  18. "fmt"
  19. "net"
  20. "os"
  21. "sync"
  22. "syscall"
  23. "github.com/flannel-io/flannel/backend"
  24. "github.com/flannel-io/flannel/pkg/ip"
  25. "github.com/flannel-io/flannel/subnet"
  26. "github.com/vishvananda/netlink"
  27. "golang.org/x/net/context"
  28. log "k8s.io/klog"
  29. )
  30. const (
  31. encapOverhead = 28 // 20 bytes IP hdr + 8 bytes UDP hdr
  32. )
  33. type network struct {
  34. backend.SimpleNetwork
  35. name string
  36. port int
  37. ctl *os.File
  38. ctl2 *os.File
  39. tun *os.File
  40. conn *net.UDPConn
  41. tunNet ip.IP4Net
  42. sm subnet.Manager
  43. }
  44. func newNetwork(sm subnet.Manager, extIface *backend.ExternalInterface, port int, nw ip.IP4Net, l *subnet.Lease) (*network, error) {
  45. n := &network{
  46. SimpleNetwork: backend.SimpleNetwork{
  47. SubnetLease: l,
  48. ExtIface: extIface,
  49. },
  50. port: port,
  51. sm: sm,
  52. }
  53. n.tunNet = nw
  54. if err := n.initTun(); err != nil {
  55. return nil, err
  56. }
  57. var err error
  58. n.conn, err = net.ListenUDP("udp4", &net.UDPAddr{IP: extIface.IfaceAddr, Port: port})
  59. if err != nil {
  60. return nil, fmt.Errorf("failed to start listening on UDP socket: %v", err)
  61. }
  62. n.ctl, n.ctl2, err = newCtlSockets()
  63. if err != nil {
  64. return nil, fmt.Errorf("failed to create control socket: %v", err)
  65. }
  66. return n, nil
  67. }
  68. func (n *network) Run(ctx context.Context) {
  69. defer func() {
  70. n.tun.Close()
  71. n.conn.Close()
  72. n.ctl.Close()
  73. n.ctl2.Close()
  74. }()
  75. // one for each goroutine below
  76. wg := sync.WaitGroup{}
  77. defer wg.Wait()
  78. wg.Add(1)
  79. go func() {
  80. runCProxy(n.tun, n.conn, n.ctl2, n.tunNet.IP, n.MTU())
  81. wg.Done()
  82. }()
  83. log.Info("Watching for new subnet leases")
  84. evts := make(chan []subnet.Event)
  85. wg.Add(1)
  86. go func() {
  87. subnet.WatchLeases(ctx, n.sm, n.SubnetLease, evts)
  88. wg.Done()
  89. }()
  90. for {
  91. select {
  92. case evtBatch, ok := <-evts:
  93. if !ok {
  94. log.Infof("evts chan closed")
  95. stopProxy(n.ctl)
  96. return
  97. }
  98. n.processSubnetEvents(evtBatch)
  99. }
  100. }
  101. }
  102. func (n *network) MTU() int {
  103. return n.ExtIface.Iface.MTU - encapOverhead
  104. }
  105. func newCtlSockets() (*os.File, *os.File, error) {
  106. fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
  107. if err != nil {
  108. return nil, nil, err
  109. }
  110. f1 := os.NewFile(uintptr(fds[0]), "ctl")
  111. f2 := os.NewFile(uintptr(fds[1]), "ctl")
  112. return f1, f2, nil
  113. }
  114. func (n *network) initTun() error {
  115. var tunName string
  116. var err error
  117. n.tun, tunName, err = ip.OpenTun("flannel%d")
  118. if err != nil {
  119. return fmt.Errorf("failed to open TUN device: %v", err)
  120. }
  121. err = configureIface(tunName, n.tunNet, n.MTU())
  122. return err
  123. }
  124. func configureIface(ifname string, ipn ip.IP4Net, mtu int) error {
  125. iface, err := netlink.LinkByName(ifname)
  126. if err != nil {
  127. return fmt.Errorf("failed to lookup interface %v", ifname)
  128. }
  129. // Ensure that the device has a /32 address so that no broadcast routes are created.
  130. // This IP is just used as a source address for host to workload traffic (so
  131. // the return path for the traffic has an address on the flannel network to use as the destination)
  132. ipnLocal := ipn
  133. ipnLocal.PrefixLen = 32
  134. err = netlink.AddrAdd(iface, &netlink.Addr{IPNet: ipnLocal.ToIPNet(), Label: ""})
  135. if err != nil {
  136. return fmt.Errorf("failed to add IP address %v to %v: %v", ipnLocal.String(), ifname, err)
  137. }
  138. err = netlink.LinkSetMTU(iface, mtu)
  139. if err != nil {
  140. return fmt.Errorf("failed to set MTU for %v: %v", ifname, err)
  141. }
  142. err = netlink.LinkSetUp(iface)
  143. if err != nil {
  144. return fmt.Errorf("failed to set interface %v to UP state: %v", ifname, err)
  145. }
  146. // explicitly add a route since there might be a route for a subnet already
  147. // installed by Docker and then it won't get auto added
  148. err = netlink.RouteAdd(&netlink.Route{
  149. LinkIndex: iface.Attrs().Index,
  150. Scope: netlink.SCOPE_UNIVERSE,
  151. Dst: ipn.Network().ToIPNet(),
  152. })
  153. if err != nil && err != syscall.EEXIST {
  154. return fmt.Errorf("failed to add route (%v -> %v): %v", ipn.Network().String(), ifname, err)
  155. }
  156. return nil
  157. }
  158. func (n *network) processSubnetEvents(batch []subnet.Event) {
  159. for _, evt := range batch {
  160. switch evt.Type {
  161. case subnet.EventAdded:
  162. log.Info("Subnet added: ", evt.Lease.Subnet)
  163. setRoute(n.ctl, evt.Lease.Subnet, evt.Lease.Attrs.PublicIP, n.port)
  164. case subnet.EventRemoved:
  165. log.Info("Subnet removed: ", evt.Lease.Subnet)
  166. removeRoute(n.ctl, evt.Lease.Subnet)
  167. default:
  168. log.Error("Internal error: unknown event type: ", int(evt.Type))
  169. }
  170. }
  171. }