device.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. "github.com/containernetworking/plugins/pkg/utils/sysctl"
  22. "github.com/flannel-io/flannel/pkg/ip"
  23. "github.com/vishvananda/netlink"
  24. log "k8s.io/klog"
  25. )
  26. type vxlanDeviceAttrs struct {
  27. vni uint32
  28. name string
  29. vtepIndex int
  30. vtepAddr net.IP
  31. vtepPort int
  32. gbp bool
  33. learning bool
  34. }
  35. type vxlanDevice struct {
  36. link *netlink.Vxlan
  37. directRouting bool
  38. }
  39. func newVXLANDevice(devAttrs *vxlanDeviceAttrs) (*vxlanDevice, error) {
  40. link := &netlink.Vxlan{
  41. LinkAttrs: netlink.LinkAttrs{
  42. Name: devAttrs.name,
  43. },
  44. VxlanId: int(devAttrs.vni),
  45. VtepDevIndex: devAttrs.vtepIndex,
  46. SrcAddr: devAttrs.vtepAddr,
  47. Port: devAttrs.vtepPort,
  48. Learning: devAttrs.learning,
  49. GBP: devAttrs.gbp,
  50. }
  51. link, err := ensureLink(link)
  52. if err != nil {
  53. return nil, err
  54. }
  55. _, _ = sysctl.Sysctl(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", devAttrs.name), "0")
  56. return &vxlanDevice{
  57. link: link,
  58. }, nil
  59. }
  60. func ensureLink(vxlan *netlink.Vxlan) (*netlink.Vxlan, error) {
  61. err := netlink.LinkAdd(vxlan)
  62. if err == syscall.EEXIST {
  63. // it's ok if the device already exists as long as config is similar
  64. log.V(1).Infof("VXLAN device already exists")
  65. existing, err := netlink.LinkByName(vxlan.Name)
  66. if err != nil {
  67. return nil, err
  68. }
  69. incompat := vxlanLinksIncompat(vxlan, existing)
  70. if incompat == "" {
  71. log.V(1).Infof("Returning existing device")
  72. return existing.(*netlink.Vxlan), nil
  73. }
  74. // delete existing
  75. log.Warningf("%q already exists with incompatable configuration: %v; recreating device", vxlan.Name, incompat)
  76. if err = netlink.LinkDel(existing); err != nil {
  77. return nil, fmt.Errorf("failed to delete interface: %v", err)
  78. }
  79. // create new
  80. if err = netlink.LinkAdd(vxlan); err != nil {
  81. return nil, fmt.Errorf("failed to create vxlan interface: %v", err)
  82. }
  83. } else if err != nil {
  84. return nil, err
  85. }
  86. ifindex := vxlan.Index
  87. link, err := netlink.LinkByIndex(vxlan.Index)
  88. if err != nil {
  89. return nil, fmt.Errorf("can't locate created vxlan device with index %v", ifindex)
  90. }
  91. var ok bool
  92. if vxlan, ok = link.(*netlink.Vxlan); !ok {
  93. return nil, fmt.Errorf("created vxlan device with index %v is not vxlan", ifindex)
  94. }
  95. return vxlan, nil
  96. }
  97. func (dev *vxlanDevice) Configure(ipa ip.IP4Net, flannelnet ip.IP4Net) error {
  98. if err := ip.EnsureV4AddressOnLink(ipa, flannelnet, dev.link); err != nil {
  99. return fmt.Errorf("failed to ensure address of interface %s: %s", dev.link.Attrs().Name, err)
  100. }
  101. if err := netlink.LinkSetUp(dev.link); err != nil {
  102. return fmt.Errorf("failed to set interface %s to UP state: %s", dev.link.Attrs().Name, err)
  103. }
  104. return nil
  105. }
  106. func (dev *vxlanDevice) ConfigureIPv6(ipn ip.IP6Net) error {
  107. if err := ip.EnsureV6AddressOnLink(ipn, dev.link); err != nil {
  108. return fmt.Errorf("failed to ensure v6 address of interface %s: %s", dev.link.Attrs().Name, err)
  109. }
  110. if err := netlink.LinkSetUp(dev.link); err != nil {
  111. return fmt.Errorf("failed to set v6 interface %s to UP state: %s", dev.link.Attrs().Name, err)
  112. }
  113. return nil
  114. }
  115. func (dev *vxlanDevice) MACAddr() net.HardwareAddr {
  116. return dev.link.HardwareAddr
  117. }
  118. type neighbor struct {
  119. MAC net.HardwareAddr
  120. IP ip.IP4
  121. IP6 *ip.IP6
  122. }
  123. func (dev *vxlanDevice) AddFDB(n neighbor) error {
  124. log.V(4).Infof("calling AddFDB: %v, %v", n.IP, n.MAC)
  125. return netlink.NeighSet(&netlink.Neigh{
  126. LinkIndex: dev.link.Index,
  127. State: netlink.NUD_PERMANENT,
  128. Family: syscall.AF_BRIDGE,
  129. Flags: netlink.NTF_SELF,
  130. IP: n.IP.ToIP(),
  131. HardwareAddr: n.MAC,
  132. })
  133. }
  134. func (dev *vxlanDevice) AddV6FDB(n neighbor) error {
  135. log.V(4).Infof("calling AddV6FDB: %v, %v", n.IP6, n.MAC)
  136. return netlink.NeighSet(&netlink.Neigh{
  137. LinkIndex: dev.link.Index,
  138. State: netlink.NUD_PERMANENT,
  139. Family: syscall.AF_BRIDGE,
  140. Flags: netlink.NTF_SELF,
  141. IP: n.IP6.ToIP(),
  142. HardwareAddr: n.MAC,
  143. })
  144. }
  145. func (dev *vxlanDevice) DelFDB(n neighbor) error {
  146. log.V(4).Infof("calling DelFDB: %v, %v", n.IP, n.MAC)
  147. return netlink.NeighDel(&netlink.Neigh{
  148. LinkIndex: dev.link.Index,
  149. Family: syscall.AF_BRIDGE,
  150. Flags: netlink.NTF_SELF,
  151. IP: n.IP.ToIP(),
  152. HardwareAddr: n.MAC,
  153. })
  154. }
  155. func (dev *vxlanDevice) DelV6FDB(n neighbor) error {
  156. log.V(4).Infof("calling DelV6FDB: %v, %v", n.IP6, n.MAC)
  157. return netlink.NeighDel(&netlink.Neigh{
  158. LinkIndex: dev.link.Index,
  159. Family: syscall.AF_BRIDGE,
  160. Flags: netlink.NTF_SELF,
  161. IP: n.IP6.ToIP(),
  162. HardwareAddr: n.MAC,
  163. })
  164. }
  165. func (dev *vxlanDevice) AddARP(n neighbor) error {
  166. log.V(4).Infof("calling AddARP: %v, %v", n.IP, n.MAC)
  167. return netlink.NeighSet(&netlink.Neigh{
  168. LinkIndex: dev.link.Index,
  169. State: netlink.NUD_PERMANENT,
  170. Type: syscall.RTN_UNICAST,
  171. IP: n.IP.ToIP(),
  172. HardwareAddr: n.MAC,
  173. })
  174. }
  175. func (dev *vxlanDevice) AddV6ARP(n neighbor) error {
  176. log.V(4).Infof("calling AddV6ARP: %v, %v", n.IP6, n.MAC)
  177. return netlink.NeighSet(&netlink.Neigh{
  178. LinkIndex: dev.link.Index,
  179. State: netlink.NUD_PERMANENT,
  180. Type: syscall.RTN_UNICAST,
  181. IP: n.IP6.ToIP(),
  182. HardwareAddr: n.MAC,
  183. })
  184. }
  185. func (dev *vxlanDevice) DelARP(n neighbor) error {
  186. log.V(4).Infof("calling DelARP: %v, %v", n.IP, n.MAC)
  187. return netlink.NeighDel(&netlink.Neigh{
  188. LinkIndex: dev.link.Index,
  189. State: netlink.NUD_PERMANENT,
  190. Type: syscall.RTN_UNICAST,
  191. IP: n.IP.ToIP(),
  192. HardwareAddr: n.MAC,
  193. })
  194. }
  195. func (dev *vxlanDevice) DelV6ARP(n neighbor) error {
  196. log.V(4).Infof("calling DelV6ARP: %v, %v", n.IP6, n.MAC)
  197. return netlink.NeighDel(&netlink.Neigh{
  198. LinkIndex: dev.link.Index,
  199. State: netlink.NUD_PERMANENT,
  200. Type: syscall.RTN_UNICAST,
  201. IP: n.IP6.ToIP(),
  202. HardwareAddr: n.MAC,
  203. })
  204. }
  205. func vxlanLinksIncompat(l1, l2 netlink.Link) string {
  206. if l1.Type() != l2.Type() {
  207. return fmt.Sprintf("link type: %v vs %v", l1.Type(), l2.Type())
  208. }
  209. v1 := l1.(*netlink.Vxlan)
  210. v2 := l2.(*netlink.Vxlan)
  211. if v1.VxlanId != v2.VxlanId {
  212. return fmt.Sprintf("vni: %v vs %v", v1.VxlanId, v2.VxlanId)
  213. }
  214. if v1.VtepDevIndex > 0 && v2.VtepDevIndex > 0 && v1.VtepDevIndex != v2.VtepDevIndex {
  215. return fmt.Sprintf("vtep (external) interface: %v vs %v", v1.VtepDevIndex, v2.VtepDevIndex)
  216. }
  217. if len(v1.SrcAddr) > 0 && len(v2.SrcAddr) > 0 && !v1.SrcAddr.Equal(v2.SrcAddr) {
  218. return fmt.Sprintf("vtep (external) IP: %v vs %v", v1.SrcAddr, v2.SrcAddr)
  219. }
  220. if len(v1.Group) > 0 && len(v2.Group) > 0 && !v1.Group.Equal(v2.Group) {
  221. return fmt.Sprintf("group address: %v vs %v", v1.Group, v2.Group)
  222. }
  223. if v1.L2miss != v2.L2miss {
  224. return fmt.Sprintf("l2miss: %v vs %v", v1.L2miss, v2.L2miss)
  225. }
  226. if v1.Port > 0 && v2.Port > 0 && v1.Port != v2.Port {
  227. return fmt.Sprintf("port: %v vs %v", v1.Port, v2.Port)
  228. }
  229. if v1.GBP != v2.GBP {
  230. return fmt.Sprintf("gbp: %v vs %v", v1.GBP, v2.GBP)
  231. }
  232. return ""
  233. }