summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--man/systemd.netdev.xml37
-rw-r--r--src/basic/missing.h13
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c9
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c11
-rw-r--r--src/network/networkd-netdev-bridge.c86
-rw-r--r--src/network/networkd-netdev-bridge.h4
-rw-r--r--src/network/networkd-netdev-gperf.gperf3
-rw-r--r--src/network/networkd-netdev.c3
-rw-r--r--src/network/networkd-netdev.h3
-rw-r--r--src/systemd/sd-netlink.h1
11 files changed, 169 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index d75a02623b..aabb5e4fe4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -321,6 +321,7 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
IFLA_GRE_ENCAP_DPORT,
IFLA_BRIDGE_VLAN_INFO,
IFLA_BRPORT_LEARNING_SYNC,
+ IFLA_BR_PRIORITY,
NDA_IFINDEX,
IFA_FLAGS],
[], [], [[
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 05bbad7f65..67c12a7173 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -277,6 +277,43 @@
</variablelist>
</refsect1>
+ <refsect1>
+ <title>[Bridge] Section Options</title>
+
+ <para>The <literal>[Bridge]</literal> section only applies for
+ netdevs of kind <literal>bridge</literal>, and accepts the
+ following key:</para>
+
+ <variablelist class='network-directives'>
+ <varlistentry>
+ <term><varname>HelloTimeSec=</varname></term>
+ <listitem>
+ <para>HelloTimeSec specifies the number of seconds a hello packet is
+ sent out by the root bridge and the designated bridges. Hello packets are
+ used to communicate information about the topology throughout the entire
+ bridged local area network.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>MaxAgeSec=</varname></term>
+ <listitem>
+ <para>MaxAgeSec specifies the number of seconds of maximum message age.
+ If the last seen (received) hello packet is more than this number of
+ seconds old, the bridge in question will start the takeover procedure
+ in attempt to become the Root Bridge itself.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>ForwardDelaySec=</varname></term>
+ <listitem>
+ <para>ForwardDelaySec specifies the number of seconds spent in each
+ of the Listening and Learning states before the Forwarding state is entered.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
<refsect1>
<title>[VLAN] Section Options</title>
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 9811b6b23e..1e3af283bb 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -842,6 +842,19 @@ static inline int setns(int fd, int nstype) {
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
#endif
+#if !HAVE_DECL_IFLA_BR_PRIORITY
+#define IFLA_BR_UNSPEC 0
+#define IFLA_BR_FORWARD_DELAY 1
+#define IFLA_BR_HELLO_TIME 2
+#define IFLA_BR_MAX_AGE 3
+#define IFLA_BR_AGEING_TIME 4
+#define IFLA_BR_STP_STATE 5
+#define IFLA_BR_PRIORITY 6
+#define __IFLA_BR_MAX 7
+
+#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
+#endif
+
#if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC
#define IFLA_BRPORT_UNSPEC 0
#define IFLA_BRPORT_STATE 1
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 0d8e37b856..cf693de5fb 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -149,6 +149,15 @@ int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) {
return 0;
}
+int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) {
+ assert_return(m, -EINVAL);
+ assert_return(flags, -EINVAL);
+
+ m->hdr->nlmsg_flags = flags;
+
+ return 0;
+}
+
int sd_netlink_message_is_broadcast(sd_netlink_message *m) {
assert_return(m, -EINVAL);
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 2128329191..4a5340e659 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -97,7 +97,7 @@ static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = {
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
};
-static const NLType rtnl_link_info_data_bridge_types[IFLA_BRIDGE_MAX + 1] = {
+static const NLType rtnl_link_bridge_management_types[IFLA_BRIDGE_MAX + 1] = {
[IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
[IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 },
/*
@@ -106,6 +106,15 @@ static const NLType rtnl_link_info_data_bridge_types[IFLA_BRIDGE_MAX + 1] = {
*/
};
+static const NLType rtnl_link_info_data_bridge_types[IFLA_BR_MAX + 1] = {
+ [IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_BR_AGEING_TIME] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_BR_STP_STATE] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 },
+};
+
static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
[IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
/*
diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c
index fd6af7e99b..2eeb86a683 100644
--- a/src/network/networkd-netdev-bridge.c
+++ b/src/network/networkd-netdev-bridge.c
@@ -20,12 +20,96 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <net/if.h>
#include "networkd-netdev-bridge.h"
#include "missing.h"
+#include "netlink-util.h"
+
+/* callback for brige netdev's parameter set */
+static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+ _cleanup_netdev_unref_ NetDev *netdev = userdata;
+ int r;
+
+ assert(netdev);
+ assert(m);
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0) {
+ log_netdev_warning_errno(netdev, r, "Bridge parameters could not be set: %m");
+ return 1;
+ }
+
+ log_netdev_debug(netdev, "Bridge parametres set success");
+
+ return 1;
+}
+
+static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ Bridge *b;
+ int r;
+
+ assert(netdev);
+
+ b = BRIDGE(netdev);
+
+ assert(b);
+
+ r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, netdev->ifindex);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m");
+
+ r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+ r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+ r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ if (b->forward_delay > 0) {
+ r = sd_netlink_message_append_u32(req, IFLA_BR_FORWARD_DELAY, b->forward_delay / USEC_PER_SEC);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m");
+ }
+
+ if (b->hello_time > 0) {
+ r = sd_netlink_message_append_u32(req, IFLA_BR_HELLO_TIME, b->hello_time / USEC_PER_SEC );
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_HELLO_TIME attribute: %m");
+ }
+
+ if (b->max_age > 0) {
+ r = sd_netlink_message_append_u32(req, IFLA_BR_MAX_AGE, b->max_age / USEC_PER_SEC);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MAX_AGE attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ r = sd_netlink_call_async(netdev->manager->rtnl, req, netdev_bridge_set_handler, netdev, 0, NULL);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
+
+ netdev_ref(netdev);
+
+ return r;
+}
const NetDevVTable bridge_vtable = {
.object_size = sizeof(Bridge),
- .sections = "Match\0NetDev\0",
+ .sections = "Match\0NetDev\0Bridge\0",
+ .post_create = netdev_bridge_post_create,
.create_type = NETDEV_CREATE_MASTER,
};
diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h
index a7d02b1c91..d3bd15e0d6 100644
--- a/src/network/networkd-netdev-bridge.h
+++ b/src/network/networkd-netdev-bridge.h
@@ -27,6 +27,10 @@ typedef struct Bridge Bridge;
struct Bridge {
NetDev meta;
+
+ usec_t forward_delay;
+ usec_t hello_time;
+ usec_t max_age;
};
extern const NetDevVTable bridge_vtable;
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index e0bd0e024a..4aac239850 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -86,3 +86,6 @@ Bond.UpDelaySec, config_parse_sec, 0,
Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay)
Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval)
Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval)
+Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time)
+Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age)
+Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay)
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index ff1edf2c39..3d4865a780 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -245,6 +245,9 @@ static int netdev_enter_ready(NetDev *netdev) {
free(callback);
}
+ if (NETDEV_VTABLE(netdev)->post_create)
+ NETDEV_VTABLE(netdev)->post_create(netdev, NULL, NULL);
+
return 0;
}
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index 1f8510c4f7..3b9ab27b67 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -141,6 +141,9 @@ struct NetDevVTable {
/* create netdev, if not done via rtnl */
int (*create)(NetDev *netdev);
+ /* perform additional configuration after netdev has been createad */
+ int (*post_create)(NetDev *netdev, Link *link, sd_netlink_message *message);
+
/* verify that compulsory configuration options were specified */
int (*config_verify)(NetDev *netdev, const char *filename);
};
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index cb462bf48f..e09b8c8e2d 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -104,6 +104,7 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump);
int sd_netlink_message_is_error(sd_netlink_message *m);
int sd_netlink_message_get_errno(sd_netlink_message *m);
int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type);
+int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags);
int sd_netlink_message_is_broadcast(sd_netlink_message *m);
/* rtnl */