From 6b8d479ae1016f5df9aca37b3e6c78d32558d287 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Tue, 15 Jan 2019 13:31:49 -0800 Subject: systemd: Add support for static neighbors These are backports of changes I contributed to systemd v240. We need these until we get v240 from oe core. Tested: Ran a romulus image and provisioned static neighbors with systemd networkd. (From meta-phosphor rev: 8b84385e3c40d1827b06d0612def2275d3ad4faf) Change-Id: I5720a3b1626e15d4e4cfc630ce24f5818b294d8a Signed-off-by: William A. Kennington III Signed-off-by: Brad Bishop --- ...0001-networkd-Track-address-configuration.patch | 77 +++ ...orkd-Use-only-a-generic-CONFIGURING-state.patch | 176 +++++++ .../0003-networkd-Static-neighbor-support.patch | 547 +++++++++++++++++++++ .../recipes-core/systemd/systemd_%.bbappend | 5 + 4 files changed, 805 insertions(+) create mode 100644 meta-phosphor/recipes-core/systemd/systemd/0001-networkd-Track-address-configuration.patch create mode 100644 meta-phosphor/recipes-core/systemd/systemd/0002-networkd-Use-only-a-generic-CONFIGURING-state.patch create mode 100644 meta-phosphor/recipes-core/systemd/systemd/0003-networkd-Static-neighbor-support.patch (limited to 'meta-phosphor/recipes-core/systemd') diff --git a/meta-phosphor/recipes-core/systemd/systemd/0001-networkd-Track-address-configuration.patch b/meta-phosphor/recipes-core/systemd/systemd/0001-networkd-Track-address-configuration.patch new file mode 100644 index 000000000..c6836697f --- /dev/null +++ b/meta-phosphor/recipes-core/systemd/systemd/0001-networkd-Track-address-configuration.patch @@ -0,0 +1,77 @@ +From a24d0d95df1929912c0f767f5ab1353552464c84 Mon Sep 17 00:00:00 2001 +From: "William A. Kennington III" +Date: Fri, 30 Nov 2018 15:54:45 -0800 +Subject: [PATCH 1/3] networkd: Track address configuration + +This will be useful to assert that our static route configuration always +happens after address configuration once our individual configure state +goes away. + +(cherry picked from commit c42ff3a1a7bfea66dc4655096c79bd481159091b) + +Upstream-Status: Backport +--- + src/network/networkd-link.c | 11 +++++++++-- + src/network/networkd-link.h | 2 ++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 4afcf843bd..0faf337069 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -728,6 +728,9 @@ void link_check_ready(Link *link) { + if (!link->network) + return; + ++ if (!link->addresses_configured) ++ return; ++ + if (!link->static_routes_configured) + return; + +@@ -835,6 +838,8 @@ static int link_enter_set_routes(Link *link) { + + assert(link); + assert(link->network); ++ assert(link->addresses_configured); ++ assert(link->address_messages == 0); + assert(link->state == LINK_STATE_SETTING_ADDRESSES); + + (void) link_set_routing_policy_rule(link); +@@ -904,6 +909,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda + + if (link->address_messages == 0) { + log_link_debug(link, "Addresses set"); ++ link->addresses_configured = true; + link_enter_set_routes(link); + } + +@@ -1204,9 +1210,10 @@ static int link_enter_set_addresses(Link *link) { + log_link_debug(link, "Offering DHCPv4 leases"); + } + +- if (link->address_messages == 0) ++ if (link->address_messages == 0) { ++ link->addresses_configured = true; + link_enter_set_routes(link); +- else ++ } else + log_link_debug(link, "Setting addresses"); + + return 0; +diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h +index 7e22dfd504..2f37cc1598 100644 +--- a/src/network/networkd-link.h ++++ b/src/network/networkd-link.h +@@ -80,6 +80,8 @@ typedef struct Link { + Set *routes; + Set *routes_foreign; + ++ bool addresses_configured; ++ + sd_dhcp_client *dhcp_client; + sd_dhcp_lease *dhcp_lease; + char *lease_file; +-- +2.20.1.97.g81188d93c3-goog + diff --git a/meta-phosphor/recipes-core/systemd/systemd/0002-networkd-Use-only-a-generic-CONFIGURING-state.patch b/meta-phosphor/recipes-core/systemd/systemd/0002-networkd-Use-only-a-generic-CONFIGURING-state.patch new file mode 100644 index 000000000..49c4cc35f --- /dev/null +++ b/meta-phosphor/recipes-core/systemd/systemd/0002-networkd-Use-only-a-generic-CONFIGURING-state.patch @@ -0,0 +1,176 @@ +From 3283d15fe33da392b7174eb4b82a5ad1ce03a6e4 Mon Sep 17 00:00:00 2001 +From: "William A. Kennington III" +Date: Fri, 30 Nov 2018 15:36:33 -0800 +Subject: [PATCH 2/3] networkd: Use only a generic CONFIGURING state + +This allows us to convey that we are performing multiple link +configuration changes in parallel. This is needed to support configuring +neighbors while simultaneously configuring addresses and routes. + +(cherry picked from commit 289e6774d0daefe86771171b8f4f97b63354683e) + +Upstream-Status: Backport +--- + src/network/networkd-link.c | 37 +++++++++++++++++-------------------- + src/network/networkd-link.h | 4 +--- + 2 files changed, 18 insertions(+), 23 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 0faf337069..71b92185cd 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -706,7 +706,7 @@ static void link_enter_configured(Link *link) { + assert(link); + assert(link->network); + +- if (link->state != LINK_STATE_SETTING_ROUTES) ++ if (link->state != LINK_STATE_CONFIGURING) + return; + + log_link_info(link, "Configured"); +@@ -810,9 +810,8 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata + int r; + + assert(link->route_messages > 0); +- assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, +- LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED, +- LINK_STATE_LINGER)); ++ assert(IN_SET(link->state, LINK_STATE_CONFIGURING, ++ LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->route_messages--; + +@@ -832,7 +831,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata + return 1; + } + +-static int link_enter_set_routes(Link *link) { ++static int link_request_set_routes(Link *link) { + Route *rt; + int r; + +@@ -840,11 +839,11 @@ static int link_enter_set_routes(Link *link) { + assert(link->network); + assert(link->addresses_configured); + assert(link->address_messages == 0); +- assert(link->state == LINK_STATE_SETTING_ADDRESSES); ++ assert(link->state != _LINK_STATE_INVALID); + +- (void) link_set_routing_policy_rule(link); ++ link_set_state(link, LINK_STATE_CONFIGURING); + +- link_set_state(link, LINK_STATE_SETTING_ROUTES); ++ (void) link_set_routing_policy_rule(link); + + LIST_FOREACH(routes, rt, link->network->static_routes) { + r = route_configure(rt, link, route_handler); +@@ -893,7 +892,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda + assert(link); + assert(link->ifname); + assert(link->address_messages > 0); +- assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, ++ assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->address_messages--; +@@ -910,7 +909,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda + if (link->address_messages == 0) { + log_link_debug(link, "Addresses set"); + link->addresses_configured = true; +- link_enter_set_routes(link); ++ link_request_set_routes(link); + } + + return 1; +@@ -1054,7 +1053,7 @@ static int link_set_bridge_fdb(Link *link) { + return 0; + } + +-static int link_enter_set_addresses(Link *link) { ++static int link_request_set_addresses(Link *link) { + AddressLabel *label; + Address *ad; + int r; +@@ -1067,7 +1066,7 @@ static int link_enter_set_addresses(Link *link) { + if (r < 0) + return r; + +- link_set_state(link, LINK_STATE_SETTING_ADDRESSES); ++ link_set_state(link, LINK_STATE_CONFIGURING); + + LIST_FOREACH(addresses, ad, link->network->static_addresses) { + r = address_configure(ad, link, address_handler, false); +@@ -1212,7 +1211,7 @@ static int link_enter_set_addresses(Link *link) { + + if (link->address_messages == 0) { + link->addresses_configured = true; +- link_enter_set_routes(link); ++ link_request_set_routes(link); + } else + log_link_debug(link, "Setting addresses"); + +@@ -2313,7 +2312,7 @@ static int link_joined(Link *link) { + if (!link_has_carrier(link) && !link->network->configure_without_carrier) + return 0; + +- return link_enter_set_addresses(link); ++ return link_request_set_addresses(link); + } + + static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { +@@ -2351,7 +2350,7 @@ static int link_enter_join_netdev(Link *link) { + assert(link->network); + assert(link->state == LINK_STATE_PENDING); + +- link_set_state(link, LINK_STATE_ENSLAVING); ++ link_set_state(link, LINK_STATE_CONFIGURING); + + link_dirty(link); + +@@ -3264,7 +3263,7 @@ static int link_carrier_gained(Link *link) { + return r; + } + +- r = link_enter_set_addresses(link); ++ r = link_request_set_addresses(link); + if (r < 0) + return r; + } +@@ -3348,7 +3347,7 @@ int link_update(Link *link, sd_netlink_message *m) { + if (link->state == LINK_STATE_LINGER) { + link_ref(link); + log_link_info(link, "Link readded"); +- link_set_state(link, LINK_STATE_ENSLAVING); ++ link_set_state(link, LINK_STATE_CONFIGURING); + + r = link_new_carrier_maps(link); + if (r < 0) +@@ -3911,9 +3910,7 @@ void link_clean(Link *link) { + + static const char* const link_state_table[_LINK_STATE_MAX] = { + [LINK_STATE_PENDING] = "pending", +- [LINK_STATE_ENSLAVING] = "configuring", +- [LINK_STATE_SETTING_ADDRESSES] = "configuring", +- [LINK_STATE_SETTING_ROUTES] = "configuring", ++ [LINK_STATE_CONFIGURING] = "configuring", + [LINK_STATE_CONFIGURED] = "configured", + [LINK_STATE_UNMANAGED] = "unmanaged", + [LINK_STATE_FAILED] = "failed", +diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h +index 2f37cc1598..5fd81be5a5 100644 +--- a/src/network/networkd-link.h ++++ b/src/network/networkd-link.h +@@ -19,9 +19,7 @@ + + typedef enum LinkState { + LINK_STATE_PENDING, +- LINK_STATE_ENSLAVING, +- LINK_STATE_SETTING_ADDRESSES, +- LINK_STATE_SETTING_ROUTES, ++ LINK_STATE_CONFIGURING, + LINK_STATE_CONFIGURED, + LINK_STATE_UNMANAGED, + LINK_STATE_FAILED, +-- +2.20.1.97.g81188d93c3-goog + diff --git a/meta-phosphor/recipes-core/systemd/systemd/0003-networkd-Static-neighbor-support.patch b/meta-phosphor/recipes-core/systemd/systemd/0003-networkd-Static-neighbor-support.patch new file mode 100644 index 000000000..86a563144 --- /dev/null +++ b/meta-phosphor/recipes-core/systemd/systemd/0003-networkd-Static-neighbor-support.patch @@ -0,0 +1,547 @@ +From 2402e69c2ccf795d67bb55d7cd073e7384d57a3d Mon Sep 17 00:00:00 2001 +From: "William A. Kennington III" +Date: Wed, 28 Nov 2018 19:00:58 -0800 +Subject: [PATCH 3/3] networkd: Static neighbor support + +When using networkd we currently have no way of ensuring that static +neighbor entries are set when our link comes up. This change adds a new +section to the network definition that allows multiple static neighbors +to be set on a link. + +(cherry picked from commit e4a71bf36f422c3728b902aaa5846add7bbc0eb9) + +Upstream-Status: Backport +--- + man/systemd.network.xml | 25 +++ + src/network/meson.build | 2 + + src/network/networkd-link.c | 34 ++++ + src/network/networkd-link.h | 3 + + src/network/networkd-neighbor.c | 234 +++++++++++++++++++++++ + src/network/networkd-neighbor.h | 37 ++++ + src/network/networkd-network-gperf.gperf | 2 + + src/network/networkd-network.c | 10 + + src/network/networkd-network.h | 4 + + 9 files changed, 351 insertions(+) + create mode 100644 src/network/networkd-neighbor.c + create mode 100644 src/network/networkd-neighbor.h + +diff --git a/man/systemd.network.xml b/man/systemd.network.xml +index fc8e0aea68..804419c31a 100644 +--- a/man/systemd.network.xml ++++ b/man/systemd.network.xml +@@ -899,6 +899,31 @@ + + + ++ ++ [Neighbor] Section Options ++ A [Neighbor] section accepts the ++ following keys. The neighbor section adds a permanent, static ++ entry to the neighbor table (IPv6) or ARP table (IPv4) for ++ the given hardware address on the links matched for the network. ++ Specify several [Neighbor] sections to configure ++ several static neighbors. ++ ++ ++ ++ Address= ++ ++ The IP address of the neighbor. ++ ++ ++ ++ MACAddress= ++ ++ The hardware address of the neighbor. ++ ++ ++ ++ ++ + + [IPv6AddressLabel] Section Options + +diff --git a/src/network/meson.build b/src/network/meson.build +index 8f5544ea04..900130ed6a 100644 +--- a/src/network/meson.build ++++ b/src/network/meson.build +@@ -62,6 +62,8 @@ sources = files(''' + networkd-manager.h + networkd-ndisc.c + networkd-ndisc.h ++ networkd-neighbor.c ++ networkd-neighbor.h + networkd-radv.c + networkd-radv.h + networkd-network-bus.c +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 71b92185cd..51f95ac55e 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -17,6 +17,7 @@ + #include "networkd-lldp-tx.h" + #include "networkd-manager.h" + #include "networkd-ndisc.h" ++#include "networkd-neighbor.h" + #include "networkd-radv.h" + #include "networkd-routing-policy-rule.h" + #include "set.h" +@@ -731,6 +732,9 @@ void link_check_ready(Link *link) { + if (!link->addresses_configured) + return; + ++ if (!link->neighbors_configured) ++ return; ++ + if (!link->static_routes_configured) + return; + +@@ -883,6 +887,34 @@ int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *use + return 1; + } + ++static int link_request_set_neighbors(Link *link) { ++ Neighbor *neighbor; ++ int r; ++ ++ assert(link); ++ assert(link->network); ++ assert(link->state != _LINK_STATE_INVALID); ++ ++ link_set_state(link, LINK_STATE_CONFIGURING); ++ ++ LIST_FOREACH(neighbors, neighbor, link->network->neighbors) { ++ r = neighbor_configure(neighbor, link, NULL); ++ if (r < 0) { ++ log_link_warning_errno(link, r, "Could not set neighbor: %m"); ++ link_enter_failed(link); ++ return r; ++ } ++ } ++ ++ if (link->neighbor_messages == 0) { ++ link->neighbors_configured = true; ++ link_check_ready(link); ++ } else ++ log_link_debug(link, "Setting neighbors"); ++ ++ return 0; ++} ++ + static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + _cleanup_(link_unrefp) Link *link = userdata; + int r; +@@ -1068,6 +1100,8 @@ static int link_request_set_addresses(Link *link) { + + link_set_state(link, LINK_STATE_CONFIGURING); + ++ link_request_set_neighbors(link); ++ + LIST_FOREACH(addresses, ad, link->network->static_addresses) { + r = address_configure(ad, link, address_handler, false); + if (r < 0) { +diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h +index 5fd81be5a5..464e93d982 100644 +--- a/src/network/networkd-link.h ++++ b/src/network/networkd-link.h +@@ -68,6 +68,7 @@ typedef struct Link { + + unsigned address_messages; + unsigned address_label_messages; ++ unsigned neighbor_messages; + unsigned route_messages; + unsigned routing_policy_rule_messages; + unsigned routing_policy_rule_remove_messages; +@@ -95,6 +96,8 @@ typedef struct Link { + bool ipv4ll_address:1; + bool ipv4ll_route:1; + ++ bool neighbors_configured; ++ + bool static_routes_configured; + bool routing_policy_rules_configured; + bool setting_mtu; +diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c +new file mode 100644 +index 0000000000..db69d310d3 +--- /dev/null ++++ b/src/network/networkd-neighbor.c +@@ -0,0 +1,234 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "sd-netlink.h" ++ ++#include "alloc-util.h" ++#include "conf-parser.h" ++#include "ether-addr-util.h" ++#include "hashmap.h" ++#include "in-addr-util.h" ++#include "netlink-util.h" ++#include "networkd-link.h" ++#include "networkd-manager.h" ++#include "networkd-neighbor.h" ++ ++void neighbor_free(Neighbor *neighbor) { ++ if (!neighbor) ++ return; ++ ++ if (neighbor->network) { ++ LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor); ++ assert(neighbor->network->n_neighbors > 0); ++ neighbor->network->n_neighbors--; ++ ++ if (neighbor->section) { ++ hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section); ++ network_config_section_free(neighbor->section); ++ } ++ } ++ ++ free(neighbor); ++} ++ ++static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) { ++ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; ++ _cleanup_(neighbor_freep) Neighbor *neighbor = NULL; ++ int r; ++ ++ assert(network); ++ assert(ret); ++ assert(!!filename == (section_line > 0)); ++ ++ if (filename) { ++ r = network_config_section_new(filename, section_line, &n); ++ if (r < 0) ++ return r; ++ ++ neighbor = hashmap_get(network->neighbors_by_section, n); ++ if (neighbor) { ++ *ret = TAKE_PTR(neighbor); ++ ++ return 0; ++ } ++ } ++ ++ neighbor = new(Neighbor, 1); ++ if (!neighbor) ++ return -ENOMEM; ++ ++ *neighbor = (Neighbor) { ++ .network = network, ++ .family = AF_UNSPEC, ++ }; ++ ++ LIST_APPEND(neighbors, network->neighbors, neighbor); ++ network->n_neighbors++; ++ ++ if (filename) { ++ neighbor->section = TAKE_PTR(n); ++ ++ r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor); ++ if (r < 0) ++ return r; ++ } ++ ++ *ret = TAKE_PTR(neighbor); ++ ++ return 0; ++} ++ ++static int neighbor_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { ++ _cleanup_(link_unrefp) Link *link = userdata; ++ int r; ++ ++ assert(link); ++ assert(link->neighbor_messages > 0); ++ ++ link->neighbor_messages--; ++ ++ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) ++ return 1; ++ ++ r = sd_netlink_message_get_errno(m); ++ if (r < 0 && r != -EEXIST) ++ log_link_warning_errno(link, r, "Could not set neighbor: %m"); ++ ++ if (link->neighbor_messages == 0) { ++ log_link_debug(link, "Neighbors set"); ++ link->neighbors_configured = true; ++ link_check_ready(link); ++ } ++ ++ return 1; ++} ++ ++int neighbor_configure(Neighbor *neighbor, Link *link, sd_netlink_message_handler_t callback) { ++ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; ++ int r; ++ ++ assert(neighbor); ++ assert(link); ++ assert(link->ifindex > 0); ++ assert(link->manager); ++ assert(link->manager->rtnl); ++ ++ if (neighbor->family == AF_UNSPEC) ++ return log_error_errno(EINVAL, "Neighbor without Address= configured"); ++ if (!neighbor->mac_configured) ++ return log_error_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) ++ return log_error_errno(r, "Could not allocate RTM_NEWNEIGH message: %m"); ++ ++ r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT); ++ if (r < 0) ++ return log_error_errno(r, "Could not set state: %m"); ++ ++ r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE); ++ 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 (r < 0) ++ return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m"); ++ ++ switch (neighbor->family) { ++ case AF_INET6: ++ r = sd_netlink_message_append_in6_addr(req, NDA_DST, &neighbor->in_addr.in6); ++ if (r < 0) ++ return log_error_errno(r, "Could not append NDA_DST attribute: %m"); ++ break; ++ case AF_INET: ++ r = sd_netlink_message_append_in_addr(req, NDA_DST, &neighbor->in_addr.in); ++ if (r < 0) ++ return log_error_errno(r, "Could not append NDA_DST attribute: %m"); ++ break; ++ default: ++ return log_error_errno(EINVAL, "Neighbor with invalid address family"); ++ } ++ ++ r = sd_netlink_call_async(link->manager->rtnl, req, callback ?: neighbor_handler, ++ link, 0, NULL); ++ if (r < 0) ++ return log_error_errno(r, "Could not send rtnetlink message: %m"); ++ ++ link->neighbor_messages++; ++ link_ref(link); ++ ++ 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_freep) 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 = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor Address is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ 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_freep) 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->mac); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ n->mac_configured = true; ++ TAKE_PTR(n); ++ ++ return 0; ++} +diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h +new file mode 100644 +index 0000000000..30a1f8fe27 +--- /dev/null ++++ b/src/network/networkd-neighbor.h +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++#pragma once ++ ++#include "sd-netlink.h" ++ ++#include "conf-parser.h" ++#include "ether-addr-util.h" ++#include "in-addr-util.h" ++#include "list.h" ++#include "macro.h" ++ ++typedef struct Neighbor Neighbor; ++ ++#include "networkd-link.h" ++#include "networkd-network.h" ++ ++struct Neighbor { ++ Network *network; ++ Link *link; ++ NetworkConfigSection *section; ++ ++ int family; ++ union in_addr_union in_addr; ++ bool mac_configured; ++ struct ether_addr mac; ++ ++ LIST_FIELDS(Neighbor, neighbors); ++}; ++ ++void neighbor_free(Neighbor *neighbor); ++ ++DEFINE_TRIVIAL_CLEANUP_FUNC(Neighbor*, neighbor_free); ++ ++int neighbor_configure(Neighbor *neighbor, Link *link, sd_netlink_message_handler_t callback); ++ ++CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address); ++CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr); +diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf +index 6ad5257f79..18405149a4 100644 +--- a/src/network/networkd-network-gperf.gperf ++++ b/src/network/networkd-network-gperf.gperf +@@ -93,6 +93,8 @@ Address.AutoJoin, config_parse_address_flags, + Address.Scope, config_parse_address_scope, 0, 0 + 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 + 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 +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 429aac5e6c..a3b8f0cec4 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -158,6 +158,10 @@ static int network_load_one(Manager *manager, const char *filename) { + if (!network->fdb_entries_by_section) + return log_oom(); + ++ network->neighbors_by_section = hashmap_new(&network_config_hash_ops); ++ if (!network->neighbors_by_section) ++ log_oom(); ++ + network->address_labels_by_section = hashmap_new(&network_config_hash_ops); + if (!network->address_labels_by_section) + log_oom(); +@@ -256,6 +260,7 @@ static int network_load_one(Manager *manager, const char *filename) { + "Link\0" + "Network\0" + "Address\0" ++ "Neighbor\0" + "IPv6AddressLabel\0" + "RoutingPolicyRule\0" + "Route\0" +@@ -340,6 +345,7 @@ void network_free(Network *network) { + IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; + RoutingPolicyRule *rule; + FdbEntry *fdb_entry; ++ Neighbor *neighbor; + AddressLabel *label; + Prefix *prefix; + Address *address; +@@ -393,6 +399,9 @@ void network_free(Network *network) { + while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) + ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); + ++ while ((neighbor = network->neighbors)) ++ neighbor_free(neighbor); ++ + while ((label = network->address_labels)) + address_label_free(label); + +@@ -405,6 +414,7 @@ void network_free(Network *network) { + hashmap_free(network->addresses_by_section); + hashmap_free(network->routes_by_section); + hashmap_free(network->fdb_entries_by_section); ++ hashmap_free(network->neighbors_by_section); + hashmap_free(network->address_labels_by_section); + hashmap_free(network->prefixes_by_section); + hashmap_free(network->rules_by_section); +diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h +index 2d46d393ac..8df18326bb 100644 +--- a/src/network/networkd-network.h ++++ b/src/network/networkd-network.h +@@ -16,6 +16,7 @@ + #include "networkd-fdb.h" + #include "networkd-ipv6-proxy-ndp.h" + #include "networkd-lldp-tx.h" ++#include "networkd-neighbor.h" + #include "networkd-radv.h" + #include "networkd-route.h" + #include "networkd-routing-policy-rule.h" +@@ -229,6 +230,7 @@ struct Network { + LIST_HEAD(Route, static_routes); + LIST_HEAD(FdbEntry, static_fdb_entries); + LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); ++ LIST_HEAD(Neighbor, neighbors); + LIST_HEAD(AddressLabel, address_labels); + LIST_HEAD(Prefix, static_prefixes); + LIST_HEAD(RoutingPolicyRule, rules); +@@ -237,6 +239,7 @@ struct Network { + unsigned n_static_routes; + unsigned n_static_fdb_entries; + unsigned n_ipv6_proxy_ndp_addresses; ++ unsigned n_neighbors; + unsigned n_address_labels; + unsigned n_static_prefixes; + unsigned n_rules; +@@ -244,6 +247,7 @@ struct Network { + Hashmap *addresses_by_section; + Hashmap *routes_by_section; + Hashmap *fdb_entries_by_section; ++ Hashmap *neighbors_by_section; + Hashmap *address_labels_by_section; + Hashmap *prefixes_by_section; + Hashmap *rules_by_section; +-- +2.20.1.97.g81188d93c3-goog + diff --git a/meta-phosphor/recipes-core/systemd/systemd_%.bbappend b/meta-phosphor/recipes-core/systemd/systemd_%.bbappend index 213f32797..0d04f28f7 100644 --- a/meta-phosphor/recipes-core/systemd/systemd_%.bbappend +++ b/meta-phosphor/recipes-core/systemd/systemd_%.bbappend @@ -9,6 +9,11 @@ SRC_URI += "file://default.network" SRC_URI += "file://0001-sd-bus-Don-t-automatically-add-ObjectManager.patch" SRC_URI += "file://0006-core-fix-the-check-if-CONFIG_CGROUP_BPF-is-on.patch" +# Static neighbor support included in v240 so remove when updated +SRC_URI += "file://0001-networkd-Track-address-configuration.patch" +SRC_URI += "file://0002-networkd-Use-only-a-generic-CONFIGURING-state.patch" +SRC_URI += "file://0003-networkd-Static-neighbor-support.patch" + RRECOMMENDS_${PN} += "obmc-targets" FILES_${PN} += "${systemd_unitdir}/network/default.network" -- cgit v1.2.3