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 : struct NetworkInterfaceConfigRegistry
159 : {
160 21 : NetworkInterfaceConfigRegistry(
161 : ::etl::span<uint8_t const> busIds, ::etl::span<NetworkInterfaceConfig const> configs)
162 21 : : busIds(busIds), configs(configs)
163 21 : {}
164 :
165 21 : virtual ~NetworkInterfaceConfigRegistry() = default;
166 :
167 : ::etl::span<uint8_t const> busIds;
168 : ::etl::span<NetworkInterfaceConfig const> configs;
169 :
170 0 : virtual NetworkInterfaceConfig getConfig(uint8_t const busId) const
171 : {
172 0 : for (size_t i = 0; i < busIds.size(); ++i)
173 : {
174 0 : if (busIds[i] == busId)
175 : {
176 0 : return configs[i];
177 : }
178 : }
179 0 : return {};
180 : }
181 :
182 : virtual bool connect(ConfigChangedSlotType const& slot) = 0;
183 : virtual void disconnect(ConfigChangedSlotType const& slot) = 0;
184 : };
185 :
186 : namespace declare
187 : {
188 : /**
189 : * Concrete NetworkInterfaceConfigRegistry that owns an etl::signal sized for a given
190 : * number of listener slots.
191 : */
192 : template<size_t SlotCapacity>
193 : struct NetworkInterfaceConfigRegistry : public ::ip::NetworkInterfaceConfigRegistry
194 : {
195 : using ConfigChangedSignal
196 : = ::etl::signal<void(uint8_t, NetworkInterfaceConfig const&), SlotCapacity>;
197 :
198 21 : NetworkInterfaceConfigRegistry(
199 : ::etl::span<uint8_t const> busIds, ::etl::span<NetworkInterfaceConfig const> configs)
200 21 : : ::ip::NetworkInterfaceConfigRegistry(busIds, configs)
201 21 : {}
202 :
203 : ConfigChangedSignal configChangedSignal;
204 :
205 20 : bool connect(ConfigChangedSlotType const& slot) override
206 : {
207 20 : return configChangedSignal.connect(slot);
208 : }
209 :
210 20 : void disconnect(ConfigChangedSlotType const& slot) override
211 : {
212 20 : configChangedSignal.disconnect(slot);
213 20 : }
214 : };
215 : } // namespace declare
216 : } // namespace ip
|