Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2025 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : #pragma once
12 :
13 : #include "ip/IPAddress.h"
14 :
15 : #include <etl/array.h>
16 : #include <etl/delegate.h>
17 : #include <etl/error_handler.h>
18 : #include <etl/signal.h>
19 : #include <etl/span.h>
20 : #include <shed/ops.h>
21 :
22 : namespace ip
23 : {
24 : struct Ip4Config
25 : {
26 : bool useDhcp = false;
27 : };
28 :
29 : /**
30 : * Represents a IP configuration for a network interface. It can represent configurations
31 : * for both IPv4 and IPv6 addressing. In case of IPv4 it holds also the corresponding
32 : * values for network mask, default gateway address and can return the valid subnet broadcast
33 : * address.
34 : */
35 :
36 : class NetworkInterfaceConfig
37 : {
38 : public:
39 : using Ip6AddressType = uint32_t[4];
40 :
41 : /**
42 : * Constructor. Represents an invalid interface configuration (not configured).
43 : */
44 : NetworkInterfaceConfig();
45 : /**
46 : * Constructor for a IPv4 interface configuration. The corresponding values are expected as raw
47 : * 32 bit values (compare the IPAddress IPv4 constructor with a single uint32_t value).
48 : * \param ip4Address raw value for the IPv4 address
49 : * \param networkMask raw value for the corresponding network mask
50 : * \param defaultGateway raw value for the IPv4 address of the default gateway
51 : */
52 : NetworkInterfaceConfig(uint32_t ip4Address, uint32_t networkMask, uint32_t defaultGateway);
53 :
54 : /**
55 : * Constructor for a IPv6 interface configuration. The corresponding address is expected as
56 : * a raw array of four 32 bit values (compare to the IPAddress IPv6 constructor with an array).
57 : * \param ip6Address raw array holding the IPv6 address
58 : */
59 : explicit NetworkInterfaceConfig(Ip6AddressType const& ip6Address);
60 :
61 : /**
62 : * Checks whether this object represents a physically linked, valid IPv4 or IPv6 configuration.
63 : * \return true if physically linked and address valid
64 : */
65 : bool isValid() const;
66 :
67 : /**
68 : * Get the family of the represented IP configuration
69 : * \return
70 : * - IPV4 in case of a valid IPv4 configuration
71 : * - IPV6 in case of a valid IPv6 configuration
72 : * - FAMILY_UNKNOWN in case of an invalid configurations
73 : */
74 : ::ip::IPAddress::Family ipFamily() const;
75 :
76 : /**
77 : * Get the IP address for the configuration.
78 : * \return a valid IPv4 or IPv6 address in case of a valid configuration, an undefined IP
79 : * address otherwise
80 : */
81 : ::ip::IPAddress ipAddress() const;
82 :
83 : /**
84 : * Get the corresponding IPv4 network mask for the configuration.
85 : * \return a valid IPv4 address holding the network mask for a IPv4 configuration, an undefined
86 : * IP address otherwise
87 : */
88 : ::ip::IPAddress networkMask() const;
89 :
90 : /**
91 : * Get the corresponding IPv4 default gateway address for the configuration.
92 : * \return a valid IPv4 default gateway address for a IPv4 configuration, an undefined IP
93 : * address otherwise
94 : */
95 : ::ip::IPAddress defaultGateway() const;
96 :
97 : /**
98 : * Calculates the subnet broadcast address for a IPv4 configuration.
99 : * \return a valid IPv4 subnet broadcat address for a IPv4 configuration, an undefined IP
100 : * address otherwise
101 : */
102 : ::ip::IPAddress broadcastAddress() const;
103 :
104 : /**
105 : * Compare two network addresses for equality.
106 : * \param lhs config on the left-hand side of the operator
107 : * \param rhs config on the right-hand side of the operator
108 : * - true if config family and all address fields are equal.
109 : * - false otherwise
110 : */
111 : friend bool operator==(NetworkInterfaceConfig const& lhs, NetworkInterfaceConfig const& rhs);
112 :
113 : /**
114 : * Compare two network addresses for inequality.
115 : * \param lhs config on the left-hand side of the operator
116 : * \param rhs config on the right-hand side of the operator
117 : * - true if config family or any address field is not equal.
118 : * - false otherwise
119 : */
120 : friend bool operator!=(NetworkInterfaceConfig const& lhs, NetworkInterfaceConfig const& rhs);
121 :
122 : private:
123 : ::etl::array<uint32_t, 4> _config{};
124 : ::ip::IPAddress::Family _family;
125 : };
126 :
127 : /**
128 : * Inline implementation.
129 : */
130 45 : inline bool NetworkInterfaceConfig::isValid() const
131 : {
132 45 : return _family != ::ip::IPAddress::FAMILY_UNKNOWN;
133 : }
134 :
135 20 : inline ::ip::IPAddress::Family NetworkInterfaceConfig::ipFamily() const { return _family; }
136 :
137 6 : inline bool operator!=(NetworkInterfaceConfig const& lhs, NetworkInterfaceConfig const& rhs)
138 : {
139 6 : return !operator==(lhs, rhs);
140 : }
141 :
142 : using NetworkInterfaceConfigKey = uint8_t;
143 :
144 : using ConfigChangedSlotType = ::etl::delegate<void(uint8_t, NetworkInterfaceConfig const&)>;
145 :
146 : inline bool updateConfig(NetworkInterfaceConfig& config, NetworkInterfaceConfig const& newConfig)
147 : {
148 : auto const change = config != newConfig;
149 : config = newConfig;
150 : return change;
151 : }
152 :
153 : /**
154 : * Interface for updating and retrieving IP address configurations of network interfaces.
155 : *
156 : * IP addresses are typically assigned dynamically to network interfaces. Therefore components
157 : * need to get notified about changes of assigned network addresses. This can be done by
158 : * registering as a listener to config changes.
159 : */
160 : class NetworkInterfaceConfigRegistry
161 : {
162 : public:
163 : virtual NetworkInterfaceConfig getConfig(uint8_t busId) const = 0;
164 : virtual bool connect(ConfigChangedSlotType const& slot) = 0;
165 : virtual void disconnect(ConfigChangedSlotType const& slot) = 0;
166 :
167 : protected:
168 20 : NetworkInterfaceConfigRegistry() = default;
169 : ~NetworkInterfaceConfigRegistry() = default;
170 : NetworkInterfaceConfigRegistry(NetworkInterfaceConfigRegistry const&) = default;
171 : NetworkInterfaceConfigRegistry& operator=(NetworkInterfaceConfigRegistry const&) = default;
172 : };
173 :
174 : namespace declare
175 : {
176 : /**
177 : * Concrete NetworkInterfaceConfigRegistry that owns an etl::signal sized for a given
178 : * number of listener slots.
179 : */
180 : template<size_t SlotCapacity, typename Table, typename BusIdColumn = uint8_t>
181 : class NetworkInterfaceConfigRegistry : public ::ip::NetworkInterfaceConfigRegistry
182 : {
183 : public:
184 : using ConfigChangedSignal
185 : = ::etl::signal<void(uint8_t, NetworkInterfaceConfig const&), SlotCapacity>;
186 :
187 : NetworkInterfaceConfigRegistry() = default;
188 :
189 : explicit NetworkInterfaceConfigRegistry(Table& table) : _table(&table) {}
190 :
191 : NetworkInterfaceConfigRegistry(NetworkInterfaceConfigRegistry const&) = default;
192 : NetworkInterfaceConfigRegistry& operator=(NetworkInterfaceConfigRegistry const&) = default;
193 :
194 : Table* _table = nullptr;
195 :
196 : ConfigChangedSignal configChangedSignal;
197 :
198 : NetworkInterfaceConfig getConfig(uint8_t const busId) const override
199 : {
200 : ETL_ASSERT(
201 : _table != nullptr, ETL_ERROR_GENERIC("NetworkInterfaceConfigRegistry not initialised"));
202 :
203 : auto const busIds = ::shed::get<BusIdColumn>(*_table).data();
204 : auto const configs = ::shed::get<NetworkInterfaceConfig>(*_table).data();
205 : for (size_t i = 0; i < busIds.size(); ++i)
206 : {
207 : if (static_cast<uint8_t>(busIds[i]) == busId)
208 : {
209 : return configs[i];
210 : }
211 : }
212 : return {};
213 : }
214 :
215 : bool connect(ConfigChangedSlotType const& slot) override
216 : {
217 : return configChangedSignal.connect(slot);
218 : }
219 :
220 : void disconnect(ConfigChangedSlotType const& slot) override
221 : {
222 : configChangedSignal.disconnect(slot);
223 : }
224 : };
225 : } // namespace declare
226 : } // namespace ip
|