Skip to content

Commit d433fa5

Browse files
authored
Fix IPVS persistence flag (#160)
* Fix IPVS persistence flag * Improve service proxy logging * Fix Destination string * Enhanced ipvs ServiceFlags handling
1 parent 3987ae1 commit d433fa5

File tree

1 file changed

+83
-27
lines changed

1 file changed

+83
-27
lines changed

app/controllers/network_services_controller.go

Lines changed: 83 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
234234
activeServiceEndpointMap := make(map[string][]string)
235235

236236
for k, svc := range serviceInfoMap {
237-
238237
var protocol uint16
239238
if svc.protocol == "tcp" {
240239
protocol = syscall.IPPROTO_TCP
@@ -269,7 +268,7 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
269268
}
270269
ipvsNodeportSvc, err = ipvsAddService(vip, protocol, uint16(svc.nodePort), svc.sessionAffinity)
271270
if err != nil {
272-
glog.Errorf("Failed to create ipvs service for node port")
271+
glog.Errorf("Failed to create ipvs service for node port due to: %s", err.Error())
273272
continue
274273
}
275274
if nsc.nodeportBindOnAllIp {
@@ -326,10 +325,12 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
326325
key := generateIpPortId(ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)))
327326
endpoints, ok := activeServiceEndpointMap[key]
328327
if !ok {
329-
glog.Infof("Found a IPVS service %s:%s:%s which is no longer needed so cleaning up", ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)))
328+
glog.Infof("Found a IPVS service %s which is no longer needed so cleaning up",
329+
ipvsServiceString(ipvsSvc))
330330
err := h.DelService(ipvsSvc)
331331
if err != nil {
332-
glog.Errorf("Failed to delete stale IPVS service: %s", err.Error())
332+
glog.Errorf("Failed to delete stale IPVS service %s due to:",
333+
ipvsServiceString(ipvsSvc), err.Error())
333334
continue
334335
}
335336
} else {
@@ -346,11 +347,12 @@ func (nsc *NetworkServicesController) syncIpvsServices(serviceInfoMap serviceInf
346347
}
347348
}
348349
if !validEp {
349-
glog.Infof("Found a IPVS service %s:%s:%s, destination %s which is no longer needed so cleaning up",
350-
ipvsSvc.Address.String(), protocol, strconv.Itoa(int(ipvsSvc.Port)), dst.Address.String())
350+
glog.Infof("Found a destination %s in service %s which is no longer needed so cleaning up",
351+
ipvsDestinationString(dst), ipvsServiceString(ipvsSvc))
351352
err := h.DelDestination(ipvsSvc, dst)
352353
if err != nil {
353-
glog.Errorf("Failed to delete server from ipvs service")
354+
glog.Errorf("Failed to delete destination %s from ipvs service %s",
355+
ipvsDestinationString(dst), ipvsServiceString(ipvsSvc))
354356
}
355357
}
356358
}
@@ -707,19 +709,76 @@ func deleteMasqueradeIptablesRule() error {
707709
return nil
708710
}
709711

