diff --git a/Changelog.md b/Changelog.md
index e99ea7d2beacb3e19f12b4cec8909820722ef9be..e0fb0c1148fefe55ce431d5331ff14627e1a73b7 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,6 +1,8 @@
 # Changelog
 
-All notable changes to this project will be documented in this file.
+## [2.11] - 2024-08-19
+- (fix) Make LibreNMS retry when a request times out
+- (fix) Adjust the mechanics of the minimum amount of links when creating an IP trunk
 
 ## [2.10] - 2024-08-06
 - Update map API endpoint
diff --git a/gso/services/librenms_client.py b/gso/services/librenms_client.py
index c700c92fc349afdb6521c65d0ef6720548f78597..2e04a866e3f85b539f22031b3f878b2149823d0f 100644
--- a/gso/services/librenms_client.py
+++ b/gso/services/librenms_client.py
@@ -3,10 +3,11 @@
 import logging
 from http import HTTPStatus
 from importlib import metadata
-from typing import Any
+from typing import Any, Literal
 
 import requests
-from requests import HTTPError
+from requests import HTTPError, Response
+from requests.adapters import HTTPAdapter
 
 from gso.settings import load_oss_params
 from gso.utils.helpers import SNMPVersion
@@ -25,12 +26,24 @@ class LibreNMSClient:
         self.base_url = config.LIBRENMS.base_url
         self.snmp_config = config.SNMP
 
-        self.headers = {
+        self.session = requests.Session()
+        self.session.mount("https://", HTTPAdapter(max_retries=5))
+        self.session.headers.update({
             "User-Agent": f"geant-service-orchestrator/{metadata.version("geant-service-orchestrator")}",
             "Accept": "application/json",
             "Content-Type": "application/json",
             "X-Auth-Token": token,
-        }
+        })
+
+    def _send_request(
+        self, method: Literal["GET", "POST", "PUT", "DELETE"], endpoint: str, data: dict[str, Any] | None = None
+    ) -> Response:
+        url = self.base_url + endpoint
+        logger.debug("LibreNMS - Sending request", extra={"method": method, "endpoint": url, "form_data": data})
+        result = self.session.request(method, url, json=data, timeout=(0.5, 75))
+        logger.debug("LibreNMS - Received response", extra=result.__dict__)
+
+        return result
 
     def get_device(self, fqdn: str) -> dict[str, Any]:
         """Get an existing device from LibreNMS.
@@ -39,7 +52,7 @@ class LibreNMSClient:
         :return dict[str, Any]: A :term:`JSON` formatted list of devices that match the queried :term:`FQDN`.
         :raises HTTPError: Raises an HTTP error 404 when the device is not found
         """
-        response = requests.get(f"{self.base_url}/devices/{fqdn}", headers=self.headers, timeout=(0.5, 75))
+        response = self._send_request("GET", f"/devices/{fqdn}")
         response.raise_for_status()
 
         return response.json()
@@ -74,7 +87,7 @@ class LibreNMSClient:
         }
         device_data.update(getattr(self.snmp_config, snmp_version))
 
-        device = requests.post(f"{self.base_url}/devices", headers=self.headers, json=device_data, timeout=(0.5, 75))
+        device = self._send_request("POST", "/devices", device_data)
         device.raise_for_status()
 
         return device.json()
