blob: b1c6a6e267ed32bcb58ff671b801062ab2f752a6 [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.
Brian O'Connor52515622015-10-09 17:03:44 -070070 *
71 * @param cfgService config service
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070072 */
Charles Chand6832882015-10-05 17:50:33 -070073 public DeviceConfiguration(NetworkConfigRegistry cfgService) {
Charles Chan4636be02015-10-07 14:21:45 -070074 // Read config from device subject, excluding gatewayIps and subnets.
75 Set<DeviceId> deviceSubjects =
Charles Chand6832882015-10-05 17:50:33 -070076 cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070077 deviceSubjects.forEach(subject -> {
Charles Chand6832882015-10-05 17:50:33 -070078 SegmentRoutingConfig config =
79 cfgService.getConfig(subject, SegmentRoutingConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070080 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070081 info.deviceId = subject;
Charles Chan4636be02015-10-07 14:21:45 -070082 info.nodeSid = config.getSid();
Charles Chand6832882015-10-05 17:50:33 -070083 info.ip = config.getIp();
84 info.mac = config.getMac();
85 info.isEdge = config.isEdgeRouter();
Charles Chan4636be02015-10-07 14:21:45 -070086 info.adjacencySids = config.getAdjacencySids();
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070087 info.gatewayIps = new HashMap<>();
Charles Chand6832882015-10-05 17:50:33 -070088 info.subnets = new HashMap<>();
Charles Chand6832882015-10-05 17:50:33 -070089
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070090 this.deviceConfigMap.put(info.deviceId, info);
91 this.allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -070092 });
Charles Chan4636be02015-10-07 14:21:45 -070093
94 // Read gatewayIps and subnets from port subject.
95 Set<ConnectPoint> portSubjects =
96 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
97 portSubjects.forEach(subject -> {
98 InterfaceConfig config =
99 cfgService.getConfig(subject, InterfaceConfig.class);
100 Set<Interface> networkInterfaces;
101 try {
102 networkInterfaces = config.getInterfaces();
103 } catch (ConfigException e) {
104 log.error("Error loading port configuration");
105 return;
106 }
107 networkInterfaces.forEach(networkInterface -> {
108 DeviceId dpid = networkInterface.connectPoint().deviceId();
109 PortNumber port = networkInterface.connectPoint().port();
110 SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
111
112 Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
113 interfaceAddresses.forEach(interfaceAddress -> {
114 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
115 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
116 });
117 });
118
119 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700120 }
121
122 /**
123 * Returns the segment id of a segment router.
124 *
125 * @param deviceId device identifier
126 * @return segment id
127 */
sanghob35a6192015-04-01 13:05:26 -0700128 @Override
129 public int getSegmentId(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700130 if (deviceConfigMap.get(deviceId) != null) {
sanghob35a6192015-04-01 13:05:26 -0700131 log.debug("getSegmentId for device{} is {}",
132 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700133 deviceConfigMap.get(deviceId).nodeSid);
134 return deviceConfigMap.get(deviceId).nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700135 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700136 log.warn("getSegmentId for device {} "
137 + "throwing IllegalStateException "
138 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700139 throw new IllegalStateException();
140 }
141 }
142
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700143 /**
144 * Returns the segment id of a segment router given its mac address.
145 *
146 * @param routerMac router mac address
147 * @return segment id
148 */
149 public int getSegmentId(MacAddress routerMac) {
150 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
151 deviceConfigMap.entrySet()) {
152 if (entry.getValue().mac.equals(routerMac)) {
153 return entry.getValue().nodeSid;
154 }
155 }
sanghob35a6192015-04-01 13:05:26 -0700156
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700157 return -1;
158 }
159
160 /**
161 * Returns the segment id of a segment router given its router ip address.
162 *
163 * @param routerAddress router ip address
164 * @return segment id
165 */
166 public int getSegmentId(Ip4Address routerAddress) {
167 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
168 deviceConfigMap.entrySet()) {
169 if (entry.getValue().ip.equals(routerAddress)) {
170 return entry.getValue().nodeSid;
171 }
172 }
173
174 return -1;
175 }
176
177 /**
178 * Returns the router mac of a segment router.
179 *
180 * @param deviceId device identifier
181 * @return router mac address
182 */
sanghob35a6192015-04-01 13:05:26 -0700183 @Override
184 public MacAddress getDeviceMac(DeviceId deviceId) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700185 if (deviceConfigMap.get(deviceId) != null) {
sanghob35a6192015-04-01 13:05:26 -0700186 log.debug("getDeviceMac for device{} is {}",
187 deviceId,
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700188 deviceConfigMap.get(deviceId).mac);
189 return deviceConfigMap.get(deviceId).mac;
sanghob35a6192015-04-01 13:05:26 -0700190 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700191 log.warn("getDeviceMac for device {} "
192 + "throwing IllegalStateException "
193 + "because device does not exist in config", deviceId);
sanghob35a6192015-04-01 13:05:26 -0700194 throw new IllegalStateException();
195 }
196 }
197
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700198 /**
199 * Returns the router ip address of a segment router.
200 *
201 * @param deviceId device identifier
202 * @return router ip address
203 */
204 public Ip4Address getRouterIp(DeviceId deviceId) {
205 if (deviceConfigMap.get(deviceId) != null) {
206 log.debug("getDeviceIp for device{} is {}",
207 deviceId,
208 deviceConfigMap.get(deviceId).ip);
209 return deviceConfigMap.get(deviceId).ip;
210 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700211 log.warn("getRouterIp for device {} "
212 + "throwing IllegalStateException "
213 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700214 throw new IllegalStateException();
sanghob35a6192015-04-01 13:05:26 -0700215 }
sanghob35a6192015-04-01 13:05:26 -0700216 }
217
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700218 /**
219 * Indicates if the segment router is a edge router or
220 * a transit/back bone router.
221 *
222 * @param deviceId device identifier
223 * @return boolean
224 */
225 @Override
226 public boolean isEdgeDevice(DeviceId deviceId) {
227 if (deviceConfigMap.get(deviceId) != null) {
228 log.debug("isEdgeDevice for device{} is {}",
229 deviceId,
230 deviceConfigMap.get(deviceId).isEdge);
231 return deviceConfigMap.get(deviceId).isEdge;
232 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700233 log.warn("isEdgeDevice for device {} "
234 + "throwing IllegalStateException "
235 + "because device does not exist in config", deviceId);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700236 throw new IllegalStateException();
237 }
238 }
239
240 /**
241 * Returns the segment ids of all configured segment routers.
242 *
243 * @return list of segment ids
244 */
sanghob35a6192015-04-01 13:05:26 -0700245 @Override
246 public List<Integer> getAllDeviceSegmentIds() {
247 return allSegmentIds;
248 }
249
sanghob35a6192015-04-01 13:05:26 -0700250 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700251 * Returns the device identifier or data plane identifier (dpid)
252 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700253 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700254 * @param sid segment id
255 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700256 */
257 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700258 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
259 deviceConfigMap.entrySet()) {
260 if (entry.getValue().nodeSid == sid) {
261 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700262 }
263 }
264
265 return null;
266 }
267
268 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700269 * Returns the device identifier or data plane identifier (dpid)
270 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700271 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700272 * @param ipAddress router ip address
273 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700274 */
275 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700276 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
277 deviceConfigMap.entrySet()) {
278 if (entry.getValue().ip.equals(ipAddress)) {
279 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700280 }
281 }
282
283 return null;
284 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700285
286 /**
287 * Returns the configured subnet gateway ip addresses for a segment router.
288 *
289 * @param deviceId device identifier
290 * @return list of ip addresses
291 */
292 public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
293 if (deviceConfigMap.get(deviceId) != null) {
294 log.debug("getSubnetGatewayIps for device{} is {}",
295 deviceId,
296 deviceConfigMap.get(deviceId).gatewayIps.values());
Sho SHIMIZUa8dbad42015-09-11 14:22:25 -0700297 return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700298 } else {
299 return null;
300 }
301 }
302
303 /**
304 * Returns the configured subnet prefixes for a segment router.
305 *
306 * @param deviceId device identifier
307 * @return list of ip prefixes
308 */
309 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
310 if (deviceConfigMap.get(deviceId) != null) {
311 log.debug("getSubnets for device{} is {}",
312 deviceId,
313 deviceConfigMap.get(deviceId).subnets.values());
Sho SHIMIZUa8dbad42015-09-11 14:22:25 -0700314 return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700315 } else {
316 return null;
317 }
318 }
319
320 /**
321 * Returns the router ip address of segment router that has the
322 * specified ip address in its subnets.
323 *
324 * @param destIpAddress target ip address
325 * @return router ip address
326 */
327 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
328 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
329 deviceConfigMap.entrySet()) {
330 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
331 if (prefix.contains(destIpAddress)) {
332 return entry.getValue().ip;
333 }
334 }
335 }
336
337 log.debug("No router was found for {}", destIpAddress);
338 return null;
339 }
340
341 /**
342 * Returns the router mac address of segment router that has the
343 * specified ip address as one of its subnet gateway ip address.
344 *
345 * @param gatewayIpAddress router gateway ip address
346 * @return router mac address
347 */
348 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
349 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
350 deviceConfigMap.entrySet()) {
351 if (entry.getValue().gatewayIps.
352 values().contains(gatewayIpAddress)) {
353 return entry.getValue().mac;
354 }
355 }
356
357 log.debug("Cannot find a router for {}", gatewayIpAddress);
358 return null;
359 }
sangho666cd6d2015-04-14 16:27:13 -0700360
361
362 /**
363 * Checks if the host is in the subnet defined in the router with the
364 * device ID given.
365 *
366 * @param deviceId device identification of the router
367 * @param hostIp host IP address to check
368 * @return true if the host is within the subnet of the router,
369 * false if no subnet is defined under the router or if the host is not
370 * within the subnet defined in the router
371 */
372 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
373
374 List<Ip4Prefix> subnets = getSubnets(deviceId);
375 if (subnets == null) {
376 return false;
377 }
378
379 for (Ip4Prefix subnet: subnets) {
380 if (subnet.contains(hostIp)) {
381 return true;
382 }
383 }
384
385 return false;
386 }
sangho1e575652015-05-14 00:39:53 -0700387
388 /**
389 * Returns the ports corresponding to the adjacency Sid given.
390 *
391 * @param deviceId device identification of the router
392 * @param sid adjacency Sid
393 * @return list of port numbers
394 */
395 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
396 if (deviceConfigMap.get(deviceId) != null) {
Charles Chand6832882015-10-05 17:50:33 -0700397 for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
Charles Chan4636be02015-10-07 14:21:45 -0700398 if (asid.getAsid() == sid) {
sangho1e575652015-05-14 00:39:53 -0700399 return asid.getPorts();
400 }
401 }
402 }
403
404 return Lists.newArrayList();
405 }
406
407 /**
408 * Check if the Sid given is whether adjacency Sid of the router device or not.
409 *
410 * @param deviceId device identification of the router
411 * @param sid Sid to check
412 * @return true if the Sid given is the adjacency Sid of the device,
413 * otherwise false
414 */
415 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
416 if (deviceConfigMap.get(deviceId) != null) {
417 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
418 return false;
419 } else {
Charles Chand6832882015-10-05 17:50:33 -0700420 for (AdjacencySid asid:
sangho1e575652015-05-14 00:39:53 -0700421 deviceConfigMap.get(deviceId).adjacencySids) {
Charles Chan4636be02015-10-07 14:21:45 -0700422 if (asid.getAsid() == sid) {
sangho1e575652015-05-14 00:39:53 -0700423 return true;
424 }
425 }
426 return false;
427 }
428 }
429
430 return false;
431 }
Charles Chand6832882015-10-05 17:50:33 -0700432}