@@ -38,6 +38,9 @@ const DefaultVXLANPort = 4789
3838
3939const DefaultDBTxnTimeout = time .Second * 100
4040
41+ // DefaultEphemeralPortRange is used for unit testing only
42+ const DefaultEphemeralPortRange = "32768-60999"
43+
4144// The following are global config parameters that other modules may access directly
4245var (
4346 // Build information. Populated at build-time.
@@ -494,6 +497,10 @@ type GatewayConfig struct {
494497 DisableForwarding bool `gcfg:"disable-forwarding"`
495498 // AllowNoUplink (disabled by default) controls if the external gateway bridge without an uplink port is allowed in local gateway mode.
496499 AllowNoUplink bool `gcfg:"allow-no-uplink"`
500+ // EphemeralPortRange is the range of ports used by egress SNAT operations in OVN. Specifically for NAT where
501+ // the source IP of the NAT will be a shared Node IP address. If unset, the value will be determined by sysctl lookup
502+ // for the kernel's ephemeral range: net.ipv4.ip_local_port_range. Format is "<min port>-<max port>".
503+ EphemeralPortRange string `gfcg:"ephemeral-port-range"`
497504}
498505
499506// OvnAuthConfig holds client authentication and location details for
@@ -664,6 +671,9 @@ func PrepareTestConfig() error {
664671 Kubernetes .DisableRequestedChassis = false
665672 EnableMulticast = false
666673 Default .OVSDBTxnTimeout = 5 * time .Second
674+ if Gateway .Mode != GatewayModeDisabled {
675+ Gateway .EphemeralPortRange = DefaultEphemeralPortRange
676+ }
667677
668678 if err := completeConfig (); err != nil {
669679 return err
@@ -1509,6 +1519,14 @@ var OVNGatewayFlags = []cli.Flag{
15091519 Usage : "Allow the external gateway bridge without an uplink port in local gateway mode" ,
15101520 Destination : & cliConfig .Gateway .AllowNoUplink ,
15111521 },
1522+ & cli.StringFlag {
1523+ Name : "ephemeral-port-range" ,
1524+ Usage : "The port range in '<min port>-<max port>' format for OVN to use when SNAT'ing to a node IP. " +
1525+ "This range should not collide with the node port range being used in Kubernetes. If not provided, " +
1526+ "the default value will be derived from checking the sysctl value of net.ipv4.ip_local_port_range on the node." ,
1527+ Destination : & cliConfig .Gateway .EphemeralPortRange ,
1528+ Value : Gateway .EphemeralPortRange ,
1529+ },
15121530 // Deprecated CLI options
15131531 & cli.BoolFlag {
15141532 Name : "init-gateways" ,
@@ -1917,6 +1935,19 @@ func buildGatewayConfig(ctx *cli.Context, cli, file *config) error {
19171935 if ! found {
19181936 return fmt .Errorf ("invalid gateway mode %q: expect one of %s" , string (Gateway .Mode ), strings .Join (validModes , "," ))
19191937 }
1938+
1939+ if len (Gateway .EphemeralPortRange ) > 0 {
1940+ if ! isValidEphemeralPortRange (Gateway .EphemeralPortRange ) {
1941+ return fmt .Errorf ("invalid ephemeral-port-range, should be in the format <min port>-<max port>" )
1942+ }
1943+ } else {
1944+ // auto-detect ephermal range
1945+ portRange , err := getKernelEphemeralPortRange ()
1946+ if err != nil {
1947+ return fmt .Errorf ("unable to auto-detect ephemeral port range to use with OVN" )
1948+ }
1949+ Gateway .EphemeralPortRange = portRange
1950+ }
19201951 }
19211952
19221953 // Options are only valid if Mode is not disabled
@@ -1927,6 +1958,9 @@ func buildGatewayConfig(ctx *cli.Context, cli, file *config) error {
19271958 if Gateway .NextHop != "" {
19281959 return fmt .Errorf ("gateway next-hop option %q not allowed when gateway is disabled" , Gateway .NextHop )
19291960 }
1961+ if len (Gateway .EphemeralPortRange ) > 0 {
1962+ return fmt .Errorf ("gateway ephemeral port range option not allowed when gateway is disabled" )
1963+ }
19301964 }
19311965
19321966 if Gateway .Mode != GatewayModeShared && Gateway .VLANID != 0 {
0 commit comments