712+
func ipvsServiceString(s *ipvs.Service) string {
713+
var flags, protocol string
714+
715+
switch s.Protocol {
716+
case syscall.IPPROTO_TCP:
717+
protocol = "TCP"
718+
case syscall.IPPROTO_UDP:
719+
protocol = "UDP"
720+
default:
721+
protocol = "UNKNOWN"
722+
}
723+
724+
if s.Flags&0x0001 != 0 {
725+
flags = flags + "[persistent port]"
726+
}
727+
728+
if s.Flags&0x0002 != 0 {
729+
flags = flags + "[hashed entry]"
730+
}
731+
732+
if s.Flags&0x0004 != 0 {
733+
flags = flags + "[one-packet scheduling]"
734+
}
735+
736+
return fmt.Sprintf("%s:%s:%v (Flags: %s)", protocol, s.Address, s.Port, flags)
737+
}
738+
739+
func ipvsDestinationString(d *ipvs.Destination) string {
740+
return fmt.Sprintf("%s:%v (Weight: %v)", d.Address, d.Port, d.Weight)
741+
}
742+
743+
func ipvsSetPersistence(svc *ipvs.Service, p bool) {
744+
if p {
745+
svc.Flags |= 0x0001
746+
svc.Netmask |= 0xFFFFFFFF
747+
// TODO: once service manifest supports timeout time remove hardcoding
748+
svc.Timeout = 180 * 60
749+
} else {
750+
svc.Flags &^= 0x0001
751+
svc.Netmask &^= 0xFFFFFFFF
752+
svc.Timeout = 0
753+
}
754+
}
755+
710756
func ipvsAddService(vip net.IP, protocol, port uint16, persistent bool) (*ipvs.Service, error) {
711757
svcs, err := h.GetServices()
712758
if err != nil {
713759
return nil, err
714760
}
761+
715762
for _, svc := range svcs {
716-
if strings.Compare(vip.String(), svc.Address.String()) == 0 &&
717-
protocol == svc.Protocol && port == svc.Port {
718-
glog.Infof("ipvs service %s:%s:%s already exists so returning", vip.String(),
719-
protocol, strconv.Itoa(int(port)))
763+
if vip.Equal(svc.Address) && protocol == svc.Protocol && port == svc.Port {
764+
if (persistent && (svc.Flags&0x0001) == 0) || (!persistent && (svc.Flags&0x0001) != 0) {
765+
ipvsSetPersistence(svc, persistent)
766+
767+
err = h.UpdateService(svc)
768+
if err != nil {
769+
return nil, err
770+
}
771+
glog.Infof("Updated persistence/session-affinity for service: %s", ipvsServiceString(svc))
772+
}
773+
774+
// TODO: Make this debug output when we get log levels
775+
// glog.Fatal("ipvs service %s:%s:%s already exists so returning", vip.String(),
776+
// protocol, strconv.Itoa(int(port)))
777+
720778
return svc, nil
721779
}
722780
}
781+
723782
svc := ipvs.Service{
724783
Address: vip,
725784
AddressFamily: syscall.AF_INET,
@@ -728,35 +787,32 @@ func ipvsAddService(vip net.IP, protocol, port uint16, persistent bool) (*ipvs.S
728787
SchedName: ipvs.RoundRobin,
729788
}
730789

731-
if persistent {
732-
// set bit to enable service persistence
733-
svc.Flags |= (1 << 24)
734-
svc.Netmask |= 0xFFFFFFFF
735-
// TODO: once service manifest supports timeout time remove hardcoding
736-
svc.Timeout = 180 * 60
737-
}
738-
if err := h.NewService(&svc); err != nil {
739-
return nil, fmt.Errorf("Failed to create service: %s:%s:%s", vip.String(), strconv.Itoa(int(protocol)), strconv.Itoa(int(port)))
790+
ipvsSetPersistence(&svc, persistent)
791+
792+
err = h.NewService(&svc)
793+
if err != nil {
794+
return nil, err
740795
}
741-
glog.Infof("Successfully added service: %s:%s:%s", vip.String(), protocol, strconv.Itoa(int(port)))
796+
glog.Infof("Successfully added service: %s", ipvsServiceString(&svc))
742797
return &svc, nil
743798
}
744799

745800
func ipvsAddServer(service *ipvs.Service, dest *ipvs.Destination) error {
746801

747802
err := h.NewDestination(service, dest)
748803
if err == nil {
749-
glog.Infof("Successfully added destination %s:%s to the service %s:%s:%s", dest.Address,
750-
strconv.Itoa(int(dest.Port)), service.Address, service.Protocol, strconv.Itoa(int(service.Port)))
804+
glog.Infof("Successfully added destination %s to the service %s",
805+
ipvsDestinationString(dest), ipvsServiceString(service))
751806
return nil
752807
}
753808

754809
if strings.Contains(err.Error(), IPVS_SERVER_EXISTS) {
755-
glog.Infof("ipvs destination %s:%s already exists in the ipvs service %s:%s:%s so not adding destination", dest.Address,
756-
strconv.Itoa(int(dest.Port)), service.Address, strconv.Itoa(int(service.Protocol)), strconv.Itoa(int(service.Port)))
810+
// TODO: Make this debug output when we get log levels
811+
// glog.Infof("ipvs destination %s already exists in the ipvs service %s so not adding destination",
812+
// ipvsDestinationString(dest), ipvsServiceString(service))
757813
} else {
758-
return fmt.Errorf("Failed to add ipvs destination %s:%s to the ipvs service %s:%s:%s due to : %s", dest.Address,
759-
strconv.Itoa(int(dest.Port)), service.Address, strconv.Itoa(int(service.Protocol)), strconv.Itoa(int(service.Port)), err.Error())
814+
return fmt.Errorf("Failed to add ipvs destination %s to the ipvs service %s due to : %s", dest.Address,
815+
ipvsDestinationString(dest), ipvsServiceString(service), err.Error())
760816
}
761817
return nil
762818
}

0 commit comments

Comments
 (0)