summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSusant Sahani <ssahani@users.noreply.github.com>2016-08-04 19:30:58 +0530
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-08-04 10:00:58 -0400
commit99d2baa2cab0706d89beff596f997d4e3a1c833f (patch)
tree3f6497ff983a597804563d09b175bc48e7a8c64c
parent3104883ddc2452ae210de3c70576c03023250a51 (diff)
networkd: add support to configure NOARP/ARP for interface (#3854)
https://lists.freedesktop.org/archives/systemd-devel/2016-August/037268.html
-rw-r--r--man/systemd.network.xml11
-rw-r--r--src/network/networkd-link.c63
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c1
-rw-r--r--src/network/networkd-network.h1
5 files changed, 77 insertions, 0 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 4541a55490..c332cd7bdc 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -212,6 +212,17 @@
below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>ARP=</varname></term>
+ <listitem>
+ <para> A boolean. Enables or disables the ARP (low-level Address Resolution Protocol)
+ for this interface. Defaults to unset, which means that the kernel default will be used.</para>
+ <para> For example, disabling ARP is useful when creating multiple MACVLAN or VLAN virtual
+ interfaces atop a single lower-level physical interface, which will then only serve as a
+ link/"bridge" device aggregating traffic to the same physical link and not participate in
+ the network otherwise.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 99784b0ebe..3e10ab1e04 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1314,6 +1314,65 @@ int link_set_mtu(Link *link, uint32_t mtu) {
return 0;
}
+static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+ _cleanup_link_unref_ Link *link = userdata;
+ int r;
+
+ assert(m);
+ assert(link);
+ assert(link->ifname);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not set link flags: %m");
+
+ return 1;
+}
+
+static int link_set_flags(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ unsigned ifi_change = 0;
+ unsigned ifi_flags = 0;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
+ if (!link->network)
+ return 0;
+
+ if (link->network->arp < 0)
+ return 0;
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+ if (link->network->arp >= 0) {
+ ifi_change |= IFF_NOARP;
+ ifi_flags |= IFF_NOARP;
+ }
+
+ r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set link flags: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, link, 0, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return 0;
+}
+
static int link_set_bridge(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
@@ -2411,6 +2470,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = link_set_flags(link);
+ if (r < 0)
+ return r;
+
if (link_ipv4ll_enabled(link)) {
r = ipv4ll_configure(link);
if (r < 0)
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 5172a7b5e9..19adac66b8 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -28,6 +28,7 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
+Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)
Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 2b764d4f24..17bbe5de9f 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -134,6 +134,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->ipv6_hop_limit = -1;
network->duid.type = _DUID_TYPE_INVALID;
network->proxy_arp = -1;
+ network->arp = -1;
network->ipv6_accept_ra_use_dns = true;
r = config_parse(NULL, filename, file,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 08ee939faa..7c0bdc1e4a 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -171,6 +171,7 @@ struct Network {
struct ether_addr *mac;
unsigned mtu;
+ int arp;
uint32_t iaid;
DUID duid;