blob: 255f740377db5c011982a5317cb90316cbbcb7a0 [file] [log] [blame]
Thomas Vachuska8fd25052015-09-10 16:15:33 -07001/*
Brian O'Connor43b53542016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska8fd25052015-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 */
Charles Chan319d1a22015-11-03 10:42:14 -080016package org.onosproject.segmentrouting.config;
sangho80f11cb2015-04-01 13:05:26 -070017
Charles Chan82ab1932016-01-30 23:22:37 -080018import com.google.common.collect.HashMultimap;
Charles Chanc6ad7752015-10-29 14:58:10 -070019import com.google.common.collect.ImmutableSet;
Charles Chan82ab1932016-01-30 23:22:37 -080020import com.google.common.collect.SetMultimap;
sangho80f11cb2015-04-01 13:05:26 -070021import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070022import org.onlab.packet.Ip4Prefix;
Pier Ventreadb4ae62016-11-23 09:57:42 -080023import org.onlab.packet.Ip6Address;
Charles Chandebfea32016-10-24 14:52:01 -070024import org.onlab.packet.IpAddress;
Charles Chan82ab1932016-01-30 23:22:37 -080025import org.onlab.packet.IpPrefix;
sangho80f11cb2015-04-01 13:05:26 -070026import org.onlab.packet.MacAddress;
Charles Chanb7f75ac2016-01-11 18:28:54 -080027import org.onlab.packet.VlanId;
Charles Chane7c61022015-10-07 14:21:45 -070028import org.onosproject.incubator.net.config.basics.ConfigException;
29import org.onosproject.incubator.net.config.basics.InterfaceConfig;
30import org.onosproject.incubator.net.intf.Interface;
31import org.onosproject.net.ConnectPoint;
Charles Chane7c61022015-10-07 14:21:45 -070032import org.onosproject.net.host.InterfaceIpAddress;
sangho80f11cb2015-04-01 13:05:26 -070033import org.onosproject.net.DeviceId;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070034import org.onosproject.net.PortNumber;
Charles Chan46fdfaf2016-11-09 20:51:44 -080035import org.onosproject.segmentrouting.SegmentRoutingManager;
sangho80f11cb2015-04-01 13:05:26 -070036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070039import java.util.ArrayList;
sangho80f11cb2015-04-01 13:05:26 -070040import java.util.HashMap;
Charles Chan9bec8a32015-12-01 10:00:51 -080041import java.util.HashSet;
sangho80f11cb2015-04-01 13:05:26 -070042import java.util.List;
43import java.util.Map;
Charles Chan72f556a2015-10-05 17:50:33 -070044import java.util.Set;
Saurav Das7c305372015-10-28 12:39:42 -070045import java.util.concurrent.ConcurrentHashMap;
Charles Chan46fdfaf2016-11-09 20:51:44 -080046import java.util.stream.Collectors;
sangho80f11cb2015-04-01 13:05:26 -070047
Charles Chanc22cef32016-04-29 14:38:22 -070048import static com.google.common.base.Preconditions.checkNotNull;
49
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070050/**
51 * Segment Routing configuration component that reads the
52 * segment routing related configuration from Network Configuration Manager
53 * component and organizes in more accessible formats.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070054 */
sangho80f11cb2015-04-01 13:05:26 -070055public class DeviceConfiguration implements DeviceProperties {
56
Charles Chan46fdfaf2016-11-09 20:51:44 -080057 private static final String ERROR_CONFIG = "Configuration error.";
58 private static final String TOO_MANY_SUBNET = ERROR_CONFIG + " Too many subnets configured on {}";
59 private static final String NO_SUBNET = "No subnet configured on {}";
60
Charles Chan43547ca2016-02-10 20:46:58 -080061 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -070062 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chanb7f75ac2016-01-11 18:28:54 -080063 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chan46fdfaf2016-11-09 20:51:44 -080064 private SegmentRoutingManager srManager;
sangho80f11cb2015-04-01 13:05:26 -070065
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070066 private class SegmentRouterInfo {
Pier Ventreadb4ae62016-11-23 09:57:42 -080067 int ipv4NodeSid;
68 int ipv6NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070069 DeviceId deviceId;
Pier Ventreadb4ae62016-11-23 09:57:42 -080070 Ip4Address ipv4Loopback;
71 Ip6Address ipv6Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070072 MacAddress mac;
73 boolean isEdge;
Charles Chan82ab1932016-01-30 23:22:37 -080074 Map<PortNumber, Ip4Address> gatewayIps;
75 SetMultimap<PortNumber, Ip4Prefix> subnets;
Charles Chan9bec8a32015-12-01 10:00:51 -080076 Map<Integer, Set<Integer>> adjacencySids;
Charles Chan2b078ae2015-10-14 11:24:40 -070077
78 public SegmentRouterInfo() {
Charles Chanb7f75ac2016-01-11 18:28:54 -080079 gatewayIps = new HashMap<>();
Charles Chan82ab1932016-01-30 23:22:37 -080080 subnets = HashMultimap.create();
Charles Chan2b078ae2015-10-14 11:24:40 -070081 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070082 }
sangho80f11cb2015-04-01 13:05:26 -070083
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070084 /**
Charles Chanb7f75ac2016-01-11 18:28:54 -080085 * Constructs device configuration for all Segment Router devices,
86 * organizing the data into various maps for easier access.
Brian O'Connor65eeb572015-10-09 17:03:44 -070087 *
Charles Chan46fdfaf2016-11-09 20:51:44 -080088 * @param srManager Segment Routing Manager
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070089 */
Charles Chan46fdfaf2016-11-09 20:51:44 -080090 public DeviceConfiguration(SegmentRoutingManager srManager) {
91 this.srManager = srManager;
Charles Chan57bd98c2016-02-22 19:27:29 -080092
Charles Chane7c61022015-10-07 14:21:45 -070093 // Read config from device subject, excluding gatewayIps and subnets.
94 Set<DeviceId> deviceSubjects =
Charles Chan46fdfaf2016-11-09 20:51:44 -080095 srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -070096 deviceSubjects.forEach(subject -> {
Charles Chan82ab1932016-01-30 23:22:37 -080097 SegmentRoutingDeviceConfig config =
Charles Chan46fdfaf2016-11-09 20:51:44 -080098 srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070099 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chan72f556a2015-10-05 17:50:33 -0700100 info.deviceId = subject;
Pier Ventreadb4ae62016-11-23 09:57:42 -0800101 info.ipv4NodeSid = config.nodeSidIPv4();
102 info.ipv6NodeSid = config.nodeSidIPv6();
103 info.ipv4Loopback = config.routerIpv4();
104 info.ipv6Loopback = config.routerIpv6();
Charles Chan9bec8a32015-12-01 10:00:51 -0800105 info.mac = config.routerMac();
Charles Chan72f556a2015-10-05 17:50:33 -0700106 info.isEdge = config.isEdgeRouter();
Charles Chan9bec8a32015-12-01 10:00:51 -0800107 info.adjacencySids = config.adjacencySids();
Charles Chanb7f75ac2016-01-11 18:28:54 -0800108 deviceConfigMap.put(info.deviceId, info);
Saurav Das07c74602016-04-27 18:35:50 -0700109 log.info("Read device config for device: {}", info.deviceId);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800110 /*
111 * IPv6 sid is not inserted. this part of the code is not used for now.
112 */
113 allSegmentIds.add(info.ipv4NodeSid);
Charles Chan72f556a2015-10-05 17:50:33 -0700114 });
Charles Chane7c61022015-10-07 14:21:45 -0700115
Charles Chan46fdfaf2016-11-09 20:51:44 -0800116 // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
117 Set<ConnectPoint> portSubjects = srManager.cfgService
118 .getSubjects(ConnectPoint.class, InterfaceConfig.class);
119 portSubjects.stream().filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
Charles Chane7c61022015-10-07 14:21:45 -0700120 InterfaceConfig config =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800121 srManager.cfgService.getConfig(subject, InterfaceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -0700122 Set<Interface> networkInterfaces;
123 try {
124 networkInterfaces = config.getInterfaces();
125 } catch (ConfigException e) {
126 log.error("Error loading port configuration");
127 return;
128 }
129 networkInterfaces.forEach(networkInterface -> {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800130 VlanId vlanId = networkInterface.vlan();
131 ConnectPoint connectPoint = networkInterface.connectPoint();
132 DeviceId dpid = connectPoint.deviceId();
133 PortNumber port = connectPoint.port();
134 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chane7c61022015-10-07 14:21:45 -0700135
Charles Chan2b078ae2015-10-14 11:24:40 -0700136 // skip if there is no corresponding device for this ConenctPoint
137 if (info != null) {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800138 // Extract subnet information
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800139 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chan2b078ae2015-10-14 11:24:40 -0700140 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan82ab1932016-01-30 23:22:37 -0800141 // Do not add /0 and /32 to gateway IP list
142 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
143 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
144 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
145 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700146 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
147 });
148 }
Charles Chane7c61022015-10-07 14:21:45 -0700149 });
Charles Chane7c61022015-10-07 14:21:45 -0700150 });
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700151 }
152
sangho80f11cb2015-04-01 13:05:26 -0700153 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800154 public boolean isConfigured(DeviceId deviceId) {
155 return deviceConfigMap.get(deviceId) != null;
156 }
157
158 @Override
Pier Ventreadb4ae62016-11-23 09:57:42 -0800159 public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700160 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
161 if (srinfo != null) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800162 log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
163 return srinfo.ipv4NodeSid;
sangho80f11cb2015-04-01 13:05:26 -0700164 } else {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800165 String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
166 throw new DeviceConfigNotFoundException(message);
167 }
168 }
169
170 @Override
171 public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
172 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
173 if (srinfo != null) {
174 log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
175 return srinfo.ipv6NodeSid;
176 } else {
177 String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
Charles Chan319d1a22015-11-03 10:42:14 -0800178 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700179 }
180 }
181
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700182 /**
Pier Ventreadb4ae62016-11-23 09:57:42 -0800183 * Returns the IPv4 Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700184 *
185 * @param routerMac router mac address
Saurav Das7c305372015-10-28 12:39:42 -0700186 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700187 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800188 public int getIPv4SegmentId(MacAddress routerMac) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700189 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
190 deviceConfigMap.entrySet()) {
191 if (entry.getValue().mac.equals(routerMac)) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800192 return entry.getValue().ipv4NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700193 }
194 }
sangho80f11cb2015-04-01 13:05:26 -0700195
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700196 return -1;
197 }
198
199 /**
Pier Ventreadb4ae62016-11-23 09:57:42 -0800200 * Returns the IPv6 Node segment id of a segment router given its Router mac address.
201 *
202 * @param routerMac router mac address
203 * @return node segment id, or -1 if not found in config
204 */
205 public int getIPv6SegmentId(MacAddress routerMac) {
206 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
207 deviceConfigMap.entrySet()) {
208 if (entry.getValue().mac.equals(routerMac)) {
209 return entry.getValue().ipv6NodeSid;
210 }
211 }
212
213 return -1;
214 }
215
216 /**
217 * Returns the IPv4 Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700218 *
219 * @param routerAddress router ip address
Saurav Das7c305372015-10-28 12:39:42 -0700220 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700221 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800222 public int getIPv4SegmentId(Ip4Address routerAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700223 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
224 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800225 if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
226 return entry.getValue().ipv4NodeSid;
227 }
228 }
229
230 return -1;
231 }
232
233 /**
234 * Returns the IPv6 Node segment id of a segment router given its Router ip address.
235 *
236 * @param routerAddress router ip address
237 * @return node segment id, or -1 if not found in config
238 */
239 public int getIPv6SegmentId(Ip6Address routerAddress) {
240 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
241 deviceConfigMap.entrySet()) {
242 if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
243 return entry.getValue().ipv6NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700244 }
245 }
246
247 return -1;
248 }
249
sangho80f11cb2015-04-01 13:05:26 -0700250 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800251 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700252 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
253 if (srinfo != null) {
254 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
255 return srinfo.mac;
sangho80f11cb2015-04-01 13:05:26 -0700256 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800257 String message = "getDeviceMac fails for device: " + deviceId + ".";
258 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700259 }
260 }
261
Charles Chan319d1a22015-11-03 10:42:14 -0800262 @Override
Pier Ventreadb4ae62016-11-23 09:57:42 -0800263 public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700264 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
265 if (srinfo != null) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800266 log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
267 return srinfo.ipv4Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700268 } else {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800269 String message = "getRouterIpv4 fails for device: " + deviceId + ".";
270 throw new DeviceConfigNotFoundException(message);
271 }
272 }
273
274 @Override
275 public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
276 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
277 if (srinfo != null) {
278 log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
279 return srinfo.ipv6Loopback;
280 } else {
281 String message = "getRouterIpv6 fails for device: " + deviceId + ".";
Charles Chan319d1a22015-11-03 10:42:14 -0800282 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700283 }
sangho80f11cb2015-04-01 13:05:26 -0700284 }
285
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700286 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800287 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700288 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
289 if (srinfo != null) {
290 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
291 return srinfo.isEdge;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700292 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800293 String message = "isEdgeDevice fails for device: " + deviceId + ".";
294 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700295 }
296 }
297
sangho80f11cb2015-04-01 13:05:26 -0700298 @Override
299 public List<Integer> getAllDeviceSegmentIds() {
300 return allSegmentIds;
301 }
302
Charles Chan77277672015-10-20 16:24:19 -0700303 @Override
Saurav Das52d4ed72016-03-28 19:00:18 -0700304 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
305 throws DeviceConfigNotFoundException {
306 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
307 if (srinfo == null) {
308 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
309 throw new DeviceConfigNotFoundException(message);
310 }
Charles Chan77277672015-10-20 16:24:19 -0700311 // Construct subnet-port mapping from port-subnet mapping
Saurav Das52d4ed72016-03-28 19:00:18 -0700312 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
313 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan82ab1932016-01-30 23:22:37 -0800314
315 portSubnetMap.entries().forEach(entry -> {
316 PortNumber port = entry.getKey();
317 Ip4Prefix subnet = entry.getValue();
318
Charles Chanbbd004c2016-02-16 23:14:49 -0800319 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
320 return;
321 }
322
Charles Chan77277672015-10-20 16:24:19 -0700323 if (subnetPortMap.containsKey(subnet)) {
324 subnetPortMap.get(subnet).add(port);
325 } else {
326 ArrayList<PortNumber> ports = new ArrayList<>();
327 ports.add(port);
328 subnetPortMap.put(subnet, ports);
329 }
330 });
Charles Chan77277672015-10-20 16:24:19 -0700331 return subnetPortMap;
332 }
333
sangho80f11cb2015-04-01 13:05:26 -0700334 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700335 * Returns the device identifier or data plane identifier (dpid)
336 * of a segment router given its segment id.
sangho80f11cb2015-04-01 13:05:26 -0700337 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700338 * @param sid segment id
339 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700340 */
341 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700342 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
343 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800344 if (entry.getValue().ipv4NodeSid == sid ||
345 entry.getValue().ipv6NodeSid == sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700346 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700347 }
348 }
349
350 return null;
351 }
352
353 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700354 * Returns the device identifier or data plane identifier (dpid)
355 * of a segment router given its router ip address.
sangho80f11cb2015-04-01 13:05:26 -0700356 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700357 * @param ipAddress router ip address
358 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700359 */
360 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700361 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
362 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800363 if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
364 return entry.getValue().deviceId;
365 }
366 }
367
368 return null;
369 }
370
371 /**
372 * Returns the device identifier or data plane identifier (dpid)
373 * of a segment router given its router ipv6 address.
374 *
375 * @param ipAddress router ipv6 address
376 * @return deviceId device identifier
377 */
378 public DeviceId getDeviceId(Ip6Address ipAddress) {
379 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
380 deviceConfigMap.entrySet()) {
381 if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700382 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700383 }
384 }
385
386 return null;
387 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700388
389 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700390 * Returns the configured port ip addresses for a segment router.
391 * These addresses serve as gateway IP addresses for the subnets configured
392 * on those ports.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700393 *
394 * @param deviceId device identifier
Saurav Dasc28b3432015-10-30 17:45:38 -0700395 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700396 */
Saurav Dasc28b3432015-10-30 17:45:38 -0700397 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700398 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
399 if (srinfo != null) {
400 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
401 srinfo.gatewayIps.values());
Saurav Dasc28b3432015-10-30 17:45:38 -0700402 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700403 }
Saurav Das7c305372015-10-28 12:39:42 -0700404 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700405 }
406
407 /**
408 * Returns the configured subnet prefixes for a segment router.
409 *
410 * @param deviceId device identifier
Saurav Das7c305372015-10-28 12:39:42 -0700411 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700412 */
Charles Chanc6ad7752015-10-29 14:58:10 -0700413 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700414 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
415 if (srinfo != null) {
Charles Chan43547ca2016-02-10 20:46:58 -0800416 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
Charles Chandebfea32016-10-24 14:52:01 -0700417 return builder.addAll(srinfo.subnets.values()).build();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700418 }
Saurav Das7c305372015-10-28 12:39:42 -0700419 return null;
420 }
421
Charles Chan46fdfaf2016-11-09 20:51:44 -0800422
Saurav Das7c305372015-10-28 12:39:42 -0700423 /**
Charles Chan46fdfaf2016-11-09 20:51:44 -0800424 * Returns the subnet configuration of given device and port.
Saurav Das7c305372015-10-28 12:39:42 -0700425 *
Charles Chan46fdfaf2016-11-09 20:51:44 -0800426 * @param deviceId Device ID
427 * @param port Port number
428 * @return The subnet configured on given port or null if
429 * the port is unconfigured, misconfigured or suppressed.
Saurav Das7c305372015-10-28 12:39:42 -0700430 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800431 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber port) {
432 ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
433
434 if (isSuppressedPort(connectPoint)) {
435 return null;
Saurav Das7c305372015-10-28 12:39:42 -0700436 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800437
438 Set<Ip4Prefix> subnets =
439 srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
440 .flatMap(intf -> intf.ipAddressesList().stream())
441 .map(InterfaceIpAddress::subnetAddress)
442 .map(IpPrefix::getIp4Prefix)
443 .collect(Collectors.toSet());
444
Jon Hall31d84782017-01-18 20:15:44 -0800445 if (subnets.isEmpty()) {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800446 log.info(NO_SUBNET, connectPoint);
447 return null;
448 } else if (subnets.size() > 1) {
449 log.warn(TOO_MANY_SUBNET, connectPoint);
450 return null;
451 } else {
452 return subnets.stream().findFirst().orElse(null);
453 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700454 }
455
456 /**
457 * Returns the router ip address of segment router that has the
458 * specified ip address in its subnets.
459 *
460 * @param destIpAddress target ip address
461 * @return router ip address
462 */
463 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
Charles Chan70661362016-12-09 12:54:49 -0800464 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
465
466 if (matchIntf == null) {
467 log.debug("No router was found for {}", destIpAddress);
468 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700469 }
470
Charles Chan70661362016-12-09 12:54:49 -0800471 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
472 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
473 if (srInfo == null) {
474 log.debug("No device config was found for {}", routerDeviceId);
475 return null;
476 }
477
Pier Ventreadb4ae62016-11-23 09:57:42 -0800478 return srInfo.ipv4Loopback;
479 }
480
481 /**
482 * Returns the router ipv6 address of segment router that has the
483 * specified ip address in its subnets.
484 *
485 * @param destIpAddress target ip address
486 * @return router ip address
487 */
488 public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
489 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
490
491 if (matchIntf == null) {
492 log.debug("No router was found for {}", destIpAddress);
493 return null;
494 }
495
496 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
497 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
498 if (srInfo == null) {
499 log.debug("No device config was found for {}", routerDeviceId);
500 return null;
501 }
502
503 return srInfo.ipv6Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700504 }
505
506 /**
507 * Returns the router mac address of segment router that has the
508 * specified ip address as one of its subnet gateway ip address.
509 *
510 * @param gatewayIpAddress router gateway ip address
Saurav Das7c305372015-10-28 12:39:42 -0700511 * @return router mac address or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700512 */
513 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
514 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
515 deviceConfigMap.entrySet()) {
516 if (entry.getValue().gatewayIps.
517 values().contains(gatewayIpAddress)) {
518 return entry.getValue().mac;
519 }
520 }
521
522 log.debug("Cannot find a router for {}", gatewayIpAddress);
523 return null;
524 }
sangho9b169e32015-04-14 16:27:13 -0700525
526
527 /**
528 * Checks if the host is in the subnet defined in the router with the
529 * device ID given.
530 *
531 * @param deviceId device identification of the router
532 * @param hostIp host IP address to check
533 * @return true if the host is within the subnet of the router,
534 * false if no subnet is defined under the router or if the host is not
535 * within the subnet defined in the router
536 */
537 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
538
Charles Chanc6ad7752015-10-29 14:58:10 -0700539 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho9b169e32015-04-14 16:27:13 -0700540 if (subnets == null) {
541 return false;
542 }
543
544 for (Ip4Prefix subnet: subnets) {
Charles Chan82ab1932016-01-30 23:22:37 -0800545 // Exclude /0 since it is a special case used for default route
546 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho9b169e32015-04-14 16:27:13 -0700547 return true;
548 }
549 }
550
551 return false;
552 }
sangho27462c62015-05-14 00:39:53 -0700553
554 /**
Charles Chandebfea32016-10-24 14:52:01 -0700555 * Checks if the IP is in the subnet defined on given connect point.
556 *
557 * @param connectPoint Connect point
558 * @param ip The IP address to check
559 * @return True if the IP belongs to the subnet.
560 * False if the IP does not belong to the subnet, or
561 * there is no subnet configuration on given connect point.
562 */
563 public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
564 Ip4Prefix portSubnet = getPortSubnet(connectPoint.deviceId(), connectPoint.port());
565 return portSubnet != null && portSubnet.contains(ip);
566 }
567
568 /**
sangho27462c62015-05-14 00:39:53 -0700569 * Returns the ports corresponding to the adjacency Sid given.
570 *
571 * @param deviceId device identification of the router
572 * @param sid adjacency Sid
Charles Chan9bec8a32015-12-01 10:00:51 -0800573 * @return set of port numbers
sangho27462c62015-05-14 00:39:53 -0700574 */
Charles Chan9bec8a32015-12-01 10:00:51 -0800575 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700576 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800577 return srinfo != null ?
578 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
579 ImmutableSet.copyOf(new HashSet<>());
sangho27462c62015-05-14 00:39:53 -0700580 }
581
582 /**
583 * Check if the Sid given is whether adjacency Sid of the router device or not.
584 *
585 * @param deviceId device identification of the router
586 * @param sid Sid to check
587 * @return true if the Sid given is the adjacency Sid of the device,
588 * otherwise false
589 */
590 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700591 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800592 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho27462c62015-05-14 00:39:53 -0700593 }
Charles Chan43547ca2016-02-10 20:46:58 -0800594
Charles Chanc91c8782016-03-30 17:54:24 -0700595 /**
Charles Chanc22cef32016-04-29 14:38:22 -0700596 * Add subnet to specific connect point.
597 *
598 * @param cp connect point
599 * @param ip4Prefix subnet being added to the device
600 */
601 public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
602 checkNotNull(cp);
603 checkNotNull(ip4Prefix);
604 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
605 if (srinfo == null) {
606 log.warn("Device {} is not configured. Abort.", cp.deviceId());
607 return;
608 }
609 srinfo.subnets.put(cp.port(), ip4Prefix);
610 }
611
612 /**
613 * Remove subnet from specific connect point.
614 *
615 * @param cp connect point
616 * @param ip4Prefix subnet being removed to the device
617 */
618 public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
619 checkNotNull(cp);
620 checkNotNull(ip4Prefix);
621 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
622 if (srinfo == null) {
623 log.warn("Device {} is not configured. Abort.", cp.deviceId());
624 return;
625 }
626 srinfo.subnets.remove(cp.port(), ip4Prefix);
627 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800628
629 private boolean isSuppressedPort(ConnectPoint connectPoint) {
630 SegmentRoutingAppConfig appConfig = srManager.cfgService
631 .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
632 if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
Charles Chandebfea32016-10-24 14:52:01 -0700633 log.info("Interface configuration on port {} is ignored", connectPoint);
Charles Chan46fdfaf2016-11-09 20:51:44 -0800634 return true;
635 }
636 return false;
637 }
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800638}