blob: 8fdf81a26787318df2fb09cd8d26a63fe32e2d46 [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Charles Chand6832882015-10-05 17:50:33 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska58de4162015-09-10 16:15:33 -07003 *
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;
sanghob35a6192015-04-01 13:05:26 -070021import org.onlab.packet.MacAddress;
Charles Chan4636be02015-10-07 14:21:45 -070022import org.onosproject.incubator.net.config.basics.ConfigException;
23import org.onosproject.incubator.net.config.basics.InterfaceConfig;
24import org.onosproject.incubator.net.intf.Interface;
25import org.onosproject.net.ConnectPoint;
Charles Chand6832882015-10-05 17:50:33 -070026import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan4636be02015-10-07 14:21:45 -070027import org.onosproject.net.host.InterfaceIpAddress;
Charles Chand6832882015-10-05 17:50:33 -070028import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
29import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070030import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
sanghob35a6192015-04-01 13:05:26 -070031import org.onosproject.net.DeviceId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070032import org.onosproject.net.PortNumber;
sanghob35a6192015-04-01 13:05:26 -070033import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070036import java.util.ArrayList;
sanghob35a6192015-04-01 13:05:26 -070037import java.util.HashMap;
38import java.util.List;
39import java.util.Map;
Charles Chand6832882015-10-05 17:50:33 -070040import java.util.Set;
sanghob35a6192015-04-01 13:05:26 -070041
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070042/**
43 * Segment Routing configuration component that reads the
44 * segment routing related configuration from Network Configuration Manager
45 * component and organizes in more accessible formats.
46 *
47 * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
48 */
sanghob35a6192015-04-01 13:05:26 -070049public class DeviceConfiguration implements DeviceProperties {
50
51 private static final Logger log = LoggerFactory
52 .getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070053 private final List<Integer> allSegmentIds = new ArrayList<>();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070054 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
sanghob35a6192015-04-01 13:05:26 -070055
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070056 private class SegmentRouterInfo {
57 int nodeSid;
58 DeviceId deviceId;
59 Ip4Address ip;
60 MacAddress mac;
61 boolean isEdge;
62 HashMap<PortNumber, Ip4Address> gatewayIps;
63 HashMap<PortNumber, Ip4Prefix> subnets;
Charles Chand6832882015-10-05 17:50:33 -070064 List<AdjacencySid> adjacencySids;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070065 }
sanghob35a6192015-04-01 13:05:26 -070066
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070067 /**
68 * Constructor. Reads all the configuration for all devices of type
69 * Segment Router and organizes into various maps for easier access.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070070 */
Charles Chand6832882015-10-05 17:50:33 -070071 public DeviceConfiguration(NetworkConfigRegistry cfgService) {
Charles Chan4636be02015-10-07 14:21:45 -070072 // Read config from device subject, excluding gatewayIps and subnets.
73 Set<DeviceId> deviceSubjects =
Charles Chand6832882015-10-05 17:50:33 -070074 cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070075 deviceSubjects.forEach(subject -> {
Charles Chand6832882015-10-05 17:50:33 -070076 SegmentRoutingConfig config =
77 cfgService.getConfig(subject, SegmentRoutingConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070078 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070079 info.deviceId = subject;
Charles Chan4636be02015-10-07 14:21:45 -070080 info.nodeSid = config.getSid();
Charles Chand6832882015-10-05 17:50:33 -070081 info.ip = config.getIp();
82 info.mac = config.getMac();
83 info.isEdge = config.isEdgeRouter();
Charles Chan4636be02015-10-07 14:21:45 -070084 info.adjacencySids = config.getAdjacencySids();
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070085 info.gatewayIps = new HashMap<>();
Charles Chand6832882015-10-05 17:50:33 -070086 info.subnets = new HashMap<>();
Charles Chand6832882015-10-05 17:50:33 -070087
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070088 this.deviceConfigMap.put(info.deviceId, info);
89 this.allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -070090 });
Charles Chan4636be02015-10-07 14:21:45 -070091
92 // Read gatewayIps and subnets from port subject.
93 Set<ConnectPoint> portSubjects =
94 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
95 portSubjects.forEach(subject -> {
96 InterfaceConfig config =
97 cfgService.getConfig(subject, InterfaceConfig.class);
98 Set<Interface> networkInterfaces;
99 try {
100 networkInterfaces = config.getInterfaces();
101 } catch (ConfigException e) {
102 log.error("Error loading port configuration");
103 return;
104 }
105 networkInterfaces.forEach(networkInterface -> {
106 DeviceId dpid = networkInterface.connectPoint().deviceId();
107 PortNumber port = networkInterface.connectPoint().port();
108 SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
109
110 Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
111 interfaceAddresses.forEach(interfaceAddress -> {
112 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
113 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
114 });
115 });
116
117 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700118 }
119
120 /**
121 * Returns the segment id of a segment router.
122 *
123 * @param deviceId device identifier
124 * @return segment id
125 */
sanghob35a6192015-04-01 13:05:26 -0700126 @Override
127 public int getSegmentId(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700128 if (deviceConfigMap.get(deviceId) != null) {
sanghob35a6192015-04-01 13:05:26 -0700129 log.debug("getSegmentId for device{} is {}",
130 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700131 deviceConfigMap.get(deviceId).nodeSid);
132 return deviceConfigMap.get(deviceId).nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700133 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700134 log.warn("getSegmentId for device {} "
135 + "throwing IllegalStateException "
136 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700137 throw new IllegalStateException();
138 }
139 }
140
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700141 /**
142 * Returns the segment id of a segment router given its mac address.
143 *
144 * @param routerMac router mac address
145 * @return segment id
146 */
147 public int getSegmentId(MacAddress routerMac) {
148 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
149 deviceConfigMap.entrySet()) {
150 if (entry.getValue().mac.equals(routerMac)) {
151 return entry.getValue().nodeSid;
152 }
153 }
sanghob35a6192015-04-01 13:05:26 -0700154
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700155 return -1;
156 }
157
158 /**
159 * Returns the segment id of a segment router given its router ip address.
160 *
161 * @param routerAddress router ip address
162 * @return segment id
163 */
164 public int getSegmentId(Ip4Address routerAddress) {
165 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
166 deviceConfigMap.entrySet()) {
167 if (entry.getValue().ip.equals(routerAddress)) {
168 return entry.getValue().nodeSid;
169 }
170 }
171
172 return -1;
173 }
174
175 /**
176 * Returns the router mac of a segment router.
177 *
178 * @param deviceId device identifier
179 * @return router mac address
180 */
sanghob35a6192015-04-01 13:05:26 -0700181 @Override
182 public MacAddress getDeviceMac(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700183 if (deviceConfigMap.get(deviceId) != null) {
sanghob35a6192015-04-01 13:05:26 -0700184 log.debug("getDeviceMac for device{} is {}",
185 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700186 deviceConfigMap.get(deviceId).mac);
187 return deviceConfigMap.get(deviceId).mac;
sanghob35a6192015-04-01 13:05:26 -0700188 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700189 log.warn("getDeviceMac for device {} "
190 + "throwing IllegalStateException "
191 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700192 throw new IllegalStateException();
193 }
194 }
195
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700196 /**
197 * Returns the router ip address of a segment router.
198 *
199 * @param deviceId device identifier
200 * @return router ip address
201 */
202 public Ip4Address getRouterIp(DeviceId deviceId) {
203 if (deviceConfigMap.get(deviceId) != null) {
204 log.debug("getDeviceIp for device{} is {}",
205 deviceId,
206 deviceConfigMap.get(deviceId).ip);
207 return deviceConfigMap.get(deviceId).ip;
208 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700209 log.warn("getRouterIp for device {} "
210 + "throwing IllegalStateException "
211 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700212 throw new IllegalStateException();
sanghob35a6192015-04-01 13:05:26 -0700213 }
sanghob35a6192015-04-01 13:05:26 -0700214 }
215
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700216 /**
217 * Indicates if the segment router is a edge router or
218 * a transit/back bone router.
219 *
220 * @param deviceId device identifier
221 * @return boolean
222 */
223 @Override
224 public boolean isEdgeDevice(DeviceId deviceId) {
225 if (deviceConfigMap.get(deviceId) != null) {
226 log.debug("isEdgeDevice for device{} is {}",
227 deviceId,
228 deviceConfigMap.get(deviceId).isEdge);
229 return deviceConfigMap.get(deviceId).isEdge;
230 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700231 log.warn("isEdgeDevice for device {} "
232 + "throwing IllegalStateException "
233 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700234 throw new IllegalStateException();
235 }
236 }
237
238 /**
239 * Returns the segment ids of all configured segment routers.
240 *
241 * @return list of segment ids
242 */
sanghob35a6192015-04-01 13:05:26 -0700243 @Override
244 public List<Integer> getAllDeviceSegmentIds() {
245 return allSegmentIds;
246 }
247
sanghob35a6192015-04-01 13:05:26 -0700248 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700249 * Returns the device identifier or data plane identifier (dpid)
250 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700251 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700252 * @param sid segment id
253 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700254 */
255 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700256 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
257 deviceConfigMap.entrySet()) {
258 if (entry.getValue().nodeSid == sid) {
259 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700260 }
261 }
262
263 return null;
264 }
265
266 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700267 * Returns the device identifier or data plane identifier (dpid)
268 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700269 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700270 * @param ipAddress router ip address
271 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700272 */
273 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700274 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
275 deviceConfigMap.entrySet()) {
276 if (entry.getValue().ip.equals(ipAddress)) {
277 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700278 }
279 }
280
281 return null;
282 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700283
284 /**
285 * Returns the configured subnet gateway ip addresses for a segment router.
286 *
287 * @param deviceId device identifier
288 * @return list of ip addresses
289 */
290 public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
291 if (deviceConfigMap.get(deviceId) != null) {
292 log.debug("getSubnetGatewayIps for device{} is {}",
293 deviceId,
294 deviceConfigMap.get(deviceId).gatewayIps.values());
Sho SHIMIZUa8dbad42015-09-11 14:22:25 -0700295 return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700296 } else {
297 return null;
298 }
299 }
300
301 /**
302 * Returns the configured subnet prefixes for a segment router.
303 *
304 * @param deviceId device identifier
305 * @return list of ip prefixes
306 */
307 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
308 if (deviceConfigMap.get(deviceId) != null) {
309 log.debug("getSubnets for device{} is {}",
310 deviceId,
311 deviceConfigMap.get(deviceId).subnets.values());
Sho SHIMIZUa8dbad42015-09-11 14:22:25 -0700312 return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700313 } else {
314 return null;
315 }
316 }
317
318 /**
319 * Returns the router ip address of segment router that has the
320 * specified ip address in its subnets.
321 *
322 * @param destIpAddress target ip address
323 * @return router ip address
324 */
325 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
326 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
327 deviceConfigMap.entrySet()) {
328 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
329 if (prefix.contains(destIpAddress)) {
330 return entry.getValue().ip;
331 }
332 }
333 }
334
335 log.debug("No router was found for {}", destIpAddress);
336 return null;
337 }
338
339 /**
340 * Returns the router mac address of segment router that has the
341 * specified ip address as one of its subnet gateway ip address.
342 *
343 * @param gatewayIpAddress router gateway ip address
344 * @return router mac address
345 */
346 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
347 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
348 deviceConfigMap.entrySet()) {
349 if (entry.getValue().gatewayIps.
350 values().contains(gatewayIpAddress)) {
351 return entry.getValue().mac;
352 }
353 }
354
355 log.debug("Cannot find a router for {}", gatewayIpAddress);
356 return null;
357 }
sangho666cd6d2015-04-14 16:27:13 -0700358
359
360 /**
361 * Checks if the host is in the subnet defined in the router with the
362 * device ID given.
363 *
364 * @param deviceId device identification of the router
365 * @param hostIp host IP address to check
366 * @return true if the host is within the subnet of the router,
367 * false if no subnet is defined under the router or if the host is not
368 * within the subnet defined in the router
369 */
370 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
371
372 List<Ip4Prefix> subnets = getSubnets(deviceId);
373 if (subnets == null) {
374 return false;
375 }
376
377 for (Ip4Prefix subnet: subnets) {
378 if (subnet.contains(hostIp)) {
379 return true;
380 }
381 }
382
383 return false;
384 }
sangho1e575652015-05-14 00:39:53 -0700385
386 /**
387 * Returns the ports corresponding to the adjacency Sid given.
388 *
389 * @param deviceId device identification of the router
390 * @param sid adjacency Sid
391 * @return list of port numbers
392 */
393 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
394 if (deviceConfigMap.get(deviceId) != null) {
Charles Chand6832882015-10-05 17:50:33 -0700395 for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
Charles Chan4636be02015-10-07 14:21:45 -0700396 if (asid.getAsid() == sid) {
sangho1e575652015-05-14 00:39:53 -0700397 return asid.getPorts();
398 }
399 }
400 }
401
402 return Lists.newArrayList();
403 }
404
405 /**
406 * Check if the Sid given is whether adjacency Sid of the router device or not.
407 *
408 * @param deviceId device identification of the router
409 * @param sid Sid to check
410 * @return true if the Sid given is the adjacency Sid of the device,
411 * otherwise false
412 */
413 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
414 if (deviceConfigMap.get(deviceId) != null) {
415 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
416 return false;
417 } else {
Charles Chand6832882015-10-05 17:50:33 -0700418 for (AdjacencySid asid:
sangho1e575652015-05-14 00:39:53 -0700419 deviceConfigMap.get(deviceId).adjacencySids) {
Charles Chan4636be02015-10-07 14:21:45 -0700420 if (asid.getAsid() == sid) {
sangho1e575652015-05-14 00:39:53 -0700421 return true;
422 }
423 }
424 return false;
425 }
426 }
427
428 return false;
429 }
Charles Chand6832882015-10-05 17:50:33 -0700430}