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