Skip to content

Commit 39efb92

Browse files
damexaauren
authored andcommitted
feat: add support for SCTP
includes workaround for musl hardcoded protocol table that is missing SCTP support by using protocol name to numeric value mapping in ipset entries closes: #1019 Signed-off-by: Roman Kuzmitskii <roman@damex.org>
1 parent 62d1788 commit 39efb92

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

pkg/controllers/netpol/network_policy_controller.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,19 @@ func (npc *NetworkPolicyController) ensureTopLevelChains() {
516516
ensureRuleAtPosition(handler,
517517
kubeInputChainName, whitelistUDPNodeports, uuid, rulePosition[family])
518518
rulePosition[family]++
519+
520+
whitelistSCTPNodeports := []string{"-p", "sctp", "-m", "comment", "--comment",
521+
"allow LOCAL SCTP traffic to node ports", "-m", "addrtype", "--dst-type", "LOCAL",
522+
"-m", "multiport", "--dports", npc.serviceNodePortRange, "-j", "RETURN"}
523+
uuid, err = addUUIDForRuleSpec(kubeInputChainName, &whitelistSCTPNodeports)
524+
if err != nil {
525+
klog.Fatalf("Failed to get uuid for rule: %s", err.Error())
526+
}
527+
klog.V(2).Infof("Allow SCTP traffic to ingress towards node port range: %s for family: %s",
528+
npc.serviceNodePortRange, family)
529+
ensureRuleAtPosition(handler,
530+
kubeInputChainName, whitelistSCTPNodeports, uuid, rulePosition[family])
531+
rulePosition[family]++
519532
}
520533

