@@ -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+
710756func 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
745800func 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