1 package org.onosproject.segmentrouting;
3 import com.google.common.collect.Lists;
4 import org.onlab.packet.Ip4Address;
5 import org.onlab.packet.Ip4Prefix;
6 import org.onlab.packet.IpPrefix;
7 import org.onlab.packet.MacAddress;
8 import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
9 import org.onosproject.net.DeviceId;
10 import org.onosproject.net.PortNumber;
11 import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig;
12 import org.onosproject.segmentrouting.config.NetworkConfigManager;
13 import org.onosproject.segmentrouting.config.SegmentRouterConfig;
14 import org.onosproject.segmentrouting.config.SegmentRouterConfig.Subnet;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
18 import static com.google.common.base.Preconditions.checkNotNull;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
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.
30 * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
32 public class DeviceConfiguration implements DeviceProperties {
34 private static final Logger log = LoggerFactory
35 .getLogger(DeviceConfiguration.class);
36 private final List<Integer> allSegmentIds = new ArrayList<Integer>();
37 private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
38 private final NetworkConfigManager configService;
40 private class SegmentRouterInfo {
46 HashMap<PortNumber, Ip4Address> gatewayIps;
47 HashMap<PortNumber, Ip4Prefix> subnets;
48 List<SegmentRouterConfig.AdjacencySid> adjacencySids;
52 * Constructor. Reads all the configuration for all devices of type
53 * Segment Router and organizes into various maps for easier access.
55 * @param configService handle to network configuration manager
56 * component from where the relevant configuration is retrieved.
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)) {
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));
85 info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids();
86 this.deviceConfigMap.put(info.deviceId, info);
87 this.allSegmentIds.add(info.nodeSid);
93 * Returns the segment id of a segment router.
95 * @param deviceId device identifier
99 public int getSegmentId(DeviceId deviceId) {
100 if (deviceConfigMap.get(deviceId) != null) {
101 log.debug("getSegmentId for device{} is {}",
103 deviceConfigMap.get(deviceId).nodeSid);
104 return deviceConfigMap.get(deviceId).nodeSid;
106 log.warn("getSegmentId for device {} "
107 + "throwing IllegalStateException "
108 + "because device does not exist in config", deviceId);
109 throw new IllegalStateException();
114 * Returns the segment id of a segment router given its mac address.
116 * @param routerMac router mac address
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;
131 * Returns the segment id of a segment router given its router ip address.
133 * @param routerAddress router ip address
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;
148 * Returns the router mac of a segment router.
150 * @param deviceId device identifier
151 * @return router mac address
154 public MacAddress getDeviceMac(DeviceId deviceId) {
155 if (deviceConfigMap.get(deviceId) != null) {
156 log.debug("getDeviceMac for device{} is {}",
158 deviceConfigMap.get(deviceId).mac);
159 return deviceConfigMap.get(deviceId).mac;
161 log.warn("getDeviceMac for device {} "
162 + "throwing IllegalStateException "
163 + "because device does not exist in config", deviceId);
164 throw new IllegalStateException();
169 * Returns the router ip address of a segment router.
171 * @param deviceId device identifier
172 * @return router ip address
174 public Ip4Address getRouterIp(DeviceId deviceId) {
175 if (deviceConfigMap.get(deviceId) != null) {
176 log.debug("getDeviceIp for device{} is {}",
178 deviceConfigMap.get(deviceId).ip);
179 return deviceConfigMap.get(deviceId).ip;
181 log.warn("getRouterIp for device {} "
182 + "throwing IllegalStateException "
183 + "because device does not exist in config", deviceId);
184 throw new IllegalStateException();
189 * Indicates if the segment router is a edge router or
190 * a transit/back bone router.
192 * @param deviceId device identifier
196 public boolean isEdgeDevice(DeviceId deviceId) {
197 if (deviceConfigMap.get(deviceId) != null) {
198 log.debug("isEdgeDevice for device{} is {}",
200 deviceConfigMap.get(deviceId).isEdge);
201 return deviceConfigMap.get(deviceId).isEdge;
203 log.warn("isEdgeDevice for device {} "
204 + "throwing IllegalStateException "
205 + "because device does not exist in config", deviceId);
206 throw new IllegalStateException();
211 * Returns the segment ids of all configured segment routers.
213 * @return list of segment ids
216 public List<Integer> getAllDeviceSegmentIds() {
217 return allSegmentIds;
221 * Returns the device identifier or data plane identifier (dpid)
222 * of a segment router given its segment id.
224 * @param sid segment id
225 * @return deviceId device identifier
227 public DeviceId getDeviceId(int sid) {
228 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
229 deviceConfigMap.entrySet()) {
230 if (entry.getValue().nodeSid == sid) {
231 return entry.getValue().deviceId;
239 * Returns the device identifier or data plane identifier (dpid)
240 * of a segment router given its router ip address.
242 * @param ipAddress router ip address
243 * @return deviceId device identifier
245 public DeviceId getDeviceId(Ip4Address ipAddress) {
246 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
247 deviceConfigMap.entrySet()) {
248 if (entry.getValue().ip.equals(ipAddress)) {
249 return entry.getValue().deviceId;
257 * Returns the configured subnet gateway ip addresses for a segment router.
259 * @param deviceId device identifier
260 * @return list of ip addresses
262 public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
263 if (deviceConfigMap.get(deviceId) != null) {
264 log.debug("getSubnetGatewayIps for device{} is {}",
266 deviceConfigMap.get(deviceId).gatewayIps.values());
267 return new ArrayList<Ip4Address>(deviceConfigMap.
268 get(deviceId).gatewayIps.values());
275 * Returns the configured subnet prefixes for a segment router.
277 * @param deviceId device identifier
278 * @return list of ip prefixes
280 public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
281 if (deviceConfigMap.get(deviceId) != null) {
282 log.debug("getSubnets for device{} is {}",
284 deviceConfigMap.get(deviceId).subnets.values());
285 return new ArrayList<Ip4Prefix>(deviceConfigMap.
286 get(deviceId).subnets.values());
293 * Returns the router ip address of segment router that has the
294 * specified ip address in its subnets.
296 * @param destIpAddress target ip address
297 * @return router ip address
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;
309 log.debug("No router was found for {}", destIpAddress);
314 * Returns the router mac address of segment router that has the
315 * specified ip address as one of its subnet gateway ip address.
317 * @param gatewayIpAddress router gateway ip address
318 * @return router mac address
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;
329 log.debug("Cannot find a router for {}", gatewayIpAddress);
335 * Checks if the host is in the subnet defined in the router with the
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
344 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
346 List<Ip4Prefix> subnets = getSubnets(deviceId);
347 if (subnets == null) {
351 for (Ip4Prefix subnet: subnets) {
352 if (subnet.contains(hostIp)) {
361 * Returns the ports corresponding to the adjacency Sid given.
363 * @param deviceId device identification of the router
364 * @param sid adjacency Sid
365 * @return list of port numbers
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();
376 return Lists.newArrayList();
380 * Check if the Sid given is whether adjacency Sid of the router device or not.
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,
387 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
388 if (deviceConfigMap.get(deviceId) != null) {
389 if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
392 for (SegmentRouterConfig.AdjacencySid asid:
393 deviceConfigMap.get(deviceId).adjacencySids) {
394 if (asid.getAdjSid() == sid) {