blob: d60c6b0f3031f5fb069ef51e5d7d1566d1aadda1 [file] [log] [blame]
Yi Tseng483ac6f2017-08-02 15:03:31 -07001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.onosproject.dhcprelay.config;
19
20import com.fasterxml.jackson.databind.JsonNode;
21import com.fasterxml.jackson.databind.node.ArrayNode;
Yi Tseng919b2df2017-09-07 16:22:51 -070022import com.google.common.base.Objects;
Yi Tseng25bfe372017-11-03 16:27:32 -070023import com.google.common.collect.Maps;
24import org.apache.commons.lang3.tuple.Pair;
Yi Tseng483ac6f2017-08-02 15:03:31 -070025import org.onlab.packet.Ip4Address;
26import org.onlab.packet.Ip6Address;
27import org.onlab.packet.IpAddress;
28import org.onosproject.net.ConnectPoint;
Yi Tseng25bfe372017-11-03 16:27:32 -070029import org.onosproject.net.DeviceId;
Charles Chan29d95982018-03-27 18:50:59 -070030import org.slf4j.Logger;
Yi Tseng483ac6f2017-08-02 15:03:31 -070031
Yi Tseng25bfe372017-11-03 16:27:32 -070032import java.util.Map;
Yi Tseng483ac6f2017-08-02 15:03:31 -070033import java.util.Optional;
34
Yi Tseng525ff402017-10-23 19:39:39 -070035import static com.google.common.base.Preconditions.checkNotNull;
36import static com.google.common.base.Preconditions.checkState;
Charles Chan29d95982018-03-27 18:50:59 -070037import static org.slf4j.LoggerFactory.getLogger;
Yi Tseng525ff402017-10-23 19:39:39 -070038
Yi Tseng483ac6f2017-08-02 15:03:31 -070039/**
40 * DHCP server configuration.
41 */
42public class DhcpServerConfig {
Charles Chan29d95982018-03-27 18:50:59 -070043 private final Logger log = getLogger(getClass());
44
Yi Tseng483ac6f2017-08-02 15:03:31 -070045 private static final String DHCP_CONNECT_POINT = "dhcpServerConnectPoint";
46 private static final String DHCP_SERVER_IP = "serverIps";
47 private static final String DHCP_GATEWAY_IP = "gatewayIps";
Yi Tseng3df7f9d2017-08-17 13:08:31 -070048 private static final String RELAY_AGENT_IP = "relayAgentIps";
Yi Tseng25bfe372017-11-03 16:27:32 -070049 private static final String IPV4 = "ipv4";
50 private static final String IPV6 = "ipv6";
Yi Tseng483ac6f2017-08-02 15:03:31 -070051
Yi Tseng919b2df2017-09-07 16:22:51 -070052 protected ConnectPoint connectPoint;
53 protected Ip4Address serverIp4Addr;
54 protected Ip4Address gatewayIp4Addr;
Yi Tseng919b2df2017-09-07 16:22:51 -070055 protected Ip6Address serverIp6Addr;
56 protected Ip6Address gatewayIp6Addr;
Yi Tseng25bfe372017-11-03 16:27:32 -070057 protected Map<DeviceId, Pair<Ip4Address, Ip6Address>> relayAgentIps = Maps.newHashMap();
Yi Tseng483ac6f2017-08-02 15:03:31 -070058
59 protected DhcpServerConfig() {
60 // empty config not allowed here
61 }
62
63 public DhcpServerConfig(JsonNode config) {
64 if (!config.has(DHCP_CONNECT_POINT)) {
65 // connect point doesn't exist
66 throw new IllegalArgumentException("Missing " + DHCP_CONNECT_POINT);
67 }
68 connectPoint = ConnectPoint.deviceConnectPoint(config.path(DHCP_CONNECT_POINT).asText());
69
70 if (!config.has(DHCP_SERVER_IP)) {
71 // server ip doesn't exist
72 throw new IllegalArgumentException("Missing " + DHCP_SERVER_IP);
73 }
74 ArrayNode serverIps = (ArrayNode) config.path(DHCP_SERVER_IP);
75 serverIps.forEach(node -> {
76 if (node.isTextual()) {
77 IpAddress ip = IpAddress.valueOf(node.asText());
78 if (ip.isIp4() && serverIp4Addr == null) {
rsahot0365bd059e2018-06-22 14:35:07 -040079 try {
80 serverIp4Addr = ip.getIp4Address();
81 } catch (IllegalArgumentException iae) {
82 log.warn("Invalid IPv4 address {} found in DHCP server config. Ignored.", ip.toString());
83 }
Yi Tseng483ac6f2017-08-02 15:03:31 -070084 }
85 if (ip.isIp6() && serverIp6Addr == null) {
rsahot0365bd059e2018-06-22 14:35:07 -040086 try {
Yi Tseng483ac6f2017-08-02 15:03:31 -070087 serverIp6Addr = ip.getIp6Address();
rsahot0365bd059e2018-06-22 14:35:07 -040088 } catch (IllegalArgumentException iae) {
89 log.warn("Invalid IPv6 address {} found in DHCP server config. Ignored.", ip.toString());
90 }
Yi Tseng483ac6f2017-08-02 15:03:31 -070091 }
92 }
93 });
94
Yi Tseng3df7f9d2017-08-17 13:08:31 -070095 if (config.has(DHCP_GATEWAY_IP)) {
96 ArrayNode gatewayIps = (ArrayNode) config.path(DHCP_GATEWAY_IP);
97 gatewayIps.forEach(node -> {
98 if (node.isTextual()) {
99 IpAddress ip = IpAddress.valueOf(node.asText());
100 if (ip.isIp4() && gatewayIp4Addr == null) {
rsahot0365bd059e2018-06-22 14:35:07 -0400101 try {
102 gatewayIp4Addr = ip.getIp4Address();
103 } catch (IllegalArgumentException iae) {
104 log.warn("Invalid IPv4 address {} found in DHCP gateway config. Ignored.", ip.toString());
105 }
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700106 }
107 if (ip.isIp6() && gatewayIp6Addr == null) {
rsahot0365bd059e2018-06-22 14:35:07 -0400108 try {
109 gatewayIp6Addr = ip.getIp6Address();
110 } catch (IllegalArgumentException iae) {
111 log.warn("Invalid IPv6 address {} found in DHCP gateway config. Ignored.", ip.toString());
112 }
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700113 }
114 }
115 });
Yi Tseng483ac6f2017-08-02 15:03:31 -0700116 }
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700117 if (config.has(RELAY_AGENT_IP)) {
Yi Tseng25bfe372017-11-03 16:27:32 -0700118 JsonNode relayAgentIpsNode = config.path(RELAY_AGENT_IP);
119 relayAgentIpsNode.fields().forEachRemaining(e -> {
120 DeviceId deviceId = DeviceId.deviceId(e.getKey());
121 JsonNode ips = e.getValue();
122 Ip4Address ipv4 = null;
123 Ip6Address ipv6 = null;
124 if (ips.has(IPV4)) {
Charles Chan29d95982018-03-27 18:50:59 -0700125 String ipv4Str = ips.get(IPV4).asText();
126 try {
127 ipv4 = Ip4Address.valueOf(ipv4Str);
128 } catch (IllegalArgumentException iae) {
129 log.warn("Invalid IPv4 address {} found in DHCP relay config. Ignored.", ipv4Str);
130 }
Yi Tseng483ac6f2017-08-02 15:03:31 -0700131 }
Yi Tseng25bfe372017-11-03 16:27:32 -0700132 if (ips.has(IPV6)) {
Charles Chan29d95982018-03-27 18:50:59 -0700133 String ipv6Str = ips.get(IPV6).asText();
134 try {
135 ipv6 = Ip6Address.valueOf(ipv6Str);
136 } catch (IllegalArgumentException iae) {
137 log.warn("Invalid IPv6 address {} found in DHCP relay config. Ignored.", ipv6Str);
138 }
Yi Tseng25bfe372017-11-03 16:27:32 -0700139 }
140 relayAgentIps.put(deviceId, Pair.of(ipv4, ipv6));
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700141 });
142 }
Yi Tseng525ff402017-10-23 19:39:39 -0700143
144 checkNotNull(connectPoint, "Connect point of DHCP server can't be null");
145 checkState(serverIp4Addr != null || serverIp6Addr != null,
146 "Should exist at least one server IP for DHCPv4 or DHCPv6");
147
Yi Tseng483ac6f2017-08-02 15:03:31 -0700148 }
149
150 /**
151 * Verify a json config is a valid DHCP server config.
152 *
153 * @param jsonConfig the json config
154 * @return true if valid; false otherwise
155 */
156 public static boolean isValid(JsonNode jsonConfig) {
157 return jsonConfig.has(DHCP_CONNECT_POINT) && jsonConfig.has(DHCP_SERVER_IP);
158 }
159
160 /**
161 * Returns the dhcp server connect point.
162 *
163 * @return dhcp server connect point
164 */
165 public Optional<ConnectPoint> getDhcpServerConnectPoint() {
166 return Optional.ofNullable(connectPoint);
167 }
168
169 /**
170 * Returns the IPv4 address of DHCP server.
171 *
172 * @return IPv4 address of server; empty value if not set
173 */
174 public Optional<Ip4Address> getDhcpServerIp4() {
175 return Optional.ofNullable(serverIp4Addr);
176 }
177
178 /**
179 * Returns the optional IPv4 address of dhcp gateway, if configured.
180 * This option is typically used if the dhcp server is not directly attached
181 * to a switch; For example, the dhcp server may be reached via an external
182 * gateway connected to the dhcpserverConnectPoint.
183 *
184 * @return IPv4 address of gateway; empty value if not set
185 */
186 public Optional<Ip4Address> getDhcpGatewayIp4() {
187 return Optional.ofNullable(gatewayIp4Addr);
188 }
189
190 /**
191 * Returns the IPv6 address of DHCP server.
192 *
193 * @return IPv6 address of server ; empty value if not set
194 */
195 public Optional<Ip6Address> getDhcpServerIp6() {
196 return Optional.ofNullable(serverIp6Addr);
197 }
198
199 /**
200 * Returns the optional IPv6 address of dhcp gateway, if configured.
201 * This option is typically used if the dhcp server is not directly attached
202 * to a switch; For example, the dhcp server may be reached via an external
203 * gateway connected to the dhcpserverConnectPoint.
204 *
205 * @return IPv6 address of gateway; empty value if not set
206 */
207 public Optional<Ip6Address> getDhcpGatewayIp6() {
208 return Optional.ofNullable(gatewayIp6Addr);
209 }
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700210
211 /**
Yi Tseng25bfe372017-11-03 16:27:32 -0700212 * Returns the optional IPv4 address for relay agent for given device,
213 * if configured.
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700214 * This option is used if we want to replace the giaddr field in DHCPv4
215 * payload.
216 *
Yi Tseng25bfe372017-11-03 16:27:32 -0700217 * @param deviceId the device
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700218 * @return the giaddr; empty value if not set
219 */
Yi Tseng25bfe372017-11-03 16:27:32 -0700220 public Optional<Ip4Address> getRelayAgentIp4(DeviceId deviceId) {
221 Pair<Ip4Address, Ip6Address> relayAgentIp = relayAgentIps.get(deviceId);
222 if (relayAgentIp == null) {
223 return Optional.empty();
224 }
225 return Optional.ofNullable(relayAgentIp.getLeft());
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700226 }
227
228 /**
Yi Tseng25bfe372017-11-03 16:27:32 -0700229 * Returns the optional IPv6 address for relay agent for given device,
230 * if configured.
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700231 * This option is used if we want to replace the link-address field in DHCPv6
232 * payload.
233 *
Yi Tseng25bfe372017-11-03 16:27:32 -0700234 * @param deviceId the device
235 * @return the link-addr; empty value if not set
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700236 */
Yi Tseng25bfe372017-11-03 16:27:32 -0700237 public Optional<Ip6Address> getRelayAgentIp6(DeviceId deviceId) {
238 Pair<Ip4Address, Ip6Address> relayAgentIp = relayAgentIps.get(deviceId);
239 if (relayAgentIp == null) {
240 return Optional.empty();
241 }
242 return Optional.ofNullable(relayAgentIp.getRight());
243 }
244
245 /**
246 * Gets all relay agent ips and device mapping.
247 *
248 * @return the mapping
249 */
250 public Map<DeviceId, Pair<Ip4Address, Ip6Address>> getRelayAgentIps() {
251 return relayAgentIps;
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700252 }
Yi Tseng919b2df2017-09-07 16:22:51 -0700253
254 @Override
255 public boolean equals(Object o) {
256 if (this == o) {
257 return true;
258 }
259 if (o == null || getClass() != o.getClass()) {
260 return false;
261 }
262 DhcpServerConfig that = (DhcpServerConfig) o;
263 return Objects.equal(connectPoint, that.connectPoint) &&
264 Objects.equal(serverIp4Addr, that.serverIp4Addr) &&
265 Objects.equal(gatewayIp4Addr, that.gatewayIp4Addr) &&
Yi Tseng919b2df2017-09-07 16:22:51 -0700266 Objects.equal(serverIp6Addr, that.serverIp6Addr) &&
267 Objects.equal(gatewayIp6Addr, that.gatewayIp6Addr) &&
Yi Tseng25bfe372017-11-03 16:27:32 -0700268 Objects.equal(relayAgentIps, that.relayAgentIps);
Yi Tseng919b2df2017-09-07 16:22:51 -0700269 }
270
271 @Override
272 public int hashCode() {
273 return Objects.hashCode(connectPoint, serverIp4Addr, gatewayIp4Addr,
Yi Tseng25bfe372017-11-03 16:27:32 -0700274 serverIp6Addr, gatewayIp6Addr, relayAgentIps);
Yi Tseng919b2df2017-09-07 16:22:51 -0700275 }
Yi Tseng483ac6f2017-08-02 15:03:31 -0700276}