Skip to content

Commit 0a0a0d4

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 0a0a0d4

File tree

4 files changed

+158
-20
lines changed

4 files changed

+158
-20
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: 70 additions & 8 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
@@ -817,41 +826,41 @@ func validateOVNKubernetes(conf *operv1.NetworkSpec) []error {
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
}
822831
_, v4Net, err = net.ParseCIDR(oc.V4InternalSubnet)
823832
if err != nil {
824833
out = append(out, errors.Errorf("v4InternalSubnet is invalid: %s", err))
825834
}
826835
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"))
836+
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))
828837
}
829838
}
830839
if oc.V6InternalSubnet != "" {
831840
if !cnHasIPv6 {
832-
out = append(out, errors.Errorf("v6InternalSubnet and ClusterNetwork must have matching IP families"))
841+
out = append(out, errors.Errorf("v6InternalSubnet %s and ClusterNetwork must have matching IP families", oc.V6InternalSubnet))
833842
}
834843
_, v6Net, err = net.ParseCIDR(oc.V6InternalSubnet)
835844
if err != nil {
836845
out = append(out, errors.Errorf("v6InternalSubnet is invalid: %s", err))
837846
}
838847
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"))
848+
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))
840849
}
841850
}
842851
for _, cn := range conf.ClusterNetwork {
843852
if utilnet.IsIPv6CIDRString(cn.CIDR) {
844853
if oc.V6InternalSubnet != "" {
845854
_, v6ClusterNet, _ := net.ParseCIDR(cn.CIDR)
846855
if iputil.NetsOverlap(*v6Net, *v6ClusterNet) {
847-
out = append(out, errors.Errorf("v6InternalSubnet overlaps with ClusterNetwork %s", cn.CIDR))
856+
out = append(out, errors.Errorf("v6InternalSubnet %s overlaps with ClusterNetwork %s", oc.V6InternalSubnet, cn.CIDR))
848857
}
849858
}
850859
} else {
851860
if oc.V4InternalSubnet != "" {
852861
_, v4ClusterNet, _ := net.ParseCIDR(cn.CIDR)
853862
if iputil.NetsOverlap(*v4Net, *v4ClusterNet) {
854-
out = append(out, errors.Errorf("v4InternalSubnet overlaps with ClusterNetwork %s", cn.CIDR))
863+
out = append(out, errors.Errorf("v4InternalSubnet %s overlaps with ClusterNetwork %s", oc.V4InternalSubnet, cn.CIDR))
855864
}
856865
}
857866
}
@@ -861,14 +870,67 @@ func validateOVNKubernetes(conf *operv1.NetworkSpec) []error {
861870
if oc.V6InternalSubnet != "" {
862871
_, v6ServiceNet, _ := net.ParseCIDR(sn)
863872
if iputil.NetsOverlap(*v6Net, *v6ServiceNet) {
864-
out = append(out, errors.Errorf("v6InternalSubnet overlaps with ServiceNetwork %s", sn))
873+
out = append(out, errors.Errorf("v6InternalSubnet %s overlaps with ServiceNetwork %s", oc.V6InternalSubnet, sn))
865874
}
866875
}
867876
} else {
868877
if oc.V4InternalSubnet != "" {
869878
_, v4ServiceNet, _ := net.ParseCIDR(sn)
870879
if iputil.NetsOverlap(*v4Net, *v4ServiceNet) {
871-
out = append(out, errors.Errorf("v4InternalSubnet overlaps with ServiceNetwork %s", sn))
880+
out = append(out, errors.Errorf("v4InternalSubnet %s overlaps with ServiceNetwork %s", oc.V4InternalSubnet, sn))
881+
}
882+
}
883+
}
884+
}
885+
if oc.GatewayConfig != nil {
886+
if oc.GatewayConfig.IPv4.InternalMasqueradeSubnet != "" {
887+
if !cnHasIPv4 {
888+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s and ClusterNetwork must have matching IP families", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet))
889+
}
890+
_, v4Net, err = net.ParseCIDR(oc.GatewayConfig.IPv4.InternalMasqueradeSubnet)
891+
if err != nil {
892+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet is invalid: %s", err))
893+
}
894+
for _, cn := range conf.ClusterNetwork {
895+
if utilnet.IsIPv4CIDRString(cn.CIDR) {
896+
_, v4ClusterNet, _ := net.ParseCIDR(cn.CIDR)
897+
if iputil.NetsOverlap(*v4Net, *v4ClusterNet) {
898+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s overlaps with ClusterNetwork %s", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet, cn.CIDR))
899+
}
900+
}
901+
}
902+
for _, sn := range conf.ServiceNetwork {
903+
if utilnet.IsIPv4CIDRString(sn) {
904+
_, v4ServiceNet, _ := net.ParseCIDR(sn)
905+
if iputil.NetsOverlap(*v4Net, *v4ServiceNet) {
906+
out = append(out, errors.Errorf("v4InternalMasqueradeSubnet %s overlaps with ServiceNetwork %s", oc.GatewayConfig.IPv4.InternalMasqueradeSubnet, sn))
907+
}
908+
}
909+
}
910+
//TODO: ADD a utility to check for overlap between ovn-k configured subnets i.e. masq subnet, join subnet, and upcoming transit switch subnet
911+
}
912+
if oc.GatewayConfig.IPv6.InternalMasqueradeSubnet != "" {
913+
if !cnHasIPv6 {
914+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s and ClusterNetwork must have matching IP families", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet))
915+
}
916+
_, v6Net, err = net.ParseCIDR(oc.GatewayConfig.IPv6.InternalMasqueradeSubnet)
917+
if err != nil {
918+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet is invalid: %s", err))
919+
}
920+
for _, cn := range conf.ClusterNetwork {
921+
if utilnet.IsIPv6CIDRString(cn.CIDR) {
922+
_, v6ClusterNet, _ := net.ParseCIDR(cn.CIDR)
923+
if iputil.NetsOverlap(*v6Net, *v6ClusterNet) {
924+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s overlaps with ClusterNetwork %s", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet, cn.CIDR))
925+
}
926+
}
927+
}
928+
for _, sn := range conf.ServiceNetwork {
929+
if utilnet.IsIPv6CIDRString(sn) {
930+
_, v6ServiceNet, _ := net.ParseCIDR(sn)
931+
if iputil.NetsOverlap(*v6Net, *v6ServiceNet) {
932+
out = append(out, errors.Errorf("v6InternalMasqueradeSubnet %s overlaps with ServiceNetwork %s", oc.GatewayConfig.IPv6.InternalMasqueradeSubnet, sn))
933+
}
872934
}
873935
}
874936
}

pkg/network/ovn_kubernetes_test.go

Lines changed: 73 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,20 @@ 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")
10431105

10441106
// invalid ipv6 mtu
10451107
ovnConfig.MTU = ptrToUint32(576)

0 commit comments

Comments
 (0)