vxlan_network.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2015 flannel authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build !windows
  15. package vxlan
  16. import (
  17. "encoding/json"
  18. "net"
  19. "sync"
  20. "syscall"
  21. "github.com/flannel-io/flannel/backend"
  22. "github.com/flannel-io/flannel/pkg/ip"
  23. "github.com/flannel-io/flannel/subnet"
  24. "github.com/vishvananda/netlink"
  25. "golang.org/x/net/context"
  26. log "k8s.io/klog"
  27. )
  28. type network struct {
  29. backend.SimpleNetwork
  30. dev *vxlanDevice
  31. v6Dev *vxlanDevice
  32. subnetMgr subnet.Manager
  33. }
  34. const (
  35. encapOverhead = 50
  36. )
  37. func newNetwork(subnetMgr subnet.Manager, extIface *backend.ExternalInterface, dev *vxlanDevice, v6Dev *vxlanDevice, _ ip.IP4Net, lease *subnet.Lease) (*network, error) {
  38. nw := &network{
  39. SimpleNetwork: backend.SimpleNetwork{
  40. SubnetLease: lease,
  41. ExtIface: extIface,
  42. },
  43. subnetMgr: subnetMgr,
  44. dev: dev,
  45. v6Dev: v6Dev,
  46. }
  47. return nw, nil
  48. }
  49. func (nw *network) Run(ctx context.Context) {
  50. wg := sync.WaitGroup{}
  51. log.V(0).Info("watching for new subnet leases")
  52. events := make(chan []subnet.Event)
  53. wg.Add(1)
  54. go func() {
  55. subnet.WatchLeases(ctx, nw.subnetMgr, nw.SubnetLease, events)
  56. log.V(1).Info("WatchLeases exited")
  57. wg.Done()
  58. }()
  59. defer wg.Wait()
  60. for {
  61. select {
  62. case evtBatch, ok := <-events:
  63. if !ok {
  64. log.Infof("evts chan closed")
  65. return
  66. }
  67. nw.handleSubnetEvents(evtBatch)
  68. }
  69. }
  70. }
  71. func (nw *network) MTU() int {
  72. return nw.ExtIface.Iface.MTU - encapOverhead
  73. }
  74. type vxlanLeaseAttrs struct {
  75. VNI uint16
  76. VtepMAC hardwareAddr
  77. }
  78. func (nw *network) handleSubnetEvents(batch []subnet.Event) {
  79. for _, event := range batch {
  80. sn := event.Lease.Subnet
  81. v6Sn := event.Lease.IPv6Subnet
  82. attrs := event.Lease.Attrs
  83. if attrs.BackendType != "vxlan" {
  84. log.Warningf("ignoring non-vxlan v4Subnet(%s) v6Subnet(%s): type=%v", sn, v6Sn, attrs.BackendType)
  85. continue
  86. }
  87. var (
  88. vxlanAttrs, v6VxlanAttrs vxlanLeaseAttrs
  89. directRoutingOK, v6DirectRoutingOK bool
  90. directRoute, v6DirectRoute netlink.Route
  91. vxlanRoute, v6VxlanRoute netlink.Route
  92. )
  93. if event.Lease.EnableIPv4 && nw.dev != nil {
  94. if err := json.Unmarshal(attrs.BackendData, &vxlanAttrs); err != nil {
  95. log.Error("error decoding subnet lease JSON: ", err)
  96. continue
  97. }
  98. // This route is used when traffic should be vxlan encapsulated
  99. vxlanRoute = netlink.Route{
  100. LinkIndex: nw.dev.link.Attrs().Index,
  101. Scope: netlink.SCOPE_UNIVERSE,
  102. Dst: sn.ToIPNet(),
  103. Gw: sn.IP.ToIP(),
  104. }
  105. vxlanRoute.SetFlag(syscall.RTNH_F_ONLINK)
  106. // directRouting is where the remote host is on the same subnet so vxlan isn't required.
  107. directRoute = netlink.Route{
  108. Dst: sn.ToIPNet(),
  109. Gw: attrs.PublicIP.ToIP(),
  110. }
  111. if nw.dev.directRouting {
  112. if dr, err := ip.DirectRouting(attrs.PublicIP.ToIP()); err != nil {
  113. log.Error(err)
  114. } else {
  115. directRoutingOK = dr
  116. }
  117. }
  118. }
  119. if event.Lease.EnableIPv6 && nw.v6Dev != nil {
  120. if err := json.Unmarshal(attrs.BackendV6Data, &v6VxlanAttrs); err != nil {
  121. log.Error("error decoding v6 subnet lease JSON: ", err)
  122. continue
  123. }
  124. if v6Sn.IP != nil && nw.v6Dev != nil {
  125. v6VxlanRoute = netlink.Route{
  126. LinkIndex: nw.v6Dev.link.Attrs().Index,
  127. Scope: netlink.SCOPE_UNIVERSE,
  128. Dst: v6Sn.ToIPNet(),
  129. Gw: v6Sn.IP.ToIP(),
  130. }
  131. v6VxlanRoute.SetFlag(syscall.RTNH_F_ONLINK)
  132. // directRouting is where the remote host is on the same subnet so vxlan isn't required.
  133. v6DirectRoute = netlink.Route{
  134. Dst: v6Sn.ToIPNet(),
  135. Gw: attrs.PublicIPv6.ToIP(),
  136. }
  137. if nw.v6Dev.directRouting {
  138. if v6Dr, err := ip.DirectRouting(attrs.PublicIPv6.ToIP()); err != nil {
  139. log.Error(err)
  140. } else {
  141. v6DirectRoutingOK = v6Dr
  142. }
  143. }
  144. }
  145. }
  146. switch event.Type {
  147. case subnet.EventAdded:
  148. if event.Lease.EnableIPv4 {
  149. if directRoutingOK {
  150. log.V(2).Infof("Adding direct route to subnet: %s PublicIP: %s", sn, attrs.PublicIP)
  151. if err := netlink.RouteReplace(&directRoute); err != nil {
  152. log.Errorf("Error adding route to %v via %v: %v", sn, attrs.PublicIP, err)
  153. continue
  154. }
  155. } else {
  156. log.V(2).Infof("adding subnet: %s PublicIP: %s VtepMAC: %s", sn, attrs.PublicIP, net.HardwareAddr(vxlanAttrs.VtepMAC))
  157. if err := nw.dev.AddARP(neighbor{IP: sn.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  158. log.Error("AddARP failed: ", err)
  159. continue
  160. }
  161. if err := nw.dev.AddFDB(neighbor{IP: attrs.PublicIP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  162. log.Error("AddFDB failed: ", err)
  163. // Try to clean up the ARP entry then continue
  164. if err := nw.dev.DelARP(neighbor{IP: event.Lease.Subnet.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  165. log.Error("DelARP failed: ", err)
  166. }
  167. continue
  168. }
  169. // Set the route - the kernel would ARP for the Gw IP address if it hadn't already been set above so make sure
  170. // this is done last.
  171. if err := netlink.RouteReplace(&vxlanRoute); err != nil {
  172. log.Errorf("failed to add vxlanRoute (%s -> %s): %v", vxlanRoute.Dst, vxlanRoute.Gw, err)
  173. // Try to clean up both the ARP and FDB entries then continue
  174. if err := nw.dev.DelARP(neighbor{IP: event.Lease.Subnet.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  175. log.Error("DelARP failed: ", err)
  176. }
  177. if err := nw.dev.DelFDB(neighbor{IP: event.Lease.Attrs.PublicIP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  178. log.Error("DelFDB failed: ", err)
  179. }
  180. continue
  181. }
  182. }
  183. }
  184. if event.Lease.EnableIPv6 {
  185. if v6DirectRoutingOK {
  186. log.V(2).Infof("Adding v6 direct route to v6 subnet: %s PublicIPv6: %s", v6Sn, attrs.PublicIPv6)
  187. if err := netlink.RouteReplace(&v6DirectRoute); err != nil {
  188. log.Errorf("Error adding v6 route to %v via %v: %v", v6Sn, attrs.PublicIPv6, err)
  189. continue
  190. }
  191. } else {
  192. log.V(2).Infof("adding v6 subnet: %s PublicIPv6: %s VtepMAC: %s", v6Sn, attrs.PublicIPv6, net.HardwareAddr(v6VxlanAttrs.VtepMAC))
  193. if err := nw.v6Dev.AddV6ARP(neighbor{IP6: v6Sn.IP, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  194. log.Error("AddV6ARP failed: ", err)
  195. continue
  196. }
  197. if err := nw.v6Dev.AddV6FDB(neighbor{IP6: attrs.PublicIPv6, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  198. log.Error("AddV6FDB failed: ", err)
  199. // Try to clean up the ARP entry then continue
  200. if err := nw.v6Dev.DelV6ARP(neighbor{IP6: event.Lease.IPv6Subnet.IP, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  201. log.Error("DelV6ARP failed: ", err)
  202. }
  203. continue
  204. }
  205. // Set the route - the kernel would ARP for the Gw IP address if it hadn't already been set above so make sure
  206. // this is done last.
  207. if err := netlink.RouteReplace(&v6VxlanRoute); err != nil {
  208. log.Errorf("failed to add v6 vxlanRoute (%s -> %s): %v", v6VxlanRoute.Dst, v6VxlanRoute.Gw, err)
  209. // Try to clean up both the ARP and FDB entries then continue
  210. if err := nw.v6Dev.DelV6ARP(neighbor{IP6: event.Lease.IPv6Subnet.IP, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  211. log.Error("DelV6ARP failed: ", err)
  212. }
  213. if err := nw.v6Dev.DelV6FDB(neighbor{IP6: event.Lease.Attrs.PublicIPv6, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  214. log.Error("DelV6FDB failed: ", err)
  215. }
  216. continue
  217. }
  218. }
  219. }
  220. case subnet.EventRemoved:
  221. if event.Lease.EnableIPv4 {
  222. if directRoutingOK {
  223. log.V(2).Infof("Removing direct route to subnet: %s PublicIP: %s", sn, attrs.PublicIP)
  224. if err := netlink.RouteDel(&directRoute); err != nil {
  225. log.Errorf("Error deleting route to %v via %v: %v", sn, attrs.PublicIP, err)
  226. }
  227. } else {
  228. log.V(2).Infof("removing subnet: %s PublicIP: %s VtepMAC: %s", sn, attrs.PublicIP, net.HardwareAddr(vxlanAttrs.VtepMAC))
  229. // Try to remove all entries - don't bail out if one of them fails.
  230. if err := nw.dev.DelARP(neighbor{IP: sn.IP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  231. log.Error("DelARP failed: ", err)
  232. }
  233. if err := nw.dev.DelFDB(neighbor{IP: attrs.PublicIP, MAC: net.HardwareAddr(vxlanAttrs.VtepMAC)}); err != nil {
  234. log.Error("DelFDB failed: ", err)
  235. }
  236. if err := netlink.RouteDel(&vxlanRoute); err != nil {
  237. log.Errorf("failed to delete vxlanRoute (%s -> %s): %v", vxlanRoute.Dst, vxlanRoute.Gw, err)
  238. }
  239. }
  240. }
  241. if event.Lease.EnableIPv6 {
  242. if v6DirectRoutingOK {
  243. log.V(2).Infof("Removing v6 direct route to subnet: %s PublicIP: %s", sn, attrs.PublicIPv6)
  244. if err := netlink.RouteDel(&directRoute); err != nil {
  245. log.Errorf("Error deleting v6 route to %v via %v: %v", v6Sn, attrs.PublicIPv6, err)
  246. }
  247. } else {
  248. log.V(2).Infof("removing v6subnet: %s PublicIPv6: %s VtepMAC: %s", v6Sn, attrs.PublicIPv6, net.HardwareAddr(v6VxlanAttrs.VtepMAC))
  249. // Try to remove all entries - don't bail out if one of them fails.
  250. if err := nw.v6Dev.DelV6ARP(neighbor{IP6: v6Sn.IP, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  251. log.Error("DelV6ARP failed: ", err)
  252. }
  253. if err := nw.v6Dev.DelV6FDB(neighbor{IP6: attrs.PublicIPv6, MAC: net.HardwareAddr(v6VxlanAttrs.VtepMAC)}); err != nil {
  254. log.Error("DelV6FDB failed: ", err)
  255. }
  256. if err := netlink.RouteDel(&v6VxlanRoute); err != nil {
  257. log.Errorf("failed to delete v6 vxlanRoute (%s -> %s): %v", v6VxlanRoute.Dst, v6VxlanRoute.Gw, err)
  258. }
  259. }
  260. }
  261. default:
  262. log.Error("internal error: unknown event type: ", int(event.Type))
  263. }
  264. }
  265. }