device.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. package vxlan
  15. import (
  16. "fmt"
  17. "net"
  18. "syscall"
  19. log "github.com/golang/glog"
  20. "github.com/vishvananda/netlink"
  21. "github.com/coreos/flannel/pkg/ip"
  22. )
  23. type vxlanDeviceAttrs struct {
  24. vni uint32
  25. name string
  26. vtepIndex int
  27. vtepAddr net.IP
  28. vtepPort int
  29. gbp bool
  30. }
  31. type vxlanDevice struct {
  32. link *netlink.Vxlan
  33. directRouting bool
  34. }
  35. func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
  36. link := &netlink.Vxlan{
  37. LinkAttrs: netlink.LinkAttrs{
  38. Name: devAttrs.name,
  39. },
  40. VxlanId: int(devAttrs.vni),
  41. VtepDevIndex: devAttrs.vtepIndex,
  42. SrcAddr: devAttrs.vtepAddr,
  43. Port: devAttrs.vtepPort,
  44. Learning: false,
  45. GBP: devAttrs.gbp,
  46. }
  47. link, err := ensureLink(link)
  48. if err != nil {
  49. return nil, err
  50. }
  51. return &vxlanDevice{
  52. link: link,
  53. }, nil
  54. }
  55. func ensureLink(vxlan *netlink.Vxlan) (*netlink.Vxlan, error) {
  56. err := netlink.LinkAdd(vxlan)
  57. if err == syscall.EEXIST {
  58. // it's ok if the device already exists as long as config is similar
  59. log.V(1).Infof("VXLAN device already exists")
  60. existing, err := netlink.LinkByName(vxlan.Name)
  61. if err != nil {
  62. return nil, err
  63. }
  64. incompat := vxlanLinksIncompat(vxlan, existing)
  65. if incompat == "" {
  66. log.V(1).Infof("Returning existing device")
  67. return existing.(*netlink.Vxlan), nil
  68. }
  69. // delete existing
  70. log.Warningf("%q already exists with incompatable configuration: %v; recreating device", vxlan.Name, incompat)
  71. if err = netlink.LinkDel(existing); err != nil {
  72. return nil, fmt.Errorf("failed to delete interface: %v", err)
  73. }
  74. // create new
  75. if err = netlink.LinkAdd(vxlan); err != nil {
  76. return nil, fmt.Errorf("failed to create vxlan interface: %v", err)
  77. }
  78. } else if err != nil {
  79. return nil, err
  80. }
  81. ifindex := vxlan.Index
  82. link, err := netlink.LinkByIndex(vxlan.Index)
  83. if err != nil {
  84. return nil, fmt.Errorf("can't locate created vxlan device with index %v", ifindex)
  85. }
  86. var ok bool
  87. if vxlan, ok = link.(*netlink.Vxlan); !ok {
  88. return nil, fmt.Errorf("created vxlan device with index %v is not vxlan", ifindex)
  89. }
  90. return vxlan, nil
  91. }
  92. func (dev *vxlanDevice) Configure(ipn ip.IP4Net) error {
  93. addr := netlink.Addr{IPNet: ipn.ToIPNet()}
  94. existingAddrs, err := netlink.AddrList(dev.link, netlink.FAMILY_V4)
  95. if err != nil {
  96. return err
  97. }
  98. // flannel will never make this happen. This situation can only be caused by a user, so get them to sort it out.
  99. if len(existingAddrs) > 1 {
  100. return fmt.Errorf("link has incompatible addresses. Remove additional addresses and try again. %s", dev.link)
  101. }
  102. // If the device has an incompatible address then delete it. This can happen if the lease changes for example.
  103. if len(existingAddrs) == 1 && !existingAddrs[0].Equal(addr) {
  104. if err := netlink.AddrDel(dev.link, &existingAddrs[0]); err != nil {
  105. return fmt.Errorf("failed to remove IP address %s from %s: %s", ipn.String(), dev.link.Attrs().Name, err)
  106. }
  107. existingAddrs = []netlink.Addr{}
  108. }
  109. // Actually add the desired address to the interface if needed.
  110. if len(existingAddrs) == 0 {
  111. if err := netlink.AddrAdd(dev.link, &addr); err != nil {
  112. return fmt.Errorf("failed to add IP address %s to %s: %s", ipn.String(), dev.link.Attrs().Name, err)
  113. }
  114. }
  115. if err := netlink.LinkSetUp(dev.link); err != nil {
  116. return fmt.Errorf("failed to set interface %s to UP state: %s", dev.link.Attrs().Name, err)
  117. }
  118. return nil
  119. }
  120. func (dev *vxlanDevice) MACAddr() net.HardwareAddr {
  121. return dev.link.HardwareAddr
  122. }
  123. func (dev *vxlanDevice) MTU() int {
  124. return dev.link.MTU
  125. }
  126. type neighbor struct {
  127. MAC net.HardwareAddr
  128. IP ip.IP4
  129. }
  130. func (dev *vxlanDevice) AddFDB(n neighbor) error {
  131. log.V(4).Infof("calling AddFDB: %v, %v", n.IP, n.MAC)
  132. return netlink.NeighSet(&netlink.Neigh{
  133. LinkIndex: dev.link.Index,
  134. State: netlink.NUD_PERMANENT,
  135. Family: syscall.AF_BRIDGE,
  136. Flags: netlink.NTF_SELF,
  137. IP: n.IP.ToIP(),
  138. HardwareAddr: n.MAC,
  139. })
  140. }
  141. func (dev *vxlanDevice) DelFDB(n neighbor) error {
  142. log.V(4).Infof("calling DelFDB: %v, %v", n.IP, n.MAC)
  143. return netlink.NeighDel(&netlink.Neigh{
  144. LinkIndex: dev.link.Index,
  145. Family: syscall.AF_BRIDGE,
  146. Flags: netlink.NTF_SELF,
  147. IP: n.IP.ToIP(),
  148. HardwareAddr: n.MAC,
  149. })
  150. }
  151. func (dev *vxlanDevice) AddARP(n neighbor) error {
  152. log.V(4).Infof("calling AddARP: %v, %v", n.IP, n.MAC)
  153. return netlink.NeighSet(&netlink.Neigh{
  154. LinkIndex: dev.link.Index,
  155. State: netlink.NUD_PERMANENT,
  156. Type: syscall.RTN_UNICAST,
  157. IP: n.IP.ToIP(),
  158. HardwareAddr: n.MAC,
  159. })
  160. }
  161. func (dev *vxlanDevice) DelARP(n neighbor) error {
  162. log.V(4).Infof("calling DelARP: %v, %v", n.IP, n.MAC)
  163. return netlink.NeighDel(&netlink.Neigh{
  164. LinkIndex: dev.link.Index,
  165. State: netlink.NUD_PERMANENT,
  166. Type: syscall.RTN_UNICAST,
  167. IP: n.IP.ToIP(),
  168. HardwareAddr: n.MAC,
  169. })
  170. }
  171. func vxlanLinksIncompat(l1, l2 netlink.Link) string {
  172. if l1.Type() != l2.Type() {
  173. return fmt.Sprintf("link type: %v vs %v", l1.Type(), l2.Type())
  174. }
  175. v1 := l1.(*netlink.Vxlan)
  176. v2 := l2.(*netlink.Vxlan)
  177. if v1.VxlanId != v2.VxlanId {
  178. return fmt.Sprintf("vni: %v vs %v", v1.VxlanId, v2.VxlanId)
  179. }
  180. if v1.VtepDevIndex > 0 && v2.VtepDevIndex > 0 && v1.VtepDevIndex != v2.VtepDevIndex {
  181. return fmt.Sprintf("vtep (external) interface: %v vs %v", v1.VtepDevIndex, v2.VtepDevIndex)
  182. }
  183. if len(v1.SrcAddr) > 0 && len(v2.SrcAddr) > 0 && !v1.SrcAddr.Equal(v2.SrcAddr) {
  184. return fmt.Sprintf("vtep (external) IP: %v vs %v", v1.SrcAddr, v2.SrcAddr)
  185. }
  186. if len(v1.Group) > 0 && len(v2.Group) > 0 && !v1.Group.Equal(v2.Group) {
  187. return fmt.Sprintf("group address: %v vs %v", v1.Group, v2.Group)
  188. }
  189. if v1.L2miss != v2.L2miss {
  190. return fmt.Sprintf("l2miss: %v vs %v", v1.L2miss, v2.L2miss)
  191. }
  192. if v1.Port > 0 && v2.Port > 0 && v1.Port != v2.Port {
  193. return fmt.Sprintf("port: %v vs %v", v1.Port, v2.Port)
  194. }
  195. if v1.GBP != v2.GBP {
  196. return fmt.Sprintf("gbp: %v vs %v", v1.GBP, v2.GBP)
  197. }
  198. return ""
  199. }