blob: 1beed3209f2faf4f71f169cec86865a8331ffdfc [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;
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;
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 Chand9681e72016-02-22 19:27:29 -080060 private ApplicationId appId;
61 private NetworkConfigService cfgService;
Charles Chanf2565a92016-02-10 20:46:58 -080062 private SegmentRoutingAppConfig appConfig;
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 Chanf2565a92016-02-10 20:46:58 -080084 * @param appId application id
Brian O'Connor52515622015-10-09 17:03:44 -070085 * @param cfgService config service
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070086 */
Charles Chanf2565a92016-02-10 20:46:58 -080087 public DeviceConfiguration(ApplicationId appId,
88 NetworkConfigRegistry cfgService) {
Charles Chand9681e72016-02-22 19:27:29 -080089 this.appId = appId;
90 this.cfgService = cfgService;
91
Charles Chan4636be02015-10-07 14:21:45 -070092 // Read config from device subject, excluding gatewayIps and subnets.
93 Set<DeviceId> deviceSubjects =
Charles Chan5270ed02016-01-30 23:22:37 -080094 cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070095 deviceSubjects.forEach(subject -> {
Charles Chan5270ed02016-01-30 23:22:37 -080096 SegmentRoutingDeviceConfig config =
97 cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070098 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -070099 info.deviceId = subject;
Charles Chan531a78b2015-12-01 10:00:51 -0800100 info.nodeSid = config.nodeSid();
101 info.ip = config.routerIp();
102 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -0700103 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800104 info.adjacencySids = config.adjacencySids();
Charles Chand6832882015-10-05 17:50:33 -0700105
Charles Chane849c192016-01-11 18:28:54 -0800106 deviceConfigMap.put(info.deviceId, info);
107 allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700108 });
Charles Chan4636be02015-10-07 14:21:45 -0700109
Charles Chand9681e72016-02-22 19:27:29 -0800110 // Read SegmentRoutingAppConfig
Charles Chanf2565a92016-02-10 20:46:58 -0800111 appConfig = cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
Charles Chanf2565a92016-02-10 20:46:58 -0800112
Charles Chan4636be02015-10-07 14:21:45 -0700113 // Read gatewayIps and subnets from port subject.
114 Set<ConnectPoint> portSubjects =
115 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
116 portSubjects.forEach(subject -> {
Charles Chand9681e72016-02-22 19:27:29 -0800117 // Do not process excluded ports
118 if (suppressSubnet().contains(subject)) {
119 return;
120 }
121
Charles Chan4636be02015-10-07 14:21:45 -0700122 InterfaceConfig config =
123 cfgService.getConfig(subject, InterfaceConfig.class);
124 Set<Interface> networkInterfaces;
125 try {
126 networkInterfaces = config.getInterfaces();
127 } catch (ConfigException e) {
128 log.error("Error loading port configuration");
129 return;
130 }
131 networkInterfaces.forEach(networkInterface -> {
Charles Chane849c192016-01-11 18:28:54 -0800132 VlanId vlanId = networkInterface.vlan();
133 ConnectPoint connectPoint = networkInterface.connectPoint();
134 DeviceId dpid = connectPoint.deviceId();
135 PortNumber port = connectPoint.port();
136 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chan4636be02015-10-07 14:21:45 -0700137
Charles Chanb8e10c82015-10-14 11:24:40 -0700138 // skip if there is no corresponding device for this ConenctPoint
139 if (info != null) {
Charles Chane849c192016-01-11 18:28:54 -0800140 // Extract subnet information
Jonathan Hart00cddda2016-02-16 10:30:37 -0800141 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chanb8e10c82015-10-14 11:24:40 -0700142 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan5270ed02016-01-30 23:22:37 -0800143 // Do not add /0 and /32 to gateway IP list
144 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
145 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
146 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
147 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700148 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
149 });
Charles Chane849c192016-01-11 18:28:54 -0800150
151 // Extract VLAN cross-connect information
152 // Do not setup cross-connect if VLAN is NONE
153 if (vlanId.equals(VlanId.NONE)) {
154 return;
155 }
156 List<ConnectPoint> connectPoints = xConnects.get(vlanId);
157 if (connectPoints != null) {
158 if (connectPoints.size() != 1) {
159 log.warn("Cross-connect should only have two endpoints. Aborting.");
160 return;
161 }
162 if (!connectPoints.get(0).deviceId().equals(connectPoint.deviceId())) {
163 log.warn("Cross-connect endpoints must be on the same switch. Aborting.");
164 return;
165 }
166 connectPoints.add(connectPoint);
167 } else {
168 connectPoints = new LinkedList<>();
169 connectPoints.add(connectPoint);
170 xConnects.put(vlanId, connectPoints);
171 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700172 }
Charles Chan4636be02015-10-07 14:21:45 -0700173 });
174
175 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700176 }
177
sanghob35a6192015-04-01 13:05:26 -0700178 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800179 public boolean isConfigured(DeviceId deviceId) {
180 return deviceConfigMap.get(deviceId) != null;
181 }
182
183 @Override
184 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700185 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
186 if (srinfo != null) {
187 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
188 return srinfo.nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700189 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800190 String message = "getSegmentId fails for device: " + deviceId + ".";
191 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700192 }
193 }
194
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700195 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700196 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700197 *
198 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700199 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700200 */
201 public int getSegmentId(MacAddress routerMac) {
202 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
203 deviceConfigMap.entrySet()) {
204 if (entry.getValue().mac.equals(routerMac)) {
205 return entry.getValue().nodeSid;
206 }
207 }
sanghob35a6192015-04-01 13:05:26 -0700208
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700209 return -1;
210 }
211
212 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700213 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700214 *
215 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700216 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700217 */
218 public int getSegmentId(Ip4Address routerAddress) {
219 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
220 deviceConfigMap.entrySet()) {
221 if (entry.getValue().ip.equals(routerAddress)) {
222 return entry.getValue().nodeSid;
223 }
224 }
225
226 return -1;
227 }
228
sanghob35a6192015-04-01 13:05:26 -0700229 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800230 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700231 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
232 if (srinfo != null) {
233 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
234 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700235 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800236 String message = "getDeviceMac fails for device: " + deviceId + ".";
237 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700238 }
239 }
240
Charles Chan0b4e6182015-11-03 10:42:14 -0800241 @Override
242 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700243 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
244 if (srinfo != null) {
245 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
246 return srinfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700247 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800248 String message = "getRouterIp fails for device: " + deviceId + ".";
249 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700250 }
sanghob35a6192015-04-01 13:05:26 -0700251 }
252
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700253 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800254 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700255 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
256 if (srinfo != null) {
257 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
258 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700259 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800260 String message = "isEdgeDevice fails for device: " + deviceId + ".";
261 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700262 }
263 }
264
sanghob35a6192015-04-01 13:05:26 -0700265 @Override
266 public List<Integer> getAllDeviceSegmentIds() {
267 return allSegmentIds;
268 }
269
Charles Chanc42e84e2015-10-20 16:24:19 -0700270 @Override
271 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId) {
272 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
273
274 // Construct subnet-port mapping from port-subnet mapping
Charles Chan5270ed02016-01-30 23:22:37 -0800275 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap =
Charles Chanc42e84e2015-10-20 16:24:19 -0700276 this.deviceConfigMap.get(deviceId).subnets;
Charles Chan5270ed02016-01-30 23:22:37 -0800277
278 portSubnetMap.entries().forEach(entry -> {
279 PortNumber port = entry.getKey();
280 Ip4Prefix subnet = entry.getValue();
281
Charles Chand0fd5dc2016-02-16 23:14:49 -0800282 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
283 return;
284 }
285
Charles Chanc42e84e2015-10-20 16:24:19 -0700286 if (subnetPortMap.containsKey(subnet)) {
287 subnetPortMap.get(subnet).add(port);
288 } else {
289 ArrayList<PortNumber> ports = new ArrayList<>();
290 ports.add(port);
291 subnetPortMap.put(subnet, ports);
292 }
293 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700294 return subnetPortMap;
295 }
296
Charles Chane849c192016-01-11 18:28:54 -0800297 @Override
298 public Map<VlanId, List<ConnectPoint>> getXConnects() {
299 return xConnects;
300 }
301
sanghob35a6192015-04-01 13:05:26 -0700302 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700303 * Returns the device identifier or data plane identifier (dpid)
304 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700305 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700306 * @param sid segment id
307 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700308 */
309 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700310 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
311 deviceConfigMap.entrySet()) {
312 if (entry.getValue().nodeSid == sid) {
313 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700314 }
315 }
316
317 return null;
318 }
319
320 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700321 * Returns the device identifier or data plane identifier (dpid)
322 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700323 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700324 * @param ipAddress router ip address
325 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700326 */
327 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700328 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
329 deviceConfigMap.entrySet()) {
330 if (entry.getValue().ip.equals(ipAddress)) {
331 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700332 }
333 }
334
335 return null;
336 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700337
338 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700339 * Returns the configured port ip addresses for a segment router.
340 * These addresses serve as gateway IP addresses for the subnets configured
341 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700342 *
343 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700344 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700345 */
Saurav Das837e0bb2015-10-30 17:45:38 -0700346 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700347 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
348 if (srinfo != null) {
349 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
350 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700351 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700352 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700353 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700354 }
355
356 /**
357 * Returns the configured subnet prefixes for a segment router.
358 *
359 * @param deviceId device identifier
Saurav Das0e99e2b2015-10-28 12:39:42 -0700360 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700361 */
Charles Chan9f676b62015-10-29 14:58:10 -0700362 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700363 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
364 if (srinfo != null) {
365 log.trace("getSubnets for device{} is {}", deviceId,
366 srinfo.subnets.values());
Charles Chanf2565a92016-02-10 20:46:58 -0800367
368 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
369 builder.addAll(srinfo.subnets.values());
Charles Chand9681e72016-02-22 19:27:29 -0800370 if (appConfig != null && deviceId.equals(appConfig.vRouterId())) {
Charles Chanf2565a92016-02-10 20:46:58 -0800371 builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
372 }
373 return builder.build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700374 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700375 return null;
376 }
377
378 /**
Charles Chan5270ed02016-01-30 23:22:37 -0800379 * Returns the configured non-/32 and non-/0 subnet on the given port,
380 * or null if no subnet has been configured on the port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700381 *
382 * @param deviceId device identifier
383 * @param pnum port identifier
384 * @return configured subnet on port, or null
385 */
386 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) {
387 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
388 if (srinfo != null) {
Charles Chan5270ed02016-01-30 23:22:37 -0800389 Optional<Ip4Prefix> result = srinfo.subnets.get(pnum).stream()
390 .filter(subnet ->
391 subnet.getIp4Prefix().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH &&
392 subnet.getIp4Prefix().prefixLength() != 0)
393 .findFirst();
394 return (result.isPresent()) ? result.get() : null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700395 }
396 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700397 }
398
399 /**
400 * Returns the router ip address of segment router that has the
401 * specified ip address in its subnets.
402 *
403 * @param destIpAddress target ip address
404 * @return router ip address
405 */
406 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
407 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
408 deviceConfigMap.entrySet()) {
Charles Chan5270ed02016-01-30 23:22:37 -0800409 for (Ip4Prefix prefix : entry.getValue().subnets.values()) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700410 if (prefix.contains(destIpAddress)) {
411 return entry.getValue().ip;
412 }
413 }
414 }
415
416 log.debug("No router was found for {}", destIpAddress);
417 return null;
418 }
419
420 /**
421 * Returns the router mac address of segment router that has the
422 * specified ip address as one of its subnet gateway ip address.
423 *
424 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700425 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700426 */
427 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
428 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
429 deviceConfigMap.entrySet()) {
430 if (entry.getValue().gatewayIps.
431 values().contains(gatewayIpAddress)) {
432 return entry.getValue().mac;
433 }
434 }
435
436 log.debug("Cannot find a router for {}", gatewayIpAddress);
437 return null;
438 }
sangho666cd6d2015-04-14 16:27:13 -0700439
440
441 /**
442 * Checks if the host is in the subnet defined in the router with the
443 * device ID given.
444 *
445 * @param deviceId device identification of the router
446 * @param hostIp host IP address to check
447 * @return true if the host is within the subnet of the router,
448 * false if no subnet is defined under the router or if the host is not
449 * within the subnet defined in the router
450 */
451 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
452
Charles Chan9f676b62015-10-29 14:58:10 -0700453 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700454 if (subnets == null) {
455 return false;
456 }
457
458 for (Ip4Prefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800459 // Exclude /0 since it is a special case used for default route
460 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700461 return true;
462 }
463 }
464
465 return false;
466 }
sangho1e575652015-05-14 00:39:53 -0700467
468 /**
469 * Returns the ports corresponding to the adjacency Sid given.
470 *
471 * @param deviceId device identification of the router
472 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800473 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700474 */
Charles Chan531a78b2015-12-01 10:00:51 -0800475 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700476 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800477 return srinfo != null ?
478 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
479 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700480 }
481
482 /**
483 * Check if the Sid given is whether adjacency Sid of the router device or not.
484 *
485 * @param deviceId device identification of the router
486 * @param sid Sid to check
487 * @return true if the Sid given is the adjacency Sid of the device,
488 * otherwise false
489 */
490 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700491 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800492 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700493 }
Charles Chanf2565a92016-02-10 20:46:58 -0800494
Charles Chand9681e72016-02-22 19:27:29 -0800495 public Set<ConnectPoint> suppressSubnet() {
496 return (appConfig != null) ? appConfig.suppressSubnet() : ImmutableSet.of();
497 }
498
499 public Set<ConnectPoint> suppressHost() {
500 return (appConfig != null) ? appConfig.suppressHost() : ImmutableSet.of();
Charles Chanf2565a92016-02-10 20:46:58 -0800501 }
Jonathan Hart00cddda2016-02-16 10:30:37 -0800502}