123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // +build linux
- package ipvs
- import (
- "net"
- "syscall"
- "time"
- "fmt"
- "github.com/vishvananda/netlink/nl"
- "github.com/vishvananda/netns"
- )
- 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
- }
- // 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(), syscall.NETLINK_GENERIC)
- if err != nil {
- return nil, err
- }
- // Add operation timeout to avoid deadlocks
- tv := syscall.NsecToTimeval(netlinkSendSocketTimeout.Nanoseconds())
- if err := sock.SetSendTimeout(&tv); err != nil {
- return nil, err
- }
- tv = syscall.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
- }
|