github.phpd.cn/cilium/cilium@v1.6.12/pkg/mtu/mtu.go (about)

     1  // Copyright 2018 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package mtu
    16  
    17  const (
    18  	// MaxMTU is the highest MTU that can be used for devices and routes
    19  	// handled by Cilium. It will typically be used to configure inbound
    20  	// paths towards containers where it is guaranteed that the packet will
    21  	// not be rerouted to another node, and therefore will not lead to
    22  	// any form of IP fragmentation.
    23  	// One might expect this to be 65535, however Linux seems to cap the
    24  	// MTU of routes at 65520, so we use this value below.
    25  	MaxMTU = 65520
    26  
    27  	// EthernetMTU is the standard MTU for Ethernet devices. It is used
    28  	// as the MTU for container devices when running direct routing mode.
    29  	EthernetMTU = 1500
    30  
    31  	// TunnelOverhead is an approximation for bytes used for tunnel
    32  	// encapsulation. It accounts for:
    33  	//    (Outer ethernet is not accounted against MTU size)
    34  	//    Outer IPv4 header:  20B
    35  	//    Outer UDP header:    8B
    36  	//    Outer VXLAN header:  8B
    37  	//    Original Ethernet:  14B
    38  	//                        ---
    39  	//    Total extra bytes:  50B
    40  	TunnelOverhead = 50
    41  
    42  	// EncryptionIPsecOverhead is an approximation for bytes used for
    43  	// encryption. Depending on key size and encryption type the actual
    44  	// size may vary here we do calculations for 128B keys and Auth. The
    45  	// overhead is accounted for as:
    46  	//    Outer IP header:    20B
    47  	//    SPI:		   4B
    48  	//    Sequece Numbers:	   4B
    49  	//    Next Header:         1B
    50  	//    ICV:		  16B
    51  	//    Padding:            16B
    52  	//    128bit Auth:        16B
    53  	//			  ---
    54  	//    Total extra bytes:  77B
    55  	EncryptionIPsecOverhead = 77
    56  
    57  	// EncryptionDefaultAuthKeyLength is 16 representing 128B key recommended
    58  	// size for GCM(AES*) in RFC4106. Users may input other lengths via
    59  	// key secrets.
    60  	EncryptionDefaultAuthKeyLength = 16
    61  )
    62  
    63  // Configuration is an MTU configuration as returned by NewConfiguration
    64  type Configuration struct {
    65  	// standardMTU is the regular MTU used for configuring devices and
    66  	// routes where packets are expected to be delivered outside the node.
    67  	//
    68  	// Note that this is a singleton for the process including this
    69  	// package. This means, for instance, that when using this from the
    70  	// ``pkg/plugins/*`` sources, it will not respect the settings
    71  	// configured inside the ``daemon/``.
    72  	standardMTU int
    73  
    74  	// tunnelMTU is the MTU used for configuring a tunnel mesh for
    75  	// inter-node connectivity.
    76  	//
    77  	// Similar to StandardMTU, this is a singleton for the process.
    78  	tunnelMTU int
    79  
    80  	// encryptMTU is the MTU used for configurations a encryption route
    81  	// without tunneling. If tunneling is enabled the tunnelMTU is used
    82  	// which will include additional encryption overhead if needed.
    83  	encryptMTU int
    84  
    85  	encapEnabled   bool
    86  	encryptEnabled bool
    87  }
    88  
    89  // NewConfiguration returns a new MTU configuration. The MTU can be manually
    90  // specified, otherwise it will be automatically detected. if encapEnabled is
    91  // true, the MTU is adjusted to account for encapsulation overhead for all
    92  // routes involved in node to node communication.
    93  func NewConfiguration(authKeySize int, encryptEnabled bool, encapEnabled bool, mtu int) Configuration {
    94  	encryptOverhead := 0
    95  
    96  	if mtu == 0 {
    97  		var err error
    98  
    99  		mtu, err = autoDetect()
   100  		if err != nil {
   101  			log.WithError(err).Warning("Unable to automatically detect MTU")
   102  			mtu = EthernetMTU
   103  		}
   104  	}
   105  
   106  	if encryptEnabled {
   107  		// Add the difference between the default and the actual key sizes here
   108  		// to account for users specifying non-default auth key lengths.
   109  		encryptOverhead = EncryptionIPsecOverhead + (authKeySize - EncryptionDefaultAuthKeyLength)
   110  	}
   111  
   112  	conf := Configuration{
   113  		standardMTU:    mtu,
   114  		tunnelMTU:      mtu - (TunnelOverhead + encryptOverhead),
   115  		encryptMTU:     mtu - encryptOverhead,
   116  		encapEnabled:   encapEnabled,
   117  		encryptEnabled: encryptEnabled,
   118  	}
   119  
   120  	if conf.tunnelMTU < 0 {
   121  		conf.tunnelMTU = 0
   122  	}
   123  
   124  	return conf
   125  }
   126  
   127  // GetRouteMTU returns the MTU to be used on the network. When running in
   128  // tunneling mode and/or with encryption enabled, this will have tunnel and
   129  // encryption overhead accounted for.
   130  func (c *Configuration) GetRouteMTU() int {
   131  	if !c.encapEnabled && !c.encryptEnabled {
   132  		return c.GetDeviceMTU()
   133  	}
   134  
   135  	if c.encryptEnabled && !c.encapEnabled {
   136  		if c.encryptMTU == 0 {
   137  			return EthernetMTU - EncryptionIPsecOverhead
   138  		}
   139  		return c.encryptMTU
   140  	}
   141  
   142  	if c.tunnelMTU == 0 {
   143  		if c.encryptEnabled {
   144  			return EthernetMTU - (TunnelOverhead + EncryptionIPsecOverhead)
   145  		}
   146  		return EthernetMTU - TunnelOverhead
   147  	}
   148  
   149  	return c.tunnelMTU
   150  }
   151  
   152  // GetDeviceMTU returns the MTU to be used on workload facing devices.
   153  func (c *Configuration) GetDeviceMTU() int {
   154  	if c.standardMTU == 0 {
   155  		return EthernetMTU
   156  	}
   157  
   158  	return c.standardMTU
   159  }