Skip to content

Commit

Permalink
Minor improvements and variables renaming
Browse files Browse the repository at this point in the history
  • Loading branch information
tigerblue77 committed Mar 1, 2024
1 parent e476ebc commit 3407d14
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 70 deletions.
76 changes: 34 additions & 42 deletions Dell_iDRAC_fan_controller.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,26 @@ trap 'gracefull_exit' SIGQUIT SIGKILL SIGTERM

# readonly DELL_FRESH_AIR_COMPLIANCE=45

# Convert current fan value to hexadecimal
function convert_current_fan_value_to_hexadecimal_format () {
HEXADECIMAL_CURRENT_FAN_SPEED=$(printf '0x%02x' $CURRENT_FAN_SPEED)
}

# Check if FAN_SPEED and HIGH_FAN_SPEED variable is in hexadecimal format. If not, convert it to hexadecimal
# Check if FAN_SPEED variable is in hexadecimal format. If not, convert it to hexadecimal
if [[ $FAN_SPEED == 0x* ]]
then
DECIMAL_FAN_SPEED=$(printf '%d' $FAN_SPEED)
HEXADECIMAL_FAN_SPEED=$FAN_SPEED
else
DECIMAL_FAN_SPEED=$FAN_SPEED
HEXADECIMAL_FAN_SPEED=$(printf '0x%02x' $FAN_SPEED)
HEXADECIMAL_FAN_SPEED=$(convert_decimal_value_to_hexadecimal $FAN_SPEED)
fi

if $ENABLE_LINE_INTERPOLATION
# Check if HIGH_FAN_SPEED variable is in hexadecimal format. If not, convert it to hexadecimal
if [[ $HIGH_FAN_SPEED == 0x* ]]
then
if [[ $HIGH_FAN_SPEED == 0x* ]]
then
DECIMAL_HIGH_FAN_SPEED=$(printf '%d' $HIGH_FAN_SPEED)
HEXADECIMAL_HIGH_FAN_SPEED=$HIGH_FAN_SPEED
else
DECIMAL_HIGH_FAN_SPEED=$HIGH_FAN_SPEED
HEXADECIMAL_HIGH_FAN_SPEED=$(printf '0x%02x' $HIGH_FAN_SPEED)
fi
readonly FAN_SPEED_INTERPOLATION_ENABLED=true

DECIMAL_HIGH_FAN_SPEED=$(printf '%d' $HIGH_FAN_SPEED)
HEXADECIMAL_HIGH_FAN_SPEED=$HIGH_FAN_SPEED
else
DECIMAL_HIGH_FAN_SPEED=$HIGH_FAN_SPEED
HEXADECIMAL_HIGH_FAN_SPEED=$(convert_decimal_value_to_hexadecimal $HIGH_FAN_SPEED)
fi

# Check if the iDRAC host is set to 'local' or not then set the IDRAC_LOGIN_STRING accordingly
Expand Down Expand Up @@ -68,21 +63,19 @@ echo "Server model: $SERVER_MANUFACTURER $SERVER_MODEL"
echo "iDRAC/IPMI host: $IDRAC_HOST"

# Log the fan speed objective, CPU temperature threshold and check interval
echo "Line interpolation enable: $ENABLE_LINE_INTERPOLATION"
if $ENABLE_LINE_INTERPOLATION
echo "Fan speed interpolation enabled: $FAN_SPEED_INTERPOLATION_ENABLED"
if $FAN_SPEED_INTERPOLATION_ENABLED
then
echo "Fan speed lower value: $DECIMAL_FAN_SPEED%"
echo "Fan speed higher value: $DECIMAL_HIGH_FAN_SPEED%"
echo "CPU lower temperature threshold: $CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION°C"
echo "CPU lower temperature threshold: $CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION°C"
echo "CPU higher temperature threshold: $CPU_TEMPERATURE_THRESHOLD°C"
echo "Check interval: ${CHECK_INTERVAL}s"
echo ""
else
echo "Fan speed objective: $DECIMAL_FAN_SPEED%"
echo "CPU temperature threshold: $CPU_TEMPERATURE_THRESHOLD°C"
echo "Check interval: ${CHECK_INTERVAL}s"
echo ""
fi
echo "Check interval: ${CHECK_INTERVAL}s"
echo ""

