2 * Copyright 2014-2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.segmentrouting;
18 import com.google.common.collect.Lists;
19 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.Ip4Prefix;
21 import org.onlab.packet.MacAddress;
22 import org.onosproject.incubator.net.config.basics.ConfigException;
23 import org.onosproject.incubator.net.config.basics.InterfaceConfig;
24 import org.onosproject.incubator.net.intf.Interface;
25 import org.onosproject.net.ConnectPoint;
26 import org.onosproject.net.config.NetworkConfigRegistry;
27 import org.onosproject.net.host.InterfaceIpAddress;
28 import org.onosproject.segmentrouting.config.SegmentRoutingConfig;
29 import org.onosproject.segmentrouting.config.SegmentRoutingConfig.AdjacencySid;
30 import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
31 import org.onosproject.net.DeviceId;
32 import org.onosproject.net.PortNumber;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.List;
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.
47 * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
49 public class DeviceConfiguration implements DeviceProperties {
51 private static final Logger log = LoggerFactory
52 .getLogger(DeviceConfiguration.class);
53 private final List<Integer> allSegmentIds = new ArrayList<>();
54 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
56 private class SegmentRouterInfo {
62 HashMap<PortNumber, Ip4Address> gatewayIps;
63 HashMap<PortNumber, Ip4Prefix> subnets;
64 List<AdjacencySid> adjacencySids;
66 public SegmentRouterInfo() {
67 this.gatewayIps = new HashMap<>();
68 this.subnets = new HashMap<>();
73 * Constructor. Reads all the configuration for all devices of type
74 * Segment Router and organizes into various maps for easier access.
76 * @param cfgService config service
78 public DeviceConfiguration(NetworkConfigRegistry cfgService) {
79 // Read config from device subject, excluding gatewayIps and subnets.
80 Set<DeviceId> deviceSubjects =
81 cfgService.getSubjects(DeviceId.class, SegmentRoutingConfig.class);
82 deviceSubjects.forEach(subject -> {
83 SegmentRoutingConfig config =
84 cfgService.getConfig(subject, SegmentRoutingConfig.class);
85 SegmentRouterInfo info = new SegmentRouterInfo();
86 info.deviceId = subject;
87 info.nodeSid = config.getSid();
88 info.ip = config.getIp();
89 info.mac = config.getMac();
90 info.isEdge = config.isEdgeRouter();
91 info.adjacencySids = config.getAdjacencySids();
93 this.deviceConfigMap.put(info.deviceId, info);
94 this.allSegmentIds.add(info.nodeSid);
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;
105 networkInterfaces = config.getInterfaces();
106 } catch (ConfigException e) {
107 log.error("Error loading port configuration");
110 networkInterfaces.forEach(networkInterface -> {
111 DeviceId dpid = networkInterface.connectPoint().deviceId();
112 PortNumber port = networkInterface.connectPoint().port();
113 SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
115 // skip if there is no corresponding device for this ConenctPoint
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());
129 * Returns the segment id of a segment router.
131 * @param deviceId device identifier
135 public int getSegmentId(DeviceId deviceId) {
136 if (deviceConfigMap.get(deviceId) != null) {
137 log.trace("getSegmentId for device{} is {}",
139 deviceConfigMap.get(deviceId).nodeSid);
140 return deviceConfigMap.get(deviceId).nodeSid;
142 log.warn("getSegmentId for device {} "
143 + "throwing IllegalStateException "
144 + "because device does not exist in config", deviceId);
145 throw new IllegalStateException();
150 * Returns the segment id of a segment router given its mac address.
152 * @param routerMac router mac address
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;
167 * Returns the segment id of a segment router given its router ip address.
169 * @param routerAddress router ip address
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;
184 * Returns the router mac of a segment router.
186 * @param deviceId device identifier
187 * @return router mac address
190 public MacAddress getDeviceMac(DeviceId deviceId) {
191 if (deviceConfigMap.get(deviceId) != null) {
192 log.trace("getDeviceMac for device{} is {}",
194 deviceConfigMap.get(deviceId).mac);
195 return deviceConfigMap.get(deviceId).mac;
197 log.warn("getDeviceMac for device {} "
198 + "throwing IllegalStateException "
199 + "because device does not exist in config", deviceId);
200 throw new IllegalStateException();
205 * Returns the router ip address of a segment router.
207 * @param deviceId device identifier
208 * @return router ip address
210 public Ip4Address getRouterIp(DeviceId deviceId) {
211 if (deviceConfigMap.get(deviceId) != null) {
212 log.trace("getDeviceIp for device{} is {}",
214 deviceConfigMap.get(deviceId).ip);
215 return deviceConfigMap.get(deviceId).ip;
217 log.warn("getRouterIp for device {} "
218 + "throwing IllegalStateException "
219 + "because device does not exist in config", deviceId);
220 throw new IllegalStateException();
225 * Indicates if the segment router is a edge router or
226 * a transit/back bone router.
228 * @param deviceId device identifier
232 public boolean isEdgeDevice(DeviceId deviceId) {
233 if (deviceConfigMap.get(deviceId) != null) {
234 log.trace("isEdgeDevice for device{} is {}",
236 deviceConfigMap.get(deviceId).isEdge);
237 return deviceConfigMap.get(deviceId).isEdge;
239 log.warn("isEdgeDevice for device {} "
240 + "throwing IllegalStateException "
241 + "because device does not exist in config", deviceId);
242 throw new IllegalStateException();
247 * Returns the segment ids of all configured segment routers.
249 * @return list of segment ids
252 public List<Integer> getAllDeviceSegmentIds() {
253 return allSegmentIds;
257 * Returns the device identifier or data plane identifier (dpid)
258 * of a segment router given its segment id.
260 * @param sid segment id
261 * @return deviceId device identifier
263 public DeviceId getDeviceId(int sid) {
264 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
265 deviceConfigMap.entrySet()) {
266 if (entry.getValue().nodeSid == sid) {
267 return entry.getValue().deviceId;
275 * Returns the device identifier or data plane identifier (dpid)
276 * of a segment router given its router ip address.
278 * @param ipAddress router ip address
279 * @return deviceId device identifier
281 public DeviceId getDeviceId(Ip4Address ipAddress) {
282 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
283 deviceConfigMap.entrySet()) {
284 if (entry.getValue().ip.equals(ipAddress)) {
285 return entry.getValue().deviceId;
293 * Returns the configured subnet gateway ip addresses for a segment router.
295 * @param deviceId device identifier
296 * @return list of ip addresses
298 public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
299 if (deviceConfigMap.get(deviceId) != null) {
300 log.trace("getSubnetGatewayIps for device{} is {}",
302 deviceConfigMap.get(deviceId).gatewayIps.values());
303 return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
310 * Returns the configured subnet prefixes for a segment router.
312 * @param deviceId device identifier
313 * @return list of ip prefixes
315 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
316 if (deviceConfigMap.get(deviceId) != null) {
317 log.trace("getSubnets for device{} is {}",
319 deviceConfigMap.get(deviceId).subnets.values());
320 return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
327 * Returns the router ip address of segment router that has the
328 * specified ip address in its subnets.
330 * @param destIpAddress target ip address
331 * @return router ip address
333 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
334 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
335 deviceConfigMap.entrySet()) {
336 for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
337 if (prefix.contains(destIpAddress)) {
338 return entry.getValue().ip;
343 log.debug("No router was found for {}", destIpAddress);
348 * Returns the router mac address of segment router that has the
349 * specified ip address as one of its subnet gateway ip address.
351 * @param gatewayIpAddress router gateway ip address
352 * @return router mac address
354 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
355 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
356 deviceConfigMap.entrySet()) {
357 if (entry.getValue().gatewayIps.
358 values().contains(gatewayIpAddress)) {
359 return entry.getValue().mac;
363 log.debug("Cannot find a router for {}", gatewayIpAddress);
369 * Checks if the host is in the subnet defined in the router with the
372 * @param deviceId device identification of the router
373 * @param hostIp host IP address to check
374 * @return true if the host is within the subnet of the router,
375 * false if no subnet is defined under the router or if the host is not
376 * within the subnet defined in the router
378 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
380 List<Ip4Prefix> subnets = getSubnets(deviceId);
381 if (subnets == null) {
385 for (Ip4Prefix subnet: subnets) {
386 if (subnet.contains(hostIp)) {
395 * Returns the ports corresponding to the adjacency Sid given.
397 * @param deviceId device identification of the router
398 * @param sid adjacency Sid
399 * @return list of port numbers
401 public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
402 if (deviceConfigMap.get(deviceId) != null) {
403 for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
404 if (asid.getAsid() == sid) {
405 return asid.getPorts();
410 return Lists.newArrayList();
414 * Check if the Sid given is whether adjacency Sid of the router device or not.
416 * @param deviceId device identification of the router
417 * @param sid Sid to check
418 * @return true if the Sid given is the adjacency Sid of the device,
421 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
422 if (deviceConfigMap.get(deviceId) != null) {
423 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
426 for (AdjacencySid asid:
427 deviceConfigMap.get(deviceId).adjacencySids) {
428 if (asid.getAsid() == sid) {