Browse Source

[ipvs] Add support for timeout configuration (Get/SetConfig)

Signed-off-by: Laurent Bernaille <laurent.bernaille@datadoghq.com>
Laurent Bernaille 6 years ago
parent
commit
7374284841
2 changed files with 72 additions and 0 deletions
  1. 17 0
      libnetwork/ipvs/ipvs.go
  2. 55 0
      libnetwork/ipvs/netlink.go

+ 17 - 0
libnetwork/ipvs/ipvs.go

@@ -68,6 +68,13 @@ type Destination struct {
 // 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 {
@@ -188,3 +195,13 @@ func (i *Handle) GetService(s *Service) (*Service, error) {
 
 	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)
+}

+ 55 - 0
libnetwork/ipvs/netlink.go

@@ -12,6 +12,7 @@ import (
 	"sync"
 	"sync/atomic"
 	"syscall"
+	"time"
 	"unsafe"
 
 	"github.com/sirupsen/logrus"
@@ -503,6 +504,60 @@ func (i *Handle) doGetDestinationsCmd(s *Service, d *Destination) ([]*Destinatio
 	return res, nil
 }
 
+// parseConfig given a ipvs netlink response this function will respond with a valid config entry, an error otherwise
+func (i *Handle) parseConfig(msg []byte) (*Config, error) {
+	var c Config
+
+	//Remove General header for this message
+	hdr := deserializeGenlMsg(msg)
+	attrs, err := nl.ParseRouteAttr(msg[hdr.Len():])
+	if err != nil {
+		return nil, err
+	}
+
+	for _, attr := range attrs {
+		attrType := int(attr.Attr.Type)
+		switch attrType {
+		case ipvsCmdAttrTimeoutTCP:
+			c.TimeoutTCP = time.Duration(native.Uint32(attr.Value)) * time.Second
+		case ipvsCmdAttrTimeoutTCPFin:
+			c.TimeoutTCPFin = time.Duration(native.Uint32(attr.Value)) * time.Second
+		case ipvsCmdAttrTimeoutUDP:
+			c.TimeoutUDP = time.Duration(native.Uint32(attr.Value)) * time.Second
+		}
+	}
+
+	return &c, nil
+}
+
+// doGetConfigCmd a wrapper function to be used by GetConfig
+func (i *Handle) doGetConfigCmd() (*Config, error) {
+	msg, err := i.doCmdWithoutAttr(ipvsCmdGetConfig)
+	if err != nil {
+		return nil, err
+	}
+
+	res, err := i.parseConfig(msg[0])
+	if err != nil {
+		return res, err
+	}
+	return res, nil
+}
+
+// doSetConfigCmd a wrapper function to be used by SetConfig
+func (i *Handle) doSetConfigCmd(c *Config) error {
+	req := newIPVSRequest(ipvsCmdSetConfig)
+	req.Seq = atomic.AddUint32(&i.seq, 1)
+
+	req.AddData(nl.NewRtAttr(ipvsCmdAttrTimeoutTCP, nl.Uint32Attr(uint32(c.TimeoutTCP.Seconds()))))
+	req.AddData(nl.NewRtAttr(ipvsCmdAttrTimeoutTCPFin, nl.Uint32Attr(uint32(c.TimeoutTCPFin.Seconds()))))
+	req.AddData(nl.NewRtAttr(ipvsCmdAttrTimeoutUDP, nl.Uint32Attr(uint32(c.TimeoutUDP.Seconds()))))
+
+	_, err := execute(i.sock, req, 0)
+
+	return err
+}
+
 // IPVS related netlink message format explained
 
 /* EACH NETLINK MSG is of the below format, this is what we will receive from execute() api.