Skip to content

Commit c6ef9f9

Browse files
committed
Add knobs in cno referencing api change
Adds the necessary knobs in the cno to consume the api change exposing the internal masquerade subnet in ovn-k where we reserve addresses for ip masquerading Had to rebase on top of small conflict with addition of logging for libovsdb in the config yamls Also adds unit tests and verification in cno for configured masquerade subnets and corrects some tests/verification of the join subnet Signed-off-by: Ben Pickard <bpickard@redhat.com>
1 parent 0d15e45 commit c6ef9f9

File tree

4 files changed

+197
-27
lines changed

4 files changed

+197
-27
lines changed

bindata/network/ovn-kubernetes/managed/004-config.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,21 @@ data:
144144
{{- if (index . "V6JoinSubnet") }}
145145
v6-join-subnet="{{.V6JoinSubnet}}"
146146
{{- end }}
147+
{{- if (index . "V4InternalMasqueradeSubnet")}}
148+
v4-internal-masquerade-subnet="{{.V4InternalMasqueradeSubnet}}"
149+
{{- end }}
150+
{{- if (index . "V6InternalMasqueradeSubnet")}}
151+
v6-internal-masquerade-subnet="{{.V6InternalMasqueradeSubnet}}"
152+
{{- end }}
153+
147154

148155
[logging]
149156
libovsdblogfile=/var/log/ovnkube/libovsdb.log
150157
logfile-maxsize=100
151158
logfile-maxbackups=5
152159
logfile-maxage=0
153-
{{- if .OVNHybridOverlayEnable }}
154160

161+
{{- if .OVNHybridOverlayEnable }}
155162
[hybridoverlay]
156163
enabled=true
157164
{{- if .OVNHybridOverlayNetCIDR }}

bindata/network/ovn-kubernetes/self-hosted/004-config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ data:
6666
v6-join-subnet="{{.V6JoinSubnet}}"
6767
{{- end }}
6868

69+
{{- if (index . "V4InternalMasqueradeSubnet")}}
70+
v4-internal-masquerade-subnet="{{.V4InternalMasqueradeSubnet}}"
71+
{{- end }}
72+
{{- if (index . "V6InternalMasqueradeSubnet")}}
73+
v6-internal-masquerade-subnet="{{.V6InternalMasqueradeSubnet}}"
74+
{{- end }}
75+
6976
[logging]
7077
libovsdblogfile=/var/log/ovnkube/libovsdb.log
7178
logfile-maxsize=100

