k8s.io/kubernetes@v1.29.3/pkg/proxy/conntrack/conntrack_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package conntrack 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 24 v1 "k8s.io/api/core/v1" 25 "k8s.io/utils/exec" 26 fakeexec "k8s.io/utils/exec/testing" 27 utilnet "k8s.io/utils/net" 28 ) 29 30 func familyParamStr(isIPv6 bool) string { 31 if isIPv6 { 32 return " -f ipv6" 33 } 34 return "" 35 } 36 37 func TestExecConntrackTool(t *testing.T) { 38 fcmd := fakeexec.FakeCmd{ 39 CombinedOutputScript: []fakeexec.FakeAction{ 40 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 41 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 42 func() ([]byte, []byte, error) { 43 return []byte(""), nil, fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted") 44 }, 45 }, 46 } 47 fexec := &fakeexec.FakeExec{ 48 CommandScript: []fakeexec.FakeCommandAction{ 49 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 50 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 51 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 52 }, 53 LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, 54 } 55 56 testCases := [][]string{ 57 {"-L", "-p", "udp"}, 58 {"-D", "-p", "udp", "-d", "10.0.240.1"}, 59 {"-D", "-p", "udp", "--orig-dst", "10.240.0.2", "--dst-nat", "10.0.10.2"}, 60 } 61 62 expectErr := []bool{false, false, true} 63 64 for i := range testCases { 65 err := Exec(fexec, testCases[i]...) 66 67 if expectErr[i] { 68 if err == nil { 69 t.Errorf("expected err, got %v", err) 70 } 71 } else { 72 if err != nil { 73 t.Errorf("expected success, got %v", err) 74 } 75 } 76 77 execCmd := strings.Join(fcmd.CombinedOutputLog[i], " ") 78 expectCmd := fmt.Sprintf("%s %s", "conntrack", strings.Join(testCases[i], " ")) 79 80 if execCmd != expectCmd { 81 t.Errorf("expect execute command: %s, but got: %s", expectCmd, execCmd) 82 } 83 } 84 } 85 86 func TestClearUDPConntrackForIP(t *testing.T) { 87 fcmd := fakeexec.FakeCmd{ 88 CombinedOutputScript: []fakeexec.FakeAction{ 89 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 90 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 91 func() ([]byte, []byte, error) { 92 return []byte(""), nil, fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted") 93 }, 94 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 95 }, 96 } 97 fexec := &fakeexec.FakeExec{ 98 CommandScript: []fakeexec.FakeCommandAction{ 99 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 100 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 101 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 102 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 103 }, 104 LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, 105 } 106 107 testCases := []struct { 108 name string 109 ip string 110 }{ 111 {"IPv4 success", "10.240.0.3"}, 112 {"IPv4 success", "10.240.0.5"}, 113 {"IPv4 simulated error", "10.240.0.4"}, 114 {"IPv6 success", "2001:db8::10"}, 115 } 116 117 svcCount := 0 118 for _, tc := range testCases { 119 if err := ClearEntriesForIP(fexec, tc.ip, v1.ProtocolUDP); err != nil { 120 t.Errorf("%s test case:, Unexpected error: %v", tc.name, err) 121 } 122 expectCommand := fmt.Sprintf("conntrack -D --orig-dst %s -p udp", tc.ip) + familyParamStr(utilnet.IsIPv6String(tc.ip)) 123 execCommand := strings.Join(fcmd.CombinedOutputLog[svcCount], " ") 124 if expectCommand != execCommand { 125 t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand) 126 } 127 svcCount++ 128 } 129 if svcCount != fexec.CommandCalls { 130 t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls) 131 } 132 } 133 134 func TestClearUDPConntrackForPort(t *testing.T) { 135 fcmd := fakeexec.FakeCmd{ 136 CombinedOutputScript: []fakeexec.FakeAction{ 137 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 138 func() ([]byte, []byte, error) { 139 return []byte(""), nil, fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted") 140 }, 141 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 142 }, 143 } 144 fexec := &fakeexec.FakeExec{ 145 CommandScript: []fakeexec.FakeCommandAction{ 146 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 147 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 148 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 149 }, 150 LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, 151 } 152 153 testCases := []struct { 154 name string 155 port int 156 isIPv6 bool 157 }{ 158 {"IPv4, no error", 8080, false}, 159 {"IPv4, simulated error", 9090, false}, 160 {"IPv6, no error", 6666, true}, 161 } 162 svcCount := 0 163 for _, tc := range testCases { 164 err := ClearEntriesForPort(fexec, tc.port, tc.isIPv6, v1.ProtocolUDP) 165 if err != nil { 166 t.Errorf("%s test case: Unexpected error: %v", tc.name, err) 167 } 168 expectCommand := fmt.Sprintf("conntrack -D -p udp --dport %d", tc.port) + familyParamStr(tc.isIPv6) 169 execCommand := strings.Join(fcmd.CombinedOutputLog[svcCount], " ") 170 if expectCommand != execCommand { 171 t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand) 172 } 173 svcCount++ 174 } 175 if svcCount != fexec.CommandCalls { 176 t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls) 177 } 178 } 179 180 func TestDeleteUDPConnections(t *testing.T) { 181 fcmd := fakeexec.FakeCmd{ 182 CombinedOutputScript: []fakeexec.FakeAction{ 183 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 184 func() ([]byte, []byte, error) { 185 return []byte(""), nil, fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted") 186 }, 187 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 188 }, 189 } 190 fexec := &fakeexec.FakeExec{ 191 CommandScript: []fakeexec.FakeCommandAction{ 192 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 193 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 194 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 195 }, 196 LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, 197 } 198 199 testCases := []struct { 200 name string 201 origin string 202 dest string 203 }{ 204 { 205 name: "IPv4 success", 206 origin: "1.2.3.4", 207 dest: "10.20.30.40", 208 }, 209 { 210 name: "IPv4 simulated failure", 211 origin: "2.3.4.5", 212 dest: "20.30.40.50", 213 }, 214 { 215 name: "IPv6 success", 216 origin: "fd00::600d:f00d", 217 dest: "2001:db8::5", 218 }, 219 } 220 svcCount := 0 221 for i, tc := range testCases { 222 err := ClearEntriesForNAT(fexec, tc.origin, tc.dest, v1.ProtocolUDP) 223 if err != nil { 224 t.Errorf("%s test case: unexpected error: %v", tc.name, err) 225 } 226 expectCommand := fmt.Sprintf("conntrack -D --orig-dst %s --dst-nat %s -p udp", tc.origin, tc.dest) + familyParamStr(utilnet.IsIPv6String(tc.origin)) 227 execCommand := strings.Join(fcmd.CombinedOutputLog[i], " ") 228 if expectCommand != execCommand { 229 t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand) 230 } 231 svcCount++ 232 } 233 if svcCount != fexec.CommandCalls { 234 t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls) 235 } 236 } 237 238 func TestClearUDPConntrackForPortNAT(t *testing.T) { 239 fcmd := fakeexec.FakeCmd{ 240 CombinedOutputScript: []fakeexec.FakeAction{ 241 func() ([]byte, []byte, error) { return []byte("1 flow entries have been deleted"), nil, nil }, 242 }, 243 } 244 fexec := &fakeexec.FakeExec{ 245 CommandScript: []fakeexec.FakeCommandAction{ 246 func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, 247 }, 248 LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, 249 } 250 testCases := []struct { 251 name string 252 port int 253 dest string 254 }{ 255 { 256 name: "IPv4 success", 257 port: 30211, 258 dest: "1.2.3.4", 259 }, 260 } 261 svcCount := 0 262 for i, tc := range testCases { 263 err := ClearEntriesForPortNAT(fexec, tc.dest, tc.port, v1.ProtocolUDP) 264 if err != nil { 265 t.Errorf("%s test case: unexpected error: %v", tc.name, err) 266 } 267 expectCommand := fmt.Sprintf("conntrack -D -p udp --dport %d --dst-nat %s", tc.port, tc.dest) + familyParamStr(utilnet.IsIPv6String(tc.dest)) 268 execCommand := strings.Join(fcmd.CombinedOutputLog[i], " ") 269 if expectCommand != execCommand { 270 t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand) 271 } 272 svcCount++ 273 } 274 if svcCount != fexec.CommandCalls { 275 t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls) 276 } 277 }