blob: 2bd993200ee3559583a4134e4da107a639aae56e [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 Chan03a73e02016-10-24 14:52:01 -070023import org.onlab.packet.IpAddress;
Charles Chan5270ed02016-01-30 23:22:37 -080024import org.onlab.packet.IpPrefix;
sanghob35a6192015-04-01 13:05:26 -070025import org.onlab.packet.MacAddress;
Charles Chane849c192016-01-11 18:28:54 -080026import org.onlab.packet.VlanId;
Charles Chan4636be02015-10-07 14:21:45 -070027import org.onosproject.incubator.net.config.basics.ConfigException;
28import org.onosproject.incubator.net.config.basics.InterfaceConfig;
29import org.onosproject.incubator.net.intf.Interface;
30import org.onosproject.net.ConnectPoint;
Charles Chan4636be02015-10-07 14:21:45 -070031import org.onosproject.net.host.InterfaceIpAddress;
sanghob35a6192015-04-01 13:05:26 -070032import org.onosproject.net.DeviceId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070033import org.onosproject.net.PortNumber;
Charles Chan2c15aca2016-11-09 20:51:44 -080034import org.onosproject.segmentrouting.SegmentRoutingManager;
sanghob35a6192015-04-01 13:05:26 -070035import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070038import java.util.ArrayList;
sanghob35a6192015-04-01 13:05:26 -070039import java.util.HashMap;
Charles Chan531a78b2015-12-01 10:00:51 -080040import java.util.HashSet;
sanghob35a6192015-04-01 13:05:26 -070041import java.util.List;
42import java.util.Map;
Charles Chand6832882015-10-05 17:50:33 -070043import java.util.Set;
Saurav Das0e99e2b2015-10-28 12:39:42 -070044import java.util.concurrent.ConcurrentHashMap;
Charles Chan2c15aca2016-11-09 20:51:44 -080045import java.util.stream.Collectors;
sanghob35a6192015-04-01 13:05:26 -070046
Charles Chan93e71ba2016-04-29 14:38:22 -070047import static com.google.common.base.Preconditions.checkNotNull;
48
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070049/**
50 * Segment Routing configuration component that reads the
51 * segment routing related configuration from Network Configuration Manager
52 * component and organizes in more accessible formats.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070053 */
sanghob35a6192015-04-01 13:05:26 -070054public class DeviceConfiguration implements DeviceProperties {
55
Charles Chan2c15aca2016-11-09 20:51:44 -080056 private static final String ERROR_CONFIG = "Configuration error.";
57 private static final String TOO_MANY_SUBNET = ERROR_CONFIG + " Too many subnets configured on {}";
58 private static final String NO_SUBNET = "No subnet configured on {}";
59
Charles Chanf2565a92016-02-10 20:46:58 -080060 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070061 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chane849c192016-01-11 18:28:54 -080062 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chan2c15aca2016-11-09 20:51:44 -080063 private SegmentRoutingManager srManager;
sanghob35a6192015-04-01 13:05:26 -070064
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070065 private class SegmentRouterInfo {
66 int nodeSid;
67 DeviceId deviceId;
68 Ip4Address ip;
69 MacAddress mac;
70 boolean isEdge;
Charles Chan5270ed02016-01-30 23:22:37 -080071 Map<PortNumber, Ip4Address> gatewayIps;
72 SetMultimap<PortNumber, Ip4Prefix> subnets;
Charles Chan531a78b2015-12-01 10:00:51 -080073 Map<Integer, Set<Integer>> adjacencySids;
Charles Chanb8e10c82015-10-14 11:24:40 -070074
75 public SegmentRouterInfo() {
Charles Chane849c192016-01-11 18:28:54 -080076 gatewayIps = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -080077 subnets = HashMultimap.create();
Charles Chanb8e10c82015-10-14 11:24:40 -070078 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070079 }
sanghob35a6192015-04-01 13:05:26 -070080
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070081 /**
Charles Chane849c192016-01-11 18:28:54 -080082 * Constructs device configuration for all Segment Router devices,
83 * organizing the data into various maps for easier access.
Brian O'Connor52515622015-10-09 17:03:44 -070084 *
Charles Chan2c15aca2016-11-09 20:51:44 -080085 * @param srManager Segment Routing Manager
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070086 */
Charles Chan2c15aca2016-11-09 20:51:44 -080087 public DeviceConfiguration(SegmentRoutingManager srManager) {
88 this.srManager = srManager;
Charles Chand9681e72016-02-22 19:27:29 -080089
Charles Chan4636be02015-10-07 14:21:45 -070090 // Read config from device subject, excluding gatewayIps and subnets.
91 Set<DeviceId> deviceSubjects =
Charles Chan2c15aca2016-11-09 20:51:44 -080092 srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070093 deviceSubjects.forEach(subject -> {
Charles Chan5270ed02016-01-30 23:22:37 -080094 SegmentRoutingDeviceConfig config =
Charles Chan2c15aca2016-11-09 20:51:44 -080095 srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070096 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070097 info.deviceId = subject;
Charles Chan531a78b2015-12-01 10:00:51 -080098 info.nodeSid = config.nodeSid();
99 info.ip = config.routerIp();
100 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -0700101 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800102 info.adjacencySids = config.adjacencySids();
Charles Chane849c192016-01-11 18:28:54 -0800103 deviceConfigMap.put(info.deviceId, info);
Saurav Das59232cf2016-04-27 18:35:50 -0700104 log.info("Read device config for device: {}", info.deviceId);
Charles Chane849c192016-01-11 18:28:54 -0800105 allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700106 });
Charles Chan4636be02015-10-07 14:21:45 -0700107
Charles Chan2c15aca2016-11-09 20:51:44 -0800108 // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
109 Set<ConnectPoint> portSubjects = srManager.cfgService
110 .getSubjects(ConnectPoint.class, InterfaceConfig.class);
111 portSubjects.stream().filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
Charles Chan4636be02015-10-07 14:21:45 -0700112 InterfaceConfig config =
Charles Chan2c15aca2016-11-09 20:51:44 -0800113 srManager.cfgService.getConfig(subject, InterfaceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -0700114 Set<Interface> networkInterfaces;
115 try {
116 networkInterfaces = config.getInterfaces();
117 } catch (ConfigException e) {
118 log.error("Error loading port configuration");
119 return;
120 }
121 networkInterfaces.forEach(networkInterface -> {
Charles Chane849c192016-01-11 18:28:54 -0800122 VlanId vlanId = networkInterface.vlan();
123 ConnectPoint connectPoint = networkInterface.connectPoint();
124 DeviceId dpid = connectPoint.deviceId();
125 PortNumber port = connectPoint.port();
126 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chan4636be02015-10-07 14:21:45 -0700127
Charles Chanb8e10c82015-10-14 11:24:40 -0700128 // skip if there is no corresponding device for this ConenctPoint
129 if (info != null) {
Charles Chane849c192016-01-11 18:28:54 -0800130 // Extract subnet information
Jonathan Hart00cddda2016-02-16 10:30:37 -0800131 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chanb8e10c82015-10-14 11:24:40 -0700132 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan5270ed02016-01-30 23:22:37 -0800133 // Do not add /0 and /32 to gateway IP list
134 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
135 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
136 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
137 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700138 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
139 });
140 }
Charles Chan4636be02015-10-07 14:21:45 -0700141 });
Charles Chan4636be02015-10-07 14:21:45 -0700142 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700143 }
144
sanghob35a6192015-04-01 13:05:26 -0700145 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800146 public boolean isConfigured(DeviceId deviceId) {
147 return deviceConfigMap.get(deviceId) != null;
148 }
149
150 @Override
151 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700152 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
153 if (srinfo != null) {
154 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
155 return srinfo.nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700156 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800157 String message = "getSegmentId fails for device: " + deviceId + ".";
158 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700159 }
160 }
161
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700162 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700163 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700164 *
165 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700166 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700167 */
168 public int getSegmentId(MacAddress routerMac) {
169 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
170 deviceConfigMap.entrySet()) {
171 if (entry.getValue().mac.equals(routerMac)) {
172 return entry.getValue().nodeSid;
173 }
174 }
sanghob35a6192015-04-01 13:05:26 -0700175
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700176 return -1;
177 }
178
179 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700180 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700181 *
182 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700183 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700184 */
185 public int getSegmentId(Ip4Address routerAddress) {
186 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
187 deviceConfigMap.entrySet()) {
188 if (entry.getValue().ip.equals(routerAddress)) {
189 return entry.getValue().nodeSid;
190 }
191 }
192
193 return -1;
194 }
195
sanghob35a6192015-04-01 13:05:26 -0700196 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800197 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700198 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
199 if (srinfo != null) {
200 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
201 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700202 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800203 String message = "getDeviceMac fails for device: " + deviceId + ".";
204 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700205 }
206 }
207
Charles Chan0b4e6182015-11-03 10:42:14 -0800208 @Override
209 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700210 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
211 if (srinfo != null) {
212 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
213 return srinfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700214 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800215 String message = "getRouterIp fails for device: " + deviceId + ".";
216 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700217 }
sanghob35a6192015-04-01 13:05:26 -0700218 }
219
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700220 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800221 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700222 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
223 if (srinfo != null) {
224 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
225 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700226 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800227 String message = "isEdgeDevice fails for device: " + deviceId + ".";
228 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700229 }
230 }
231
sanghob35a6192015-04-01 13:05:26 -0700232 @Override
233 public List<Integer> getAllDeviceSegmentIds() {
234 return allSegmentIds;
235 }
236
Charles Chanc42e84e2015-10-20 16:24:19 -0700237 @Override
Saurav Das7a1ffca2016-03-28 19:00:18 -0700238 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
239 throws DeviceConfigNotFoundException {
240 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
241 if (srinfo == null) {
242 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
243 throw new DeviceConfigNotFoundException(message);
244 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700245 // Construct subnet-port mapping from port-subnet mapping
Saurav Das7a1ffca2016-03-28 19:00:18 -0700246 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
247 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -0800248
249 portSubnetMap.entries().forEach(entry -> {
250 PortNumber port = entry.getKey();
251 Ip4Prefix subnet = entry.getValue();
252
Charles Chand0fd5dc2016-02-16 23:14:49 -0800253 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
254 return;
255 }
256
Charles Chanc42e84e2015-10-20 16:24:19 -0700257 if (subnetPortMap.containsKey(subnet)) {
258 subnetPortMap.get(subnet).add(port);
259 } else {
260 ArrayList<PortNumber> ports = new ArrayList<>();
261 ports.add(port);
262 subnetPortMap.put(subnet, ports);
263 }
264 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700265 return subnetPortMap;
266 }
267
sanghob35a6192015-04-01 13:05:26 -0700268 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700269 * Returns the device identifier or data plane identifier (dpid)
270 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700271 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700272 * @param sid segment id
273 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700274 */
275 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700276 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
277 deviceConfigMap.entrySet()) {
278 if (entry.getValue().nodeSid == sid) {
279 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700280 }
281 }
282
283 return null;
284 }
285
286 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700287 * Returns the device identifier or data plane identifier (dpid)
288 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700289 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700290 * @param ipAddress router ip address
291 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700292 */
293 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700294 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
295 deviceConfigMap.entrySet()) {
296 if (entry.getValue().ip.equals(ipAddress)) {
297 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700298 }
299 }
300
301 return null;
302 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700303
304 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700305 * Returns the configured port ip addresses for a segment router.
306 * These addresses serve as gateway IP addresses for the subnets configured
307 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700308 *
309 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700310 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700311 */
Saurav Das837e0bb2015-10-30 17:45:38 -0700312 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700313 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
314 if (srinfo != null) {
315 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
316 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700317 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700318 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700319 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700320 }
321
322 /**
323 * Returns the configured subnet prefixes for a segment router.
324 *
325 * @param deviceId device identifier
Saurav Das0e99e2b2015-10-28 12:39:42 -0700326 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700327 */
Charles Chan9f676b62015-10-29 14:58:10 -0700328 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700329 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
330 if (srinfo != null) {
Charles Chanf2565a92016-02-10 20:46:58 -0800331 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
Charles Chan03a73e02016-10-24 14:52:01 -0700332 return builder.addAll(srinfo.subnets.values()).build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700333 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700334 return null;
335 }
336
Charles Chan2c15aca2016-11-09 20:51:44 -0800337
Saurav Das0e99e2b2015-10-28 12:39:42 -0700338 /**
Charles Chan2c15aca2016-11-09 20:51:44 -0800339 * Returns the subnet configuration of given device and port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700340 *
Charles Chan2c15aca2016-11-09 20:51:44 -0800341 * @param deviceId Device ID
342 * @param port Port number
343 * @return The subnet configured on given port or null if
344 * the port is unconfigured, misconfigured or suppressed.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700345 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800346 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber port) {
347 ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
348
349 if (isSuppressedPort(connectPoint)) {
350 return null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700351 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800352
353 Set<Ip4Prefix> subnets =
354 srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
355 .flatMap(intf -> intf.ipAddressesList().stream())
356 .map(InterfaceIpAddress::subnetAddress)
357 .map(IpPrefix::getIp4Prefix)
358 .collect(Collectors.toSet());
359
Jon Hallcbd1b392017-01-18 20:15:44 -0800360 if (subnets.isEmpty()) {
Charles Chan2c15aca2016-11-09 20:51:44 -0800361 log.info(NO_SUBNET, connectPoint);
362 return null;
363 } else if (subnets.size() > 1) {
364 log.warn(TOO_MANY_SUBNET, connectPoint);
365 return null;
366 } else {
367 return subnets.stream().findFirst().orElse(null);
368 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700369 }
370
371 /**
372 * Returns the router ip address of segment router that has the
373 * specified ip address in its subnets.
374 *
375 * @param destIpAddress target ip address
376 * @return router ip address
377 */
378 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
Charles Chan68aaad52016-12-09 12:54:49 -0800379 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
380
381 if (matchIntf == null) {
382 log.debug("No router was found for {}", destIpAddress);
383 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700384 }
385
Charles Chan68aaad52016-12-09 12:54:49 -0800386 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
387 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
388 if (srInfo == null) {
389 log.debug("No device config was found for {}", routerDeviceId);
390 return null;
391 }
392
393 return srInfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700394 }
395
396 /**
397 * Returns the router mac address of segment router that has the
398 * specified ip address as one of its subnet gateway ip address.
399 *
400 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700401 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700402 */
403 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
404 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
405 deviceConfigMap.entrySet()) {
406 if (entry.getValue().gatewayIps.
407 values().contains(gatewayIpAddress)) {
408 return entry.getValue().mac;
409 }
410 }
411
412 log.debug("Cannot find a router for {}", gatewayIpAddress);
413 return null;
414 }
sangho666cd6d2015-04-14 16:27:13 -0700415
416
417 /**
418 * Checks if the host is in the subnet defined in the router with the
419 * device ID given.
420 *
421 * @param deviceId device identification of the router
422 * @param hostIp host IP address to check
423 * @return true if the host is within the subnet of the router,
424 * false if no subnet is defined under the router or if the host is not
425 * within the subnet defined in the router
426 */
427 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
428
Charles Chan9f676b62015-10-29 14:58:10 -0700429 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700430 if (subnets == null) {
431 return false;
432 }
433
434 for (Ip4Prefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800435 // Exclude /0 since it is a special case used for default route
436 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700437 return true;
438 }
439 }
440
441 return false;
442 }
sangho1e575652015-05-14 00:39:53 -0700443
444 /**
Charles Chan03a73e02016-10-24 14:52:01 -0700445 * Checks if the IP is in the subnet defined on given connect point.
446 *
447 * @param connectPoint Connect point
448 * @param ip The IP address to check
449 * @return True if the IP belongs to the subnet.
450 * False if the IP does not belong to the subnet, or
451 * there is no subnet configuration on given connect point.
452 */
453 public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
454 Ip4Prefix portSubnet = getPortSubnet(connectPoint.deviceId(), connectPoint.port());
455 return portSubnet != null && portSubnet.contains(ip);
456 }
457
458 /**
sangho1e575652015-05-14 00:39:53 -0700459 * Returns the ports corresponding to the adjacency Sid given.
460 *
461 * @param deviceId device identification of the router
462 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800463 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700464 */
Charles Chan531a78b2015-12-01 10:00:51 -0800465 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700466 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800467 return srinfo != null ?
468 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
469 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700470 }
471
472 /**
473 * Check if the Sid given is whether adjacency Sid of the router device or not.
474 *
475 * @param deviceId device identification of the router
476 * @param sid Sid to check
477 * @return true if the Sid given is the adjacency Sid of the device,
478 * otherwise false
479 */
480 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700481 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800482 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700483 }
Charles Chanf2565a92016-02-10 20:46:58 -0800484
Charles Chand55e84d2016-03-30 17:54:24 -0700485 /**
Charles Chan93e71ba2016-04-29 14:38:22 -0700486 * Add subnet to specific connect point.
487 *
488 * @param cp connect point
489 * @param ip4Prefix subnet being added to the device
490 */
491 public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
492 checkNotNull(cp);
493 checkNotNull(ip4Prefix);
494 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
495 if (srinfo == null) {
496 log.warn("Device {} is not configured. Abort.", cp.deviceId());
497 return;
498 }
499 srinfo.subnets.put(cp.port(), ip4Prefix);
500 }
501
502 /**
503 * Remove subnet from specific connect point.
504 *
505 * @param cp connect point
506 * @param ip4Prefix subnet being removed to the device
507 */
508 public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
509 checkNotNull(cp);
510 checkNotNull(ip4Prefix);
511 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
512 if (srinfo == null) {
513 log.warn("Device {} is not configured. Abort.", cp.deviceId());
514 return;
515 }
516 srinfo.subnets.remove(cp.port(), ip4Prefix);
517 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800518
519 private boolean isSuppressedPort(ConnectPoint connectPoint) {
520 SegmentRoutingAppConfig appConfig = srManager.cfgService
521 .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
522 if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
Charles Chan03a73e02016-10-24 14:52:01 -0700523 log.info("Interface configuration on port {} is ignored", connectPoint);
Charles Chan2c15aca2016-11-09 20:51:44 -0800524 return true;
525 }
526 return false;
527 }
Jonathan Hart00cddda2016-02-16 10:30:37 -0800528}