# Define the interval for printing
readonly TABLE_HEADER_PRINT_INTERVAL=10
Expand Down Expand Up @@ -156,46 +149,45 @@ while true; do
COMMENT="CPU 2 temperature is too high, Dell default dynamic fan control profile applied for safety"
fi
else
if $ENABLE_LINE_INTERPOLATION
if $FAN_SPEED_INTERPOLATION_ENABLED
then
CURRENT_FAN_SPEED=$DECIMAL_FAN_SPEED
DECIMAL_CURRENT_FAN_SPEED=$DECIMAL_FAN_SPEED

CPU_HIGHER_TEMP=$CPU1_TEMPERATURE
HIGHEST_CPU_TEMPERATURE=$CPU1_TEMPERATURE
if $IS_CPU2_TEMPERATURE_SENSOR_PRESENT
then
if [ $CPU2_TEMPERATURE -gt $CPU1_TEMPERATURE ];
then
CPU_HIGHER_TEMP=$CPU2_TEMPERATURE
HIGHEST_CPU_TEMPERATURE=$CPU2_TEMPERATURE
fi
fi

if [ $CPU_HIGHER_TEMP -gt $CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION ];
if [ $HIGHEST_CPU_TEMPERATURE -gt $CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION ];
then
#
# F1 - lower fan speed
# F2 - higher fan speed
# T_CPU - higher temperature from both CPUs (if only one exist that will be CPU1 temp value)
# T_CPU - highest temperature of both CPUs (if only one exists that will be CPU1 temp value)
# T1 - lower temperature threshold
# T2 - higher temperature threshold
# Fan speed = F1 + ( ( F2 - F1 ) * ( T_CPU - T1 ) / ( T2 - T1 ) )
#
# Difference between higher and lower temperature
TEMP_WINDOW="$((CPU_TEMPERATURE_THRESHOLD - CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION))"
# Temperature above lower value
TEMPERATURE_ABOVE_LOWER_THRESHOLD="$((CPU_HIGHER_TEMP - CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION))"
# Difference between higher and lower fan speed
FAN_WINDOW="$((DECIMAL_HIGH_FAN_SPEED - DECIMAL_FAN_SPEED))"
# Temperature interpolation activation range
TEMPERATURE_INTERPOLATION_ACTIVATION_RANGE="$((CPU_TEMPERATURE_THRESHOLD - CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION))"
FAN_VALUE_TO_ADD=0
# Check if TEMP_WINDOW is grater than 0
if [ $TEMP_WINDOW -gt $FAN_VALUE_TO_ADD ];
# Check if TEMPERATURE_INTERPOLATION_ACTIVATION_RANGE is > 0
if [ $TEMPERATURE_INTERPOLATION_ACTIVATION_RANGE -gt $FAN_VALUE_TO_ADD ];
then
FAN_VALUE_TO_ADD="$((FAN_WINDOW * TEMPERATURE_ABOVE_LOWER_THRESHOLD / TEMP_WINDOW))"
# Temperature above lower value
TEMPERATURE_ABOVE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION="$((HIGHEST_CPU_TEMPERATURE - CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION))"
# Difference between higher and lower fan speed
FAN_WINDOW="$((DECIMAL_HIGH_FAN_SPEED - DECIMAL_FAN_SPEED))"
FAN_VALUE_TO_ADD="$((FAN_WINDOW * TEMPERATURE_ABOVE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION / TEMPERATURE_INTERPOLATION_ACTIVATION_RANGE))"
fi
CURRENT_FAN_SPEED="$((DECIMAL_FAN_SPEED + FAN_VALUE_TO_ADD))"
DECIMAL_CURRENT_FAN_SPEED="$((DECIMAL_FAN_SPEED + FAN_VALUE_TO_ADD))"
fi
# Convert decimal to hexadecimal value of fan speed
convert_current_fan_value_to_hexadecimal_format
apply_line_interpolation_fan_control_profile
$HEXADECIMAL_CURRENT_FAN_SPEED=$(convert_decimal_value_to_hexadecimal $DECIMAL_CURRENT_FAN_SPEED)
apply_fan_speed_interpolation_fan_control_profile
else
apply_user_fan_control_profile