521534
for idx, externalIPRange := range npc.serviceExternalIPRanges {

pkg/controllers/netpol/network_policy_controller_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ func TestNetworkPolicyBuilder(t *testing.T) {
436436
port, port1 := intstr.FromInt(30000), intstr.FromInt(34000)
437437
ingressPort := intstr.FromInt(37000)
438438
endPort, endPort1 := int32(31000), int32(35000)
439+
sctpPort := intstr.FromInt(36000)
440+
sctpProto := v1.ProtocolSCTP
439441
testCases := []tNetpolTestCase{
440442
{
441443
name: "Simple Egress Destination Port",
@@ -530,6 +532,58 @@ func TestNetworkPolicyBuilder(t *testing.T) {
530532
"-A KUBE-NWPLCY-2UTXQIFBI5TAPUCL -m comment --comment \"rule to ACCEPT traffic from source pods to all destinations selected by policy name: simple-egress-pr namespace nsA\" --dport 34000:35000 -j MARK --set-xmark 0x10000/0x10000 \n" +
531533
"-A KUBE-NWPLCY-2UTXQIFBI5TAPUCL -m comment --comment \"rule to ACCEPT traffic from source pods to all destinations selected by policy name: simple-egress-pr namespace nsA\" --dport 34000:35000 -m mark --mark 0x10000/0x10000 -j RETURN \n",
532534
},
535+
{
536+
name: "Simple SCTP Egress Destination Port",
537+
netpol: tNetpol{name: "sctp-egress", namespace: "nsA",
538+
podSelector: metav1.LabelSelector{
539+
MatchExpressions: []metav1.LabelSelectorRequirement{
540+
{
541+
Key: "app",
542+
Operator: "In",
543+
Values: []string{"a"},
544+
},
545+
},
546+
},
547+
egress: []netv1.NetworkPolicyEgressRule{
548+
{
549+
Ports: []netv1.NetworkPolicyPort{
550+
{
551+
Protocol: &sctpProto,
552+
Port: &sctpPort,
553+
},
554+
},
555+
},
556+
},
557+
},
558+
expectedRule: "-A KUBE-NWPLCY-HHGHJNRMJN6UUDNA -m comment --comment \"rule to ACCEPT traffic from source pods to all destinations selected by policy name: sctp-egress namespace nsA\" -p SCTP --dport 36000 -j MARK --set-xmark 0x10000/0x10000 \n" +
559+
"-A KUBE-NWPLCY-HHGHJNRMJN6UUDNA -m comment --comment \"rule to ACCEPT traffic from source pods to all destinations selected by policy name: sctp-egress namespace nsA\" -p SCTP --dport 36000 -m mark --mark 0x10000/0x10000 -j RETURN \n",
560+
},
561+
{
562+
name: "Simple SCTP Ingress Destination Port",
563+
netpol: tNetpol{name: "sctp-ingress", namespace: "nsA",
564+
podSelector: metav1.LabelSelector{
565+
MatchExpressions: []metav1.LabelSelectorRequirement{
566+
{
567+
Key: "app",
568+
Operator: "In",
569+
Values: []string{"a"},
570+
},
571+
},
572+
},
573+
ingress: []netv1.NetworkPolicyIngressRule{
574+
{
575+
Ports: []netv1.NetworkPolicyPort{
576+
{
577+
Protocol: &sctpProto,
578+
Port: &sctpPort,
579+
},
580+
},
581+
},
582+
},
583+
},
584+
expectedRule: "-A KUBE-NWPLCY-BHQGYKZ6X5RBPUOB -m comment --comment \"rule to ACCEPT traffic from all sources to dest pods selected by policy name: sctp-ingress namespace nsA\" -p SCTP --dport 36000 -j MARK --set-xmark 0x10000/0x10000 \n" +
585+
"-A KUBE-NWPLCY-BHQGYKZ6X5RBPUOB -m comment --comment \"rule to ACCEPT traffic from all sources to dest pods selected by policy name: sctp-ingress namespace nsA\" -p SCTP --dport 36000 -m mark --mark 0x10000/0x10000 -j RETURN \n",
586+
},
533587
{
534588
name: "Port > EndPort (invalid condition, should drop endport)",
535589
netpol: tNetpol{name: "invalid-endport", namespace: "nsA",

pkg/controllers/proxy/network_services_controller.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ const (
102102

103103
tcpProtocol = "tcp"
104104
udpProtocol = "udp"
105+
sctpProtocol = "sctp"
105106
noneProtocol = "none"
106107
tunnelInterfaceType = "tunnel"
107108

@@ -705,7 +706,11 @@ func (nsc *NetworkServicesController) syncIpvsFirewall() error {
705706

706707
serviceIPsSets[family] = append(serviceIPsSets[family], []string{address.String(), utils.OptionTimeout, "0"})
707708

708-
ipvsAddressWithPort := fmt.Sprintf("%s,%s:%d", address, protocol, port)
709+
ipsetProto := protocol
710+
if protocol == sctpProtocol {
711+
ipsetProto = strconv.FormatUint(uint64(convertSvcProtoToSysCallProto(protocol)), 10)
712+
}
713+
ipvsAddressWithPort := fmt.Sprintf("%s,%s:%d", address, ipsetProto, port)
709714
serviceIPPortsIPSets[family] = append(serviceIPPortsIPSets[family],
710715
[]string{ipvsAddressWithPort, utils.OptionTimeout, "0"})
711716

pkg/controllers/proxy/service_endpoints_sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ func (nsc *NetworkServicesController) cleanupStaleIPVSConfig(activeServiceEndpoi
746746
var protocol string
747747
for _, ipvsSvc := range ipvsSvcs {
748748
// Note that this isn't all that safe of an assumption because FWMark services have a completely different
749-
// protocol. So do SCTP services. However, we don't deal with SCTP in kube-router and FWMark is handled below.
749+
// protocol, which is handled below.
750750
protocol = convertSysCallProtoToSvcProto(ipvsSvc.Protocol)
751751
// FWMark services by definition don't have a protocol, so we exclude those from the conditional so that they
752752
// can be cleaned up correctly.

pkg/controllers/proxy/utils.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ func convertSvcProtoToSysCallProto(svcProtocol string) uint16 {
220220
return syscall.IPPROTO_TCP
221221
case udpProtocol:
222222
return syscall.IPPROTO_UDP
223+
case sctpProtocol:
224+
return syscall.IPPROTO_SCTP
223225
default:
224226
return syscall.IPPROTO_NONE
225227
}
@@ -233,6 +235,8 @@ func convertSysCallProtoToSvcProto(sysProtocol uint16) string {
233235
return tcpProtocol
234236
case syscall.IPPROTO_UDP:
235237
return udpProtocol
238+
case syscall.IPPROTO_SCTP:
239+
return sctpProtocol
236240
default:
237241
return noneProtocol
238242
}

0 commit comments

Comments
 (0)