Skip to content

Commit aa7cffb

Browse files
dssengaauren
authored andcommitted
fix(NSC): only set rp_filter to 2 if it is 1
Setting rp_filter to 2 when it is 0 will override its status to be always enabled (in the loose mode). This behavior could break some networking solutions as it made packet admission rules more strict.
1 parent b2e2ef8 commit aa7cffb

File tree

2 files changed

+67
-19
lines changed

2 files changed

+67
-19
lines changed

pkg/controllers/proxy/network_services_controller.go

+22-7
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,15 @@ type endpointSliceInfo struct {
225225
// map of all endpoints, with unique service id(namespace name, service name, port) as key
226226
type endpointSliceInfoMap map[string][]endpointSliceInfo
227227

228+
func checkRPFilter1(ifname string) bool {
229+
rpFilterValue, err := utils.GetSysctlSingleTemplate(utils.IPv4ConfRPFilterTemplate, ifname)
230+
if err != nil {
231+
klog.Errorf("failed to get rp_filter value for %s: %s", ifname, err.Error())
232+
return false
233+
}
234+
return strings.TrimSpace(rpFilterValue) == "1"
235+
}
236+
228237
// Run periodically sync ipvs configuration to reflect desired state of services and endpoints
229238
func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.ControllerHeartbeat,
230239
stopCh <-chan struct{}, wg *sync.WaitGroup) {
@@ -286,16 +295,22 @@ func (nsc *NetworkServicesController) Run(healthChan chan<- *healthcheck.Control
286295
// https://github.com/kubernetes/kubernetes/pull/70530/files
287296
setSysCtlAndCheckError(utils.IPv4ConfAllArpAnnounce, arpAnnounceUseBestLocalAddress)
288297

289-
// Ensure rp_filter=2 for DSR capability, see:
298+
// Ensure rp_filter=2 (or leave 0 untouched) for DSR capability, see:
290299
// * https://access.redhat.com/solutions/53031
291300
// * https://github.com/cloudnativelabs/kube-router/pull/1651#issuecomment-2072851683
301+
// Only override rp_filter if it is set to 1, as enabling it from 0 to 2 can cause issues
302+
// with some network configurations which use reverse routing
292303
if nsc.krNode.IsIPv4Capable() {
293-
sysctlErr := utils.SetSysctlSingleTemplate(utils.IPv4ConfRPFilterTemplate, "all", 2)
294-
if sysctlErr != nil {
295-
if sysctlErr.IsFatal() {
296-
klog.Fatal(sysctlErr.Error())
297-
} else {
298-
klog.Error(sysctlErr.Error())
304+
for _, ifname := range []string{"all", "kube-bridge", "kube-dummy-if", nsc.krNode.GetNodeInterfaceName()} {
305+
if checkRPFilter1(ifname) {
306+
sysctlErr := utils.SetSysctlSingleTemplate(utils.IPv4ConfRPFilterTemplate, ifname, 2)
307+
if sysctlErr != nil {
308+
if sysctlErr.IsFatal() {
309+
klog.Fatal(sysctlErr.Error())
310+
} else {
311+
klog.Error(sysctlErr.Error())
312+
}
313+
}
299314
}
300315
}
301316
}

pkg/utils/sysctl.go

+45-12
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,18 @@ type SysctlError struct {
2929
additionalInfo string
3030
err error
3131
option string
32+
hasValue bool
3233
value int
3334
fatal bool
3435
}
3536

3637
// Error return the error as string
3738
func (e *SysctlError) Error() string {
38-
return fmt.Sprintf("Sysctl %s=%d : %s (%s)", e.option, e.value, e.err, e.additionalInfo)
39+
value := ""
40+
if e.hasValue {
41+
value = fmt.Sprintf("=%d", e.value)
42+
}
43+
return fmt.Sprintf("Sysctl %s%s : %s (%s)", e.option, value, e.err, e.additionalInfo)
3944
}
4045

4146
// IsFatal was the error fatal and reason to exit kube-router
@@ -48,6 +53,39 @@ func (e *SysctlError) Unwrap() error {
4853
return e.err
4954
}
5055

56+
func sysctlStat(path string, hasValue bool, value int) (string, *SysctlError) {
57+
sysctlPath := fmt.Sprintf("/proc/sys/%s", path)
58+
if _, err := os.Stat(sysctlPath); err != nil {
59+
if os.IsNotExist(err) {
60+
return sysctlPath, &SysctlError{
61+
"option not found, Does your kernel version support this feature?",
62+
err, path, hasValue, value, false}
63+
}
64+
return sysctlPath, &SysctlError{"path existed, but could not be stat'd", err, path, hasValue, value, true}
65+
}
66+
return sysctlPath, nil
67+
}
68+
69+
// GetSysctlSingleTemplate gets a sysctl value by first formatting the PathTemplate parameter with the substitute string
70+
// and then getting the sysctl value and converting it into a string
71+
func GetSysctlSingleTemplate(pathTemplate string, substitute string) (string, *SysctlError) {
72+
actualPath := fmt.Sprintf(pathTemplate, substitute)
73+
return GetSysctl(actualPath)
74+
}
75+
76+
// GetSysctl gets a sysctl value
77+
func GetSysctl(path string) (string, *SysctlError) {
78+
sysctlPath, err := sysctlStat(path, false, 0)
79+
if err != nil {
80+
return "", err
81+
}
82+
buf, readErr := os.ReadFile(sysctlPath)
83+
if readErr != nil {
84+
return "", &SysctlError{"path could not be read", err, path, false, 0, true}
85+
}
86+
return string(buf), nil
87+
}
88+
5189
// SetSysctlSingleTemplate sets a sysctl value by first formatting the PathTemplate parameter with the substitute string
5290
// and then setting the sysctl to the value parameter
5391
func SetSysctlSingleTemplate(pathTemplate string, substitute string, value int) *SysctlError {
@@ -57,18 +95,13 @@ func SetSysctlSingleTemplate(pathTemplate string, substitute string, value int)
5795

5896
// SetSysctl sets a sysctl value
5997
func SetSysctl(path string, value int) *SysctlError {
60-
sysctlPath := fmt.Sprintf("/proc/sys/%s", path)
61-
if _, err := os.Stat(sysctlPath); err != nil {
62-
if os.IsNotExist(err) {
63-
return &SysctlError{
64-
"option not found, Does your kernel version support this feature?",
65-
err, path, value, false}
66-
}
67-
return &SysctlError{"path existed, but could not be stat'd", err, path, value, true}
68-
}
69-
err := os.WriteFile(sysctlPath, []byte(strconv.Itoa(value)), 0640)
98+
sysctlPath, err := sysctlStat(path, true, value)
7099
if err != nil {
71-
return &SysctlError{"path could not be set", err, path, value, true}
100+
return err
101+
}
102+
writeErr := os.WriteFile(sysctlPath, []byte(strconv.Itoa(value)), 0640)
103+
if writeErr != nil {
104+
return &SysctlError{"path could not be set", err, path, true, value, true}
72105
}
73106
return nil
74107
}

0 commit comments

Comments
 (0)