blob: 15e9fa775834318f193b477fa3fde773c2692c29 [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present 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 */
Charles Chan0b4e6182015-11-03 10:42:14 -080016package org.onosproject.segmentrouting.config;
sanghob35a6192015-04-01 13:05:26 -070017
Charles Chan5270ed02016-01-30 23:22:37 -080018import com.google.common.collect.HashMultimap;
Charles Chan9f676b62015-10-29 14:58:10 -070019import com.google.common.collect.ImmutableSet;
Charles Chan5270ed02016-01-30 23:22:37 -080020import com.google.common.collect.SetMultimap;
sanghob35a6192015-04-01 13:05:26 -070021import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070022import org.onlab.packet.Ip4Prefix;
Charles Chan5270ed02016-01-30 23:22:37 -080023import org.onlab.packet.IpPrefix;
sanghob35a6192015-04-01 13:05:26 -070024import org.onlab.packet.MacAddress;
Charles Chane849c192016-01-11 18:28:54 -080025import org.onlab.packet.VlanId;
Charles Chan4636be02015-10-07 14:21:45 -070026import org.onosproject.incubator.net.config.basics.ConfigException;
27import org.onosproject.incubator.net.config.basics.InterfaceConfig;
28import org.onosproject.incubator.net.intf.Interface;
29import org.onosproject.net.ConnectPoint;
Charles Chan4636be02015-10-07 14:21:45 -070030import org.onosproject.net.host.InterfaceIpAddress;
sanghob35a6192015-04-01 13:05:26 -070031import org.onosproject.net.DeviceId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070032import org.onosproject.net.PortNumber;
Charles Chan2c15aca2016-11-09 20:51:44 -080033import org.onosproject.segmentrouting.SegmentRoutingManager;
sanghob35a6192015-04-01 13:05:26 -070034import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070037import java.util.ArrayList;
sanghob35a6192015-04-01 13:05:26 -070038import java.util.HashMap;
Charles Chan531a78b2015-12-01 10:00:51 -080039import java.util.HashSet;
sanghob35a6192015-04-01 13:05:26 -070040import java.util.List;
41import java.util.Map;
Charles Chand6832882015-10-05 17:50:33 -070042import java.util.Set;
Saurav Das0e99e2b2015-10-28 12:39:42 -070043import java.util.concurrent.ConcurrentHashMap;
Charles Chan2c15aca2016-11-09 20:51:44 -080044import java.util.stream.Collectors;
sanghob35a6192015-04-01 13:05:26 -070045
Charles Chan93e71ba2016-04-29 14:38:22 -070046import static com.google.common.base.Preconditions.checkNotNull;
47
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070048/**
49 * Segment Routing configuration component that reads the
50 * segment routing related configuration from Network Configuration Manager
51 * component and organizes in more accessible formats.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070052 */
sanghob35a6192015-04-01 13:05:26 -070053public class DeviceConfiguration implements DeviceProperties {
54
Charles Chan2c15aca2016-11-09 20:51:44 -080055 private static final String ERROR_CONFIG = "Configuration error.";
56 private static final String TOO_MANY_SUBNET = ERROR_CONFIG + " Too many subnets configured on {}";
57 private static final String NO_SUBNET = "No subnet configured on {}";
58
Charles Chanf2565a92016-02-10 20:46:58 -080059 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070060 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chane849c192016-01-11 18:28:54 -080061 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chan2c15aca2016-11-09 20:51:44 -080062 private SegmentRoutingManager srManager;
sanghob35a6192015-04-01 13:05:26 -070063
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070064 private class SegmentRouterInfo {
65 int nodeSid;
66 DeviceId deviceId;
67 Ip4Address ip;
68 MacAddress mac;
69 boolean isEdge;
Charles Chan5270ed02016-01-30 23:22:37 -080070 Map<PortNumber, Ip4Address> gatewayIps;
71 SetMultimap<PortNumber, Ip4Prefix> subnets;
Charles Chan531a78b2015-12-01 10:00:51 -080072 Map<Integer, Set<Integer>> adjacencySids;
Charles Chanb8e10c82015-10-14 11:24:40 -070073
74 public SegmentRouterInfo() {
Charles Chane849c192016-01-11 18:28:54 -080075 gatewayIps = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -080076 subnets = HashMultimap.create();
Charles Chanb8e10c82015-10-14 11:24:40 -070077 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070078 }
sanghob35a6192015-04-01 13:05:26 -070079
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070080 /**
Charles Chane849c192016-01-11 18:28:54 -080081 * Constructs device configuration for all Segment Router devices,
82 * organizing the data into various maps for easier access.
Brian O'Connor52515622015-10-09 17:03:44 -070083 *
Charles Chan2c15aca2016-11-09 20:51:44 -080084 * @param srManager Segment Routing Manager
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070085 */
Charles Chan2c15aca2016-11-09 20:51:44 -080086 public DeviceConfiguration(SegmentRoutingManager srManager) {
87 this.srManager = srManager;
Charles Chand9681e72016-02-22 19:27:29 -080088
Charles Chan4636be02015-10-07 14:21:45 -070089 // Read config from device subject, excluding gatewayIps and subnets.
90 Set<DeviceId> deviceSubjects =
Charles Chan2c15aca2016-11-09 20:51:44 -080091 srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070092 deviceSubjects.forEach(subject -> {
Charles Chan5270ed02016-01-30 23:22:37 -080093 SegmentRoutingDeviceConfig config =
Charles Chan2c15aca2016-11-09 20:51:44 -080094 srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070095 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070096 info.deviceId = subject;
Charles Chan531a78b2015-12-01 10:00:51 -080097 info.nodeSid = config.nodeSid();
98 info.ip = config.routerIp();
99 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -0700100 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800101 info.adjacencySids = config.adjacencySids();
Charles Chane849c192016-01-11 18:28:54 -0800102 deviceConfigMap.put(info.deviceId, info);
Saurav Das59232cf2016-04-27 18:35:50 -0700103 log.info("Read device config for device: {}", info.deviceId);
Charles Chane849c192016-01-11 18:28:54 -0800104 allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700105 });
Charles Chan4636be02015-10-07 14:21:45 -0700106
Charles Chan2c15aca2016-11-09 20:51:44 -0800107 // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
108 Set<ConnectPoint> portSubjects = srManager.cfgService
109 .getSubjects(ConnectPoint.class, InterfaceConfig.class);
110 portSubjects.stream().filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
Charles Chan4636be02015-10-07 14:21:45 -0700111 InterfaceConfig config =
Charles Chan2c15aca2016-11-09 20:51:44 -0800112 srManager.cfgService.getConfig(subject, InterfaceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -0700113 Set<Interface> networkInterfaces;
114 try {
115 networkInterfaces = config.getInterfaces();
116 } catch (ConfigException e) {
117 log.error("Error loading port configuration");
118 return;
119 }
120 networkInterfaces.forEach(networkInterface -> {
Charles Chane849c192016-01-11 18:28:54 -0800121 VlanId vlanId = networkInterface.vlan();
122 ConnectPoint connectPoint = networkInterface.connectPoint();
123 DeviceId dpid = connectPoint.deviceId();
124 PortNumber port = connectPoint.port();
125 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chan4636be02015-10-07 14:21:45 -0700126
Charles Chanb8e10c82015-10-14 11:24:40 -0700127 // skip if there is no corresponding device for this ConenctPoint
128 if (info != null) {
Charles Chane849c192016-01-11 18:28:54 -0800129 // Extract subnet information
Jonathan Hart00cddda2016-02-16 10:30:37 -0800130 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chanb8e10c82015-10-14 11:24:40 -0700131 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan5270ed02016-01-30 23:22:37 -0800132 // Do not add /0 and /32 to gateway IP list
133 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
134 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
135 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
136 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700137 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
138 });
139 }
Charles Chan4636be02015-10-07 14:21:45 -0700140 });
Charles Chan4636be02015-10-07 14:21:45 -0700141 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700142 }
143
sanghob35a6192015-04-01 13:05:26 -0700144 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800145 public boolean isConfigured(DeviceId deviceId) {
146 return deviceConfigMap.get(deviceId) != null;
147 }
148
149 @Override
150 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700151 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
152 if (srinfo != null) {
153 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
154 return srinfo.nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700155 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800156 String message = "getSegmentId fails for device: " + deviceId + ".";
157 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700158 }
159 }
160
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700161 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700162 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700163 *
164 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700165 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700166 */
167 public int getSegmentId(MacAddress routerMac) {
168 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
169 deviceConfigMap.entrySet()) {
170 if (entry.getValue().mac.equals(routerMac)) {
171 return entry.getValue().nodeSid;
172 }
173 }
sanghob35a6192015-04-01 13:05:26 -0700174
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700175 return -1;
176 }
177
178 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700179 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700180 *
181 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700182 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700183 */
184 public int getSegmentId(Ip4Address routerAddress) {
185 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
186 deviceConfigMap.entrySet()) {
187 if (entry.getValue().ip.equals(routerAddress)) {
188 return entry.getValue().nodeSid;
189 }
190 }
191
192 return -1;
193 }
194
sanghob35a6192015-04-01 13:05:26 -0700195 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800196 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700197 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
198 if (srinfo != null) {
199 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
200 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700201 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800202 String message = "getDeviceMac fails for device: " + deviceId + ".";
203 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700204 }
205 }
206
Charles Chan0b4e6182015-11-03 10:42:14 -0800207 @Override
208 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700209 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
210 if (srinfo != null) {
211 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
212 return srinfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700213 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800214 String message = "getRouterIp fails for device: " + deviceId + ".";
215 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700216 }
sanghob35a6192015-04-01 13:05:26 -0700217 }
218
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700219 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800220 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700221 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
222 if (srinfo != null) {
223 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
224 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700225 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800226 String message = "isEdgeDevice fails for device: " + deviceId + ".";
227 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700228 }
229 }
230
sanghob35a6192015-04-01 13:05:26 -0700231 @Override
232 public List<Integer> getAllDeviceSegmentIds() {
233 return allSegmentIds;
234 }
235
Charles Chanc42e84e2015-10-20 16:24:19 -0700236 @Override
Saurav Das7a1ffca2016-03-28 19:00:18 -0700237 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
238 throws DeviceConfigNotFoundException {
239 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
240 if (srinfo == null) {
241 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
242 throw new DeviceConfigNotFoundException(message);
243 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700244 // Construct subnet-port mapping from port-subnet mapping
Saurav Das7a1ffca2016-03-28 19:00:18 -0700245 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
246 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -0800247
248 portSubnetMap.entries().forEach(entry -> {
249 PortNumber port = entry.getKey();
250 Ip4Prefix subnet = entry.getValue();
251
Charles Chand0fd5dc2016-02-16 23:14:49 -0800252 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
253 return;
254 }
255
Charles Chanc42e84e2015-10-20 16:24:19 -0700256 if (subnetPortMap.containsKey(subnet)) {
257 subnetPortMap.get(subnet).add(port);
258 } else {
259 ArrayList<PortNumber> ports = new ArrayList<>();
260 ports.add(port);
261 subnetPortMap.put(subnet, ports);
262 }
263 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700264 return subnetPortMap;
265 }
266
sanghob35a6192015-04-01 13:05:26 -0700267 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700268 * Returns the device identifier or data plane identifier (dpid)
269 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700270 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700271 * @param sid segment id
272 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700273 */
274 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700275 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
276 deviceConfigMap.entrySet()) {
277 if (entry.getValue().nodeSid == sid) {
278 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700279 }
280 }
281
282 return null;
283 }
284
285 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700286 * Returns the device identifier or data plane identifier (dpid)
287 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700288 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700289 * @param ipAddress router ip address
290 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700291 */
292 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700293 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
294 deviceConfigMap.entrySet()) {
295 if (entry.getValue().ip.equals(ipAddress)) {
296 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700297 }
298 }
299
300 return null;
301 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700302
303 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700304 * Returns the configured port ip addresses for a segment router.
305 * These addresses serve as gateway IP addresses for the subnets configured
306 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700307 *
308 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700309 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700310 */
Saurav Das837e0bb2015-10-30 17:45:38 -0700311 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700312 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
313 if (srinfo != null) {
314 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
315 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700316 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700317 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700318 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700319 }
320
321 /**
322 * Returns the configured subnet prefixes for a segment router.
323 *
324 * @param deviceId device identifier
Saurav Das0e99e2b2015-10-28 12:39:42 -0700325 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700326 */
Charles Chan9f676b62015-10-29 14:58:10 -0700327 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700328 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
329 if (srinfo != null) {
330 log.trace("getSubnets for device{} is {}", deviceId,
331 srinfo.subnets.values());
Charles Chanf2565a92016-02-10 20:46:58 -0800332
333 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
334 builder.addAll(srinfo.subnets.values());
Charles Chan2196a922016-03-07 00:49:33 -0800335 SegmentRoutingAppConfig appConfig =
Charles Chan2c15aca2016-11-09 20:51:44 -0800336 srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
Charles Chan2196a922016-03-07 00:49:33 -0800337 if (appConfig != null) {
338 if (deviceId.equals(appConfig.vRouterId().orElse(null))) {
339 builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
340 }
Charles Chanf2565a92016-02-10 20:46:58 -0800341 }
342 return builder.build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700343 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700344 return null;
345 }
346
Charles Chan2c15aca2016-11-09 20:51:44 -0800347
Saurav Das0e99e2b2015-10-28 12:39:42 -0700348 /**
Charles Chan2c15aca2016-11-09 20:51:44 -0800349 * Returns the subnet configuration of given device and port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700350 *
Charles Chan2c15aca2016-11-09 20:51:44 -0800351 * @param deviceId Device ID
352 * @param port Port number
353 * @return The subnet configured on given port or null if
354 * the port is unconfigured, misconfigured or suppressed.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700355 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800356 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber port) {
357 ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
358
359 if (isSuppressedPort(connectPoint)) {
360 return null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700361 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800362
363 Set<Ip4Prefix> subnets =
364 srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
365 .flatMap(intf -> intf.ipAddressesList().stream())
366 .map(InterfaceIpAddress::subnetAddress)
367 .map(IpPrefix::getIp4Prefix)
368 .collect(Collectors.toSet());
369
370 if (subnets.size() == 0) {
371 log.info(NO_SUBNET, connectPoint);
372 return null;
373 } else if (subnets.size() > 1) {
374 log.warn(TOO_MANY_SUBNET, connectPoint);
375 return null;
376 } else {
377 return subnets.stream().findFirst().orElse(null);
378 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700379 }
380
381 /**
382 * Returns the router ip address of segment router that has the
383 * specified ip address in its subnets.
384 *
385 * @param destIpAddress target ip address
386 * @return router ip address
387 */
388 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
389 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
390 deviceConfigMap.entrySet()) {
Charles Chan5270ed02016-01-30 23:22:37 -0800391 for (Ip4Prefix prefix : entry.getValue().subnets.values()) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700392 if (prefix.contains(destIpAddress)) {
393 return entry.getValue().ip;
394 }
395 }
396 }
397
398 log.debug("No router was found for {}", destIpAddress);
399 return null;
400 }
401
402 /**
403 * Returns the router mac address of segment router that has the
404 * specified ip address as one of its subnet gateway ip address.
405 *
406 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700407 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700408 */
409 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
410 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
411 deviceConfigMap.entrySet()) {
412 if (entry.getValue().gatewayIps.
413 values().contains(gatewayIpAddress)) {
414 return entry.getValue().mac;
415 }
416 }
417
418 log.debug("Cannot find a router for {}", gatewayIpAddress);
419 return null;
420 }
sangho666cd6d2015-04-14 16:27:13 -0700421
422
423 /**
424 * Checks if the host is in the subnet defined in the router with the
425 * device ID given.
426 *
427 * @param deviceId device identification of the router
428 * @param hostIp host IP address to check
429 * @return true if the host is within the subnet of the router,
430 * false if no subnet is defined under the router or if the host is not
431 * within the subnet defined in the router
432 */
433 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
434
Charles Chan9f676b62015-10-29 14:58:10 -0700435 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700436 if (subnets == null) {
437 return false;
438 }
439
440 for (Ip4Prefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800441 // Exclude /0 since it is a special case used for default route
442 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700443 return true;
444 }
445 }
446
447 return false;
448 }
sangho1e575652015-05-14 00:39:53 -0700449
450 /**
451 * Returns the ports corresponding to the adjacency Sid given.
452 *
453 * @param deviceId device identification of the router
454 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800455 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700456 */
Charles Chan531a78b2015-12-01 10:00:51 -0800457 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700458 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800459 return srinfo != null ?
460 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
461 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700462 }
463
464 /**
465 * Check if the Sid given is whether adjacency Sid of the router device or not.
466 *
467 * @param deviceId device identification of the router
468 * @param sid Sid to check
469 * @return true if the Sid given is the adjacency Sid of the device,
470 * otherwise false
471 */
472 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700473 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800474 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700475 }
Charles Chanf2565a92016-02-10 20:46:58 -0800476
Charles Chand55e84d2016-03-30 17:54:24 -0700477 /**
Charles Chan93e71ba2016-04-29 14:38:22 -0700478 * Add subnet to specific connect point.
479 *
480 * @param cp connect point
481 * @param ip4Prefix subnet being added to the device
482 */
483 public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
484 checkNotNull(cp);
485 checkNotNull(ip4Prefix);
486 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
487 if (srinfo == null) {
488 log.warn("Device {} is not configured. Abort.", cp.deviceId());
489 return;
490 }
491 srinfo.subnets.put(cp.port(), ip4Prefix);
492 }
493
494 /**
495 * Remove subnet from specific connect point.
496 *
497 * @param cp connect point
498 * @param ip4Prefix subnet being removed to the device
499 */
500 public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
501 checkNotNull(cp);
502 checkNotNull(ip4Prefix);
503 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
504 if (srinfo == null) {
505 log.warn("Device {} is not configured. Abort.", cp.deviceId());
506 return;
507 }
508 srinfo.subnets.remove(cp.port(), ip4Prefix);
509 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800510
511 private boolean isSuppressedPort(ConnectPoint connectPoint) {
512 SegmentRoutingAppConfig appConfig = srManager.cfgService
513 .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
514 if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
515 log.info("Ignore suppressed port {}", connectPoint);
516 return true;
517 }
518 return false;
519 }
Jonathan Hart00cddda2016-02-16 10:30:37 -0800520}