pkg/network/ovn_kubernetes.go

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,17 @@ func renderOVNKubernetes(conf *operv1.NetworkSpec, bootstrapResult *bootstrap.Bo
119119
data.Data["TokenAudience"] = os.Getenv("TOKEN_AUDIENCE")
120120
data.Data["MTU"] = c.MTU
121121
data.Data["RoutableMTU"] = nil
122+
// v4 and v6 join subnet are used when the user wants to use the addresses that we reserve for the join subnet in ovn-k
123+
// TODO: this field is being deprecated and will turn into c.GatewayConfig.IPv4/6.InternalJoinSubnet when we introduce the transit switch config into the api
122124
data.Data["V4JoinSubnet"] = c.V4InternalSubnet
123125
data.Data["V6JoinSubnet"] = c.V6InternalSubnet
126+
// v4 and v6InternalMasqueradeSubnet are used when the user wants to use the addresses that we reserve in ovn-k for ip masquerading
127+
if c.GatewayConfig != nil && c.GatewayConfig.IPv4.InternalMasqueradeSubnet != "" {
128+
data.Data["V4InternalMasqueradeSubnet"] = c.GatewayConfig.IPv4.InternalMasqueradeSubnet
129+
}
130+
if c.GatewayConfig != nil && c.GatewayConfig.IPv6.InternalMasqueradeSubnet != "" {
131+
data.Data["V6InternalMasqueradeSubnet"] = c.GatewayConfig.IPv6.InternalMasqueradeSubnet
132+
}
124133
data.Data["EnableUDPAggregation"] = !bootstrapResult.OVN.OVNKubernetesConfig.DisableUDPAggregation
125134
data.Data["NETWORK_NODE_IDENTITY_ENABLE"] = bootstrapResult.Infra.NetworkNodeIdentityEnabled
126135
data.Data["NodeIdentityCertDuration"] = OVN_NODE_IDENTITY_CERT_DURATION
@@ -813,45 +822,53 @@ func validateOVNKubernetes(conf *operv1.NetworkSpec) []error {
813822
if oc.GenevePort != nil && (*oc.GenevePort < 1 || *oc.GenevePort > 65535) {
814823
out = append(out, errors.Errorf("invalid GenevePort %d", *oc.GenevePort))
815824
}
816-
var v4Net, v6Net *net.IPNet
825+
var v4JoinNet, v6JoinNet, v4MasqNet, v6MasqNet *net.IPNet
817826
var err error
818827
if oc.V4InternalSubnet != "" {
819828
if !cnHasIPv4 {
820-
out = append(out, errors.Errorf("v4InternalSubnet and ClusterNetwork must have matching IP families"))
829+
out = append(out, errors.Errorf("v4InternalSubnet %s and ClusterNetwork must have matching IP families", oc.V4InternalSubnet))
821830
}
822-
_, v4Net, err = net.ParseCIDR(oc.V4InternalSubnet)
831+
_, v4JoinNet, err = net.ParseCIDR(oc.V4InternalSubnet)
823832
if err != nil {
824833
out = append(out, errors.Errorf("v4InternalSubnet is invalid: %s", err))
825834
}
835+
if v4JoinNet == nil {
836+
out = append(out, errors.Errorf("Unable to parse cidr for v4InternalSubnet %s", oc.V4InternalSubnet))
837+
return out
838+
}
826839
if !isV4InternalSubnetLargeEnough(conf) {
827-
out = append(out, errors.Errorf("v4InternalSubnet is no large enough for the maximum number of nodes which can be supported by ClusterNetwork"))
840+
out = append(out, errors.Errorf("v4InternalSubnet %s is not large enough for the maximum number of nodes which can be supported by ClusterNetwork", oc.V4InternalSubnet))
828841
}
829842
}
830843
if oc.V6InternalSubnet != "" {
831844
if !cnHasIPv6 {
832-
out = append(out, errors.Errorf("v6InternalSubnet and ClusterNetwork must have matching IP families"))
845+
out = append(out, errors.Errorf("v6InternalSubnet %s and ClusterNetwork must have matching IP families", oc.V6InternalSubnet))
833846
}
834-
_, v6Net, err = net.ParseCIDR(oc.V6InternalSubnet)
847+
_, v6JoinNet, err = net.ParseCIDR(oc.V6InternalSubnet)
835848
if err != nil {
836849
out = append(out, errors.Errorf("v6InternalSubnet is invalid: %s", err))
837850
}
851+
if v6JoinNet == nil {
852+
out = append(out, errors.Errorf("Unable to parse cidr for v6InternalSubnet %s", oc.V6InternalSubnet))
853+
return out
854+
}
838855
if !isV6InternalSubnetLargeEnough(conf) {
839-
out = append(out, errors.Errorf("v6InternalSubnet is no large enough for the maximum number of nodes which can be supported by ClusterNetwork"))
856+
out = append(out, errors.Errorf("v6InternalSubnet %s is not large enough for the maximum number of nodes which can be supported by ClusterNetwork", oc.V6InternalSubnet))
840857
}
841858
}
842859
for _, cn := range conf.ClusterNetwork {
843860
if utilnet.IsIPv6CIDRString(cn.CIDR) {
844861
if oc.V6InternalSubnet != "" {
845862
_, v6ClusterNet, _ := net.ParseCIDR(cn.CIDR)
846-
if iputil.NetsOverlap(*v6Net, *v6ClusterNet) {
847-
out = append(out, errors.Errorf("v6InternalSubnet overlaps with ClusterNetwork %s", cn.CIDR))
863+
if iputil.NetsOverlap(*v6JoinNet, *v6ClusterNet) {
864+
out = append(out, errors.Errorf("v6InternalSubnet %s overlaps with ClusterNetwork %s", oc.V6InternalSubnet, cn.CIDR))
848865
}
849866
}
850867
} else {
851868
if oc.V4InternalSubnet != "" {
852869
_, v4ClusterNet, _ := net.ParseCIDR(cn.CIDR)
853-
if iputil.NetsOverlap(*v4Net, *v4ClusterNet) {
854-
out = append(out, errors.Errorf("v4InternalSubnet overlaps with ClusterNetwork %s", cn.CIDR))
870+
if iputil.NetsOverlap(*v4JoinNet, *v4ClusterNet) {
871+
out = append(out, errors.Errorf("v4InternalSubnet %s overlaps with ClusterNetwork %s", oc.V4InternalSubnet, cn.CIDR))
855872
}
856873
}
857874
}
@@ -860,15 +877,86 @@ func validateOVNKubernetes(conf *operv1.NetworkSpec) []error {
860877
if utilnet.IsIPv6CIDRString(sn) {
861878
if oc.V6InternalSubnet != "" {
862879
_, v6ServiceNet, _ := net.ParseCIDR(sn)
863-
if iputil.NetsOverlap(*v6Net, *v6ServiceNet) {
864-
out = append(out, errors.Errorf("v6InternalSubnet overlaps with ServiceNetwork %s", sn))
880+
if iputil.NetsOverlap(*v6JoinNet, *v6ServiceNet) {
881+
out = append(out, errors.Errorf("v6InternalSubnet %s overlaps with ServiceNetwork %s", oc.V6InternalSubnet, sn))
865882
}
866883
}
867884
} else {
868885
if oc.V4InternalSubnet != "" {
869886
_, v4ServiceNet, _ := net.ParseCIDR(sn)
870-
if iputil.NetsOverlap(*v4Net, *v4ServiceNet) {
871-
out = append(out, errors.Errorf("v4InternalSubnet overlaps with ServiceNetwork %s", sn))
887+
if iputil.NetsOverlap(*v4JoinNet, *v4ServiceNet) {
888+
out = append(out, errors.Errorf("v4InternalSubnet %s overlaps with ServiceNetwork %s", oc.V4InternalSubnet, sn))
889+
}
890+
}
891+
}
892+
}
893+
if oc.GatewayConfig != nil {
894+
if oc.GatewayConfig.IPv4.InternalMasqueradeSubnet != "" {
895+
if !cnHasIPv4 {
896+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s and ClusterNetwork must have matching IP families", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet))
897+
}
898+
_, v4MasqNet, err = net.ParseCIDR(oc.GatewayConfig.IPv4.InternalMasqueradeSubnet)
899+
if v4MasqNet == nil {
900+
out = append(out, errors.Errorf("Unable to parse cidr for v4InternalMasqueradeSubnet %s", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet))
901+
return out
902+
}
903+
if err != nil {
904+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet is invalid: %s", err))
905+
}
906+
for _, cn := range conf.ClusterNetwork {
907+
if utilnet.IsIPv4CIDRString(cn.CIDR) {
908+
_, v4ClusterNet, _ := net.ParseCIDR(cn.CIDR)
909+
if iputil.NetsOverlap(*v4MasqNet, *v4ClusterNet) {
910+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s overlaps with ClusterNetwork %s", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet, cn.CIDR))
911+
}
912+
}
913+
}
914+
for _, sn := range conf.ServiceNetwork {
915+
if utilnet.IsIPv4CIDRString(sn) {
916+
_, v4ServiceNet, _ := net.ParseCIDR(sn)
917+
if iputil.NetsOverlap(*v4MasqNet, *v4ServiceNet) {
918+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s overlaps with ServiceNetwork %s", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet, sn))
919+
}
920+
}
921+
}
922+
if oc.V4InternalSubnet != "" {
923+
if iputil.NetsOverlap(*v4JoinNet, *v4MasqNet) {
924+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s overlaps with v4InternalSubnet %s", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet, oc.V4InternalSubnet))
925+
}
926+
}
927+
//TODO: ADD a utility to check for overlap between ovn-k configured subnets i.e. masq subnet, join subnet, and upcoming transit switch subnet
928+
}
929+
if oc.GatewayConfig.IPv6.InternalMasqueradeSubnet != "" {
930+
if !cnHasIPv6 {
931+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s and ClusterNetwork must have matching IP families", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet))
932+
}
933+
_, v6MasqNet, err = net.ParseCIDR(oc.GatewayConfig.IPv6.InternalMasqueradeSubnet)
934+
if err != nil {
935+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet is invalid: %s", err))
936+
}
937+
if v6MasqNet == nil {
938+
out = append(out, errors.Errorf("Unable to parse cidr for v6InternalMasqueradeSubnet %s", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet))
939+
return out
940+
}
941+
for _, cn := range conf.ClusterNetwork {
942+
if utilnet.IsIPv6CIDRString(cn.CIDR) {
943+
_, v6ClusterNet, _ := net.ParseCIDR(cn.CIDR)
944+
if iputil.NetsOverlap(*v6MasqNet, *v6ClusterNet) {
945+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s overlaps with ClusterNetwork %s", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet, cn.CIDR))
946+
}
947+
}
948+
}
949+
for _, sn := range conf.ServiceNetwork {
950+
if utilnet.IsIPv6CIDRString(sn) {
951+
_, v6ServiceNet, _ := net.ParseCIDR(sn)
952+
if iputil.NetsOverlap(*v6MasqNet, *v6ServiceNet) {
953+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s overlaps with ServiceNetwork %s", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet, sn))
954+
}
955+
}
956+
}
957+
if oc.V6InternalSubnet != "" {
958+
if iputil.NetsOverlap(*v6JoinNet, *v6MasqNet) {
959+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s overlaps with v6InternalSubnet %s", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet, oc.V6InternalSubnet))
872960
}
873961
}
874962
}

pkg/network/ovn_kubernetes_test.go

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,53 @@ logfile-maxage=0`,
276276
v4InternalSubnet: "100.99.0.0/16",
277277
controlPlaneReplicaCount: 2,
278278
},
279+
{
280+
desc: "custom masquerade subnet",
281+
expected: `
282+
[default]
283+
mtu="1500"
284+
cluster-subnets="10.128.0.0/15/23,10.0.0.0/14/24"
285+
encap-port="8061"
286+
enable-lflow-cache=true
287+
lflow-cache-limit-kb=1048576
288+
enable-udp-aggregation=true
289+
290+
[kubernetes]
291+
service-cidrs="172.30.0.0/16"
292+
ovn-config-namespace="openshift-ovn-kubernetes"
293+
apiserver="https://testing.test:8443"
294+
host-network-namespace="openshift-host-network"
295+
platform-type="GCP"
296+
healthz-bind-address="0.0.0.0:10256"
297+
dns-service-namespace="openshift-dns"
298+
dns-service-name="dns-default"
299+
300+
[ovnkubernetesfeature]
301+
enable-egress-ip=true
302+
enable-egress-firewall=true
303+
enable-egress-qos=true
304+
enable-egress-service=true
305+
egressip-node-healthcheck-port=9107
306+
enable-multi-network=true
307+
enable-multi-external-gateway=true
308+
309+
[gateway]
310+
mode=shared
311+
nodeport=true
312+
v4-internal-masquerade-subnet="100.98.0.0/16"
313+
314+
[logging]
315+
libovsdblogfile=/var/log/ovnkube/libovsdb.log
316+
logfile-maxsize=100
317+
logfile-maxbackups=5
318+
logfile-maxage=0`,
319+
controlPlaneReplicaCount: 2,
320+
gatewayConfig: &operv1.GatewayConfig{
321+
IPv4: operv1.IPv4GatewayConfig{
322+
InternalMasqueradeSubnet: "100.98.0.0/16",
323+
},
324+
},
325+
},
279326
{
280327
desc: "HybridOverlay",
281328
expected: `
@@ -783,8 +830,11 @@ logfile-maxage=0`,
783830
if tc.hybridOverlayConfig != nil {
784831
OVNKubeConfig.Spec.DefaultNetwork.OVNKubernetesConfig.HybridOverlayConfig = tc.hybridOverlayConfig
785832
}
786-
if tc.hybridOverlayConfig != nil {
833+
if tc.gatewayConfig != nil {
787834
OVNKubeConfig.Spec.DefaultNetwork.OVNKubernetesConfig.GatewayConfig = tc.gatewayConfig
835+
if tc.gatewayConfig.IPv4.InternalMasqueradeSubnet != "" {
836+
OVNKubeConfig.Spec.DefaultNetwork.OVNKubernetesConfig.GatewayConfig.IPv4.InternalMasqueradeSubnet = tc.gatewayConfig.IPv4.InternalMasqueradeSubnet
837+
}
788838
}
789839
if tc.egressIPConfig != nil {
790840
OVNKubeConfig.Spec.DefaultNetwork.OVNKubernetesConfig.EgressIPConfig = *tc.egressIPConfig
@@ -988,6 +1038,7 @@ func TestValidateOVNKubernetes(t *testing.T) {
9881038
crd := OVNKubernetesConfig.DeepCopy()
9891039
config := &crd.Spec
9901040
ovnConfig := config.DefaultNetwork.OVNKubernetesConfig
1041+
ovnConfig.GatewayConfig = &operv1.GatewayConfig{}
9911042

9921043
err := validateOVNKubernetes(config)
9931044
g.Expect(err).To(BeEmpty())
@@ -1009,15 +1060,21 @@ func TestValidateOVNKubernetes(t *testing.T) {
10091060
}
10101061

10111062
ovnConfig.V4InternalSubnet = "100.64.0.0/22"
1012-
errExpect("v4InternalSubnet is no large enough for the maximum number of nodes which can be supported by ClusterNetwork")
1063+
errExpect("v4InternalSubnet 100.64.0.0/22 is not large enough for the maximum number of nodes which can be supported by ClusterNetwork")
10131064
ovnConfig.V4InternalSubnet = "100.64.0.0/21"
1014-
errNotExpect("v4InternalSubnet is no large enough for the maximum number of nodes which can be supported by ClusterNetwork")
1065+
errNotExpect("v4InternalSubnet 100.64.0.0/21 is not large enough for the maximum number of nodes which can be supported by ClusterNetwork")
10151066
ovnConfig.V6InternalSubnet = "fd01::/48"
1016-
errExpect("v6InternalSubnet and ClusterNetwork must have matching IP families")
1067+
errExpect("v6InternalSubnet fd01::/48 and ClusterNetwork must have matching IP families")
10171068
ovnConfig.V4InternalSubnet = "10.128.0.0/16"
1018-
errExpect("v4InternalSubnet overlaps with ClusterNetwork 10.128.0.0/15")
1069+
errExpect("v4InternalSubnet 10.128.0.0/16 overlaps with ClusterNetwork 10.128.0.0/15")
10191070
ovnConfig.V4InternalSubnet = "172.30.0.0/18"
1020-
errExpect("v4InternalSubnet overlaps with ServiceNetwork 172.30.0.0/16")
1071+
errExpect("v4InternalSubnet 172.30.0.0/18 overlaps with ServiceNetwork 172.30.0.0/16")
1072+
ovnConfig.GatewayConfig.IPv4.InternalMasqueradeSubnet = "10.128.0.0/16"
1073+
errExpect("v4InternalMasqueradeSubnet 10.128.0.0/16 overlaps with ClusterNetwork 10.128.0.0/15")
1074+
ovnConfig.GatewayConfig.IPv6.InternalMasqueradeSubnet = "fd01::/48"
1075+
errExpect("v6InternalMasqueradeSubnet fd01::/48 and ClusterNetwork must have matching IP families")
1076+
ovnConfig.GatewayConfig.IPv4.InternalMasqueradeSubnet = "172.30.0.0/18"
1077+
errExpect("v4InternalMasqueradeSubnet 172.30.0.0/18 overlaps with ServiceNetwork 172.30.0.0/16")
10211078

10221079
// set mtu to insanity
10231080
ovnConfig.MTU = ptrToUint32(70000)
@@ -1031,15 +1088,26 @@ func TestValidateOVNKubernetes(t *testing.T) {
10311088
config.ClusterNetwork = []operv1.ClusterNetworkEntry{{
10321089
CIDR: "fd01::/48", HostPrefix: 64,
10331090
}}
1034-
errExpect("v4InternalSubnet and ClusterNetwork must have matching IP families")
1091+
errExpect("v4InternalSubnet 172.30.0.0/18 and ClusterNetwork must have matching IP families")
1092+
errExpect("v4InternalMasqueradeSubnet 172.30.0.0/18 and ClusterNetwork must have matching IP families")
10351093
ovnConfig.V6InternalSubnet = "fd01::/64"
1036-
errExpect("v6InternalSubnet overlaps with ClusterNetwork fd01::/48")
1094+
errExpect("v6InternalSubnet fd01::/64 overlaps with ClusterNetwork fd01::/48")
10371095
ovnConfig.V6InternalSubnet = "fd03::/112"
1038-
errExpect("v6InternalSubnet is no large enough for the maximum number of nodes which can be supported by ClusterNetwork")
1096+
errExpect("v6InternalSubnet fd03::/112 is not large enough for the maximum number of nodes which can be supported by ClusterNetwork")
10391097
ovnConfig.V6InternalSubnet = "fd03::/111"
1040-
errNotExpect("v6InternalSubnet is no large enough for the maximum number of nodes which can be supported by ClusterNetwork")
1098+
errNotExpect("v6InternalSubnet fd03::/111 is not large enough for the maximum number of nodes which can be supported by ClusterNetwork")
10411099
ovnConfig.V6InternalSubnet = "fd02::/64"
1042-
errExpect("v6InternalSubnet overlaps with ServiceNetwork fd02::/112")
1100+
errExpect("v6InternalSubnet fd02::/64 overlaps with ServiceNetwork fd02::/112")
1101+
ovnConfig.GatewayConfig.IPv6.InternalMasqueradeSubnet = "fd01::/64"
1102+
errExpect("v6InternalMasqueradeSubnet fd01::/64 overlaps with ClusterNetwork fd01::/48")
1103+
ovnConfig.GatewayConfig.IPv6.InternalMasqueradeSubnet = "fd02::/64"
1104+
errExpect("v6InternalMasqueradeSubnet fd02::/64 overlaps with ServiceNetwork fd02::/112")
1105+
ovnConfig.V4InternalSubnet = "100.99.0.0/16"
1106+
ovnConfig.GatewayConfig.IPv4.InternalMasqueradeSubnet = "100.99.0.0/16"
1107+
errExpect("v4InternalMasqueradeSubnet 100.99.0.0/16 overlaps with v4InternalSubnet 100.99.0.0/16")
1108+
ovnConfig.V6InternalSubnet = "fd69::/125"
1109+
ovnConfig.GatewayConfig.IPv6.InternalMasqueradeSubnet = "fd69::/125"
1110+
errExpect("v6InternalMasqueradeSubnet fd69::/125 overlaps with v6InternalSubnet fd69::/125")
10431111

10441112
// invalid ipv6 mtu
10451113
ovnConfig.MTU = ptrToUint32(576)

0 commit comments

Comments
 (0)