diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 1de7bb0538..e8e01f9094 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -3227,6 +3227,15 @@ Token=prefixstable:2002:da8:1::
+
+ [IPoIB] Section Options
+ The [IPoIB] section manages the IP over Infiniband and accepts the following keys:
+
+
+
+
+
+
[QDisc] Section Options
The [QDisc] section manages the traffic control queueing discipline (qdisc).
diff --git a/src/network/netdev/ipoib.c b/src/network/netdev/ipoib.c
index b341001bc4..c3f583fc46 100644
--- a/src/network/netdev/ipoib.c
+++ b/src/network/netdev/ipoib.c
@@ -4,6 +4,7 @@
#include
#include "ipoib.h"
+#include "networkd-network.h"
#include "parse-util.h"
#include "string-table.h"
@@ -56,6 +57,48 @@ static int netdev_ipoib_fill_message_create(NetDev *netdev, Link *link, sd_netli
return 0;
}
+int ipoib_set_netlink_message(Link *link, sd_netlink_message *m) {
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(m);
+
+ r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Could not set netlink flags: %m");
+
+ r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to open IFLA_LINKINFO container: %m");
+
+ r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Could not open IFLA_INFO_DATA container: %m");
+
+ if (link->network->ipoib_mode >= 0) {
+ r = sd_netlink_message_append_u16(m, IFLA_IPOIB_MODE, link->network->ipoib_mode);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Could not append IFLA_IPOIB_MODE attribute: %m");
+ }
+
+ if (link->network->ipoib_umcast >= 0) {
+ r = sd_netlink_message_append_u16(m, IFLA_IPOIB_UMCAST, link->network->ipoib_umcast);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Could not append IFLA_IPOIB_UMCAST attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(m);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to close IFLA_INFO_DATA container: %m");
+
+ r = sd_netlink_message_close_container(m);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to close IFLA_LINKINFO container: %m");
+
+ return 0;
+}
+
static const char * const ipoib_mode_table[_IP_OVER_INFINIBAND_MODE_MAX] = {
[IP_OVER_INFINIBAND_MODE_DATAGRAM] = "datagram",
[IP_OVER_INFINIBAND_MODE_CONNECTED] = "connected",
diff --git a/src/network/netdev/ipoib.h b/src/network/netdev/ipoib.h
index d2f5d9350f..415d3b107c 100644
--- a/src/network/netdev/ipoib.h
+++ b/src/network/netdev/ipoib.h
@@ -24,5 +24,7 @@ typedef struct IPoIB {
DEFINE_NETDEV_CAST(IPOIB, IPoIB);
extern const NetDevVTable ipoib_vtable;
+int ipoib_set_netlink_message(Link *link, sd_netlink_message *m);
+
CONFIG_PARSER_PROTOTYPE(config_parse_ipoib_pkey);
CONFIG_PARSER_PROTOTYPE(config_parse_ipoib_mode);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 4df3e19220..266334e78c 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1101,6 +1101,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = link_request_to_set_ipoib(link);
+ if (r < 0)
+ return r;
+
r = link_request_to_set_flags(link);
if (r < 0)
return r;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 4ac58a26ad..3b8d45c1bb 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -382,6 +382,8 @@ CAN.PresumeACK, config_parse_can_control_mode,
CAN.FDNonISO, config_parse_can_control_mode, CAN_CTRLMODE_FD_NON_ISO, 0
CAN.ClassicDataLengthCode, config_parse_can_control_mode, CAN_CTRLMODE_CC_LEN8_DLC, 0
CAN.Termination, config_parse_can_termination, 0, 0
+IPoIB.Mode, config_parse_ipoib_mode, 0, offsetof(Network, ipoib_mode)
+IPoIB.IgnoreUserspaceMulticastGroups, config_parse_tristate, 0, offsetof(Network, ipoib_umcast)
QDisc.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
QDisc.Handle, config_parse_qdisc_handle, _QDISC_KIND_INVALID, 0
BFIFO.Parent, config_parse_qdisc_parent, QDISC_KIND_BFIFO, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 7640429f46..6651c6c04c 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -476,6 +476,9 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
.can_termination = -1,
+
+ .ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
+ .ipoib_umcast = -1,
};
r = config_parse_many(
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 2fdd4994c4..9304ceaafb 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -11,6 +11,7 @@
#include "condition.h"
#include "conf-parser.h"
#include "hashmap.h"
+#include "ipoib.h"
#include "net-condition.h"
#include "netdev.h"
#include "networkd-bridge-vlan.h"
@@ -286,6 +287,10 @@ struct Network {
uint16_t can_termination;
bool can_termination_set;
+ /* IPoIB support */
+ IPoIBMode ipoib_mode;
+ int ipoib_umcast;
+
/* sysctl settings */
AddressFamily ip_forward;
int ipv4_accept_local;
diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c
index e7b39778da..d32dc81794 100644
--- a/src/network/networkd-setlink.c
+++ b/src/network/networkd-setlink.c
@@ -24,6 +24,7 @@ static const char *const set_link_operation_table[_SET_LINK_OPERATION_MAX] = {
[SET_LINK_CAN] = "CAN interface configurations",
[SET_LINK_FLAGS] = "link flags",
[SET_LINK_GROUP] = "interface group",
+ [SET_LINK_IPOIB] = "IPoIB configurations",
[SET_LINK_MAC] = "MAC address",
[SET_LINK_MASTER] = "master interface",
[SET_LINK_MTU] = "MTU",
@@ -153,6 +154,10 @@ static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
return set_link_handler_internal(rtnl, m, link, SET_LINK_GROUP, /* ignore = */ false, NULL);
}
+static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ return set_link_handler_internal(rtnl, m, link, SET_LINK_IPOIB, /* ignore = */ true, NULL);
+}
+
static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return set_link_handler_internal(rtnl, m, link, SET_LINK_MAC, /* ignore = */ true, get_link_default_handler);
}
@@ -236,7 +241,7 @@ static int link_configure(
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->master_ifindex);
if (r < 0)
return log_link_debug_errno(link, r, "Could not allocate RTM_NEWLINK message: %m");
- } else if (op == SET_LINK_CAN) {
+ } else if (IN_SET(op, SET_LINK_CAN, SET_LINK_IPOIB)) {
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->ifindex);
if (r < 0)
return log_link_debug_errno(link, r, "Could not allocate RTM_NEWLINK message: %m");
@@ -468,6 +473,11 @@ static int link_configure(
if (r < 0)
return log_link_debug_errno(link, r, "Could not append IFLA_ADDRESS attribute: %m");
break;
+ case SET_LINK_IPOIB:
+ r = ipoib_set_netlink_message(link, req);
+ if (r < 0)
+ return r;
+ break;
case SET_LINK_MASTER:
r = sd_netlink_message_append_u32(req, IFLA_MASTER, PTR_TO_UINT32(userdata));
if (r < 0)
@@ -800,6 +810,20 @@ int link_request_to_set_mac(Link *link, bool allow_retry) {
NULL);
}
+int link_request_to_set_ipoib(Link *link) {
+ assert(link);
+ assert(link->network);
+
+ if (link->iftype != ARPHRD_INFINIBAND)
+ return 0;
+
+ if (link->network->ipoib_mode < 0 &&
+ link->network->ipoib_umcast < 0)
+ return 0;
+
+ return link_request_set_link(link, SET_LINK_IPOIB, link_set_ipoib_handler, NULL);
+}
+
int link_request_to_set_master(Link *link) {
assert(link);
assert(link->network);
diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h
index d3e9f2b9d7..39a85a6871 100644
--- a/src/network/networkd-setlink.h
+++ b/src/network/networkd-setlink.h
@@ -14,6 +14,7 @@ typedef enum SetLinkOperation {
SET_LINK_CAN, /* Setting CAN interface configs. */
SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */
SET_LINK_GROUP, /* Setting interface group. */
+ SET_LINK_IPOIB, /* Setting IPoIB configs. */
SET_LINK_MAC, /* Setting MAC address. */
SET_LINK_MASTER, /* Setting IFLA_MASTER. */
SET_LINK_MTU, /* Setting MTU. */
@@ -33,6 +34,7 @@ int link_request_to_set_can(Link *link);
int link_request_to_set_flags(Link *link);
int link_request_to_set_group(Link *link);
int link_request_to_set_mac(Link *link, bool allow_retry);
+int link_request_to_set_ipoib(Link *link);
int link_request_to_set_master(Link *link);
int link_request_to_set_mtu(Link *link, uint32_t mtu);
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 68cf1ba691..c1c0026234 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -287,6 +287,9 @@ Loopback=
OneShot=
PresumeACK=
ClassicDataLengthCode=
+[IPoIB]
+Mode=
+IgnoreUserspaceMulticastGroups=
[Address]
DuplicateAddressDetection=
AutoJoin=