blob: f222bb35929c7c1e420ae70c3bd79ae9f6d06df3 [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Charles Chand6832882015-10-05 17:50:33 -07002 * Copyright 2014-2015 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;
Charles Chanf2565a92016-02-10 20:46:58 -080021import com.google.common.collect.Sets;
sanghob35a6192015-04-01 13:05:26 -070022import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070023import org.onlab.packet.Ip4Prefix;
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 Chanf2565a92016-02-10 20:46:58 -080027import org.onosproject.core.ApplicationId;
Charles Chan4636be02015-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 Chand6832882015-10-05 17:50:33 -070032import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan4636be02015-10-07 14:21:45 -070033import org.onosproject.net.host.InterfaceIpAddress;
sanghob35a6192015-04-01 13:05:26 -070034import org.onosproject.net.DeviceId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070035import org.onosproject.net.PortNumber;
sanghob35a6192015-04-01 13:05:26 -070036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070039import java.util.ArrayList;
sanghob35a6192015-04-01 13:05:26 -070040import java.util.HashMap;
Charles Chan531a78b2015-12-01 10:00:51 -080041import java.util.HashSet;
Charles Chane849c192016-01-11 18:28:54 -080042import java.util.LinkedList;
sanghob35a6192015-04-01 13:05:26 -070043import java.util.List;
44import java.util.Map;
Charles Chan5270ed02016-01-30 23:22:37 -080045import java.util.Optional;
Charles Chand6832882015-10-05 17:50:33 -070046import java.util.Set;
Saurav Das0e99e2b2015-10-28 12:39:42 -070047import java.util.concurrent.ConcurrentHashMap;
sanghob35a6192015-04-01 13:05:26 -070048
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 Chanf2565a92016-02-10 20:46:58 -080056 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070057 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chane849c192016-01-11 18:28:54 -080058 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
59 private final Map<VlanId, List<ConnectPoint>> xConnects = new ConcurrentHashMap<>();
Charles Chanf2565a92016-02-10 20:46:58 -080060 private final Set<ConnectPoint> excludedPorts = Sets.newConcurrentHashSet();
61 private SegmentRoutingAppConfig appConfig;
sanghob35a6192015-04-01 13:05:26 -070062
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070063 private class SegmentRouterInfo {
64 int nodeSid;
65 DeviceId deviceId;
66 Ip4Address ip;
67 MacAddress mac;
68 boolean isEdge;
Charles Chan5270ed02016-01-30 23:22:37 -080069 Map<PortNumber, Ip4Address> gatewayIps;
70 SetMultimap<PortNumber, Ip4Prefix> subnets;
Charles Chan531a78b2015-12-01 10:00:51 -080071 Map<Integer, Set<Integer>> adjacencySids;
Charles Chanb8e10c82015-10-14 11:24:40 -070072
73 public SegmentRouterInfo() {
Charles Chane849c192016-01-11 18:28:54 -080074 gatewayIps = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -080075 subnets = HashMultimap.create();
Charles Chanb8e10c82015-10-14 11:24:40 -070076 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070077 }
sanghob35a6192015-04-01 13:05:26 -070078
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070079 /**
Charles Chane849c192016-01-11 18:28:54 -080080 * Constructs device configuration for all Segment Router devices,
81 * organizing the data into various maps for easier access.
Brian O'Connor52515622015-10-09 17:03:44 -070082 *
Charles Chanf2565a92016-02-10 20:46:58 -080083 * @param appId application id
Brian O'Connor52515622015-10-09 17:03:44 -070084 * @param cfgService config service
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070085 */
Charles Chanf2565a92016-02-10 20:46:58 -080086 public DeviceConfiguration(ApplicationId appId,
87 NetworkConfigRegistry cfgService) {
Charles Chan4636be02015-10-07 14:21:45 -070088 // Read config from device subject, excluding gatewayIps and subnets.
89 Set<DeviceId> deviceSubjects =
Charles Chan5270ed02016-01-30 23:22:37 -080090 cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070091 deviceSubjects.forEach(subject -> {
Charles Chan5270ed02016-01-30 23:22:37 -080092 SegmentRoutingDeviceConfig config =
93 cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070094 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070095 info.deviceId = subject;
Charles Chan531a78b2015-12-01 10:00:51 -080096 info.nodeSid = config.nodeSid();
97 info.ip = config.routerIp();
98 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -070099 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800100 info.adjacencySids = config.adjacencySids();
Charles Chand6832882015-10-05 17:50:33 -0700101
Charles Chane849c192016-01-11 18:28:54 -0800102 deviceConfigMap.put(info.deviceId, info);
103 allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700104 });
Charles Chan4636be02015-10-07 14:21:45 -0700105
Charles Chanf2565a92016-02-10 20:46:58 -0800106 // Read excluded port names from config
107 appConfig = cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
108 Set<String> excludePorts = (appConfig != null) ?
109 appConfig.excludePorts() : ImmutableSet.of();
110
Charles Chan4636be02015-10-07 14:21:45 -0700111 // Read gatewayIps and subnets from port subject.
112 Set<ConnectPoint> portSubjects =
113 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
114 portSubjects.forEach(subject -> {
115 InterfaceConfig config =
116 cfgService.getConfig(subject, InterfaceConfig.class);
117 Set<Interface> networkInterfaces;
118 try {
119 networkInterfaces = config.getInterfaces();
120 } catch (ConfigException e) {
121 log.error("Error loading port configuration");
122 return;
123 }
124 networkInterfaces.forEach(networkInterface -> {
Charles Chanf2565a92016-02-10 20:46:58 -0800125 // Do not process excluded ports
126 if (excludePorts.contains(networkInterface.name())) {
127 excludedPorts.add(subject);
128 return;
129 }
130
Charles Chane849c192016-01-11 18:28:54 -0800131 VlanId vlanId = networkInterface.vlan();
132 ConnectPoint connectPoint = networkInterface.connectPoint();
133 DeviceId dpid = connectPoint.deviceId();
134 PortNumber port = connectPoint.port();
135 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chan4636be02015-10-07 14:21:45 -0700136
Charles Chanb8e10c82015-10-14 11:24:40 -0700137 // skip if there is no corresponding device for this ConenctPoint
138 if (info != null) {
Charles Chane849c192016-01-11 18:28:54 -0800139 // Extract subnet information
Charles Chanb8e10c82015-10-14 11:24:40 -0700140 Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
141 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan5270ed02016-01-30 23:22:37 -0800142 // Do not add /0 and /32 to gateway IP list
143 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
144 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
145 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
146 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700147 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
148 });
Charles Chane849c192016-01-11 18:28:54 -0800149
150 // Extract VLAN cross-connect information
151 // Do not setup cross-connect if VLAN is NONE
152 if (vlanId.equals(VlanId.NONE)) {
153 return;
154 }
155 List<ConnectPoint> connectPoints = xConnects.get(vlanId);
156 if (connectPoints != null) {
157 if (connectPoints.size() != 1) {
158 log.warn("Cross-connect should only have two endpoints. Aborting.");
159 return;
160 }
161 if (!connectPoints.get(0).deviceId().equals(connectPoint.deviceId())) {
162 log.warn("Cross-connect endpoints must be on the same switch. Aborting.");
163 return;
164 }
165 connectPoints.add(connectPoint);
166 } else {
167 connectPoints = new LinkedList<>();
168 connectPoints.add(connectPoint);
169 xConnects.put(vlanId, connectPoints);
170 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700171 }
Charles Chan4636be02015-10-07 14:21:45 -0700172 });
173
174 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700175 }
176
sanghob35a6192015-04-01 13:05:26 -0700177 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800178 public boolean isConfigured(DeviceId deviceId) {
179 return deviceConfigMap.get(deviceId) != null;
180 }
181
182 @Override
183 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700184 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
185 if (srinfo != null) {
186 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
187 return srinfo.nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700188 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800189 String message = "getSegmentId fails for device: " + deviceId + ".";
190 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700191 }
192 }
193
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700194 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700195 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700196 *
197 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700198 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700199 */
200 public int getSegmentId(MacAddress routerMac) {
201 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
202 deviceConfigMap.entrySet()) {
203 if (entry.getValue().mac.equals(routerMac)) {
204 return entry.getValue().nodeSid;
205 }
206 }
sanghob35a6192015-04-01 13:05:26 -0700207
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700208 return -1;
209 }
210
211 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700212 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700213 *
214 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700215 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700216 */
217 public int getSegmentId(Ip4Address routerAddress) {
218 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
219 deviceConfigMap.entrySet()) {
220 if (entry.getValue().ip.equals(routerAddress)) {
221 return entry.getValue().nodeSid;
222 }
223 }
224
225 return -1;
226 }
227
sanghob35a6192015-04-01 13:05:26 -0700228 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800229 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700230 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
231 if (srinfo != null) {
232 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
233 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700234 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800235 String message = "getDeviceMac fails for device: " + deviceId + ".";
236 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700237 }
238 }
239
Charles Chan0b4e6182015-11-03 10:42:14 -0800240 @Override
241 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700242 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
243 if (srinfo != null) {
244 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
245 return srinfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700246 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800247 String message = "getRouterIp fails for device: " + deviceId + ".";
248 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700249 }
sanghob35a6192015-04-01 13:05:26 -0700250 }
251
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700252 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800253 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700254 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
255 if (srinfo != null) {
256 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
257 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700258 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800259 String message = "isEdgeDevice fails for device: " + deviceId + ".";
260 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700261 }
262 }
263
sanghob35a6192015-04-01 13:05:26 -0700264 @Override
265 public List<Integer> getAllDeviceSegmentIds() {
266 return allSegmentIds;
267 }
268
Charles Chanc42e84e2015-10-20 16:24:19 -0700269 @Override
270 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId) {
271 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
272
273 // Construct subnet-port mapping from port-subnet mapping
Charles Chan5270ed02016-01-30 23:22:37 -0800274 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap =
Charles Chanc42e84e2015-10-20 16:24:19 -0700275 this.deviceConfigMap.get(deviceId).subnets;
Charles Chan5270ed02016-01-30 23:22:37 -0800276
277 portSubnetMap.entries().forEach(entry -> {
278 PortNumber port = entry.getKey();
279 Ip4Prefix subnet = entry.getValue();
280
Charles Chanc42e84e2015-10-20 16:24:19 -0700281 if (subnetPortMap.containsKey(subnet)) {
282 subnetPortMap.get(subnet).add(port);
283 } else {
284 ArrayList<PortNumber> ports = new ArrayList<>();
285 ports.add(port);
286 subnetPortMap.put(subnet, ports);
287 }
288 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700289 return subnetPortMap;
290 }
291
Charles Chane849c192016-01-11 18:28:54 -0800292 @Override
293 public Map<VlanId, List<ConnectPoint>> getXConnects() {
294 return xConnects;
295 }
296
sanghob35a6192015-04-01 13:05:26 -0700297 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700298 * Returns the device identifier or data plane identifier (dpid)
299 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700300 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700301 * @param sid segment id
302 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700303 */
304 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700305 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
306 deviceConfigMap.entrySet()) {
307 if (entry.getValue().nodeSid == sid) {
308 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700309 }
310 }
311
312 return null;
313 }
314
315 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700316 * Returns the device identifier or data plane identifier (dpid)
317 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700318 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700319 * @param ipAddress router ip address
320 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700321 */
322 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700323 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
324 deviceConfigMap.entrySet()) {
325 if (entry.getValue().ip.equals(ipAddress)) {
326 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700327 }
328 }
329
330 return null;
331 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700332
333 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700334 * Returns the configured port ip addresses for a segment router.
335 * These addresses serve as gateway IP addresses for the subnets configured
336 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700337 *
338 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700339 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700340 */
Saurav Das837e0bb2015-10-30 17:45:38 -0700341 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700342 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
343 if (srinfo != null) {
344 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
345 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700346 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700347 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700348 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700349 }
350
351 /**
352 * Returns the configured subnet prefixes for a segment router.
353 *
354 * @param deviceId device identifier
Saurav Das0e99e2b2015-10-28 12:39:42 -0700355 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700356 */
Charles Chan9f676b62015-10-29 14:58:10 -0700357 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700358 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
359 if (srinfo != null) {
360 log.trace("getSubnets for device{} is {}", deviceId,
361 srinfo.subnets.values());
Charles Chanf2565a92016-02-10 20:46:58 -0800362
363 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
364 builder.addAll(srinfo.subnets.values());
365 if (deviceId.equals(appConfig.vRouterId())) {
366 builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
367 }
368 return builder.build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700369 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700370 return null;
371 }
372
373 /**
Charles Chan5270ed02016-01-30 23:22:37 -0800374 * Returns the configured non-/32 and non-/0 subnet on the given port,
375 * or null if no subnet has been configured on the port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700376 *
377 * @param deviceId device identifier
378 * @param pnum port identifier
379 * @return configured subnet on port, or null
380 */
381 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) {
382 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
383 if (srinfo != null) {
Charles Chan5270ed02016-01-30 23:22:37 -0800384 Optional<Ip4Prefix> result = srinfo.subnets.get(pnum).stream()
385 .filter(subnet ->
386 subnet.getIp4Prefix().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH &&
387 subnet.getIp4Prefix().prefixLength() != 0)
388 .findFirst();
389 return (result.isPresent()) ? result.get() : null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700390 }
391 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700392 }
393
394 /**
395 * Returns the router ip address of segment router that has the
396 * specified ip address in its subnets.
397 *
398 * @param destIpAddress target ip address
399 * @return router ip address
400 */
401 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
402 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
403 deviceConfigMap.entrySet()) {
Charles Chan5270ed02016-01-30 23:22:37 -0800404 for (Ip4Prefix prefix : entry.getValue().subnets.values()) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700405 if (prefix.contains(destIpAddress)) {
406 return entry.getValue().ip;
407 }
408 }
409 }
410
411 log.debug("No router was found for {}", destIpAddress);
412 return null;
413 }
414
415 /**
416 * Returns the router mac address of segment router that has the
417 * specified ip address as one of its subnet gateway ip address.
418 *
419 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700420 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700421 */
422 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
423 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
424 deviceConfigMap.entrySet()) {
425 if (entry.getValue().gatewayIps.
426 values().contains(gatewayIpAddress)) {
427 return entry.getValue().mac;
428 }
429 }
430
431 log.debug("Cannot find a router for {}", gatewayIpAddress);
432 return null;
433 }
sangho666cd6d2015-04-14 16:27:13 -0700434
435
436 /**
437 * Checks if the host is in the subnet defined in the router with the
438 * device ID given.
439 *
440 * @param deviceId device identification of the router
441 * @param hostIp host IP address to check
442 * @return true if the host is within the subnet of the router,
443 * false if no subnet is defined under the router or if the host is not
444 * within the subnet defined in the router
445 */
446 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
447
Charles Chan9f676b62015-10-29 14:58:10 -0700448 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700449 if (subnets == null) {
450 return false;
451 }
452
453 for (Ip4Prefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800454 // Exclude /0 since it is a special case used for default route
455 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700456 return true;
457 }
458 }
459
460 return false;
461 }
sangho1e575652015-05-14 00:39:53 -0700462
463 /**
464 * Returns the ports corresponding to the adjacency Sid given.
465 *
466 * @param deviceId device identification of the router
467 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800468 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700469 */
Charles Chan531a78b2015-12-01 10:00:51 -0800470 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700471 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800472 return srinfo != null ?
473 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
474 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700475 }
476
477 /**
478 * Check if the Sid given is whether adjacency Sid of the router device or not.
479 *
480 * @param deviceId device identification of the router
481 * @param sid Sid to check
482 * @return true if the Sid given is the adjacency Sid of the device,
483 * otherwise false
484 */
485 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700486 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800487 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700488 }
Charles Chanf2565a92016-02-10 20:46:58 -0800489
490 /**
491 * Returns a set of excluded ports.
492 *
493 * @return excluded ports
494 */
495 public Set<ConnectPoint> excludedPorts() {
496 return excludedPorts;
497 }
Charles Chand6832882015-10-05 17:50:33 -0700498}