after_script:
- $CI_MANAGERS/debian.sh CLEANUP
- - name: Ubuntu Xenial
- language: bash
- script:
- - set -e
- - sudo $CI_MANAGERS/xenial.sh
- - set +e
-
- name: FuzzBuzz
language: bash
script:
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>SendRelease=</varname></term>
+ <listitem>
+ <para>When true, the DHCPv4 client sends a DHCP release packet when it stops.
+ Defaults to false.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>RapidCommit=</varname></term>
<listitem>
Defaults to unset.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>AssociatedWith=</varname></term>
+ <listitem>
+ <para>Specifies where the address is associated with. Takes one of <literal>use</literal>,
+ <literal>self</literal>, <literal>master</literal> or <literal>router</literal>.
+ <literal>use</literal> means the address is in use. User space can use this option to
+ indicate to the kernel that the fdb entry is in use. <literal>self</literal> means
+ the address is associated with the port drivers fdb. Usually hardware. <literal>master</literal>
+ means the address is associated with master devices fdb. <literal>router</literal> means
+ the destination address is associated with a router. Note that it's valid if the referenced
+ device is a VXLAN type device and has route shortcircuit enabled. Defaults to <literal>self</literal>.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
or runtime environment doesn't require their functionality. Use the various
<varname>AssertArchitecture=</varname>, <varname>AssertVirtualization=</varname>, … options for a similar
mechanism that causes the job to fail (instead of being skipped) and results in logging about the failed check
- (instead of being silently processed). For details about assertion conditions see below.</para>
+ (instead of being silently processed). For details about assertion conditions see below. Units with failed
+ conditions are considered to be in a clean state and will be garbage collected if they are not referenced.
+ This means, that when queried, the condition failure may or may not show up in the state of the unit.</para>
<para><varname>ConditionArchitecture=</varname> may be used to
check whether the system is running on a specific
assert(ret);
assert(_optlen);
assert(_optoffset);
- assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
+ assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE));
optlen = DHCP_MIN_OPTIONS_SIZE;
size = sizeof(DHCPPacket) + optlen;
MAY contain the Parameter Request List option. */
/* NOTE: in case that there would be an option to do not send
* any PRL at all, the size should be checked before sending */
- if (client->req_opts_size > 0) {
+ if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
client->req_opts_size, client->req_opts);
*/
/* RFC7844 section 3:
SHOULD NOT contain any other option. */
- if (!client->anonymize) {
+ if (!client->anonymize && type != DHCP_RELEASE) {
max_size = htobe16(size);
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
return 0;
}
+static int client_send_release(sd_dhcp_client *client) {
+ _cleanup_free_ DHCPPacket *release = NULL;
+ size_t optoffset, optlen;
+ int r;
+
+ assert(client);
+ assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
+
+ r = client_message_init(client, &release, DHCP_RELEASE,
+ &optlen, &optoffset);
+ if (r < 0)
+ return r;
+
+ /* Fill up release IP and MAC */
+ release->dhcp.ciaddr = client->lease->address;
+ memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
+
+ r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_END, 0, NULL);
+ if (r < 0)
+ return r;
+
+ r = dhcp_network_send_udp_socket(client->fd,
+ client->lease->server_address,
+ DHCP_PORT_SERVER,
+ &release->dhcp,
+ sizeof(DHCPMessage) + optoffset);
+ if (r < 0)
+ return r;
+
+ log_dhcp_client(client, "RELEASE");
+
+ return 0;
+}
+
static int client_send_request(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *request = NULL;
size_t optoffset, optlen;
return r;
}
+int sd_dhcp_client_send_release(sd_dhcp_client *client) {
+ assert_return(client, -EINVAL);
+
+ client_send_release(client);
+
+ return 0;
+}
+
int sd_dhcp_client_stop(sd_dhcp_client *client) {
DHCP_CLIENT_DONT_DESTROY(client);
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
+ if (link->network->dhcp_send_release)
+ (void) sd_dhcp_client_send_release(client);
+
_fallthrough_;
case SD_DHCP_CLIENT_EVENT_EXPIRED:
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
#include "networkd-manager.h"
#include "parse-util.h"
#include "string-util.h"
+#include "string-table.h"
#include "util.h"
#include "vlan-util.h"
#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U
+static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = {
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use",
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self",
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master",
+ [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags);
+
/* create a new FDB entry or get an existing one. */
static int fdb_entry_new_static(
Network *network,
.network = network,
.mac_addr = TAKE_PTR(mac_addr),
.vni = VXLAN_VID_MAX + 1,
+ .fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
};
LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
/* send a request to the kernel to add a FDB entry in its static MAC table. */
int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- sd_netlink *rtnl;
- Bridge *bridge;
- uint8_t flags;
int r;
assert(link);
assert(link->manager);
assert(fdb_entry);
- rtnl = link->manager->rtnl;
- bridge = BRIDGE(link->network->bridge);
-
/* create new RTM message */
- r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
+ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
if (r < 0)
return rtnl_log_create_error(r);
- if (bridge)
- flags = NTF_MASTER;
- else
- flags = NTF_SELF;
-
- r = sd_rtnl_message_neigh_set_flags(req, flags);
+ r = sd_rtnl_message_neigh_set_flags(req, fdb_entry->fdb_ntf_flags);
if (r < 0)
return rtnl_log_create_error(r);
}
/* send message to the kernel to update its internal static MAC table. */
- r = netlink_call_async(rtnl, NULL, req, set_fdb_handler,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, set_fdb_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return 0;
}
+
+
+int config_parse_fdb_ntf_flags(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
+ Network *network = userdata;
+ NeighborCacheEntryFlags f;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
+ if (r < 0)
+ return log_oom();
+
+ f = fdb_ntf_flags_from_string(rvalue);
+ if (f < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "FDB failed to parse AssociatedWith=, ignoring assignment: %s",
+ rvalue);
+ return 0;
+ }
+
+ fdb_entry->fdb_ntf_flags = f;
+ fdb_entry = NULL;
+
+ return 0;
+}
Copyright © 2014 Intel Corporation. All rights reserved.
***/
+#include <linux/neighbour.h>
+
#include "conf-parser.h"
#include "list.h"
#include "macro.h"
typedef struct Link Link;
typedef struct NetworkConfigSection NetworkConfigSection;
+typedef enum NeighborCacheEntryFlags {
+ NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE,
+ NEIGHBOR_CACHE_ENTRY_FLAGS_SELF = NTF_SELF,
+ NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER = NTF_MASTER,
+ NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER = NTF_ROUTER,
+ _NEIGHBOR_CACHE_ENTRY_FLAGS_MAX,
+ _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1,
+} NeighborCacheEntryFlags;
+
struct FdbEntry {
Network *network;
NetworkConfigSection *section;
struct ether_addr *mac_addr;
union in_addr_union destination_addr;
+ NeighborCacheEntryFlags fdb_ntf_flags;
LIST_FIELDS(FdbEntry, static_fdb_entries);
};
DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free);
+const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_;
+NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_;
+
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination);
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vxlan_vni);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_ntf_flags);
assert(link->manager);
assert(link->manager->rtnl);
+ if (!socket_ipv6_is_supported())
+ return 0;
+
log_link_debug(link, "Setting address genmode for link");
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
return log_link_error_errno(link, r, "Could not set MAC address: %m");
}
- if (link_ipv6_enabled(link)) {
- uint8_t ipv6ll_mode;
-
- r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
-
- /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
- r = sd_netlink_message_open_container(req, AF_INET6);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
-
- if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
- r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
- }
-
- if (!link_ipv6ll_enabled(link))
- ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
- else if (sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL) < 0)
- /* The file may not exist. And event if it exists, when stable_secret is unset,
- * reading the file fails with EIO. */
- ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
- else
- ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
-
- r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
-
- r = sd_netlink_message_close_container(req);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
-
- r = sd_netlink_message_close_container(req);
- if (r < 0)
- return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
- }
-
r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
link_netlink_destroy_callback, link);
if (r < 0)
if (r < 0)
return r;
- if (socket_ipv6_is_supported()) {
- r = link_configure_addrgen_mode(link);
- if (r < 0)
- return r;
- }
+ r = link_configure_addrgen_mode(link);
+ if (r < 0)
+ return r;
return link_configure_after_setting_mtu(link);
}
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCP.IAID, config_parse_iaid, 0, 0
DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
+DHCP.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release)
DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
DHCP.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0
DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
BridgeFDB.Destination, config_parse_fdb_destination, 0, 0
BridgeFDB.VNI, config_parse_fdb_vxlan_vni, 0, 0
+BridgeFDB.AssociatedWith, config_parse_fdb_ntf_flags, 0, 0
BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0
BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0
BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0
bool rapid_commit;
bool dhcp_use_hostname;
bool dhcp_route_table_set;
+ bool dhcp_send_release;
DHCPUseDomains dhcp_use_domains;
Set *dhcp_black_listed_ip;
int sd_dhcp_client_stop(sd_dhcp_client *client);
int sd_dhcp_client_start(sd_dhcp_client *client);
+int sd_dhcp_client_send_release(sd_dhcp_client *client);
sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
MACAddress=
Destination=
VNI=
+AssociatedWith=
[DHCP]
UseDomains=
UseRoutes=
UseTimezone=
RouteTable=
BlackList=
+SendRelease=
[Route]
Destination=
Protocol=
[Network]
DHCP=ipv6
+IPv6Token=::1a:2b:3c:4d
def test_dhcp_client_ipv6_only(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
- self.start_networkd()
-
- self.assertTrue(self.link_exits('veth99'))
+ self.start_networkd(0)
+ self.wait_online(['veth-peer:carrier'])
self.start_dnsmasq()
+ self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, '2600::')
self.assertNotRegex(output, '192.168.5')
+ # Confirm that ipv6 token is not set in the kernel
+ output = subprocess.check_output(['ip', 'token', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+ print(output)
+ self.assertRegex(output, 'token :: dev veth99')
+
def test_dhcp_client_ipv4_only(self):
self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
self.start_networkd()
tmpfiles = [['home.conf', ''],
['journal-nocow.conf', ''],
- ['systemd-nologin.conf', ''],
+ ['systemd-nologin.conf', 'HAVE_PAM'],
['systemd-nspawn.conf', 'ENABLE_MACHINED'],
['systemd-tmp.conf', ''],
['portables.conf', 'ENABLE_PORTABLED'],