Change:
}, }, }, <ins> { name: "node port service with protocol sctp and externalTrafficPolicy local", services: []*v1.Service{ makeTestService("ns1", "svc1", func(svc *v1.Service) { svc.Spec.Type = "NodePort" svc.Spec.ClusterIP = "10.20.30.41" svc.Spec.Ports = []v1.ServicePort{{ Name:     "p80", Port:     int32(80), Protocol: v1.ProtocolSCTP, NodePort: int32(3001), }} svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal }), }, endpoints: []*discovery.EndpointSlice{ makeTestEndpointSlice("ns1", "svc1", 1, func(eps *discovery.EndpointSlice) { eps.AddressType = discovery.AddressTypeIPv4 eps.Endpoints = []discovery.Endpoint{{ Addresses: []string{"10.180.0.1"}, NodeName:  utilpointer.StringPtr(testHostname), }, { Addresses: []string{"10.180.1.1"}, NodeName:  utilpointer.StringPtr("otherHost"), }} eps.Ports = []discovery.EndpointPort{{ Name:     utilpointer.String("p80"), Port:     utilpointer.Int32(80), Protocol: &sctpProtocol, }} }), }, nodeIPs: []net.IP{ netutils.ParseIPSloppy("100.101.102.103"), }, nodePortAddresses: []string{}, expectedIPVS: &ipvstest.FakeIPVS{ Services: map[ipvstest.ServiceKey]*utilipvs.VirtualServer{ { IP:       "10.20.30.41", Port:     80, Protocol: "SCTP", }: { Address:   netutils.ParseIPSloppy("10.20.30.41"), Protocol:  "SCTP", Port:      uint16(80), Scheduler: "rr", }, { IP:       "100.101.102.103", Port:     3001, Protocol: "SCTP", }: { Address:   netutils.ParseIPSloppy("100.101.102.103"), Protocol:  "SCTP", Port:      uint16(3001), Scheduler: "rr", }, }, Destinations: map[ipvstest.ServiceKey][]*utilipvs.RealServer{ { IP:       "10.20.30.41", Port:     80, Protocol: "SCTP", }: { { Address: netutils.ParseIPSloppy("10.180.0.1"), Port:    uint16(80), Weight:  1, }, { Address: netutils.ParseIPSloppy("10.180.1.1"), Port:    uint16(80), Weight:  1, }, }, { IP:       "100.101.102.103", Port:     3001, Protocol: "SCTP", }: { { Address: netutils.ParseIPSloppy("10.180.0.1"), Port:    uint16(80), Weight:  1, }, }, }, }, expectedIPSets: netlinktest.ExpectedIPSet{ kubeNodePortSetSCTP: { { IP:       "100.101.102.103", Port:     3001, Protocol: strings.ToLower(string(v1.ProtocolSCTP)), SetType:  utilipset.HashIPPort, }, }, kubeNodePortLocalSetSCTP: { { IP:       "100.101.102.103", Port:     3001, Protocol: strings.ToLower(string(v1.ProtocolSCTP)), SetType:  utilipset.HashIPPort, }, }, }, expectedIptablesChains: netlinktest.ExpectedIptablesChain{ string(KubeNodePortChain): {{ JumpChain: "RETURN", MatchSet: kubeNodePortLocalSetSCTP, }, { JumpChain: string(KubeMarkMasqChain), MatchSet: kubeNodePortSetSCTP, }, { JumpChain: "ACCEPT", MatchSet: kubeHealthCheckNodePortSet, }}, }, }, </ins> } for _, test := range tests {

Discussion:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --ipvs mode didn't preserve client IP for NodePort Service with protocol SCTP and ExternalTrafficPolicy Local. iptables mode works fine. ipvs mode with TCP and UDP protocol works fine. Client IP for NodePort Service should be preseved when ExternalTrafficPolicy is Local regardless of the mode and the protocol. kube-proxy mode to ipvs a NodePort service with protocol SCTP and ExternalTrafficPolicy Local the NodePort service, the client IP was not preserved This is caused by wrong order of iptables rules that match kubeNodePortLocalSetSCTP and kubeNodePortSetSCTP: Kubernetes version (use ): v1.22.0 Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
/sig network /assign
/triage accepted