blob: 1d45d0a96d83ae58f6ce5af96841e89dd831e867 [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;
Charles Chanb8e10c82015-10-14 11:24:40 -070065
66 public SegmentRouterInfo() {
67 this.gatewayIps = new HashMap<>();
68 this.subnets = new HashMap<>();
69 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070070 }
sanghob35a6192015-04-01 13:05:26 -070071
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070072 /**
73 * Constructor. Reads all the configuration for all devices of type
74 * Segment Router and organizes into various maps for easier access.
Brian O'Connor52515622015-10-09 17:03:44 -070075 *
76 * @param cfgService config service
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070077 */
Charles Chand6832882015-10-05 17:50:33 -070078 public DeviceConfiguration(NetworkConfigRegistry cfgService) {
Charles Chan4636be02015-10-07 14:21:45 -070079 // Read config from device subject, excluding gatewayIps and subnets.
80 Set<DeviceId> deviceSubjects =
Charles Chand6832882015-10-05 17:50:33 -070081 cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070082 deviceSubjects.forEach(subject -> {
Charles Chand6832882015-10-05 17:50:33 -070083 SegmentRoutingConfig config =
84 cfgService.getConfig(subject, SegmentRoutingConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070085 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070086 info.deviceId = subject;
Charles Chan4636be02015-10-07 14:21:45 -070087 info.nodeSid = config.getSid();
Charles Chand6832882015-10-05 17:50:33 -070088 info.ip = config.getIp();
89 info.mac = config.getMac();
90 info.isEdge = config.isEdgeRouter();
Charles Chan4636be02015-10-07 14:21:45 -070091 info.adjacencySids = config.getAdjacencySids();
Charles Chand6832882015-10-05 17:50:33 -070092
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070093 this.deviceConfigMap.put(info.deviceId, info);
94 this.allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -070095 });
Charles Chan4636be02015-10-07 14:21:45 -070096
97 // Read gatewayIps and subnets from port subject.
98 Set<ConnectPoint> portSubjects =
99 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
100 portSubjects.forEach(subject -> {
101 InterfaceConfig config =
102 cfgService.getConfig(subject, InterfaceConfig.class);
103 Set<Interface> networkInterfaces;
104 try {
105 networkInterfaces = config.getInterfaces();
106 } catch (ConfigException e) {
107 log.error("Error loading port configuration");
108 return;
109 }
110 networkInterfaces.forEach(networkInterface -> {
111 DeviceId dpid = networkInterface.connectPoint().deviceId();
112 PortNumber port = networkInterface.connectPoint().port();
113 SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
114
Charles Chanb8e10c82015-10-14 11:24:40 -0700115 // skip if there is no corresponding device for this ConenctPoint
116 if (info != null) {
117 Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
118 interfaceAddresses.forEach(interfaceAddress -> {
119 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
120 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
121 });
122 }
Charles Chan4636be02015-10-07 14:21:45 -0700123 });
124
125 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700126 }
127
128 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700129 * Returns the Node segment id of a segment router.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700130 *
131 * @param deviceId device identifier
132 * @return segment id
133 */
sanghob35a6192015-04-01 13:05:26 -0700134 @Override
135 public int getSegmentId(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700136 if (deviceConfigMap.get(deviceId) != null) {
Saurav Dasa07f2032015-10-19 14:37:36 -0700137 log.trace("getSegmentId for device{} is {}",
sanghob35a6192015-04-01 13:05:26 -0700138 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700139 deviceConfigMap.get(deviceId).nodeSid);
140 return deviceConfigMap.get(deviceId).nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700141 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700142 log.warn("getSegmentId for device {} "
143 + "throwing IllegalStateException "
144 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700145 throw new IllegalStateException();
146 }
147 }
148
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700149 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700150 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700151 *
152 * @param routerMac router mac address
153 * @return segment id
154 */
155 public int getSegmentId(MacAddress routerMac) {
156 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
157 deviceConfigMap.entrySet()) {
158 if (entry.getValue().mac.equals(routerMac)) {
159 return entry.getValue().nodeSid;
160 }
161 }
sanghob35a6192015-04-01 13:05:26 -0700162
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700163 return -1;
164 }
165
166 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700167 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700168 *
169 * @param routerAddress router ip address
170 * @return segment id
171 */
172 public int getSegmentId(Ip4Address routerAddress) {
173 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
174 deviceConfigMap.entrySet()) {
175 if (entry.getValue().ip.equals(routerAddress)) {
176 return entry.getValue().nodeSid;
177 }
178 }
179
180 return -1;
181 }
182
183 /**
184 * Returns the router mac of a segment router.
185 *
186 * @param deviceId device identifier
187 * @return router mac address
188 */
sanghob35a6192015-04-01 13:05:26 -0700189 @Override
190 public MacAddress getDeviceMac(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700191 if (deviceConfigMap.get(deviceId) != null) {
Saurav Dasa07f2032015-10-19 14:37:36 -0700192 log.trace("getDeviceMac for device{} is {}",
sanghob35a6192015-04-01 13:05:26 -0700193 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700194 deviceConfigMap.get(deviceId).mac);
195 return deviceConfigMap.get(deviceId).mac;
sanghob35a6192015-04-01 13:05:26 -0700196 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700197 log.warn("getDeviceMac for device {} "
198 + "throwing IllegalStateException "
199 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700200 throw new IllegalStateException();
201 }
202 }
203
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700204 /**
205 * Returns the router ip address of a segment router.
206 *
207 * @param deviceId device identifier
208 * @return router ip address
209 */
210 public Ip4Address getRouterIp(DeviceId deviceId) {
211 if (deviceConfigMap.get(deviceId) != null) {
Saurav Dasa07f2032015-10-19 14:37:36 -0700212 log.trace("getDeviceIp for device{} is {}",
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700213 deviceId,
214 deviceConfigMap.get(deviceId).ip);
215 return deviceConfigMap.get(deviceId).ip;
216 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700217 log.warn("getRouterIp for device {} "
218 + "throwing IllegalStateException "
219 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700220 throw new IllegalStateException();
sanghob35a6192015-04-01 13:05:26 -0700221 }
sanghob35a6192015-04-01 13:05:26 -0700222 }
223
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700224 /**
225 * Indicates if the segment router is a edge router or
Saurav Das822c4e22015-10-23 10:51:11 -0700226 * a core/backbone router.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700227 *
228 * @param deviceId device identifier
229 * @return boolean
230 */
231 @Override
232 public boolean isEdgeDevice(DeviceId deviceId) {
233 if (deviceConfigMap.get(deviceId) != null) {
Saurav Dasa07f2032015-10-19 14:37:36 -0700234 log.trace("isEdgeDevice for device{} is {}",
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700235 deviceId,
236 deviceConfigMap.get(deviceId).isEdge);
237 return deviceConfigMap.get(deviceId).isEdge;
238 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700239 log.warn("isEdgeDevice for device {} "
240 + "throwing IllegalStateException "
241 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700242 throw new IllegalStateException();
243 }
244 }
245
246 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700247 * Returns the node segment ids of all configured segment routers.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700248 *
Saurav Das822c4e22015-10-23 10:51:11 -0700249 * @return list of node segment ids
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700250 */
sanghob35a6192015-04-01 13:05:26 -0700251 @Override
252 public List<Integer> getAllDeviceSegmentIds() {
253 return allSegmentIds;
254 }
255
sanghob35a6192015-04-01 13:05:26 -0700256 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700257 * Returns the device identifier or data plane identifier (dpid)
258 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700259 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700260 * @param sid segment id
261 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700262 */
263 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700264 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
265 deviceConfigMap.entrySet()) {
266 if (entry.getValue().nodeSid == sid) {
267 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700268 }
269 }
270
271 return null;
272 }
273
274 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700275 * Returns the device identifier or data plane identifier (dpid)
276 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700277 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700278 * @param ipAddress router ip address
279 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700280 */
281 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700282 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
283 deviceConfigMap.entrySet()) {
284 if (entry.getValue().ip.equals(ipAddress)) {
285 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700286 }
287 }
288
289 return null;
290 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700291
292 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700293 * Returns the configured port ip addresses for a segment router.
294 * These addresses serve as gateway IP addresses for the subnets configured
295 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700296 *
297 * @param deviceId device identifier
Saurav Das822c4e22015-10-23 10:51:11 -0700298 * @return list of ip addresses configured on the ports
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700299 */
Saurav Das822c4e22015-10-23 10:51:11 -0700300 public List<Ip4Address> getPortIPs(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700301 if (deviceConfigMap.get(deviceId) != null) {
Saurav Dasa07f2032015-10-19 14:37:36 -0700302 log.trace("getSubnetGatewayIps for device{} is {}",
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700303 deviceId,
304 deviceConfigMap.get(deviceId).gatewayIps.values());
Sho SHIMIZUa8dbad42015-09-11 14:22:25 -0700305 return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700306 } else {
307 return null;
308 }
309 }
310
311 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700312 * Returns the configured IP addresses per port
313 * for a segment router.
314 *
315 * @param deviceId device identifier
316 * @return map of port to gateway IP addresses
317 */
318 public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) {
319 if (deviceConfigMap.get(deviceId) != null) {
320 return deviceConfigMap.get(deviceId).gatewayIps;
321 }
322 return null;
323 }
324
325 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700326 * Returns the configured subnet prefixes for a segment router.
327 *
328 * @param deviceId device identifier
329 * @return list of ip prefixes
330 */
331 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
332 if (deviceConfigMap.get(deviceId) != null) {
Saurav Dasa07f2032015-10-19 14:37:36 -0700333 log.trace("getSubnets for device{} is {}",
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700334 deviceId,
335 deviceConfigMap.get(deviceId).subnets.values());
Sho SHIMIZUa8dbad42015-09-11 14:22:25 -0700336 return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700337 } else {
338 return null;
339 }
340 }
341
342 /**
343 * Returns the router ip address of segment router that has the
344 * specified ip address in its subnets.
345 *
346 * @param destIpAddress target ip address
347 * @return router ip address
348 */
349 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
350 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
351 deviceConfigMap.entrySet()) {
352 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
353 if (prefix.contains(destIpAddress)) {
354 return entry.getValue().ip;
355 }
356 }
357 }
358
359 log.debug("No router was found for {}", destIpAddress);
360 return null;
361 }
362
363 /**
364 * Returns the router mac address of segment router that has the
365 * specified ip address as one of its subnet gateway ip address.
366 *
367 * @param gatewayIpAddress router gateway ip address
368 * @return router mac address
369 */
370 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
371 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
372 deviceConfigMap.entrySet()) {
373 if (entry.getValue().gatewayIps.
374 values().contains(gatewayIpAddress)) {
375 return entry.getValue().mac;
376 }
377 }
378
379 log.debug("Cannot find a router for {}", gatewayIpAddress);
380 return null;
381 }
sangho666cd6d2015-04-14 16:27:13 -0700382
383
384 /**
385 * Checks if the host is in the subnet defined in the router with the
386 * device ID given.
387 *
388 * @param deviceId device identification of the router
389 * @param hostIp host IP address to check
390 * @return true if the host is within the subnet of the router,
391 * false if no subnet is defined under the router or if the host is not
392 * within the subnet defined in the router
393 */
394 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
395
396 List<Ip4Prefix> subnets = getSubnets(deviceId);
397 if (subnets == null) {
398 return false;
399 }
400
401 for (Ip4Prefix subnet: subnets) {
402 if (subnet.contains(hostIp)) {
403 return true;
404 }
405 }
406
407 return false;
408 }
sangho1e575652015-05-14 00:39:53 -0700409
410 /**
411 * Returns the ports corresponding to the adjacency Sid given.
412 *
413 * @param deviceId device identification of the router
414 * @param sid adjacency Sid
415 * @return list of port numbers
416 */
417 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
418 if (deviceConfigMap.get(deviceId) != null) {
Charles Chand6832882015-10-05 17:50:33 -0700419 for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
Charles Chan4636be02015-10-07 14:21:45 -0700420 if (asid.getAsid() == sid) {
sangho1e575652015-05-14 00:39:53 -0700421 return asid.getPorts();
422 }
423 }
424 }
425
426 return Lists.newArrayList();
427 }
428
429 /**
430 * Check if the Sid given is whether adjacency Sid of the router device or not.
431 *
432 * @param deviceId device identification of the router
433 * @param sid Sid to check
434 * @return true if the Sid given is the adjacency Sid of the device,
435 * otherwise false
436 */
437 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
438 if (deviceConfigMap.get(deviceId) != null) {
439 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
440 return false;
441 } else {
Charles Chand6832882015-10-05 17:50:33 -0700442 for (AdjacencySid asid:
sangho1e575652015-05-14 00:39:53 -0700443 deviceConfigMap.get(deviceId).adjacencySids) {
Charles Chan4636be02015-10-07 14:21:45 -0700444 if (asid.getAsid() == sid) {
sangho1e575652015-05-14 00:39:53 -0700445 return true;
446 }
447 }
448 return false;
449 }
450 }
451
452 return false;
453 }
Charles Chand6832882015-10-05 17:50:33 -0700454}