blob: d82eb5eca3454c702a0bd9e5b515c88b90dcf7c7 [file] [log] [blame]
sangho80f11cb2015-04-01 13:05:26 -07001package org.onosproject.segmentrouting;
2
sangho27462c62015-05-14 00:39:53 -07003import com.google.common.collect.Lists;
sangho80f11cb2015-04-01 13:05:26 -07004import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -07005import org.onlab.packet.Ip4Prefix;
6import org.onlab.packet.IpPrefix;
sangho80f11cb2015-04-01 13:05:26 -07007import org.onlab.packet.MacAddress;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -07008import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
sangho80f11cb2015-04-01 13:05:26 -07009import org.onosproject.net.DeviceId;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070010import org.onosproject.net.PortNumber;
11import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig;
12import org.onosproject.segmentrouting.config.NetworkConfigManager;
13import org.onosproject.segmentrouting.config.SegmentRouterConfig;
14import org.onosproject.segmentrouting.config.SegmentRouterConfig.Subnet;
sangho80f11cb2015-04-01 13:05:26 -070015import org.slf4j.Logger;
16import org.slf4j.LoggerFactory;
17
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070018import static com.google.common.base.Preconditions.checkNotNull;
19
20import java.util.ArrayList;
sangho80f11cb2015-04-01 13:05:26 -070021import java.util.HashMap;
22import java.util.List;
23import java.util.Map;
24
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070025/**
26 * Segment Routing configuration component that reads the
27 * segment routing related configuration from Network Configuration Manager
28 * component and organizes in more accessible formats.
29 *
30 * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
31 */
sangho80f11cb2015-04-01 13:05:26 -070032public class DeviceConfiguration implements DeviceProperties {
33
34 private static final Logger log = LoggerFactory
35 .getLogger(DeviceConfiguration.class);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070036 private final List<Integer> allSegmentIds = new ArrayList<Integer>();
37 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
38 private final NetworkConfigManager configService;
sangho80f11cb2015-04-01 13:05:26 -070039
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070040 private class SegmentRouterInfo {
41 int nodeSid;
42 DeviceId deviceId;
43 Ip4Address ip;
44 MacAddress mac;
45 boolean isEdge;
46 HashMap<PortNumber, Ip4Address> gatewayIps;
47 HashMap<PortNumber, Ip4Prefix> subnets;
sangho27462c62015-05-14 00:39:53 -070048 List<SegmentRouterConfig.AdjacencySid> adjacencySids;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070049 }
sangho80f11cb2015-04-01 13:05:26 -070050
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070051 /**
52 * Constructor. Reads all the configuration for all devices of type
53 * Segment Router and organizes into various maps for easier access.
54 *
55 * @param configService handle to network configuration manager
56 * component from where the relevant configuration is retrieved.
57 */
58 public DeviceConfiguration(NetworkConfigManager configService) {
59 this.configService = checkNotNull(configService);
60 List<SwitchConfig> allSwitchCfg =
61 this.configService.getConfiguredAllowedSwitches();
62 for (SwitchConfig cfg : allSwitchCfg) {
63 if (!(cfg instanceof SegmentRouterConfig)) {
64 continue;
65 }
66 SegmentRouterInfo info = new SegmentRouterInfo();
67 info.nodeSid = ((SegmentRouterConfig) cfg).getNodeSid();
68 info.deviceId = ((SegmentRouterConfig) cfg).getDpid();
69 info.mac = MacAddress.valueOf(((
70 SegmentRouterConfig) cfg).getRouterMac());
71 String routerIp = ((SegmentRouterConfig) cfg).getRouterIp();
72 Ip4Prefix prefix = checkNotNull(IpPrefix.valueOf(routerIp).getIp4Prefix());
73 info.ip = prefix.address();
74 info.isEdge = ((SegmentRouterConfig) cfg).isEdgeRouter();
75 info.subnets = new HashMap<>();
76 info.gatewayIps = new HashMap<PortNumber, Ip4Address>();
77 for (Subnet s: ((SegmentRouterConfig) cfg).getSubnets()) {
78 info.subnets.put(PortNumber.portNumber(s.getPortNo()),
79 Ip4Prefix.valueOf(s.getSubnetIp()));
80 String gatewayIp = s.getSubnetIp().
81 substring(0, s.getSubnetIp().indexOf('/'));
82 info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()),
83 Ip4Address.valueOf(gatewayIp));
84 }
sangho27462c62015-05-14 00:39:53 -070085 info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070086 this.deviceConfigMap.put(info.deviceId, info);
87 this.allSegmentIds.add(info.nodeSid);
sangho27462c62015-05-14 00:39:53 -070088
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070089 }
90 }
91
92 /**
93 * Returns the segment id of a segment router.
94 *
95 * @param deviceId device identifier
96 * @return segment id
97 */
sangho80f11cb2015-04-01 13:05:26 -070098 @Override
99 public int getSegmentId(DeviceId deviceId) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700100 if (deviceConfigMap.get(deviceId) != null) {
sangho80f11cb2015-04-01 13:05:26 -0700101 log.debug("getSegmentId for device{} is {}",
102 deviceId,
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700103 deviceConfigMap.get(deviceId).nodeSid);
104 return deviceConfigMap.get(deviceId).nodeSid;
sangho80f11cb2015-04-01 13:05:26 -0700105 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700106 log.warn("getSegmentId for device {} "
107 + "throwing IllegalStateException "
108 + "because device does not exist in config", deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700109 throw new IllegalStateException();
110 }
111 }
112
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700113 /**
114 * Returns the segment id of a segment router given its mac address.
115 *
116 * @param routerMac router mac address
117 * @return segment id
118 */
119 public int getSegmentId(MacAddress routerMac) {
120 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
121 deviceConfigMap.entrySet()) {
122 if (entry.getValue().mac.equals(routerMac)) {
123 return entry.getValue().nodeSid;
124 }
125 }
sangho80f11cb2015-04-01 13:05:26 -0700126
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700127 return -1;
128 }
129
130 /**
131 * Returns the segment id of a segment router given its router ip address.
132 *
133 * @param routerAddress router ip address
134 * @return segment id
135 */
136 public int getSegmentId(Ip4Address routerAddress) {
137 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
138 deviceConfigMap.entrySet()) {
139 if (entry.getValue().ip.equals(routerAddress)) {
140 return entry.getValue().nodeSid;
141 }
142 }
143
144 return -1;
145 }
146
147 /**
148 * Returns the router mac of a segment router.
149 *
150 * @param deviceId device identifier
151 * @return router mac address
152 */
sangho80f11cb2015-04-01 13:05:26 -0700153 @Override
154 public MacAddress getDeviceMac(DeviceId deviceId) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700155 if (deviceConfigMap.get(deviceId) != null) {
sangho80f11cb2015-04-01 13:05:26 -0700156 log.debug("getDeviceMac for device{} is {}",
157 deviceId,
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700158 deviceConfigMap.get(deviceId).mac);
159 return deviceConfigMap.get(deviceId).mac;
sangho80f11cb2015-04-01 13:05:26 -0700160 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700161 log.warn("getDeviceMac for device {} "
162 + "throwing IllegalStateException "
163 + "because device does not exist in config", deviceId);
sangho80f11cb2015-04-01 13:05:26 -0700164 throw new IllegalStateException();
165 }
166 }
167
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700168 /**
169 * Returns the router ip address of a segment router.
170 *
171 * @param deviceId device identifier
172 * @return router ip address
173 */
174 public Ip4Address getRouterIp(DeviceId deviceId) {
175 if (deviceConfigMap.get(deviceId) != null) {
176 log.debug("getDeviceIp for device{} is {}",
177 deviceId,
178 deviceConfigMap.get(deviceId).ip);
179 return deviceConfigMap.get(deviceId).ip;
180 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700181 log.warn("getRouterIp for device {} "
182 + "throwing IllegalStateException "
183 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700184 throw new IllegalStateException();
sangho80f11cb2015-04-01 13:05:26 -0700185 }
sangho80f11cb2015-04-01 13:05:26 -0700186 }
187
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700188 /**
189 * Indicates if the segment router is a edge router or
190 * a transit/back bone router.
191 *
192 * @param deviceId device identifier
193 * @return boolean
194 */
195 @Override
196 public boolean isEdgeDevice(DeviceId deviceId) {
197 if (deviceConfigMap.get(deviceId) != null) {
198 log.debug("isEdgeDevice for device{} is {}",
199 deviceId,
200 deviceConfigMap.get(deviceId).isEdge);
201 return deviceConfigMap.get(deviceId).isEdge;
202 } else {
Srikanth Vavilapalli7cd16712015-05-04 09:48:09 -0700203 log.warn("isEdgeDevice for device {} "
204 + "throwing IllegalStateException "
205 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700206 throw new IllegalStateException();
207 }
208 }
209
210 /**
211 * Returns the segment ids of all configured segment routers.
212 *
213 * @return list of segment ids
214 */
sangho80f11cb2015-04-01 13:05:26 -0700215 @Override
216 public List<Integer> getAllDeviceSegmentIds() {
217 return allSegmentIds;
218 }
219
sangho80f11cb2015-04-01 13:05:26 -0700220 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700221 * Returns the device identifier or data plane identifier (dpid)
222 * of a segment router given its segment id.
sangho80f11cb2015-04-01 13:05:26 -0700223 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700224 * @param sid segment id
225 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700226 */
227 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700228 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
229 deviceConfigMap.entrySet()) {
230 if (entry.getValue().nodeSid == sid) {
231 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700232 }
233 }
234
235 return null;
236 }
237
238 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700239 * Returns the device identifier or data plane identifier (dpid)
240 * of a segment router given its router ip address.
sangho80f11cb2015-04-01 13:05:26 -0700241 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700242 * @param ipAddress router ip address
243 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700244 */
245 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700246 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
247 deviceConfigMap.entrySet()) {
248 if (entry.getValue().ip.equals(ipAddress)) {
249 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700250 }
251 }
252
253 return null;
254 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700255
256 /**
257 * Returns the configured subnet gateway ip addresses for a segment router.
258 *
259 * @param deviceId device identifier
260 * @return list of ip addresses
261 */
262 public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
263 if (deviceConfigMap.get(deviceId) != null) {
264 log.debug("getSubnetGatewayIps for device{} is {}",
265 deviceId,
266 deviceConfigMap.get(deviceId).gatewayIps.values());
267 return new ArrayList<Ip4Address>(deviceConfigMap.
268 get(deviceId).gatewayIps.values());
269 } else {
270 return null;
271 }
272 }
273
274 /**
275 * Returns the configured subnet prefixes for a segment router.
276 *
277 * @param deviceId device identifier
278 * @return list of ip prefixes
279 */
280 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
281 if (deviceConfigMap.get(deviceId) != null) {
282 log.debug("getSubnets for device{} is {}",
283 deviceId,
284 deviceConfigMap.get(deviceId).subnets.values());
285 return new ArrayList<Ip4Prefix>(deviceConfigMap.
286 get(deviceId).subnets.values());
287 } else {
288 return null;
289 }
290 }
291
292 /**
293 * Returns the router ip address of segment router that has the
294 * specified ip address in its subnets.
295 *
296 * @param destIpAddress target ip address
297 * @return router ip address
298 */
299 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
300 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
301 deviceConfigMap.entrySet()) {
302 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
303 if (prefix.contains(destIpAddress)) {
304 return entry.getValue().ip;
305 }
306 }
307 }
308
309 log.debug("No router was found for {}", destIpAddress);
310 return null;
311 }
312
313 /**
314 * Returns the router mac address of segment router that has the
315 * specified ip address as one of its subnet gateway ip address.
316 *
317 * @param gatewayIpAddress router gateway ip address
318 * @return router mac address
319 */
320 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
321 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
322 deviceConfigMap.entrySet()) {
323 if (entry.getValue().gatewayIps.
324 values().contains(gatewayIpAddress)) {
325 return entry.getValue().mac;
326 }
327 }
328
329 log.debug("Cannot find a router for {}", gatewayIpAddress);
330 return null;
331 }
sangho9b169e32015-04-14 16:27:13 -0700332
333
334 /**
335 * Checks if the host is in the subnet defined in the router with the
336 * device ID given.
337 *
338 * @param deviceId device identification of the router
339 * @param hostIp host IP address to check
340 * @return true if the host is within the subnet of the router,
341 * false if no subnet is defined under the router or if the host is not
342 * within the subnet defined in the router
343 */
344 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
345
346 List<Ip4Prefix> subnets = getSubnets(deviceId);
347 if (subnets == null) {
348 return false;
349 }
350
351 for (Ip4Prefix subnet: subnets) {
352 if (subnet.contains(hostIp)) {
353 return true;
354 }
355 }
356
357 return false;
358 }
sangho27462c62015-05-14 00:39:53 -0700359
360 /**
361 * Returns the ports corresponding to the adjacency Sid given.
362 *
363 * @param deviceId device identification of the router
364 * @param sid adjacency Sid
365 * @return list of port numbers
366 */
367 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
368 if (deviceConfigMap.get(deviceId) != null) {
369 for (SegmentRouterConfig.AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
370 if (asid.getAdjSid() == sid) {
371 return asid.getPorts();
372 }
373 }
374 }
375
376 return Lists.newArrayList();
377 }
378
379 /**
380 * Check if the Sid given is whether adjacency Sid of the router device or not.
381 *
382 * @param deviceId device identification of the router
383 * @param sid Sid to check
384 * @return true if the Sid given is the adjacency Sid of the device,
385 * otherwise false
386 */
387 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
388 if (deviceConfigMap.get(deviceId) != null) {
389 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
390 return false;
391 } else {
392 for (SegmentRouterConfig.AdjacencySid asid:
393 deviceConfigMap.get(deviceId).adjacencySids) {
394 if (asid.getAdjSid() == sid) {
395 return true;
396 }
397 }
398 return false;
399 }
400 }
401
402 return false;
403 }
sangho80f11cb2015-04-01 13:05:26 -0700404}