@@ -86,7 +99,7 @@ class LibreNMSClient:
         :return dict[str, Any]: A JSON representation of the device that got removed.
         :raises HTTPError: Raises an exception if the request did not succeed.
         """
-        device = requests.delete(f"{self.base_url}/devices/{fqdn}", headers=self.headers, timeout=(0.5, 75))
+        device = self._send_request("DELETE", f"/devices/{fqdn}")
         device.raise_for_status()
 
         return device.json()
diff --git a/gso/utils/helpers.py b/gso/utils/helpers.py
index fdf851e8495c697e95ad45747d07269f29e7a2db..cca681a4be8d56c0772aaae40f5929f516c3dbc5 100644
--- a/gso/utils/helpers.py
+++ b/gso/utils/helpers.py
@@ -12,7 +12,7 @@ from pydantic_core.core_schema import ValidationInfo
 from pydantic_forms.validators import Choice
 
 from gso import settings
-from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock
+from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock, PhysicalPortCapacity
 from gso.products.product_blocks.router import RouterRole
 from gso.products.product_blocks.site import LatitudeCoordinate, LongitudeCoordinate, SiteTier
 from gso.products.product_types.router import Router
@@ -332,3 +332,18 @@ def generate_inventory_for_active_routers(
             }
         }
     }
+
+
+def calculate_recommended_minimum_links(iptrunk_number_of_members: int, iptrunk_speed: PhysicalPortCapacity) -> int:
+    """Calculate the recommended minimum number of links for an IP trunk based on the number of members and speed.
+
+    If the IP trunk speed is 400G, the recommended minimum number of links is the number of members minus 1.
+    Otherwise, the recommended minimum number of links is the number of members.
+
+    :param int iptrunk_number_of_members: The number of members in the IP trunk.
+    :param PhysicalPortCapacity iptrunk_speed: The speed of the IP trunk.
+    :return: The recommended minimum number of links for the IP trunk.
+    """
+    if iptrunk_speed == PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND:
+        return iptrunk_number_of_members - 1
+    return iptrunk_number_of_members
diff --git a/gso/workflows/iptrunk/create_iptrunk.py b/gso/workflows/iptrunk/create_iptrunk.py
index 95703094cf67299b6b235e914de4959ff5426832..373dfc03b63e378b2889c62aca3496011121f909 100644
--- a/gso/workflows/iptrunk/create_iptrunk.py
+++ b/gso/workflows/iptrunk/create_iptrunk.py
@@ -35,6 +35,7 @@ from gso.utils.helpers import (
     LAGMember,
     available_interfaces_choices,
     available_lags_choices,
+    calculate_recommended_minimum_links,
     get_router_vendor,
     validate_interface_name_list,
     validate_iptrunk_unique_interface,
@@ -70,12 +71,13 @@ def initial_input_form_generator(product_name: str) -> FormGenerator:
             return validate_tt_number(tt_number)
 
     initial_user_input = yield CreateIptrunkForm
+    recommended_minimum_links = calculate_recommended_minimum_links(
+        initial_user_input.iptrunk_number_of_members, initial_user_input.iptrunk_speed
+    )
 
     class VerifyMinimumLinksForm(FormPage):
-        info_label: Label = (
-            f"This is the calculated minimum-links for this LAG: " f"{initial_user_input.iptrunk_number_of_members - 1}"
-        )
-        iptrunk_minimum_links: int = initial_user_input.iptrunk_number_of_members - 1
+        info_label: Label = f"This is the calculated minimum-links for this LAG: {recommended_minimum_links}"
+        iptrunk_minimum_links: int = recommended_minimum_links
         info_label2: Label = "Please confirm or modify."
 
     verify_minimum_links = yield VerifyMinimumLinksForm
diff --git a/gso/workflows/iptrunk/modify_trunk_interface.py b/gso/workflows/iptrunk/modify_trunk_interface.py
index 7ed4c0bc110c827aa5e7880f5d723d8a8b28e549..f5d17d7752503d8fdb8979d0eefadd7818af4936 100644
--- a/gso/workflows/iptrunk/modify_trunk_interface.py
+++ b/gso/workflows/iptrunk/modify_trunk_interface.py
@@ -28,6 +28,7 @@ from gso.utils.helpers import (
     LAGMember,
     available_interfaces_choices,
     available_interfaces_choices_including_current_members,
+    calculate_recommended_minimum_links,
     get_router_vendor,
     validate_interface_name_list,
     validate_iptrunk_unique_interface,
@@ -93,7 +94,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
             "You will need to add the new AE members in the next steps."
         )
         iptrunk_speed: PhysicalPortCapacity = subscription.iptrunk.iptrunk_speed
-        iptrunk_number_of_members: int = subscription.iptrunk.iptrunk_minimum_links + 1
+        iptrunk_number_of_members: int = len(subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members)
         iptrunk_isis_metric: ReadOnlyField(subscription.iptrunk.iptrunk_isis_metric, default_type=int)  # type: ignore[valid-type]
         iptrunk_ipv4_network: ReadOnlyField(  # type: ignore[valid-type]
             str(subscription.iptrunk.iptrunk_ipv4_network), default_type=IPv4AddressType
@@ -108,12 +109,15 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
 
     initial_user_input = yield ModifyIptrunkForm
 
+    recommended_minimum_links = calculate_recommended_minimum_links(
+        initial_user_input.iptrunk_number_of_members, initial_user_input.iptrunk_speed
+    )
+
     class VerifyMinimumLinksForm(FormPage):
-        info_label: Label = (
-            f"This is the calculated minimum-links for this LAG: " f"{initial_user_input.iptrunk_number_of_members - 1}"
-        )
-        iptrunk_minimum_links: int = initial_user_input.iptrunk_number_of_members - 1
-        info_label2: Label = "Please confirm or modify."
+        info_label: Label = f"Current value of minimum-links : {subscription.iptrunk.iptrunk_minimum_links}"
+        info_label1: Label = f"Recommended minimum-links for this LAG: {recommended_minimum_links}"
+        iptrunk_minimum_links: int = recommended_minimum_links
+        info_label2: Label = "Please review the recommended value and adjust if necessary."
 
     verify_minimum_links = yield VerifyMinimumLinksForm
     ae_members_side_a = initialize_ae_members(subscription, initial_user_input.model_dump(), 0)
diff --git a/setup.py b/setup.py
index eedcacefcf3e943a30fc8a84ab84e5247be5c083..c61a2ba1d1da316081a80efe62328a2888138868 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
 
 setup(
     name="geant-service-orchestrator",
-    version="2.10",
+    version="2.11",
     author="GÉANT Orchestration and Automation Team",
     author_email="goat@geant.org",
     description="GÉANT Service Orchestrator",
diff --git a/test/services/test_librenms_client.py b/test/services/test_librenms_client.py
index 7668ddea0ad41a31b2fa92e5462eb2931da3207b..e28eaef74742d59d8b443ba0fad1d323f5b26254 100644
--- a/test/services/test_librenms_client.py
+++ b/test/services/test_librenms_client.py
@@ -10,7 +10,7 @@ from gso.utils.helpers import SNMPVersion
 
 @pytest.fixture()
 def mock_get_device_success(faker):
-    with patch("gso.services.librenms_client.requests.get") as mock_get_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_get_device:
         mock_get_device().status_code = HTTPStatus.OK
         mock_get_device().json.return_value = {
             "status": "ok",
@@ -81,14 +81,14 @@ def mock_get_device_success(faker):
 
 @pytest.fixture()
 def mock_get_device_not_found():
-    with patch("gso.services.librenms_client.requests.get") as mock_get_not_found:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_get_not_found:
         mock_get_not_found().status_code = HTTPStatus.NOT_FOUND
         mock_get_not_found().json.return_value = {
             "status": "error",
             "message": "Device non-existent-url does not exist",
         }
         mock_get_not_found().raise_for_status.side_effect = HTTPError(
-            "404 Client Error: Not Found for url: http://librenms/devices/non-existent-url",
+            "404 Client Error: Not Found for url: https://librenms/devices/non-existent-url",
             response=mock_get_not_found(),
         )
 
@@ -97,7 +97,7 @@ def mock_get_device_not_found():
 
 @pytest.fixture()
 def mock_get_device_misconfigured(faker):
-    with patch("gso.services.librenms_client.requests.get") as mock_get_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_get_device:
         mock_get_device().status_code = HTTPStatus.OK
         mock_get_device().json.return_value = {
             "status": "ok",
@@ -169,7 +169,7 @@ def mock_get_device_misconfigured(faker):
 @pytest.fixture()
 def mock_get_device_unauthenticated():
     with (
-        patch("gso.services.librenms_client.requests.get") as mock_get_unauthorized,
+        patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_get_unauthorized,
         patch(
             "gso.services.librenms_client.LibreNMSClient.get_device",
         ) as mock_get_device,
@@ -177,7 +177,7 @@ def mock_get_device_unauthenticated():
         mock_get_unauthorized().status_code = HTTPStatus.UNAUTHORIZED
         mock_get_unauthorized().json.return_value = {"message": "Unauthenticated."}
         mock_get_device.side_effect = HTTPError(
-            "401 Client Error: Unauthorized for url: http://librenms/devices/naughty-url",
+            "401 Client Error: Unauthorized for url: https://librenms/devices/naughty-url",
             response=mock_get_unauthorized(),
         )
 
@@ -186,7 +186,7 @@ def mock_get_device_unauthenticated():
 
 @pytest.fixture()
 def mock_add_device_success():
-    with patch("gso.services.librenms_client.requests.post") as mock_post_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_post_device:
         mock_post_device().status_code = HTTPStatus.OK
         mock_post_device().json.return_value = {
             "status": "ok",
@@ -222,14 +222,14 @@ def mock_add_device_success():
 
 @pytest.fixture()
 def mock_add_device_bad_url():
-    with patch("gso.services.librenms_client.requests.post") as mock_post_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_post_device:
         mock_post_device().status_code = HTTPStatus.INTERNAL_SERVER_ERROR
         mock_post_device().json.return_value = {
             "status": "error",
             "message": "Could not ping non-existent-url (Hostname did not resolve to IP)",
         }
         mock_post_device().raise_for_status.side_effect = HTTPError(
-            "500 Server Error: Internal server error for url: http://librenms/devices",
+            "500 Server Error: Internal server error for url: https://librenms/devices",
             response=mock_post_device(),
         )
 
@@ -238,14 +238,14 @@ def mock_add_device_bad_url():
 
 @pytest.fixture()
 def mock_add_device_unreachable():
-    with patch("gso.services.librenms_client.requests.post") as mock_post_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_post_device:
         mock_post_device().status_code = HTTPStatus.INTERNAL_SERVER_ERROR
         mock_post_device().json.return_value = {
             "status": "error",
             "message": "Could not connect to non-existent-url, please check the snmp details and snmp reachability",
         }
         mock_post_device().raise_for_status.side_effect = HTTPError(
-            "500 Server Error: Internal server error for url: http://librenms/devices",
+            "500 Server Error: Internal server error for url: https://librenms/devices",
             response=mock_post_device(),
         )
 
@@ -254,7 +254,7 @@ def mock_add_device_unreachable():
 
 @pytest.fixture()
 def mock_remove_device_success(faker):
-    with patch("gso.services.librenms_client.requests.delete") as mock_remove_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_remove_device:
         mock_remove_device().status_code = HTTPStatus.OK
         mock_remove_device().json.return_value = {
             "status": "ok",
@@ -326,11 +326,11 @@ def mock_remove_device_success(faker):
 
 @pytest.fixture()
 def mock_remove_device_non_existent(faker):
-    with patch("gso.services.librenms_client.requests.delete") as mock_remove_device:
+    with patch("gso.services.librenms_client.LibreNMSClient._send_request") as mock_remove_device:
         mock_remove_device().status_code = HTTPStatus.NOT_FOUND
         mock_remove_device().json.return_value = {"status": "error", "message": "Device non-existent-url not found"}
         mock_remove_device().raise_for_status.side_effect = HTTPError(
-            "404 Client Error: Not Found for url: http://librenms/devices/non-existent-url",
+            "404 Client Error: Not Found for url: https://librenms/devices/non-existent-url",
             response=mock_remove_device(),
         )
 
@@ -353,7 +353,7 @@ def test_get_device_not_found(mock_get_device_not_found):
 
     assert e.value.response.status_code == HTTPStatus.NOT_FOUND
     assert e.value.response.json() == {"status": "error", "message": "Device non-existent-url does not exist"}
-    assert e.value.args[0] == "404 Client Error: Not Found for url: http://librenms/devices/non-existent-url"
+    assert e.value.args[0] == "404 Client Error: Not Found for url: https://librenms/devices/non-existent-url"
 
 
 def test_device_exists_true(mock_get_device_success):
@@ -376,7 +376,7 @@ def test_device_exists_bad_request(mock_get_device_unauthenticated):
 
     assert e.value.response.status_code == HTTPStatus.UNAUTHORIZED
     assert e.value.response.json() == {"message": "Unauthenticated."}
-    assert e.value.args[0] == "401 Client Error: Unauthorized for url: http://librenms/devices/naughty-url"
+    assert e.value.args[0] == "401 Client Error: Unauthorized for url: https://librenms/devices/naughty-url"
 
 
 def test_add_device_success(mock_add_device_success):
@@ -401,7 +401,7 @@ def test_add_device_bad_fqdn(mock_add_device_bad_url):
         "status": "error",
         "message": "Could not ping non-existent-url (Hostname did not resolve to IP)",
     }
-    assert e.value.args[0] == "500 Server Error: Internal server error for url: http://librenms/devices"
+    assert e.value.args[0] == "500 Server Error: Internal server error for url: https://librenms/devices"
 
 
 def test_add_device_no_ping(mock_add_device_unreachable):
@@ -416,7 +416,7 @@ def test_add_device_no_ping(mock_add_device_unreachable):
         "status": "error",
         "message": "Could not connect to non-existent-url, please check the snmp details and snmp reachability",
     }
-    assert e.value.args[0] == "500 Server Error: Internal server error for url: http://librenms/devices"
+    assert e.value.args[0] == "500 Server Error: Internal server error for url: https://librenms/devices"
 
 
 def test_remove_device_success(mock_remove_device_success):
@@ -435,7 +435,7 @@ def test_remove_non_existent_device(mock_remove_device_non_existent):
 
     assert e.value.response.status_code == HTTPStatus.NOT_FOUND
     assert e.value.response.json() == {"status": "error", "message": "Device non-existent-url not found"}
-    assert e.value.args[0] == "404 Client Error: Not Found for url: http://librenms/devices/non-existent-url"
+    assert e.value.args[0] == "404 Client Error: Not Found for url: https://librenms/devices/non-existent-url"
 
 
 def test_validate_device_success(mock_get_device_success):