#!/bin/sh
#
# Network Performance Meter
# Copyright (C) 2009-2024 by Thomas Dreibholz
#
# 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/>.
#
# Contact: thomas.dreibholz@gmail.com
#

if [ $# -lt 1 ] ; then
   echo >&2 "Usage: $0 [cmt off|normal|rp] [dac on|off] [nrsack on|off] [bufferSplitting none|senderOnly|reeiverOnly|bothSides] [initialCwnd SIZE_IN_MTU] [cwndMaxBurst on|off"
   exit 1
fi


# ====== Get parameters =====================================================
CMT=0
DAC=0
NRSACK=0
BUFFERSPLITTING=0
INITIAL_CWND=3
CWND_MAXBURST=0

while [ "$1" != "" ] ; do
   if [ "$1" = "cmt" ] ; then
      if [ "$2" = "off" ] ; then
         CMT=0
      elif [ "$2" = "cmt" -o "$2" = "normal" ] ; then
         CMT=1
      elif [ "$2" = "cmtrpv1" -o "$2" = "rp" ] ; then
         CMT=2
      elif [ "$2" = "cmtrpv2" ] ; then
         CMT=3
      elif [ "$2" = "like-mptcp" -o "$2" = "mptcp-like" -o "$2" = "mptcp" ] ; then
         CMT=4
      elif [ $2 -ge 2 -o $2 -lt 256 ] ; then
         CMT=$2
      else
         echo >&2 "ERROR: Bad setting for cmt!"
         exit 1
      fi
      shift ; shift

   elif [ "$1" = "dac" ] ; then
      if [ "$2" = "on" -o "$2" = "true" ] ; then
         DAC=1
      elif [ "$2" = "off" -o "$2" = "false" ] ; then
         DAC=0
      else
         echo >&2 "ERROR: Bad setting for dac!"
         exit 1
      fi
      shift ; shift

   elif [ "$1" = "nrsack" ] ; then
      if [ "$2" = "on" -o "$2" = "true" ] ; then
         NRSACK=1
      elif [ "$2" = "off" -o "$2" = "false" ] ; then
         NRSACK=0
      else
         echo >&2 "ERROR: Bad setting for nrsack!"
         exit 1
      fi
      shift ; shift

   elif [ "$1" = "cwndMaxBurst" ] ; then
      if [ "$2" = "on" -o "$2" = "true" ] ; then
         CWND_MAXBURST=1
      elif [ "$2" = "off" -o "$2" = "false" ] ; then
         CWND_MAXBURST=0
      else
         echo >&2 "ERROR: Bad setting for cwndMaxBurst!"
         exit 1
      fi
      shift ; shift

   elif [ "$1" = "bufferSplitting" ] ; then
      if [ "$2" = "none" ] ; then
         BUFFERSPLITTING=0
      elif [ "$2" = "senderOnly" ] ; then
         BUFFERSPLITTING=1
      elif [ "$2" = "receiverOnly" ] ; then
         BUFFERSPLITTING=2
      elif [ "$2" = "bothSides" ] ; then
         BUFFERSPLITTING=3
      else
         echo >&2 "ERROR: Bad setting for bufferSplitting!"
         exit 1
      fi
      shift ; shift

   elif [ "$1" = "initialCwnd" ] ; then
      INITIAL_CWND=$2
      shift ; shift

   else
      echo >&2 "ERROR: Unknown setting $1!"
      exit 1
   fi
done


echo "SCTP Configuration:"
echo " - CMT:             $CMT"
echo " - DAC:             $DAC"
echo " - NRSACK:          $NRSACK"
echo " - BUFFERSPLITTING: $BUFFERSPLITTING"
echo " - CWND_MAXBURST:   $CWND_MAXBURST"


success=1
SYSTEM=`uname`
# ====== FreeBSD QoS setup ==================================================
if [ "$SYSTEM" = "FreeBSD" ] ; then
   /sbin/sysctl net.inet.sctp.cmt_on_off=$CMT >/dev/null || success=0
   /sbin/sysctl net.inet.sctp.cmt_use_dac=$DAC >/dev/null || success=0
   /sbin/sysctl net.inet.sctp.nr_sack_on_off=$NRSACK >/dev/null || success=0
   /sbin/sysctl net.inet.sctp.buffer_splitting=$BUFFERSPLITTING >/dev/null || success=0
   /sbin/sysctl net.inet.sctp.initial_cwnd=$INITIAL_CWND >/dev/null || success=0
   /sbin/sysctl net.inet.sctp.cwnd_maxburst=$CWND_MAXBURST >/dev/null || success=0
   /sbin/sysctl kern.ipc.maxsockbuf=1000050000 >/dev/null || success=0      # This is the absolute socket buffer limit!
#   /sbin/sysctl net.inet.sctp.sendspace=10000000 >/dev/null || success=0   # SCTP limit, seems to need full pages!
#   /sbin/sysctl net.inet.sctp.recvspace=10000000 >/dev/null || success=0   # SCTP limit, seems to need full pages!

# ====== Linux ==============================================================
elif [ "$SYSTEM" = "Linux" ] ; then
   # echo >&2 "###### WARNING! setsctp does not usefully support Linux yet ######"

   modprobe sctp

   # /sbin/sysctl net.sctp.auth_enable=1
   # /sbin/sysctl net.sctp.addip_enable=1

# ====== Other systems ======================================================
else
   echo >&2 "ERROR: Unsupported system $SYSTEM!"
   exit 1
fi


# ====== Check whether SCTP configuration has been successful ===============
if [ $success -ne 1 ] ; then
   echo >&2 "ERROR: setsctp has failed to configure sysctl settings!"
   echo >&2 "Command on `hostname`: $0 $@"
   exit 1
fi
