mirror of
https://github.com/systemd/systemd.git
synced 2025-03-22 06:50:18 +03:00
Merge pull request #13017 from yuwata/network-neighbor-lladdr-13015
network: rename Neighbor.MACAddress= and also support IPv4 address
This commit is contained in:
commit
be9d8212a5
@ -1016,9 +1016,9 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>MACAddress=</varname></term>
|
||||
<term><varname>LinkLayerAddress=</varname></term>
|
||||
<listitem>
|
||||
<para>The hardware address of the neighbor.</para>
|
||||
<para>The link layer address (MAC address or IP address) of the neighbor.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@ -611,7 +611,7 @@ int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t s
|
||||
if (data)
|
||||
memcpy(data, attr_data, size);
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
|
||||
|
@ -663,7 +663,7 @@ static const NLTypeSystem rtnl_route_type_system = {
|
||||
|
||||
static const NLType rtnl_neigh_types[] = {
|
||||
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[NDA_LLADDR] = { /* struct ether_addr or struct in_addr */ },
|
||||
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
|
||||
[NDA_PROBES] = { .type = NETLINK_TYPE_U32 },
|
||||
[NDA_VLAN] = { .type = NETLINK_TYPE_U16 },
|
||||
|
@ -519,7 +519,7 @@ static int get_gateway_description(
|
||||
if (!in_addr_equal(fam, &gw, gateway))
|
||||
continue;
|
||||
|
||||
r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac);
|
||||
r = sd_netlink_message_read(m, NDA_LLADDR, sizeof(mac), &mac);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
|
@ -39,7 +39,6 @@ static int fdb_entry_new_static(
|
||||
|
||||
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
|
||||
_cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL;
|
||||
_cleanup_free_ struct ether_addr *mac_addr = NULL;
|
||||
int r;
|
||||
|
||||
assert(network);
|
||||
@ -63,11 +62,6 @@ static int fdb_entry_new_static(
|
||||
if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX)
|
||||
return -E2BIG;
|
||||
|
||||
/* allocate space for MAC address. */
|
||||
mac_addr = new0(struct ether_addr, 1);
|
||||
if (!mac_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
/* allocate space for and FDB entry. */
|
||||
fdb_entry = new(FdbEntry, 1);
|
||||
if (!fdb_entry)
|
||||
@ -76,7 +70,6 @@ static int fdb_entry_new_static(
|
||||
/* init FDB structure. */
|
||||
*fdb_entry = (FdbEntry) {
|
||||
.network = network,
|
||||
.mac_addr = TAKE_PTR(mac_addr),
|
||||
.vni = VXLAN_VID_MAX + 1,
|
||||
.fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
|
||||
};
|
||||
@ -143,7 +136,7 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
|
||||
if (r < 0)
|
||||
return rtnl_log_create_error(r);
|
||||
|
||||
r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr);
|
||||
r = sd_netlink_message_append_data(req, NDA_LLADDR, &fdb_entry->mac_addr, sizeof(fdb_entry->mac_addr));
|
||||
if (r < 0)
|
||||
return rtnl_log_create_error(r);
|
||||
|
||||
@ -192,7 +185,6 @@ void fdb_entry_free(FdbEntry *fdb_entry) {
|
||||
}
|
||||
|
||||
network_config_section_free(fdb_entry->section);
|
||||
free(fdb_entry->mac_addr);
|
||||
free(fdb_entry);
|
||||
}
|
||||
|
||||
@ -223,17 +215,9 @@ int config_parse_fdb_hwaddr(
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
/* read in the MAC address for the FDB table. */
|
||||
r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
|
||||
&fdb_entry->mac_addr->ether_addr_octet[0],
|
||||
&fdb_entry->mac_addr->ether_addr_octet[1],
|
||||
&fdb_entry->mac_addr->ether_addr_octet[2],
|
||||
&fdb_entry->mac_addr->ether_addr_octet[3],
|
||||
&fdb_entry->mac_addr->ether_addr_octet[4],
|
||||
&fdb_entry->mac_addr->ether_addr_octet[5]);
|
||||
|
||||
if (r != ETHER_ADDR_LEN) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
|
||||
r = ether_addr_from_string(rvalue, &fdb_entry->mac_addr);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ struct FdbEntry {
|
||||
int family;
|
||||
uint16_t vlan_id;
|
||||
|
||||
struct ether_addr *mac_addr;
|
||||
struct ether_addr mac_addr;
|
||||
union in_addr_union destination_addr;
|
||||
NeighborCacheEntryFlags fdb_ntf_flags;
|
||||
|
||||
|
@ -59,6 +59,7 @@ static int neighbor_new_static(Network *network, const char *filename, unsigned
|
||||
*neighbor = (Neighbor) {
|
||||
.network = network,
|
||||
.family = AF_UNSPEC,
|
||||
.lladdr_type = _NEIGHBOR_LLADDR_INVALID,
|
||||
};
|
||||
|
||||
LIST_APPEND(neighbors, network->neighbors, neighbor);
|
||||
@ -115,11 +116,6 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
|
||||
if (neighbor->family == AF_UNSPEC)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without Address= configured");
|
||||
if (!neighbor->mac_configured)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without MACAddress= configured");
|
||||
|
||||
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
|
||||
link->ifindex, neighbor->family);
|
||||
if (r < 0)
|
||||
@ -133,7 +129,10 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not set flags: %m");
|
||||
|
||||
r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, &neighbor->mac);
|
||||
if (neighbor->lladdr_type == NEIGHBOR_LLADDR_MAC)
|
||||
r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr.mac, sizeof(neighbor->lladdr.mac));
|
||||
else
|
||||
r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr.ip.in, sizeof(neighbor->lladdr.ip.in));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m");
|
||||
|
||||
@ -152,16 +151,36 @@ int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_hand
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_neighbor_address(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) {
|
||||
int neighbor_section_verify(Neighbor *neighbor) {
|
||||
if (section_is_invalid(neighbor->section))
|
||||
return -EINVAL;
|
||||
|
||||
if (neighbor->family == AF_UNSPEC)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s: Neighbor section without Address= configured. "
|
||||
"Ignoring [Neighbor] section from line %u.",
|
||||
neighbor->section->filename, neighbor->section->line);
|
||||
|
||||
if (neighbor->lladdr_type < 0)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s: Neighbor section without LinkLayerAddress= configured. "
|
||||
"Ignoring [Neighbor] section from line %u.",
|
||||
neighbor->section->filename, neighbor->section->line);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_neighbor_address(
|
||||
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) {
|
||||
|
||||
Network *network = userdata;
|
||||
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
|
||||
@ -188,16 +207,17 @@ int config_parse_neighbor_address(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_neighbor_hwaddr(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) {
|
||||
int config_parse_neighbor_lladdr(
|
||||
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) {
|
||||
|
||||
Network *network = userdata;
|
||||
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
|
||||
@ -213,13 +233,56 @@ int config_parse_neighbor_hwaddr(const char *unit,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ether_addr_from_string(rvalue, &n->mac);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
r = ether_addr_from_string(rvalue, &n->lladdr.mac);
|
||||
if (r >= 0)
|
||||
n->lladdr_type = NEIGHBOR_LLADDR_MAC;
|
||||
else {
|
||||
r = in_addr_from_string(AF_INET, rvalue, &n->lladdr.ip);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor LinkLayerAddress= is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
n->lladdr_type = NEIGHBOR_LLADDR_IP;
|
||||
}
|
||||
|
||||
n->mac_configured = true;
|
||||
TAKE_PTR(n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_neighbor_hwaddr(
|
||||
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) {
|
||||
|
||||
Network *network = userdata;
|
||||
_cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(section);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = neighbor_new_static(network, filename, section_line, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ether_addr_from_string(rvalue, &n->lladdr.mac);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress= is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n->lladdr_type = NEIGHBOR_LLADDR_MAC;
|
||||
TAKE_PTR(n);
|
||||
|
||||
return 0;
|
||||
|
@ -15,6 +15,13 @@ typedef struct Neighbor Neighbor;
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
typedef enum {
|
||||
NEIGHBOR_LLADDR_MAC,
|
||||
NEIGHBOR_LLADDR_IP,
|
||||
_NEIGHBOR_LLADDR_MAX,
|
||||
_NEIGHBOR_LLADDR_INVALID = -1,
|
||||
} NeighborLLAddressType;
|
||||
|
||||
struct Neighbor {
|
||||
Network *network;
|
||||
Link *link;
|
||||
@ -22,8 +29,11 @@ struct Neighbor {
|
||||
|
||||
int family;
|
||||
union in_addr_union in_addr;
|
||||
bool mac_configured;
|
||||
struct ether_addr mac;
|
||||
union {
|
||||
struct ether_addr mac;
|
||||
union in_addr_union ip;
|
||||
} lladdr;
|
||||
NeighborLLAddressType lladdr_type;
|
||||
|
||||
LIST_FIELDS(Neighbor, neighbors);
|
||||
};
|
||||
@ -34,5 +44,8 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free);
|
||||
|
||||
int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
|
||||
|
||||
int neighbor_section_verify(Neighbor *neighbor);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr);
|
||||
|
@ -108,7 +108,8 @@ Address.Scope, config_parse_address_scope,
|
||||
IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0
|
||||
IPv6AddressLabel.Label, config_parse_address_label, 0, 0
|
||||
Neighbor.Address, config_parse_neighbor_address, 0, 0
|
||||
Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0
|
||||
Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0
|
||||
Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0 /* deprecated */
|
||||
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule_tos, 0, 0
|
||||
RoutingPolicyRule.Priority, config_parse_routing_policy_rule_priority, 0, 0
|
||||
RoutingPolicyRule.Table, config_parse_routing_policy_rule_table, 0, 0
|
||||
|
@ -269,7 +269,7 @@ int network_verify(Network *network) {
|
||||
fdb_entry_free(fdb);
|
||||
|
||||
LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors)
|
||||
if (section_is_invalid(neighbor->section))
|
||||
if (neighbor_section_verify(neighbor) < 0)
|
||||
neighbor_free(neighbor);
|
||||
|
||||
LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels)
|
||||
|
@ -223,6 +223,7 @@ Managed=
|
||||
OtherInformation=
|
||||
[Neighbor]
|
||||
Address=
|
||||
LinkLayerAddress=
|
||||
MACAddress=
|
||||
[IPv6AddressLabel]
|
||||
Label=
|
||||
|
6
test/test-network/conf/25-neighbor-ip-dummy.network
Normal file
6
test/test-network/conf/25-neighbor-ip-dummy.network
Normal file
@ -0,0 +1,6 @@
|
||||
[Match]
|
||||
Name=dummy98
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Tunnel=gretun97
|
10
test/test-network/conf/25-neighbor-ip.network
Normal file
10
test/test-network/conf/25-neighbor-ip.network
Normal file
@ -0,0 +1,10 @@
|
||||
[Match]
|
||||
Name=gretun97
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.21
|
||||
|
||||
[Neighbor]
|
||||
Address=10.0.0.22
|
||||
LinkLayerAddress=10.65.223.239
|
@ -6,8 +6,8 @@ IPv6AcceptRA=no
|
||||
|
||||
[Neighbor]
|
||||
Address=192.168.10.1
|
||||
MACAddress=00:00:5e:00:02:65
|
||||
LinkLayerAddress=00:00:5e:00:02:65
|
||||
|
||||
[Neighbor]
|
||||
Address=2004:da8:1:0::1
|
||||
MACAddress=00:00:5e:00:02:66
|
||||
LinkLayerAddress=00:00:5e:00:02:66
|
||||
|
@ -1376,7 +1376,9 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
'bond199',
|
||||
'dummy98',
|
||||
'dummy99',
|
||||
'test1']
|
||||
'gretun97',
|
||||
'test1'
|
||||
]
|
||||
|
||||
units = [
|
||||
'11-dummy.netdev',
|
||||
@ -1391,8 +1393,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
'25-bond-active-backup-slave.netdev',
|
||||
'25-fibrule-invert.network',
|
||||
'25-fibrule-port-range.network',
|
||||
'25-gre-tunnel-remote-any.netdev',
|
||||
'25-ipv6-address-label-section.network',
|
||||
'25-neighbor-section.network',
|
||||
'25-neighbor-ip-dummy.network',
|
||||
'25-neighbor-ip.network',
|
||||
'25-link-local-addressing-no.network',
|
||||
'25-link-local-addressing-yes.network',
|
||||
'25-link-section-unmanaged.network',
|
||||
@ -1620,7 +1625,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
print(output)
|
||||
self.assertRegex(output, '2004:da8:1::/64')
|
||||
|
||||
def test_ipv6_neighbor(self):
|
||||
def test_neighbor_section(self):
|
||||
copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
|
||||
start_networkd()
|
||||
wait_online(['dummy98:degraded'], timeout='40s')
|
||||
@ -1630,6 +1635,16 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
|
||||
self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
|
||||
|
||||
def test_neighbor_gre(self):
|
||||
copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ip-dummy.network',
|
||||
'12-dummy.netdev', '25-gre-tunnel-remote-any.netdev')
|
||||
start_networkd()
|
||||
wait_online(['dummy98:degraded', 'gretun97:routable'], timeout='40s')
|
||||
|
||||
output = check_output('ip neigh list dev gretun97')
|
||||
print(output)
|
||||
self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
|
||||
|
||||
def test_link_local_addressing(self):
|
||||
copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
|
||||
'25-link-local-addressing-no.network', '12-dummy.netdev')
|
||||
|
Loading…
x
Reference in New Issue
Block a user