device.go 5.6 KB

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