blob: e18ebfa8c84ac95ee7aacb99540bbe4125708854 [file] [log] [blame]
Thomas Vachuska58de4162015-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 */
sanghob35a6192015-04-01 13:05:26 -070016package org.onosproject.segmentrouting;
17
sangho1e575652015-05-14 00:39:53 -070018import com.google.common.collect.Lists;
sanghob35a6192015-04-01 13:05:26 -070019import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070020import org.onlab.packet.Ip4Prefix;
21import org.onlab.packet.IpPrefix;
sanghob35a6192015-04-01 13:05:26 -070022import org.onlab.packet.MacAddress;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070023import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
sanghob35a6192015-04-01 13:05:26 -070024import org.onosproject.net.DeviceId;
Srikanth Vavilapalli4db76e32015-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;
sanghob35a6192015-04-01 13:05:26 -070030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070033import static com.google.common.base.Preconditions.checkNotNull;
34
35import java.util.ArrayList;
sanghob35a6192015-04-01 13:05:26 -070036import java.util.HashMap;
37import java.util.List;
38import java.util.Map;
39
Srikanth Vavilapalli4db76e32015-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 */
sanghob35a6192015-04-01 13:05:26 -070047public class DeviceConfiguration implements DeviceProperties {
48
49 private static final Logger log = LoggerFactory
50 .getLogger(DeviceConfiguration.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070051 private final List<Integer> allSegmentIds = new ArrayList<Integer>();
52 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
53 private final NetworkConfigManager configService;
sanghob35a6192015-04-01 13:05:26 -070054
Srikanth Vavilapalli4db76e32015-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;
sangho1e575652015-05-14 00:39:53 -070063 List<SegmentRouterConfig.AdjacencySid> adjacencySids;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070064 }
sanghob35a6192015-04-01 13:05:26 -070065
Srikanth Vavilapalli4db76e32015-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();
83 info.deviceId = ((SegmentRouterConfig) cfg).getDpid();
84 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<>();
91 info.gatewayIps = new HashMap<PortNumber, Ip4Address>();
92 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 }
sangho1e575652015-05-14 00:39:53 -0700100 info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700101 this.deviceConfigMap.put(info.deviceId, info);
102 this.allSegmentIds.add(info.nodeSid);
sangho1e575652015-05-14 00:39:53 -0700103
Srikanth Vavilapalli4db76e32015-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 */
sanghob35a6192015-04-01 13:05:26 -0700113 @Override
114 public int getSegmentId(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700115 if (deviceConfigMap.get(deviceId) != null) {
sanghob35a6192015-04-01 13:05:26 -0700116 log.debug("getSegmentId for device{} is {}",
117 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700118 deviceConfigMap.get(deviceId).nodeSid);
119 return deviceConfigMap.get(deviceId).nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700120 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700121 log.warn("getSegmentId for device {} "
122 + "throwing IllegalStateException "
123 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700124 throw new IllegalStateException();
125 }
126 }
127
Srikanth Vavilapalli4db76e32015-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 }
sanghob35a6192015-04-01 13:05:26 -0700141
Srikanth Vavilapalli4db76e32015-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 */
sanghob35a6192015-04-01 13:05:26 -0700168 @Override
169 public MacAddress getDeviceMac(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700170 if (deviceConfigMap.get(deviceId) != null) {
sanghob35a6192015-04-01 13:05:26 -0700171 log.debug("getDeviceMac for device{} is {}",
172 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700173 deviceConfigMap.get(deviceId).mac);
174 return deviceConfigMap.get(deviceId).mac;
sanghob35a6192015-04-01 13:05:26 -0700175 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700176 log.warn("getDeviceMac for device {} "
177 + "throwing IllegalStateException "
178 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700179 throw new IllegalStateException();
180 }
181 }
182
Srikanth Vavilapalli4db76e32015-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 Vavilapalli23181912015-05-04 09:48:09 -0700196 log.warn("getRouterIp for device {} "
197 + "throwing IllegalStateException "
198 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700199 throw new IllegalStateException();
sanghob35a6192015-04-01 13:05:26 -0700200 }
sanghob35a6192015-04-01 13:05:26 -0700201 }
202
Srikanth Vavilapalli4db76e32015-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 Vavilapalli23181912015-05-04 09:48:09 -0700218 log.warn("isEdgeDevice for device {} "
219 + "throwing IllegalStateException "
220 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-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 */
sanghob35a6192015-04-01 13:05:26 -0700230 @Override
231 public List<Integer> getAllDeviceSegmentIds() {
232 return allSegmentIds;
233 }
234
sanghob35a6192015-04-01 13:05:26 -0700235 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700236 * Returns the device identifier or data plane identifier (dpid)
237 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700238 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700239 * @param sid segment id
240 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700241 */
242 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-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;
sanghob35a6192015-04-01 13:05:26 -0700247 }
248 }
249
250 return null;
251 }
252
253 /**
Srikanth Vavilapalli4db76e32015-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.
sanghob35a6192015-04-01 13:05:26 -0700256 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700257 * @param ipAddress router ip address
258 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700259 */
260 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-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;
sanghob35a6192015-04-01 13:05:26 -0700265 }
266 }
267
268 return null;
269 }
Srikanth Vavilapalli4db76e32015-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());
282 return new ArrayList<Ip4Address>(deviceConfigMap.
283 get(deviceId).gatewayIps.values());
284 } else {
285 return null;
286 }
287 }
288
289 /**
290 * Returns the configured subnet prefixes for a segment router.
291 *
292 * @param deviceId device identifier
293 * @return list of ip prefixes
294 */
295 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
296 if (deviceConfigMap.get(deviceId) != null) {
297 log.debug("getSubnets for device{} is {}",
298 deviceId,
299 deviceConfigMap.get(deviceId).subnets.values());
300 return new ArrayList<Ip4Prefix>(deviceConfigMap.
301 get(deviceId).subnets.values());
302 } else {
303 return null;
304 }
305 }
306
307 /**
308 * Returns the router ip address of segment router that has the
309 * specified ip address in its subnets.
310 *
311 * @param destIpAddress target ip address
312 * @return router ip address
313 */
314 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
315 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
316 deviceConfigMap.entrySet()) {
317 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
318 if (prefix.contains(destIpAddress)) {
319 return entry.getValue().ip;
320 }
321 }
322 }
323
324 log.debug("No router was found for {}", destIpAddress);
325 return null;
326 }
327
328 /**
329 * Returns the router mac address of segment router that has the
330 * specified ip address as one of its subnet gateway ip address.
331 *
332 * @param gatewayIpAddress router gateway ip address
333 * @return router mac address
334 */
335 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
336 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
337 deviceConfigMap.entrySet()) {
338 if (entry.getValue().gatewayIps.
339 values().contains(gatewayIpAddress)) {
340 return entry.getValue().mac;
341 }
342 }
343
344 log.debug("Cannot find a router for {}", gatewayIpAddress);
345 return null;
346 }
sangho666cd6d2015-04-14 16:27:13 -0700347
348
349 /**
350 * Checks if the host is in the subnet defined in the router with the
351 * device ID given.
352 *
353 * @param deviceId device identification of the router
354 * @param hostIp host IP address to check
355 * @return true if the host is within the subnet of the router,
356 * false if no subnet is defined under the router or if the host is not
357 * within the subnet defined in the router
358 */
359 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
360
361 List<Ip4Prefix> subnets = getSubnets(deviceId);
362 if (subnets == null) {
363 return false;
364 }
365
366 for (Ip4Prefix subnet: subnets) {
367 if (subnet.contains(hostIp)) {
368 return true;
369 }
370 }
371
372 return false;
373 }
sangho1e575652015-05-14 00:39:53 -0700374
375 /**
376 * Returns the ports corresponding to the adjacency Sid given.
377 *
378 * @param deviceId device identification of the router
379 * @param sid adjacency Sid
380 * @return list of port numbers
381 */
382 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
383 if (deviceConfigMap.get(deviceId) != null) {
384 for (SegmentRouterConfig.AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
385 if (asid.getAdjSid() == sid) {
386 return asid.getPorts();
387 }
388 }
389 }
390
391 return Lists.newArrayList();
392 }
393
394 /**
395 * Check if the Sid given is whether adjacency Sid of the router device or not.
396 *
397 * @param deviceId device identification of the router
398 * @param sid Sid to check
399 * @return true if the Sid given is the adjacency Sid of the device,
400 * otherwise false
401 */
402 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
403 if (deviceConfigMap.get(deviceId) != null) {
404 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
405 return false;
406 } else {
407 for (SegmentRouterConfig.AdjacencySid asid:
408 deviceConfigMap.get(deviceId).adjacencySids) {
409 if (asid.getAdjSid() == sid) {
410 return true;
411 }
412 }
413 return false;
414 }
415 }
416
417 return false;
418 }
sanghob35a6192015-04-01 13:05:26 -0700419}