Expand Down
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ ENV CPU_TEMPERATURE_THRESHOLD 50
ENV CHECK_INTERVAL 60
ENV DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE false

ENV CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION 40
ENV ENABLE_LINE_INTERPOLATION false
ENV HIGH_FAN_SPEED 45
ENV CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION 40
ENV HIGH_FAN_SPEED 40

CMD ["./Dell_iDRAC_fan_controller.sh"]
44 changes: 21 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ docker run -d \
-e CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold> \
-e CHECK_INTERVAL=<seconds between each check> \
-e DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false> \
-e ENABLE_LINE_INTERPOLATION=<true or false> \
-e CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, olny when interpolation enabled> \
-e CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION=<decimal temperature lower threshold, olny when interpolation enabled> \
-e HIGH_FAN_SPEED=<decimal or hexadecimal fan speed, only when interpolation enabled> \
--device=/dev/ipmi0:/dev/ipmi0:rw \
tigerblue77/dell_idrac_fan_controller:latest
Expand All @@ -101,8 +100,7 @@ docker run -d \
-e CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold> \
-e CHECK_INTERVAL=<seconds between each check> \
-e DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false> \
-e ENABLE_LINE_INTERPOLATION=<true or false> \
-e CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled> \
-e CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled> \
-e HIGH_FAN_SPEED=<decimal or hexadecimal fan speed, only when interpolation enabled> \
tigerblue77/dell_idrac_fan_controller:latest
```
Expand All @@ -124,8 +122,7 @@ services:
- CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold>
- CHECK_INTERVAL=<seconds between each check>
- DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false>
- ENABLE_LINE_INTERPOLATION=<true or false>
- CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled>
- CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled>
- HIGH_FAN_SPEED=<decimal or hexadecimal fan speed when interpolation enabled>
devices:
- /dev/ipmi0:/dev/ipmi0:rw
Expand All @@ -149,8 +146,7 @@ services:
- CPU_TEMPERATURE_THRESHOLD=<decimal temperature threshold>
- CHECK_INTERVAL=<seconds between each check>
- DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE=<true or false>
- ENABLE_LINE_INTERPOLATION=<true or false>
- CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled>
- CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION=<decimal temperature lower threshold, only when interpolation enabled>
- HIGH_FAN_SPEED=<decimal or hexadecimal fan speed when interpolation enabled>
```
Expand All @@ -168,26 +164,28 @@ All parameters are optional as they have default values (including default iDRAC
- `CPU_TEMPERATURE_THRESHOLD` parameter is the T°junction (junction temperature) threshold beyond which the Dell fan mode defined in your BIOS will become active again (to protect the server hardware against overheat). **Default** value is 50(°C).
- `CHECK_INTERVAL` parameter is the time (in seconds) between each temperature check and potential profile change. **Default** value is 60(s).
- `DISABLE_THIRD_PARTY_PCIE_CARD_DELL_DEFAULT_COOLING_RESPONSE` parameter is a boolean that allows to disable third-party PCIe card Dell default cooling response. **Default** value is false.
- `ENABLE_LINE_INTERPOLATION` parameter is a boolean that allows to enable line interpolation. If temperature value going above **CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION** they will proportionally increase fan speed to **HIGH_FAN_SPEED** when **CPU_TEMPERATURE_THRESHOLD** will reached. **Default** value is false.
- `CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION` parameter is only necessary if you're using line interpolation. Must be lower than **CPU_TEMPERATURE_THRESHOLD**. **Default** value is 40(°C).
- `HIGH_FAN_SPEED` parameter is only necessary if you're using line interpolation. It defines maximum fan speed before swiching to dell temperature control. **Default** value is 45(%).

Example of how interpolation work:
If you want to enable fan speed interpolation, add the following parameters :
- `CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION` parameter enables fan speed interpolation once exceeded. Fan speed interpolation will increase your fan speed proportionally to **HIGH_FAN_SPEED** until **CPU_TEMPERATURE_THRESHOLD** is reached. This parameter must be lower than **CPU_TEMPERATURE_THRESHOLD**. **Default** value is 40(°C).
- `HIGH_FAN_SPEED` parameter is the fan speed that will be set at `CPU_TEMPERATURE_THRESHOLD`. In other words, it defines maximum fan speed before swiching to the Dell fan mode (see `CPU_TEMPERATURE_THRESHOLD` parameter). **Default** value is 40(%).

Example of how interpolation works:
- `FAN_SPEED` = 10
- `HIGH_FAN_SPEED` = 50
- `CPU_TEMPERATURE_FOR_START_LINE_INTERPOLATION` = 30
- `CPU_TEMPERATURE_THRESHOLD_FOR_FAN_SPEED_INTERPOLATION` = 30
- `CPU_TEMPERATURE_THRESHOLD` = 70

| CPU Temperature | Fan Speed |
| ------------- | ------------- |
| 15 °C | 10 % |
| 30 °C | 10 % |
| 35 °C | 15 % |
| 50 °C | 30 % |
| 69 °C | 49 % |
| 70 °C | Dell fan control |
| CPU temperature | Fan speed |
| --------------- | ---------------- |
| 15 °C | 10 % |
| 30 °C | 10 % |
| 35 °C | 15 % |
| 50 °C | 30 % |
| 69 °C | 49 % |
| 70 °C | Dell fan control |
| 80 °C | Dell fan control |

When using line interpolation it's recommended to lower **CHECK_INTERVAL** to value such as 3 seconds.
When using fan speed interpolation, we recommend decreasing **CHECK_INTERVAL**, for example "3" (seconds), to avoid the noise nuisance associated with a sudden increase in fan speed.

<p align="right">(<a href="#top">back to top</a>)</p>

Expand All @@ -196,7 +194,7 @@ When using line interpolation it's recommended to lower **CHECK_INTERVAL** to va

If your server frequently switches back to the default Dell fan mode:
1. Check `Tcase` (case temperature) of your CPU on Intel Ark website and then set `CPU_TEMPERATURE_THRESHOLD` to a slightly lower value. Example with my CPUs ([Intel Xeon E5-2630L v2](https://www.intel.com/content/www/us/en/products/sku/75791/intel-xeon-processor-e52630l-v2-15m-cache-2-40-ghz/specifications.html)) : Tcase = 63°C, I set `CPU_TEMPERATURE_THRESHOLD` to 60(°C).
2. If it's already good, adapt your `FAN_SPEED` value to increase the airflow and thus further decrease the temperature of your CPU(s) or enable and experiment with line interpolation
2. If it's already good, adapt your `FAN_SPEED` value to increase the airflow and thus further decrease the temperature of your CPU(s) or enable and experiment with fan speed interpolation
3. If neither increasing the fan speed nor increasing the threshold solves your problem, then it may be time to replace your thermal paste

<p align="right">(<a href="#top">back to top</a>)</p>
Expand Down
14 changes: 12 additions & 2 deletions functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,20 @@ function apply_user_fan_control_profile () {
CURRENT_FAN_CONTROL_PROFILE="User static fan control profile ($DECIMAL_FAN_SPEED%)"
}

function apply_line_interpolation_fan_control_profile () {
# This function applies a user-specified interpolated fan control profile
function apply_fan_speed_interpolation_fan_control_profile () {
ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x01 0x00 > /dev/null
ipmitool -I $IDRAC_LOGIN_STRING raw 0x30 0x30 0x02 0xff $HEXADECIMAL_CURRENT_FAN_SPEED > /dev/null
CURRENT_FAN_CONTROL_PROFILE="Interpolated fan control profile ($CURRENT_FAN_SPEED%)"
CURRENT_FAN_CONTROL_PROFILE="Interpolated fan control profile ($DECIMAL_CURRENT_FAN_SPEED%)"
}

# Convert DECIMAL_NUMBER to hexadecimal
# Usage : convert_decimal_value_to_hexadecimal $DECIMAL_NUMBER
# Returns : hexadecimal value of DECIMAL_NUMBER
function convert_decimal_value_to_hexadecimal () {
local DECIMAL_NUMBER=$1
local HEXADECIMAL_NUMBER=$(printf '0x%02x' $DECIMAL_NUMBER)
return $HEXADECIMAL_NUMBER
}

# Retrieve temperature sensors data using ipmitool
Expand Down

0 comments on commit 3407d14

Please sign in to comment.