@@ -41,31 +41,49 @@ func (t *TunnelManager) SetupTunnels(containerName string) error {
4141 }
4242
4343 klog .V (0 ).Infof ("setting IPv4 address %s associated to container %s" , ipv4 , containerName )
44- output , err := AddIPToLocalInterface (ipv4 )
45- if err != nil {
46- return fmt .Errorf ("error adding IP to local interface: %w - %s" , err , output )
44+ // check if the IP is already assigned to the local interface
45+ if ! ipOnHost (ipv4 ) {
46+ output , err := AddIPToLocalInterface (ipv4 )
47+ if err != nil {
48+ return fmt .Errorf ("error adding IP to local interface: %w - %s" , err , output )
49+ }
4750 }
4851
4952 // create tunnel from the ip:svcport to the localhost:portmap
5053 t .mu .Lock ()
5154 defer t .mu .Unlock ()
55+ _ , ok := t .tunnels [containerName ]
56+ if ! ok {
57+ t .tunnels [containerName ] = map [string ]* tunnel {}
58+ }
59+
60+ // Reconcile: Remove tunnels that are not in portmaps
61+ for containerPort , tun := range t .tunnels [containerName ] {
62+ if _ , ok := portmaps [containerPort ]; ! ok {
63+ klog .V (0 ).Infof ("removing tunnel for %s %s as it is no longer in portmaps" , containerName , containerPort )
64+ tun .Stop () // nolint: errcheck
65+ delete (t .tunnels [containerName ], containerPort )
66+ }
67+ }
68+
5269 // There is one IP per Service and a tunnel per Service Port
5370 for containerPort , hostPort := range portmaps {
5471 parts := strings .Split (containerPort , "/" )
5572 if len (parts ) != 2 {
5673 return fmt .Errorf ("expected format port/protocol for container port, got %s" , containerPort )
5774 }
5875
76+ if _ , ok := t.tunnels [containerName ][containerPort ]; ok {
77+ klog .V (2 ).Infof ("tunnel for %s %s already exists" , containerName , containerPort )
78+ continue
79+ }
80+
5981 tun := NewTunnel (ipv4 , parts [0 ], parts [1 ], "localhost" , hostPort )
6082 // TODO check if we can leak tunnels
6183 err = tun .Start ()
6284 if err != nil {
6385 return err
6486 }
65- _ , ok := t .tunnels [containerName ]
66- if ! ok {
67- t .tunnels [containerName ] = map [string ]* tunnel {}
68- }
6987 t.tunnels [containerName ][containerPort ] = tun
7088 }
7189 return nil
@@ -88,6 +106,7 @@ func (t *TunnelManager) RemoveTunnels(containerName string) error {
88106 }
89107 tunnel .Stop () // nolint: errcheck
90108 }
109+ delete (t .tunnels , containerName )
91110
92111 klog .V (0 ).Infof ("Removing IPv4 address %s associated to local interface" , tunnelIP )
93112 output , err := RemoveIPFromLocalInterface (tunnelIP )
@@ -275,3 +294,29 @@ func (t *tunnel) handleUDPConnection(conn *net.UDPConn) error {
275294
276295 return err
277296}
297+
298+ func ipOnHost (ip string ) bool {
299+ ifaces , err := net .Interfaces ()
300+ if err != nil {
301+ return false
302+ }
303+ for _ , i := range ifaces {
304+ addrs , err := i .Addrs ()
305+ if err != nil {
306+ continue
307+ }
308+ for _ , addr := range addrs {
309+ var ipAddr net.IP
310+ switch v := addr .(type ) {
311+ case * net.IPNet :
312+ ipAddr = v .IP
313+ case * net.IPAddr :
314+ ipAddr = v .IP
315+ }
316+ if ipAddr != nil && ipAddr .String () == ip {
317+ return true
318+ }
319+ }
320+ }
321+ return false
322+ }
0 commit comments