1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/libnetwork/ipvs/ipvs.go
Sebastiaan van Stijn d152888722 Bump vishvananda/netlink to 1.0.0
Changes included:

- Allow index specification at link creation time
- replace syscall with golang.org/x/sys/unix
  - related: Use IFF_MULTI_QUEUE from x/sys/unix to define TUNTAP_MULTI_QUEUE
  - related: Use IFLA_* constants from x/sys/unix
- Fix index out of range when no metadata for gretap
- added encapsulation attributes for Iptun and Sittun to support SIT tunnels
- Expose xfrm state's statistics
- Support invert in ip rules
- Support LWTUNNEL_ENCAP_SEG6
- Support setting and retrieving route MTU/AdvMSS
- Fix CalcRtable array parameter bug
- added support for Foo-over-UDP netlink calls
- Support num{tx,rx}queues and udp6zerocsum{tx,rx}
- tuntap: Add multiqueue support
- Retrieve VLAN ID when listing neighbour
- Fix LinkAdd for sit tunnel on 3.10 kernel
- Add support for managing source MACVLANs
- Two functions: one for adding bond slave, one for getting veth peer index
- Eliminate cgo from netlink
- Don't overwrite the XDP file descriptor with flags
- Fix reference to BPF instructions (on Kernel 4.13)
- Add Matchall filter
- Send IFA_CACHEINFO when setting up addresses
- Support IPv6 GRE Tun and Tap
- Add List option to RouteSubscribeWithOptions, AddrSubscribeWithOptions, and LinkSubscribeWithOptions
- Add Fq and Fq_Codel Qdisc support

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-24 14:56:49 +02:00

206 lines
5.1 KiB
Go

// +build linux
package ipvs
import (
"fmt"
"net"
"time"
"github.com/vishvananda/netlink/nl"
"github.com/vishvananda/netns"
"golang.org/x/sys/unix"
)
const (
netlinkRecvSocketsTimeout = 3 * time.Second
netlinkSendSocketTimeout = 30 * time.Second
)
// Service defines an IPVS service in its entirety.
type Service struct {
// Virtual service address.
Address net.IP
Protocol uint16
Port uint16
FWMark uint32 // Firewall mark of the service.
// Virtual service options.
SchedName string
Flags uint32
Timeout uint32
Netmask uint32
AddressFamily uint16
PEName string
Stats SvcStats
}
// SvcStats defines an IPVS service statistics
type SvcStats struct {
Connections uint32
PacketsIn uint32
PacketsOut uint32
BytesIn uint64
BytesOut uint64
CPS uint32
BPSOut uint32
PPSIn uint32
PPSOut uint32
BPSIn uint32
}
// Destination defines an IPVS destination (real server) in its
// entirety.
type Destination struct {
Address net.IP
Port uint16
Weight int
ConnectionFlags uint32
AddressFamily uint16
UpperThreshold uint32
LowerThreshold uint32
ActiveConnections int
InactiveConnections int
Stats DstStats
}
// DstStats defines IPVS destination (real server) statistics
type DstStats SvcStats
// Config defines IPVS timeout configuration
type Config struct {
TimeoutTCP time.Duration
TimeoutTCPFin time.Duration
TimeoutUDP time.Duration
}
// Handle provides a namespace specific ipvs handle to program ipvs
// rules.
type Handle struct {
seq uint32
sock *nl.NetlinkSocket
}
// New provides a new ipvs handle in the namespace pointed to by the
// passed path. It will return a valid handle or an error in case an
// error occurred while creating the handle.
func New(path string) (*Handle, error) {
setup()
n := netns.None()
if path != "" {
var err error
n, err = netns.GetFromPath(path)
if err != nil {
return nil, err
}
}
defer n.Close()
sock, err := nl.GetNetlinkSocketAt(n, netns.None(), unix.NETLINK_GENERIC)
if err != nil {
return nil, err
}
// Add operation timeout to avoid deadlocks
tv := unix.NsecToTimeval(netlinkSendSocketTimeout.Nanoseconds())
if err := sock.SetSendTimeout(&tv); err != nil {
return nil, err
}
tv = unix.NsecToTimeval(netlinkRecvSocketsTimeout.Nanoseconds())
if err := sock.SetReceiveTimeout(&tv); err != nil {
return nil, err
}
return &Handle{sock: sock}, nil
}
// Close closes the ipvs handle. The handle is invalid after Close
// returns.
func (i *Handle) Close() {
if i.sock != nil {
i.sock.Close()
}
}
// NewService creates a new ipvs service in the passed handle.
func (i *Handle) NewService(s *Service) error {
return i.doCmd(s, nil, ipvsCmdNewService)
}
// IsServicePresent queries for the ipvs service in the passed handle.
func (i *Handle) IsServicePresent(s *Service) bool {
return nil == i.doCmd(s, nil, ipvsCmdGetService)
}
// UpdateService updates an already existing service in the passed
// handle.
func (i *Handle) UpdateService(s *Service) error {
return i.doCmd(s, nil, ipvsCmdSetService)
}
// DelService deletes an already existing service in the passed
// handle.
func (i *Handle) DelService(s *Service) error {
return i.doCmd(s, nil, ipvsCmdDelService)
}
// Flush deletes all existing services in the passed
// handle.
func (i *Handle) Flush() error {
_, err := i.doCmdWithoutAttr(ipvsCmdFlush)
return err
}
// NewDestination creates a new real server in the passed ipvs
// service which should already be existing in the passed handle.
func (i *Handle) NewDestination(s *Service, d *Destination) error {
return i.doCmd(s, d, ipvsCmdNewDest)
}
// UpdateDestination updates an already existing real server in the
// passed ipvs service in the passed handle.
func (i *Handle) UpdateDestination(s *Service, d *Destination) error {
return i.doCmd(s, d, ipvsCmdSetDest)
}
// DelDestination deletes an already existing real server in the
// passed ipvs service in the passed handle.
func (i *Handle) DelDestination(s *Service, d *Destination) error {
return i.doCmd(s, d, ipvsCmdDelDest)
}
// GetServices returns an array of services configured on the Node
func (i *Handle) GetServices() ([]*Service, error) {
return i.doGetServicesCmd(nil)
}
// GetDestinations returns an array of Destinations configured for this Service
func (i *Handle) GetDestinations(s *Service) ([]*Destination, error) {
return i.doGetDestinationsCmd(s, nil)
}
// GetService gets details of a specific IPVS services, useful in updating statisics etc.,
func (i *Handle) GetService(s *Service) (*Service, error) {
res, err := i.doGetServicesCmd(s)
if err != nil {
return nil, err
}
// We are looking for exactly one service otherwise error out
if len(res) != 1 {
return nil, fmt.Errorf("Expected only one service obtained=%d", len(res))
}
return res[0], nil
}
// GetConfig returns the current timeout configuration
func (i *Handle) GetConfig() (*Config, error) {
return i.doGetConfigCmd()
}
// SetConfig set the current timeout configuration. 0: no change
func (i *Handle) SetConfig(c *Config) error {
return i.doSetConfigCmd(c)
}