blob: cea83223f98e50af6d28704582fd3ca10ae0b96e [file] [log] [blame]
Thomas Vachuska8fd25052015-09-10 16:15:33 -07001/*
2 * Copyright 2015 Open Networking Laboratory
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 */
sangho80f11cb2015-04-01 13:05:26 -070016package org.onosproject.segmentrouting;
17
sangho27462c62015-05-14 00:39:53 -070018import com.google.common.collect.Lists;
sangho80f11cb2015-04-01 13:05:26 -070019import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070020import org.onlab.packet.Ip4Prefix;
21import org.onlab.packet.IpPrefix;
sangho80f11cb2015-04-01 13:05:26 -070022import org.onlab.packet.MacAddress;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070023import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
sangho80f11cb2015-04-01 13:05:26 -070024import org.onosproject.net.DeviceId;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070025import org.onosproject.net.PortNumber;
26import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig;
27import org.onosproject.segmentrouting.config.NetworkConfigManager;
28import org.onosproject.segmentrouting.config.SegmentRouterConfig;
29import org.onosproject.segmentrouting.config.SegmentRouterConfig.Subnet;
sangho80f11cb2015-04-01 13:05:26 -070030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070033import static com.google.common.base.Preconditions.checkNotNull;
34
35import java.util.ArrayList;
sangho80f11cb2015-04-01 13:05:26 -070036import java.util.HashMap;
37import java.util.List;
38import java.util.Map;
39
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070040/**
41 * Segment Routing configuration component that reads the
42 * segment routing related configuration from Network Configuration Manager
43 * component and organizes in more accessible formats.
44 *
45 * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
46 */
sangho80f11cb2015-04-01 13:05:26 -070047public class DeviceConfiguration implements DeviceProperties {
48
49 private static final Logger log = LoggerFactory
50 .getLogger(DeviceConfiguration.class);
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -070051 private final List<Integer> allSegmentIds = new ArrayList<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070052 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
53 private final NetworkConfigManager configService;
sangho80f11cb2015-04-01 13:05:26 -070054
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070055 private class SegmentRouterInfo {
56 int nodeSid;
57 DeviceId deviceId;
58 Ip4Address ip;
59 MacAddress mac;
60 boolean isEdge;
61 HashMap<PortNumber, Ip4Address> gatewayIps;
62 HashMap<PortNumber, Ip4Prefix> subnets;
sangho27462c62015-05-14 00:39:53 -070063 List<SegmentRouterConfig.AdjacencySid> adjacencySids;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070064 }
sangho80f11cb2015-04-01 13:05:26 -070065
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070066 /**
67 * Constructor. Reads all the configuration for all devices of type
68 * Segment Router and organizes into various maps for easier access.
69 *
70 * @param configService handle to network configuration manager
71 * component from where the relevant configuration is retrieved.
72 */
73 public DeviceConfiguration(NetworkConfigManager configService) {
74 this.configService = checkNotNull(configService);
75 List<SwitchConfig> allSwitchCfg =
76 this.configService.getConfiguredAllowedSwitches();
77 for (SwitchConfig cfg : allSwitchCfg) {
78 if (!(cfg instanceof SegmentRouterConfig)) {
79 continue;
80 }
81 SegmentRouterInfo info = new SegmentRouterInfo();
82 info.nodeSid = ((SegmentRouterConfig) cfg).getNodeSid();
Sho SHIMIZU0f732b02015-09-29 14:32:49 -070083 info.deviceId = cfg.getDpid();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070084 info.mac = MacAddress.valueOf(((
85 SegmentRouterConfig) cfg).getRouterMac());
86 String routerIp = ((SegmentRouterConfig) cfg).getRouterIp();
87 Ip4Prefix prefix = checkNotNull(IpPrefix.valueOf(routerIp).getIp4Prefix());
88 info.ip = prefix.address();
89 info.isEdge = ((SegmentRouterConfig) cfg).isEdgeRouter();
90 info.subnets = new HashMap<>();
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -070091 info.gatewayIps = new HashMap<>();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070092 for (Subnet s: ((SegmentRouterConfig) cfg).getSubnets()) {
93 info.subnets.put(PortNumber.portNumber(s.getPortNo()),
94 Ip4Prefix.valueOf(s.getSubnetIp()));
95 String gatewayIp = s.getSubnetIp().
96 substring(0, s.getSubnetIp().indexOf('/'));
97 info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()),
98 Ip4Address.valueOf(gatewayIp));
99 }
sangho27462c62015-05-14 00:39:53 -0700100 info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700101 this.deviceConfigMap.put(info.deviceId, info);
102 this.allSegmentIds.add(info.nodeSid);
sangho27462c62015-05-14 00:39:53 -0700103
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700104 }
105 }
106
107 /**
108 * Returns the segment id of a segment router.
109 *
110 * @param deviceId device identifier
111 * @return segment id
112 */
sangho80f11cb2015-04-01 13:05:26 -0700113 @Override
114 public int getSegmentId(DeviceId deviceId) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700115 if (deviceConfigMap.get(deviceId) != null) {
sangho80f11cb2015-04-01 13:05:26 -0700116 log.debug("getSegmentId for device{} is {}",
117 deviceId,
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700118 deviceConfigMap.get(deviceId).nodeSid);
119 return deviceConfigMap.get(deviceId).nodeSid;
sangho80f11cb2015-04-01 13:05:26 -0700120 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700121 log.warn("getSegmentId for device {} "
122 + "throwing IllegalStateException "
123 + "because device does not exist in config", deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700124 throw new IllegalStateException();
125 }
126 }
127
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700128 /**
129 * Returns the segment id of a segment router given its mac address.
130 *
131 * @param routerMac router mac address
132 * @return segment id
133 */
134 public int getSegmentId(MacAddress routerMac) {
135 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
136 deviceConfigMap.entrySet()) {
137 if (entry.getValue().mac.equals(routerMac)) {
138 return entry.getValue().nodeSid;
139 }
140 }
sangho80f11cb2015-04-01 13:05:26 -0700141
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700142 return -1;
143 }
144
145 /**
146 * Returns the segment id of a segment router given its router ip address.
147 *
148 * @param routerAddress router ip address
149 * @return segment id
150 */
151 public int getSegmentId(Ip4Address routerAddress) {
152 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
153 deviceConfigMap.entrySet()) {
154 if (entry.getValue().ip.equals(routerAddress)) {
155 return entry.getValue().nodeSid;
156 }
157 }
158
159 return -1;
160 }
161
162 /**
163 * Returns the router mac of a segment router.
164 *
165 * @param deviceId device identifier
166 * @return router mac address
167 */
sangho80f11cb2015-04-01 13:05:26 -0700168 @Override
169 public MacAddress getDeviceMac(DeviceId deviceId) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700170 if (deviceConfigMap.get(deviceId) != null) {
sangho80f11cb2015-04-01 13:05:26 -0700171 log.debug("getDeviceMac for device{} is {}",
172 deviceId,
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700173 deviceConfigMap.get(deviceId).mac);
174 return deviceConfigMap.get(deviceId).mac;
sangho80f11cb2015-04-01 13:05:26 -0700175 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700176 log.warn("getDeviceMac for device {} "
177 + "throwing IllegalStateException "
178 + "because device does not exist in config", deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700179 throw new IllegalStateException();
180 }
181 }
182
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700183 /**
184 * Returns the router ip address of a segment router.
185 *
186 * @param deviceId device identifier
187 * @return router ip address
188 */
189 public Ip4Address getRouterIp(DeviceId deviceId) {
190 if (deviceConfigMap.get(deviceId) != null) {
191 log.debug("getDeviceIp for device{} is {}",
192 deviceId,
193 deviceConfigMap.get(deviceId).ip);
194 return deviceConfigMap.get(deviceId).ip;
195 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700196 log.warn("getRouterIp for device {} "
197 + "throwing IllegalStateException "
198 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700199 throw new IllegalStateException();
sangho80f11cb2015-04-01 13:05:26 -0700200 }
sangho80f11cb2015-04-01 13:05:26 -0700201 }
202
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700203 /**
204 * Indicates if the segment router is a edge router or
205 * a transit/back bone router.
206 *
207 * @param deviceId device identifier
208 * @return boolean
209 */
210 @Override
211 public boolean isEdgeDevice(DeviceId deviceId) {
212 if (deviceConfigMap.get(deviceId) != null) {
213 log.debug("isEdgeDevice for device{} is {}",
214 deviceId,
215 deviceConfigMap.get(deviceId).isEdge);
216 return deviceConfigMap.get(deviceId).isEdge;
217 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700218 log.warn("isEdgeDevice for device {} "
219 + "throwing IllegalStateException "
220 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700221 throw new IllegalStateException();
222 }
223 }
224
225 /**
226 * Returns the segment ids of all configured segment routers.
227 *
228 * @return list of segment ids
229 */
sangho80f11cb2015-04-01 13:05:26 -0700230 @Override
231 public List<Integer> getAllDeviceSegmentIds() {
232 return allSegmentIds;
233 }
234
sangho80f11cb2015-04-01 13:05:26 -0700235 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700236 * Returns the device identifier or data plane identifier (dpid)
237 * of a segment router given its segment id.
sangho80f11cb2015-04-01 13:05:26 -0700238 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700239 * @param sid segment id
240 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700241 */
242 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700243 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
244 deviceConfigMap.entrySet()) {
245 if (entry.getValue().nodeSid == sid) {
246 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700247 }
248 }
249
250 return null;
251 }
252
253 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700254 * Returns the device identifier or data plane identifier (dpid)
255 * of a segment router given its router ip address.
sangho80f11cb2015-04-01 13:05:26 -0700256 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700257 * @param ipAddress router ip address
258 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700259 */
260 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700261 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
262 deviceConfigMap.entrySet()) {
263 if (entry.getValue().ip.equals(ipAddress)) {
264 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700265 }
266 }
267
268 return null;
269 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700270
271 /**
272 * Returns the configured subnet gateway ip addresses for a segment router.
273 *
274 * @param deviceId device identifier
275 * @return list of ip addresses
276 */
277 public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
278 if (deviceConfigMap.get(deviceId) != null) {
279 log.debug("getSubnetGatewayIps for device{} is {}",
280 deviceId,
281 deviceConfigMap.get(deviceId).gatewayIps.values());
Sho SHIMIZU03375032015-09-11 14:22:25 -0700282 return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700283 } else {
284 return null;
285 }
286 }
287
288 /**
289 * Returns the configured subnet prefixes for a segment router.
290 *
291 * @param deviceId device identifier
292 * @return list of ip prefixes
293 */
294 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
295 if (deviceConfigMap.get(deviceId) != null) {
296 log.debug("getSubnets for device{} is {}",
297 deviceId,
298 deviceConfigMap.get(deviceId).subnets.values());
Sho SHIMIZU03375032015-09-11 14:22:25 -0700299 return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700300 } else {
301 return null;
302 }
303 }
304
305 /**
306 * Returns the router ip address of segment router that has the
307 * specified ip address in its subnets.
308 *
309 * @param destIpAddress target ip address
310 * @return router ip address
311 */
312 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
313 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
314 deviceConfigMap.entrySet()) {
315 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
316 if (prefix.contains(destIpAddress)) {
317 return entry.getValue().ip;
318 }
319 }
320 }
321
322 log.debug("No router was found for {}", destIpAddress);
323 return null;
324 }
325
326 /**
327 * Returns the router mac address of segment router that has the
328 * specified ip address as one of its subnet gateway ip address.
329 *
330 * @param gatewayIpAddress router gateway ip address
331 * @return router mac address
332 */
333 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
334 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
335 deviceConfigMap.entrySet()) {
336 if (entry.getValue().gatewayIps.
337 values().contains(gatewayIpAddress)) {
338 return entry.getValue().mac;
339 }
340 }
341
342 log.debug("Cannot find a router for {}", gatewayIpAddress);
343 return null;
344 }
sangho9b169e32015-04-14 16:27:13 -0700345
346
347 /**
348 * Checks if the host is in the subnet defined in the router with the
349 * device ID given.
350 *
351 * @param deviceId device identification of the router
352 * @param hostIp host IP address to check
353 * @return true if the host is within the subnet of the router,
354 * false if no subnet is defined under the router or if the host is not
355 * within the subnet defined in the router
356 */
357 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
358
359 List<Ip4Prefix> subnets = getSubnets(deviceId);
360 if (subnets == null) {
361 return false;
362 }
363
364 for (Ip4Prefix subnet: subnets) {
365 if (subnet.contains(hostIp)) {
366 return true;
367 }
368 }
369
370 return false;
371 }
sangho27462c62015-05-14 00:39:53 -0700372
373 /**
374 * Returns the ports corresponding to the adjacency Sid given.
375 *
376 * @param deviceId device identification of the router
377 * @param sid adjacency Sid
378 * @return list of port numbers
379 */
380 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
381 if (deviceConfigMap.get(deviceId) != null) {
382 for (SegmentRouterConfig.AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
383 if (asid.getAdjSid() == sid) {
384 return asid.getPorts();
385 }
386 }
387 }
388
389 return Lists.newArrayList();
390 }
391
392 /**
393 * Check if the Sid given is whether adjacency Sid of the router device or not.
394 *
395 * @param deviceId device identification of the router
396 * @param sid Sid to check
397 * @return true if the Sid given is the adjacency Sid of the device,
398 * otherwise false
399 */
400 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
401 if (deviceConfigMap.get(deviceId) != null) {
402 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
403 return false;
404 } else {
405 for (SegmentRouterConfig.AdjacencySid asid:
406 deviceConfigMap.get(deviceId).adjacencySids) {
407 if (asid.getAdjSid() == sid) {
408 return true;
409 }
410 }
411 return false;
412 }
413 }
414
415 return false;
416 }
sangho80f11cb2015-04-01 13:05:26 -0700417}