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