Script to set the MTU size in RedHat

The following script makes it easy to set the MTU size if you are using RedHat or CentOS 7.x, and has also been tested successfully on RedHat 6.x.

It works out what the default network interface is and then updates the network configuration file and DHCP client configuration file before restarting the network. If no MTU size is specified on the command line it defaults to 1492 bytes (for no other reason than the fact that this reflects the MTU size of my internet connection).

Note – The script comments out any IPv6 settings in the network configuration file as well, this seems necessary to allow the MTU size to be set to a value less than 1280 bytes (which is the minimum MTU size for IPv6).

#!/bin/bash
#
#   set-mtu.sh
#
# - Description:
#
#   This script will configure the MTU size of the default network interface
#   and on a RedHat/Centos 7.x system and then re-start the network.
#
#   As well as any existing MTU settings all the existing IPv6 settings will
#   will also be commented out (otherwise if you are using DHCP the MTU size
#   setting is ignored) then the new MTU setting will be added at the end of
#   the file.
#
#   The DHCP client configuration will also be updated to stop it requesting
#   a  value for the MTU size (which would otherwise override the setting in
#   the network configuration file.
#
# - Licence:
#
#   This  program is free software: you can redistribute it and/or modify it
#   under  the terms of the GNU General Public License as published  by  the
#   Free  Software Foundation, either version 3 of the License, or (at  your
#   option) any later version.
#
#   This  program  is  distributed in the hope that it will be  useful,  but
#   WITHOUT   ANY   WARRANTY;   without  even   the  implied   warranty   of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
#   Public  License for more details.
#
#   You  should have received a copy of the GNU General Public License along
#   with this program. If not, see <http://www.gnu.org/licenses/>
#
# - Change History:
#
#   06 Apr 19   0.1   0001  - Initial version - MT
#               0.2   0002  - Allows an integer value for the MTU size to be
#                             specified on the command line - MT
#                     0003  - Added a function to check that the MTU size is
#                             a positive integer - MT
#                           - Now  updates the DHCP client configuration  to
#                             stop it overriding the desired value - MT
#   07 Apr 19         0004  - Search  for the configuration files and  check
#                             that they exist usign the path - MT
#               0.3   0005  - Comments out any IPv6 settings - MT
#                           - No  longer uses a function to check  that  the
#                             MTU size is a positive integer - MT
#               0.4   0006  - Only  updates  the DHCP  client  configuration
#                             file if it exists and checks for systemctl and
#                             uses ifdown/ifup if it is not installed.  This
#                             should  allow the script to be used all recent
#                             releases of RedHat/Centos - MT
#  08 Apr 19    0.5   0007  - Redirects all error messages to stderr - MT
#                           - Continue  function now returns a value instead
#                             of exiting and is renamed confirm - MT
#                     0008  - Checks that the MTU has been changed - MT
#
# - To Do:
#
#                           - Check that the default interface is up?
#
# - Set up default device name and MTU size.
#
_device="$(ip route | grep "default" | sed -e "s/^.*dev.//" -e "s/.proto.*//")"
_mtu=1498
#
_dhcp_config=$(find / -type f -name dhclient.conf 2>/dev/null) # Find DHCP config file.
_device_config=$(find / -type f -name ifcfg-$_device 2>/dev/null) # Find device config file.
#
# - Check if argument is a positive integer
#
_isnumber () {
  case $1 in
    ''|*[!0-9]*) return 1 ;; # Rejects empty strings and strings containing but digits.
    *) return 0 ;;
  esac
}
#
# - Prompt user to confirm action.
#
_confirm () {
  while true; do
    read -r -p "$@ (y/N) : " _confirm
    case $_confirm in
      [yY][eE][sS]|[yY]) return 0;;
      ''|[Nn][Oo]|[Nn]) return 1;;
      *) ;; # Try again...
    esac
  done
}
#
# - Event handler for Ctrl-C.
#
_quit() {
  echoexit 1
}
#
trap '_quit' SIGINT
#
if [[ -z $2 ]]; then
  if [[ ! -z $1 ]]; then _mtu=$1; fi # Set the MTU size if an argument was specified (or use the default).
  if [[ "$_mtu" =~ ^[0-9]+$ ]]; then # OR use ( _isnumber "$_mtu" ) # Check the MTU is a positive integer
    if [ "$_mtu" -ge 768 ] && [ "$_mtu" -le 1500 ]; then # Check the MTU size is between 786 and 1500.
      if [ ! -z "$_device_config" ]; then # Check that the config file exists.
        if [ ! -z "$_dhcp_config" ]; then # Update DHCP client config if it exists
          sed -i -e "/^[^#]*interface-mtu/s/, interface-mtu//" "$_dhcp_config" # Remove interface-mtu from the DHCP client request.
          sed -i -e "/^[^#]*interface-mtu/s/interface-mtu, //" "$_dhcp_config"
        fi
        sed  -i -e "s/^\\s*IPV6/#&/" "$_device_config" # Comment out any IPv6 settings.
        sed  -i -e "/^\\s*MTU=$_mtu/d" "$_device_config" # Delete existing entry if it matches the new seting.
        sed  -i -e "s/^\\s*MTU=/#&/" "$_device_config" # Comment out any other existing MTU settings.
        sed -i -e "\$aMTU=$_mtu" "$_device_config" # Append the new MTU setting to file.
        if (grep "^MTU=$_mtu$" "$_device_config" 1>/dev/null); then # Check that the file was updated successfully...
          echo
          echo "Network configuration updated, the changes will not take effect until the"
          echo "the next time the system is rebooted or the network is restarted..."
          echo
          if _confirm "Do you want to restart the network"then
            if (type systemctl >/dev/null 2>&1); then
              if !(systemctl restart network 2>/dev/null); then # Restart the network and check that it was restarted.
                echo "$(basename $0): Unable to restart the network." >&2
              fi
            else
              ifdown $_device >/dev/null 2>&1
              if !(ifup $_device >/dev/null 2>&1); then # Restart the network and check that it was restarted.
                echo "$(basename $0): Unable to start the network." >&2
              fi
            fi
            _updated=$(ping -s 9999 -M do -c 1 $(ip route | grep "default" | \
              sed -e "s/^.*via //" | cut -d ' ' -f 1) 2>&1 | \
              grep "mtu=" | sed -e "s/^.* mtu=//")
            if [ $_mtu -ne $_updated ]; then
              echo "$(basename $0): Unable to set MTU size (MTU is $_updated bytes)." >&2
            fi
          fi
        else
          echo "$(basename $0): Unable to update : '$_device_config'" >&2
        fi
      else
        echo "$(basename $0): Could not find configuration file." >&2
      fi
    else
      echo "$(basename $0): MTU size must be between 768 and 1500." >&2
    fi
  else
    echo "$(basename $0): MTU size must be an positive integer between 768 and 1500." >&2
  fi
else
  echo "$(basename $0): Too many arguments specified." >&2
fi

Yes – I know the whole change history thing is a bit excessive but it helps me keep track of things!

Advertisements
This entry was posted in Linux, Networking, RedHat and tagged . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.