ipvs_linux.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. // +build linux
  2. /*
  3. Copyright 2017 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. package ipvs
  15. import (
  16. "errors"
  17. "fmt"
  18. "net"
  19. "strings"
  20. "sync"
  21. "syscall"
  22. libipvs "github.com/docker/libnetwork/ipvs"
  23. "k8s.io/klog"
  24. utilexec "k8s.io/utils/exec"
  25. )
  26. // runner implements ipvs.Interface.
  27. type runner struct {
  28. exec utilexec.Interface
  29. ipvsHandle *libipvs.Handle
  30. mu sync.Mutex // Protect Netlink calls
  31. }
  32. // Protocol is the IPVS service protocol type
  33. type Protocol uint16
  34. // New returns a new Interface which will call ipvs APIs.
  35. func New(exec utilexec.Interface) Interface {
  36. handle, err := libipvs.New("")
  37. if err != nil {
  38. klog.Errorf("IPVS interface can't be initialized, error: %v", err)
  39. return nil
  40. }
  41. return &runner{
  42. exec: exec,
  43. ipvsHandle: handle,
  44. }
  45. }
  46. // AddVirtualServer is part of ipvs.Interface.
  47. func (runner *runner) AddVirtualServer(vs *VirtualServer) error {
  48. svc, err := toIPVSService(vs)
  49. if err != nil {
  50. return err
  51. }
  52. runner.mu.Lock()
  53. defer runner.mu.Unlock()
  54. return runner.ipvsHandle.NewService(svc)
  55. }
  56. // UpdateVirtualServer is part of ipvs.Interface.
  57. func (runner *runner) UpdateVirtualServer(vs *VirtualServer) error {
  58. svc, err := toIPVSService(vs)
  59. if err != nil {
  60. return err
  61. }
  62. runner.mu.Lock()
  63. defer runner.mu.Unlock()
  64. return runner.ipvsHandle.UpdateService(svc)
  65. }
  66. // DeleteVirtualServer is part of ipvs.Interface.
  67. func (runner *runner) DeleteVirtualServer(vs *VirtualServer) error {
  68. svc, err := toIPVSService(vs)
  69. if err != nil {
  70. return err
  71. }
  72. runner.mu.Lock()
  73. defer runner.mu.Unlock()
  74. return runner.ipvsHandle.DelService(svc)
  75. }
  76. // GetVirtualServer is part of ipvs.Interface.
  77. func (runner *runner) GetVirtualServer(vs *VirtualServer) (*VirtualServer, error) {
  78. svc, err := toIPVSService(vs)
  79. if err != nil {
  80. return nil, err
  81. }
  82. runner.mu.Lock()
  83. ipvsSvc, err := runner.ipvsHandle.GetService(svc)
  84. runner.mu.Unlock()
  85. if err != nil {
  86. return nil, err
  87. }
  88. vServ, err := toVirtualServer(ipvsSvc)
  89. if err != nil {
  90. return nil, err
  91. }
  92. return vServ, nil
  93. }
  94. // GetVirtualServers is part of ipvs.Interface.
  95. func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) {
  96. runner.mu.Lock()
  97. ipvsSvcs, err := runner.ipvsHandle.GetServices()
  98. runner.mu.Unlock()
  99. if err != nil {
  100. return nil, err
  101. }
  102. vss := make([]*VirtualServer, 0)
  103. for _, ipvsSvc := range ipvsSvcs {
  104. vs, err := toVirtualServer(ipvsSvc)
  105. if err != nil {
  106. return nil, err
  107. }
  108. vss = append(vss, vs)
  109. }
  110. return vss, nil
  111. }
  112. // Flush is part of ipvs.Interface. Currently we delete IPVS services one by one
  113. func (runner *runner) Flush() error {
  114. runner.mu.Lock()
  115. defer runner.mu.Unlock()
  116. return runner.ipvsHandle.Flush()
  117. }
  118. // AddRealServer is part of ipvs.Interface.
  119. func (runner *runner) AddRealServer(vs *VirtualServer, rs *RealServer) error {
  120. svc, err := toIPVSService(vs)
  121. if err != nil {
  122. return err
  123. }
  124. dst, err := toIPVSDestination(rs)
  125. if err != nil {
  126. return err
  127. }
  128. runner.mu.Lock()
  129. defer runner.mu.Unlock()
  130. return runner.ipvsHandle.NewDestination(svc, dst)
  131. }
  132. // DeleteRealServer is part of ipvs.Interface.
  133. func (runner *runner) DeleteRealServer(vs *VirtualServer, rs *RealServer) error {
  134. svc, err := toIPVSService(vs)
  135. if err != nil {
  136. return err
  137. }
  138. dst, err := toIPVSDestination(rs)
  139. if err != nil {
  140. return err
  141. }
  142. runner.mu.Lock()
  143. defer runner.mu.Unlock()
  144. return runner.ipvsHandle.DelDestination(svc, dst)
  145. }
  146. func (runner *runner) UpdateRealServer(vs *VirtualServer, rs *RealServer) error {
  147. svc, err := toIPVSService(vs)
  148. if err != nil {
  149. return err
  150. }
  151. dst, err := toIPVSDestination(rs)
  152. if err != nil {
  153. return err
  154. }
  155. runner.mu.Lock()
  156. defer runner.mu.Unlock()
  157. return runner.ipvsHandle.UpdateDestination(svc, dst)
  158. }
  159. // GetRealServers is part of ipvs.Interface.
  160. func (runner *runner) GetRealServers(vs *VirtualServer) ([]*RealServer, error) {
  161. svc, err := toIPVSService(vs)
  162. if err != nil {
  163. return nil, err
  164. }
  165. runner.mu.Lock()
  166. dsts, err := runner.ipvsHandle.GetDestinations(svc)
  167. runner.mu.Unlock()
  168. if err != nil {
  169. return nil, err
  170. }
  171. rss := make([]*RealServer, 0)
  172. for _, dst := range dsts {
  173. dst, err := toRealServer(dst)
  174. // TODO: aggregate errors?
  175. if err != nil {
  176. return nil, err
  177. }
  178. rss = append(rss, dst)
  179. }
  180. return rss, nil
  181. }
  182. // toVirtualServer converts an IPVS Service to the equivalent VirtualServer structure.
  183. func toVirtualServer(svc *libipvs.Service) (*VirtualServer, error) {
  184. if svc == nil {
  185. return nil, errors.New("ipvs svc should not be empty")
  186. }
  187. vs := &VirtualServer{
  188. Address: svc.Address,
  189. Port: svc.Port,
  190. Scheduler: svc.SchedName,
  191. Protocol: protocolToString(Protocol(svc.Protocol)),
  192. Timeout: svc.Timeout,
  193. }
  194. // Test Flags >= 0x2, valid Flags ranges [0x2, 0x3]
  195. if svc.Flags&FlagHashed == 0 {
  196. return nil, fmt.Errorf("Flags of successfully created IPVS service should be >= %d since every service is hashed into the service table", FlagHashed)
  197. }
  198. // Sub Flags to 0x2
  199. // 011 -> 001, 010 -> 000
  200. vs.Flags = ServiceFlags(svc.Flags &^ uint32(FlagHashed))
  201. if vs.Address == nil {
  202. if svc.AddressFamily == syscall.AF_INET {
  203. vs.Address = net.IPv4zero
  204. } else {
  205. vs.Address = net.IPv6zero
  206. }
  207. }
  208. return vs, nil
  209. }
  210. // toRealServer converts an IPVS Destination to the equivalent RealServer structure.
  211. func toRealServer(dst *libipvs.Destination) (*RealServer, error) {
  212. if dst == nil {
  213. return nil, errors.New("ipvs destination should not be empty")
  214. }
  215. return &RealServer{
  216. Address: dst.Address,
  217. Port: dst.Port,
  218. Weight: dst.Weight,
  219. ActiveConn: dst.ActiveConnections,
  220. InactiveConn: dst.InactiveConnections,
  221. }, nil
  222. }
  223. // toIPVSService converts a VirtualServer to the equivalent IPVS Service structure.
  224. func toIPVSService(vs *VirtualServer) (*libipvs.Service, error) {
  225. if vs == nil {
  226. return nil, errors.New("virtual server should not be empty")
  227. }
  228. ipvsSvc := &libipvs.Service{
  229. Address: vs.Address,
  230. Protocol: stringToProtocol(vs.Protocol),
  231. Port: vs.Port,
  232. SchedName: vs.Scheduler,
  233. Flags: uint32(vs.Flags),
  234. Timeout: vs.Timeout,
  235. }
  236. if ip4 := vs.Address.To4(); ip4 != nil {
  237. ipvsSvc.AddressFamily = syscall.AF_INET
  238. ipvsSvc.Netmask = 0xffffffff
  239. } else {
  240. ipvsSvc.AddressFamily = syscall.AF_INET6
  241. ipvsSvc.Netmask = 128
  242. }
  243. return ipvsSvc, nil
  244. }
  245. // toIPVSDestination converts a RealServer to the equivalent IPVS Destination structure.
  246. func toIPVSDestination(rs *RealServer) (*libipvs.Destination, error) {
  247. if rs == nil {
  248. return nil, errors.New("real server should not be empty")
  249. }
  250. return &libipvs.Destination{
  251. Address: rs.Address,
  252. Port: rs.Port,
  253. Weight: rs.Weight,
  254. }, nil
  255. }
  256. // stringToProtocolType returns the protocol type for the given name
  257. func stringToProtocol(protocol string) uint16 {
  258. switch strings.ToLower(protocol) {
  259. case "tcp":
  260. return uint16(syscall.IPPROTO_TCP)
  261. case "udp":
  262. return uint16(syscall.IPPROTO_UDP)
  263. case "sctp":
  264. return uint16(syscall.IPPROTO_SCTP)
  265. }
  266. return uint16(0)
  267. }
  268. // protocolTypeToString returns the name for the given protocol.
  269. func protocolToString(proto Protocol) string {
  270. switch proto {
  271. case syscall.IPPROTO_TCP:
  272. return "TCP"
  273. case syscall.IPPROTO_UDP:
  274. return "UDP"
  275. case syscall.IPPROTO_SCTP:
  276. return "SCTP"
  277. }
  278. return ""
  279. }