Skip to content

Commit 1aef26a

Browse files
authored
Merge pull request kubernetes#130256 from adrianmoisey/netlink-without-tests
Add retries to some netlink calls - without tests
2 parents c2b8721 + faf6dc1 commit 1aef26a

File tree

5 files changed

+69
-10
lines changed

5 files changed

+69
-10
lines changed

pkg/proxy/conntrack/cleanup.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ limitations under the License.
2020
package conntrack
2121

2222
import (
23+
"errors"
2324
"time"
2425

2526
"github.com/vishvananda/netlink"
@@ -43,8 +44,12 @@ func CleanStaleEntries(ct Interface, ipFamily v1.IPFamily,
4344

4445
entries, err := ct.ListEntries(ipFamilyMap[ipFamily])
4546
if err != nil {
46-
klog.ErrorS(err, "Failed to list conntrack entries")
47-
return
47+
if errors.Is(err, unix.EINTR) {
48+
klog.V(2).ErrorS(err, "received a partial result, continuing to clean with partial result")
49+
} else {
50+
klog.ErrorS(err, "Failed to list conntrack entries")
51+
return
52+
}
4853
}
4954

5055
// serviceIPEndpointIPs maps service IPs (ClusterIP, LoadBalancerIPs and ExternalIPs)

pkg/proxy/conntrack/conntrack.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ import (
2424

2525
"github.com/vishvananda/netlink"
2626

27+
"k8s.io/client-go/util/retry"
2728
"k8s.io/klog/v2"
29+
"k8s.io/kubernetes/pkg/proxy/util"
2830
)
2931

3032
// Interface for dealing with conntrack
@@ -57,8 +59,12 @@ func newConntracker(handler netlinkHandler) Interface {
5759
}
5860

5961
// ListEntries list all conntrack entries for connections of the given IP family.
60-
func (ct *conntracker) ListEntries(ipFamily uint8) ([]*netlink.ConntrackFlow, error) {
61-
return ct.handler.ConntrackTableList(netlink.ConntrackTable, netlink.InetFamily(ipFamily))
62+
func (ct *conntracker) ListEntries(ipFamily uint8) (entries []*netlink.ConntrackFlow, err error) {
63+
err = retry.OnError(util.MaxAttemptsEINTR, util.ShouldRetryOnEINTR, func() error {
64+
entries, err = ct.handler.ConntrackTableList(netlink.ConntrackTable, netlink.InetFamily(ipFamily))
65+
return err
66+
})
67+
return entries, err
6268
}
6369

6470
// ClearEntries deletes conntrack entries for connections of the given IP family,
@@ -69,7 +75,15 @@ func (ct *conntracker) ClearEntries(ipFamily uint8, filters ...netlink.CustomCon
6975
return 0, nil
7076
}
7177

72-
n, err := ct.handler.ConntrackDeleteFilters(netlink.ConntrackTable, netlink.InetFamily(ipFamily), filters...)
78+
var n uint
79+
var err error
80+
err = retry.OnError(util.MaxAttemptsEINTR, util.ShouldRetryOnEINTR, func() error {
81+
var count uint
82+
count, err = ct.handler.ConntrackDeleteFilters(netlink.ConntrackTable, netlink.InetFamily(ipFamily), filters...)
83+
n += count
84+
return err
85+
})
86+
7387
if err != nil {
7488
return int(n), fmt.Errorf("error deleting conntrack entries, error: %w", err)
7589
}

pkg/proxy/util/nfacct/nfacct.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ type Interface interface {
3131
Add(name string) error
3232
// Get retrieves the nfacct counter with the specified name, returning an error if it doesn't exist.
3333
Get(name string) (*Counter, error)
34-
// List retrieves all nfacct counters.
34+
// List retrieves nfacct counters, it could receive all counters or a subset of them with an unix.EINTR error.
3535
List() ([]*Counter, error)
3636
}

pkg/proxy/util/nfacct/nfacct_linux.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import (
2929

3030
"github.com/vishvananda/netlink/nl"
3131
"golang.org/x/sys/unix"
32+
33+
"k8s.io/client-go/util/retry"
34+
"k8s.io/kubernetes/pkg/proxy/util"
3235
)
3336

3437
// MaxLength represents the maximum length allowed for the name in a nfacct counter.
@@ -146,9 +149,15 @@ func (r *runner) Get(name string) (*Counter, error) {
146149

147150
// List is part of the interface.
148151
func (r *runner) List() ([]*Counter, error) {
149-
req := r.handler.newRequest(cmdGet, unix.NLM_F_REQUEST|unix.NLM_F_DUMP)
150-
msgs, err := req.Execute(unix.NETLINK_NETFILTER, 0)
151-
if err != nil {
152+
var err error
153+
var msgs [][]byte
154+
err = retry.OnError(util.MaxAttemptsEINTR, util.ShouldRetryOnEINTR, func() error {
155+
req := r.handler.newRequest(cmdGet, unix.NLM_F_REQUEST|unix.NLM_F_DUMP)
156+
msgs, err = req.Execute(unix.NETLINK_NETFILTER, 0)
157+
return err
158+
})
159+
160+
if err != nil && !errors.Is(err, unix.EINTR) {
152161
return nil, handleError(err)
153162
}
154163

@@ -160,7 +169,7 @@ func (r *runner) List() ([]*Counter, error) {
160169
}
161170
counters = append(counters, counter)
162171
}
163-
return counters, nil
172+
return counters, err
164173
}
165174

166175
var ErrObjectNotFound = errors.New("object not found")

pkg/proxy/util/utils_linux.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//go:build linux
2+
// +build linux
3+
4+
/*
5+
Copyright 2025 The Kubernetes Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
*/
19+
20+
package util
21+
22+
import (
23+
"errors"
24+
25+
"golang.org/x/sys/unix"
26+
27+
"k8s.io/apimachinery/pkg/util/wait"
28+
)
29+
30+
var MaxAttemptsEINTR = wait.Backoff{Steps: 5}
31+
var ShouldRetryOnEINTR = func(err error) bool { return errors.Is(err, unix.EINTR) }

0 commit comments

Comments
 (0)