blob: c1af6f2c76f5b80a390fce0dd56f0039e464a03d [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 Chanf2565a92016-02-10 20:46:58 -080026import org.onosproject.core.ApplicationId;
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 Chand6832882015-10-05 17:50:33 -070031import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chand9681e72016-02-22 19:27:29 -080032import org.onosproject.net.config.NetworkConfigService;
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;
sanghob35a6192015-04-01 13:05:26 -070042import java.util.List;
43import java.util.Map;
Charles Chan5270ed02016-01-30 23:22:37 -080044import java.util.Optional;
Charles Chand6832882015-10-05 17:50:33 -070045import java.util.Set;
Saurav Das0e99e2b2015-10-28 12:39:42 -070046import java.util.concurrent.ConcurrentHashMap;
sanghob35a6192015-04-01 13:05:26 -070047
Charles Chan93e71ba2016-04-29 14:38:22 -070048import static com.google.common.base.Preconditions.checkNotNull;
49
Srikanth Vavilapalli4db76e32015-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 Vavilapalli4db76e32015-04-07 15:12:32 -070054 */
sanghob35a6192015-04-01 13:05:26 -070055public class DeviceConfiguration implements DeviceProperties {
56
Charles Chanf2565a92016-02-10 20:46:58 -080057 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070058 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chane849c192016-01-11 18:28:54 -080059 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chand9681e72016-02-22 19:27:29 -080060 private ApplicationId appId;
61 private NetworkConfigService cfgService;
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 Chand9681e72016-02-22 19:27:29 -080088 this.appId = appId;
89 this.cfgService = cfgService;
90
Charles Chan4636be02015-10-07 14:21:45 -070091 // Read config from device subject, excluding gatewayIps and subnets.
92 Set<DeviceId> deviceSubjects =
Charles Chan5270ed02016-01-30 23:22:37 -080093 cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070094 deviceSubjects.forEach(subject -> {
Charles Chan5270ed02016-01-30 23:22:37 -080095 SegmentRoutingDeviceConfig config =
96 cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070097 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070098 info.deviceId = subject;
Charles Chan531a78b2015-12-01 10:00:51 -080099 info.nodeSid = config.nodeSid();
100 info.ip = config.routerIp();
101 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -0700102 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800103 info.adjacencySids = config.adjacencySids();
Charles Chane849c192016-01-11 18:28:54 -0800104 deviceConfigMap.put(info.deviceId, info);
Saurav Das59232cf2016-04-27 18:35:50 -0700105 log.info("Read device config for device: {}", info.deviceId);
Charles Chane849c192016-01-11 18:28:54 -0800106 allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700107 });
Charles Chan4636be02015-10-07 14:21:45 -0700108
109 // Read gatewayIps and subnets from port subject.
110 Set<ConnectPoint> portSubjects =
111 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
112 portSubjects.forEach(subject -> {
Charles Chand9681e72016-02-22 19:27:29 -0800113 // Do not process excluded ports
Charles Chan6ea94fc2016-05-10 17:29:47 -0700114 SegmentRoutingAppConfig appConfig =
115 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
116 if (appConfig != null && appConfig.suppressSubnet().contains(subject)) {
117 log.info("Ignore suppressed port {}", subject);
Charles Chand9681e72016-02-22 19:27:29 -0800118 return;
119 }
120
Charles Chan4636be02015-10-07 14:21:45 -0700121 InterfaceConfig config =
122 cfgService.getConfig(subject, InterfaceConfig.class);
123 Set<Interface> networkInterfaces;
124 try {
125 networkInterfaces = config.getInterfaces();
126 } catch (ConfigException e) {
127 log.error("Error loading port configuration");
128 return;
129 }
130 networkInterfaces.forEach(networkInterface -> {
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
Jonathan Hart00cddda2016-02-16 10:30:37 -0800140 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chanb8e10c82015-10-14 11:24:40 -0700141 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 });
149 }
Charles Chan4636be02015-10-07 14:21:45 -0700150 });
Charles Chan4636be02015-10-07 14:21:45 -0700151 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700152 }
153
sanghob35a6192015-04-01 13:05:26 -0700154 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800155 public boolean isConfigured(DeviceId deviceId) {
156 return deviceConfigMap.get(deviceId) != null;
157 }
158
159 @Override
160 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700161 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
162 if (srinfo != null) {
163 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
164 return srinfo.nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700165 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800166 String message = "getSegmentId fails for device: " + deviceId + ".";
167 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700168 }
169 }
170
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700171 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700172 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700173 *
174 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700175 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700176 */
177 public int getSegmentId(MacAddress routerMac) {
178 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
179 deviceConfigMap.entrySet()) {
180 if (entry.getValue().mac.equals(routerMac)) {
181 return entry.getValue().nodeSid;
182 }
183 }
sanghob35a6192015-04-01 13:05:26 -0700184
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700185 return -1;
186 }
187
188 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700189 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700190 *
191 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700192 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700193 */
194 public int getSegmentId(Ip4Address routerAddress) {
195 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
196 deviceConfigMap.entrySet()) {
197 if (entry.getValue().ip.equals(routerAddress)) {
198 return entry.getValue().nodeSid;
199 }
200 }
201
202 return -1;
203 }
204
sanghob35a6192015-04-01 13:05:26 -0700205 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800206 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700207 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
208 if (srinfo != null) {
209 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
210 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700211 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800212 String message = "getDeviceMac fails for device: " + deviceId + ".";
213 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700214 }
215 }
216
Charles Chan0b4e6182015-11-03 10:42:14 -0800217 @Override
218 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700219 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
220 if (srinfo != null) {
221 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
222 return srinfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700223 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800224 String message = "getRouterIp fails for device: " + deviceId + ".";
225 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700226 }
sanghob35a6192015-04-01 13:05:26 -0700227 }
228
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700229 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800230 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700231 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
232 if (srinfo != null) {
233 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
234 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700235 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800236 String message = "isEdgeDevice fails for device: " + deviceId + ".";
237 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700238 }
239 }
240
sanghob35a6192015-04-01 13:05:26 -0700241 @Override
242 public List<Integer> getAllDeviceSegmentIds() {
243 return allSegmentIds;
244 }
245
Charles Chanc42e84e2015-10-20 16:24:19 -0700246 @Override
Saurav Das7a1ffca2016-03-28 19:00:18 -0700247 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
248 throws DeviceConfigNotFoundException {
249 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
250 if (srinfo == null) {
251 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
252 throw new DeviceConfigNotFoundException(message);
253 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700254 // Construct subnet-port mapping from port-subnet mapping
Saurav Das7a1ffca2016-03-28 19:00:18 -0700255 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
256 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -0800257
258 portSubnetMap.entries().forEach(entry -> {
259 PortNumber port = entry.getKey();
260 Ip4Prefix subnet = entry.getValue();
261
Charles Chand0fd5dc2016-02-16 23:14:49 -0800262 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
263 return;
264 }
265
Charles Chanc42e84e2015-10-20 16:24:19 -0700266 if (subnetPortMap.containsKey(subnet)) {
267 subnetPortMap.get(subnet).add(port);
268 } else {
269 ArrayList<PortNumber> ports = new ArrayList<>();
270 ports.add(port);
271 subnetPortMap.put(subnet, ports);
272 }
273 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700274 return subnetPortMap;
275 }
276
sanghob35a6192015-04-01 13:05:26 -0700277 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700278 * Returns the device identifier or data plane identifier (dpid)
279 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700280 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700281 * @param sid segment id
282 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700283 */
284 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700285 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
286 deviceConfigMap.entrySet()) {
287 if (entry.getValue().nodeSid == sid) {
288 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700289 }
290 }
291
292 return null;
293 }
294
295 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700296 * Returns the device identifier or data plane identifier (dpid)
297 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700298 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700299 * @param ipAddress router ip address
300 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700301 */
302 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700303 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
304 deviceConfigMap.entrySet()) {
305 if (entry.getValue().ip.equals(ipAddress)) {
306 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700307 }
308 }
309
310 return null;
311 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700312
313 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700314 * Returns the configured port ip addresses for a segment router.
315 * These addresses serve as gateway IP addresses for the subnets configured
316 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700317 *
318 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700319 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700320 */
Saurav Das837e0bb2015-10-30 17:45:38 -0700321 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700322 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
323 if (srinfo != null) {
324 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
325 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700326 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700327 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700328 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700329 }
330
331 /**
332 * Returns the configured subnet prefixes for a segment router.
333 *
334 * @param deviceId device identifier
Saurav Das0e99e2b2015-10-28 12:39:42 -0700335 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700336 */
Charles Chan9f676b62015-10-29 14:58:10 -0700337 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700338 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
339 if (srinfo != null) {
340 log.trace("getSubnets for device{} is {}", deviceId,
341 srinfo.subnets.values());
Charles Chanf2565a92016-02-10 20:46:58 -0800342
343 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
344 builder.addAll(srinfo.subnets.values());
Charles Chan2196a922016-03-07 00:49:33 -0800345 SegmentRoutingAppConfig appConfig =
346 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
347 if (appConfig != null) {
348 if (deviceId.equals(appConfig.vRouterId().orElse(null))) {
349 builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
350 }
Charles Chanf2565a92016-02-10 20:46:58 -0800351 }
352 return builder.build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700353 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700354 return null;
355 }
356
357 /**
Charles Chan5270ed02016-01-30 23:22:37 -0800358 * Returns the configured non-/32 and non-/0 subnet on the given port,
359 * or null if no subnet has been configured on the port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700360 *
361 * @param deviceId device identifier
362 * @param pnum port identifier
363 * @return configured subnet on port, or null
364 */
365 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) {
366 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
367 if (srinfo != null) {
Charles Chan5270ed02016-01-30 23:22:37 -0800368 Optional<Ip4Prefix> result = srinfo.subnets.get(pnum).stream()
369 .filter(subnet ->
370 subnet.getIp4Prefix().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH &&
371 subnet.getIp4Prefix().prefixLength() != 0)
372 .findFirst();
373 return (result.isPresent()) ? result.get() : null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700374 }
375 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700376 }
377
378 /**
379 * Returns the router ip address of segment router that has the
380 * specified ip address in its subnets.
381 *
382 * @param destIpAddress target ip address
383 * @return router ip address
384 */
385 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
386 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
387 deviceConfigMap.entrySet()) {
Charles Chan5270ed02016-01-30 23:22:37 -0800388 for (Ip4Prefix prefix : entry.getValue().subnets.values()) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700389 if (prefix.contains(destIpAddress)) {
390 return entry.getValue().ip;
391 }
392 }
393 }
394
395 log.debug("No router was found for {}", destIpAddress);
396 return null;
397 }
398
399 /**
400 * Returns the router mac address of segment router that has the
401 * specified ip address as one of its subnet gateway ip address.
402 *
403 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700404 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700405 */
406 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
407 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
408 deviceConfigMap.entrySet()) {
409 if (entry.getValue().gatewayIps.
410 values().contains(gatewayIpAddress)) {
411 return entry.getValue().mac;
412 }
413 }
414
415 log.debug("Cannot find a router for {}", gatewayIpAddress);
416 return null;
417 }
sangho666cd6d2015-04-14 16:27:13 -0700418
419
420 /**
421 * Checks if the host is in the subnet defined in the router with the
422 * device ID given.
423 *
424 * @param deviceId device identification of the router
425 * @param hostIp host IP address to check
426 * @return true if the host is within the subnet of the router,
427 * false if no subnet is defined under the router or if the host is not
428 * within the subnet defined in the router
429 */
430 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
431
Charles Chan9f676b62015-10-29 14:58:10 -0700432 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700433 if (subnets == null) {
434 return false;
435 }
436
437 for (Ip4Prefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800438 // Exclude /0 since it is a special case used for default route
439 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700440 return true;
441 }
442 }
443
444 return false;
445 }
sangho1e575652015-05-14 00:39:53 -0700446
447 /**
448 * Returns the ports corresponding to the adjacency Sid given.
449 *
450 * @param deviceId device identification of the router
451 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800452 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700453 */
Charles Chan531a78b2015-12-01 10:00:51 -0800454 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700455 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800456 return srinfo != null ?
457 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
458 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700459 }
460
461 /**
462 * Check if the Sid given is whether adjacency Sid of the router device or not.
463 *
464 * @param deviceId device identification of the router
465 * @param sid Sid to check
466 * @return true if the Sid given is the adjacency Sid of the device,
467 * otherwise false
468 */
469 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700470 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800471 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700472 }
Charles Chanf2565a92016-02-10 20:46:58 -0800473
Charles Chand55e84d2016-03-30 17:54:24 -0700474 /**
Charles Chan93e71ba2016-04-29 14:38:22 -0700475 * Add subnet to specific connect point.
476 *
477 * @param cp connect point
478 * @param ip4Prefix subnet being added to the device
479 */
480 public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
481 checkNotNull(cp);
482 checkNotNull(ip4Prefix);
483 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
484 if (srinfo == null) {
485 log.warn("Device {} is not configured. Abort.", cp.deviceId());
486 return;
487 }
488 srinfo.subnets.put(cp.port(), ip4Prefix);
489 }
490
491 /**
492 * Remove subnet from specific connect point.
493 *
494 * @param cp connect point
495 * @param ip4Prefix subnet being removed to the device
496 */
497 public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
498 checkNotNull(cp);
499 checkNotNull(ip4Prefix);
500 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
501 if (srinfo == null) {
502 log.warn("Device {} is not configured. Abort.", cp.deviceId());
503 return;
504 }
505 srinfo.subnets.remove(cp.port(), ip4Prefix);
506 }
Jonathan Hart00cddda2016-02-16 10:30:37 -0800507}