blob: 5013e83cfe7ea9536b2691605d2263607b2c3d8f [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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 Chan82fac582017-09-12 12:09:22 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
Charles Chan5270ed02016-01-30 23:22:37 -080021import com.google.common.collect.HashMultimap;
Charles Chan9f676b62015-10-29 14:58:10 -070022import com.google.common.collect.ImmutableSet;
Charles Chan411beb22019-04-17 14:20:26 -070023import com.google.common.collect.Lists;
Charles Chan9c44ec72018-03-20 13:30:38 -070024import com.google.common.collect.Multimaps;
Charles Chan5270ed02016-01-30 23:22:37 -080025import com.google.common.collect.SetMultimap;
Charles Chan411beb22019-04-17 14:20:26 -070026import com.google.common.collect.Sets;
sanghob35a6192015-04-01 13:05:26 -070027import org.onlab.packet.Ip4Address;
Pier Ventree0ae7a32016-11-23 09:57:42 -080028import org.onlab.packet.Ip6Address;
Charles Chan03a73e02016-10-24 14:52:01 -070029import org.onlab.packet.IpAddress;
Charles Chan5270ed02016-01-30 23:22:37 -080030import org.onlab.packet.IpPrefix;
sanghob35a6192015-04-01 13:05:26 -070031import org.onlab.packet.MacAddress;
Charles Chane849c192016-01-11 18:28:54 -080032import org.onlab.packet.VlanId;
Charles Chan4636be02015-10-07 14:21:45 -070033import org.onosproject.net.ConnectPoint;
sanghob35a6192015-04-01 13:05:26 -070034import org.onosproject.net.DeviceId;
Charles Chan72ff3d92019-04-18 14:30:41 -070035import org.onosproject.net.HostId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070036import org.onosproject.net.PortNumber;
Jonathan Hart8ca2bc02017-11-30 18:23:42 -080037import org.onosproject.net.config.ConfigException;
Andrea Campanellaad95aaf2020-03-27 12:53:46 +010038import org.onosproject.net.config.basics.BasicDeviceConfig;
Jonathan Hart8ca2bc02017-11-30 18:23:42 -080039import org.onosproject.net.config.basics.InterfaceConfig;
40import org.onosproject.net.host.InterfaceIpAddress;
41import org.onosproject.net.intf.Interface;
Charles Chan411beb22019-04-17 14:20:26 -070042import org.onosproject.routeservice.Route;
Charles Chan2c15aca2016-11-09 20:51:44 -080043import org.onosproject.segmentrouting.SegmentRoutingManager;
sanghob35a6192015-04-01 13:05:26 -070044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070047import java.util.ArrayList;
Jonathan Hart8ca2bc02017-11-30 18:23:42 -080048import java.util.Collection;
Pier Ventre10bd8d12016-11-26 21:05:22 -080049import java.util.Collections;
sanghob35a6192015-04-01 13:05:26 -070050import java.util.HashMap;
Charles Chan531a78b2015-12-01 10:00:51 -080051import java.util.HashSet;
sanghob35a6192015-04-01 13:05:26 -070052import java.util.List;
53import java.util.Map;
Charles Chan61eb99e2019-03-22 10:04:27 -070054import java.util.Objects;
Charles Chand6832882015-10-05 17:50:33 -070055import java.util.Set;
Saurav Das0e99e2b2015-10-28 12:39:42 -070056import java.util.concurrent.ConcurrentHashMap;
Charles Chan2c15aca2016-11-09 20:51:44 -080057import java.util.stream.Collectors;
Charles Chan72ff3d92019-04-18 14:30:41 -070058import java.util.stream.Stream;
sanghob35a6192015-04-01 13:05:26 -070059
Charles Chan93e71ba2016-04-29 14:38:22 -070060import static com.google.common.base.Preconditions.checkNotNull;
61
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070062/**
63 * Segment Routing configuration component that reads the
64 * segment routing related configuration from Network Configuration Manager
65 * component and organizes in more accessible formats.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070066 */
sanghob35a6192015-04-01 13:05:26 -070067public class DeviceConfiguration implements DeviceProperties {
68
Charles Chan2c15aca2016-11-09 20:51:44 -080069 private static final String NO_SUBNET = "No subnet configured on {}";
70
Charles Chanf2565a92016-02-10 20:46:58 -080071 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070072 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chane849c192016-01-11 18:28:54 -080073 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chan2c15aca2016-11-09 20:51:44 -080074 private SegmentRoutingManager srManager;
sanghob35a6192015-04-01 13:05:26 -070075
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070076 private class SegmentRouterInfo {
Charles Chan6fa516e2018-10-02 12:52:29 -070077 int ipv4NodeSid = -1;
78 int ipv6NodeSid = -1;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070079 DeviceId deviceId;
Pier Ventree0ae7a32016-11-23 09:57:42 -080080 Ip4Address ipv4Loopback;
81 Ip6Address ipv6Loopback;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070082 MacAddress mac;
83 boolean isEdge;
Pier Ventre10bd8d12016-11-26 21:05:22 -080084 SetMultimap<PortNumber, IpAddress> gatewayIps;
85 SetMultimap<PortNumber, IpPrefix> subnets;
Charles Chan531a78b2015-12-01 10:00:51 -080086 Map<Integer, Set<Integer>> adjacencySids;
Saurav Das7bcbe702017-06-13 15:35:54 -070087 DeviceId pairDeviceId;
88 PortNumber pairLocalPort;
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -070089 int pwRoutingLabel;
Charles Chanb8e10c82015-10-14 11:24:40 -070090
91 public SegmentRouterInfo() {
Charles Chan9c44ec72018-03-20 13:30:38 -070092 gatewayIps = Multimaps.synchronizedSetMultimap(HashMultimap.create());
93 subnets = Multimaps.synchronizedSetMultimap(HashMultimap.create());
Charles Chanb8e10c82015-10-14 11:24:40 -070094 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070095 }
sanghob35a6192015-04-01 13:05:26 -070096
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070097 /**
Charles Chane849c192016-01-11 18:28:54 -080098 * Constructs device configuration for all Segment Router devices,
99 * organizing the data into various maps for easier access.
Brian O'Connor52515622015-10-09 17:03:44 -0700100 *
Charles Chan2c15aca2016-11-09 20:51:44 -0800101 * @param srManager Segment Routing Manager
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700102 */
Charles Chan2c15aca2016-11-09 20:51:44 -0800103 public DeviceConfiguration(SegmentRoutingManager srManager) {
104 this.srManager = srManager;
Saurav Das7bcbe702017-06-13 15:35:54 -0700105 updateConfig();
106 }
Charles Chand9681e72016-02-22 19:27:29 -0800107
Saurav Das7bcbe702017-06-13 15:35:54 -0700108 public void updateConfig() {
Charles Chan4636be02015-10-07 14:21:45 -0700109 // Read config from device subject, excluding gatewayIps and subnets.
110 Set<DeviceId> deviceSubjects =
Charles Chan2c15aca2016-11-09 20:51:44 -0800111 srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -0700112 deviceSubjects.forEach(subject -> {
Andrea Campanellaad95aaf2020-03-27 12:53:46 +0100113 //Setting purge on disconnection flag for the device SR has control over.
114 // addConfig returns a config if it exists or creates a new one.
115 log.info("PurgeOnDisconnection set to true for device {}", subject);
116 BasicDeviceConfig basicDeviceConfig = srManager.cfgService.addConfig(subject, BasicDeviceConfig.class);
117 basicDeviceConfig.purgeOnDisconnection(true);
118 srManager.cfgService.applyConfig(subject, BasicDeviceConfig.class, basicDeviceConfig.node());
Charles Chan5270ed02016-01-30 23:22:37 -0800119 SegmentRoutingDeviceConfig config =
Charles Chan2c15aca2016-11-09 20:51:44 -0800120 srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700121 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -0700122 info.deviceId = subject;
Pier Ventree0ae7a32016-11-23 09:57:42 -0800123 info.ipv4NodeSid = config.nodeSidIPv4();
124 info.ipv6NodeSid = config.nodeSidIPv6();
125 info.ipv4Loopback = config.routerIpv4();
126 info.ipv6Loopback = config.routerIpv6();
Charles Chan531a78b2015-12-01 10:00:51 -0800127 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -0700128 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800129 info.adjacencySids = config.adjacencySids();
Saurav Das7bcbe702017-06-13 15:35:54 -0700130 info.pairDeviceId = config.pairDeviceId();
131 info.pairLocalPort = config.pairLocalPort();
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700132 info.pwRoutingLabel = info.ipv4NodeSid + 1000;
Charles Chane849c192016-01-11 18:28:54 -0800133 deviceConfigMap.put(info.deviceId, info);
Charles Chan278ce832017-06-26 15:25:09 -0700134 log.debug("Read device config for device: {}", info.deviceId);
Pier Ventree0ae7a32016-11-23 09:57:42 -0800135 /*
136 * IPv6 sid is not inserted. this part of the code is not used for now.
137 */
138 allSegmentIds.add(info.ipv4NodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700139 });
Charles Chan4636be02015-10-07 14:21:45 -0700140
Charles Chan2c15aca2016-11-09 20:51:44 -0800141 // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
142 Set<ConnectPoint> portSubjects = srManager.cfgService
143 .getSubjects(ConnectPoint.class, InterfaceConfig.class);
Jonathan Hart8ca2bc02017-11-30 18:23:42 -0800144 portSubjects.stream()
145 .filter(subject -> deviceConfigMap.containsKey(subject.deviceId()))
146 .filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
Charles Chan4636be02015-10-07 14:21:45 -0700147 InterfaceConfig config =
Charles Chan2c15aca2016-11-09 20:51:44 -0800148 srManager.cfgService.getConfig(subject, InterfaceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -0700149 Set<Interface> networkInterfaces;
150 try {
151 networkInterfaces = config.getInterfaces();
152 } catch (ConfigException e) {
153 log.error("Error loading port configuration");
154 return;
155 }
156 networkInterfaces.forEach(networkInterface -> {
Charles Chane849c192016-01-11 18:28:54 -0800157 VlanId vlanId = networkInterface.vlan();
158 ConnectPoint connectPoint = networkInterface.connectPoint();
159 DeviceId dpid = connectPoint.deviceId();
160 PortNumber port = connectPoint.port();
Charles Chan82fac582017-09-12 12:09:22 -0700161 MacAddress mac = networkInterface.mac();
Charles Chane849c192016-01-11 18:28:54 -0800162 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chan4636be02015-10-07 14:21:45 -0700163
Charles Chanb8e10c82015-10-14 11:24:40 -0700164 // skip if there is no corresponding device for this ConenctPoint
165 if (info != null) {
Charles Chane849c192016-01-11 18:28:54 -0800166 // Extract subnet information
Jonathan Hart00cddda2016-02-16 10:30:37 -0800167 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chanb8e10c82015-10-14 11:24:40 -0700168 interfaceAddresses.forEach(interfaceAddress -> {
Pier Ventre10bd8d12016-11-26 21:05:22 -0800169 // Do not add /0, /32 and /128 to gateway IP list
Charles Chan5270ed02016-01-30 23:22:37 -0800170 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
Pier Ventre10bd8d12016-11-26 21:05:22 -0800171 IpPrefix ipPrefix = interfaceAddress.subnetAddress();
172 if (ipPrefix.isIp4()) {
173 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
174 info.gatewayIps.put(port, interfaceAddress.ipAddress());
175 }
176 info.subnets.put(port, interfaceAddress.subnetAddress());
177 } else {
178 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET6_MASK_LENGTH) {
179 info.gatewayIps.put(port, interfaceAddress.ipAddress());
180 }
181 info.subnets.put(port, interfaceAddress.subnetAddress());
Charles Chan5270ed02016-01-30 23:22:37 -0800182 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700183 });
Charles Chan82fac582017-09-12 12:09:22 -0700184
185 // Override interface mac with router mac
186 if (!mac.equals(info.mac)) {
187 ArrayNode array = (ArrayNode) config.node();
188 for (JsonNode intfNode : array) {
189 ObjectNode objNode = (ObjectNode) intfNode;
190 objNode.put(InterfaceConfig.MAC, info.mac.toString());
191 }
192 srManager.cfgService.applyConfig(connectPoint, InterfaceConfig.class, array);
193 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700194 }
Charles Chan4636be02015-10-07 14:21:45 -0700195 });
Pier Luigi0e358632017-01-31 09:35:05 -0800196 // We register the connect point with the NRS.
Pier Ventre10bd8d12016-11-26 21:05:22 -0800197 srManager.registerConnectPoint(subject);
Charles Chan4636be02015-10-07 14:21:45 -0700198 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700199 }
200
Jonathan Hart8ca2bc02017-11-30 18:23:42 -0800201 public Collection<DeviceId> getRouters() {
202 return deviceConfigMap.keySet();
203 }
Saurav Das7bcbe702017-06-13 15:35:54 -0700204
sanghob35a6192015-04-01 13:05:26 -0700205 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800206 public boolean isConfigured(DeviceId deviceId) {
207 return deviceConfigMap.get(deviceId) != null;
208 }
209
210 @Override
Pier Ventree0ae7a32016-11-23 09:57:42 -0800211 public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700212 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
213 if (srinfo != null) {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800214 log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
215 return srinfo.ipv4NodeSid;
sanghob35a6192015-04-01 13:05:26 -0700216 } else {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800217 String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
218 throw new DeviceConfigNotFoundException(message);
219 }
220 }
221
222 @Override
223 public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
224 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
225 if (srinfo != null) {
226 log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
227 return srinfo.ipv6NodeSid;
228 } else {
229 String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
Charles Chan0b4e6182015-11-03 10:42:14 -0800230 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700231 }
232 }
233
Andreas Pantelopoulos27532cd2017-10-23 12:18:25 -0700234 @Override
235 public int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException {
236 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
237 if (srinfo != null) {
238 log.trace("pwRoutingLabel for device{} is {}", deviceId, srinfo.pwRoutingLabel);
239 return srinfo.pwRoutingLabel;
240 } else {
241 String message = "getPWRoutingLabel fails for device: " + deviceId + ".";
242 throw new DeviceConfigNotFoundException(message);
243 }
244 }
245
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700246 /**
Pier Ventree0ae7a32016-11-23 09:57:42 -0800247 * Returns the IPv4 Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700248 *
249 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700250 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700251 */
Pier Ventree0ae7a32016-11-23 09:57:42 -0800252 public int getIPv4SegmentId(MacAddress routerMac) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700253 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
254 deviceConfigMap.entrySet()) {
255 if (entry.getValue().mac.equals(routerMac)) {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800256 return entry.getValue().ipv4NodeSid;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700257 }
258 }
sanghob35a6192015-04-01 13:05:26 -0700259
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700260 return -1;
261 }
262
263 /**
Pier Ventree0ae7a32016-11-23 09:57:42 -0800264 * Returns the IPv6 Node segment id of a segment router given its Router mac address.
265 *
266 * @param routerMac router mac address
267 * @return node segment id, or -1 if not found in config
268 */
269 public int getIPv6SegmentId(MacAddress routerMac) {
270 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
271 deviceConfigMap.entrySet()) {
272 if (entry.getValue().mac.equals(routerMac)) {
273 return entry.getValue().ipv6NodeSid;
274 }
275 }
276
277 return -1;
278 }
279
280 /**
281 * Returns the IPv4 Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700282 *
283 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700284 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700285 */
Pier Ventree0ae7a32016-11-23 09:57:42 -0800286 public int getIPv4SegmentId(Ip4Address routerAddress) {
Charles Chan6fa516e2018-10-02 12:52:29 -0700287 for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
288 Ip4Address ipv4Loopback = entry.getValue().ipv4Loopback;
289 if (ipv4Loopback == null) {
290 continue;
291 }
Pier Ventree0ae7a32016-11-23 09:57:42 -0800292 if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
Charles Chan6fa516e2018-10-02 12:52:29 -0700293 if (entry.getValue().ipv4NodeSid == -1) {
294 continue;
295 }
Pier Ventree0ae7a32016-11-23 09:57:42 -0800296 return entry.getValue().ipv4NodeSid;
297 }
298 }
299
300 return -1;
301 }
302
303 /**
304 * Returns the IPv6 Node segment id of a segment router given its Router ip address.
305 *
306 * @param routerAddress router ip address
307 * @return node segment id, or -1 if not found in config
308 */
309 public int getIPv6SegmentId(Ip6Address routerAddress) {
Charles Chan6fa516e2018-10-02 12:52:29 -0700310 for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
311 Ip6Address ipv6Loopback = entry.getValue().ipv6Loopback;
312 if (ipv6Loopback == null) {
313 continue;
314 }
Pier Ventree0ae7a32016-11-23 09:57:42 -0800315 if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
Charles Chan6fa516e2018-10-02 12:52:29 -0700316 if (entry.getValue().ipv6NodeSid == -1) {
317 continue;
318 }
Pier Ventree0ae7a32016-11-23 09:57:42 -0800319 return entry.getValue().ipv6NodeSid;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700320 }
321 }
322
323 return -1;
324 }
325
sanghob35a6192015-04-01 13:05:26 -0700326 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800327 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700328 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
329 if (srinfo != null) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700330 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700331 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800332 String message = "getDeviceMac fails for device: " + deviceId + ".";
333 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700334 }
335 }
336
Charles Chan0b4e6182015-11-03 10:42:14 -0800337 @Override
Pier Ventree0ae7a32016-11-23 09:57:42 -0800338 public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700339 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
340 if (srinfo != null) {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800341 log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
342 return srinfo.ipv4Loopback;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700343 } else {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800344 String message = "getRouterIpv4 fails for device: " + deviceId + ".";
345 throw new DeviceConfigNotFoundException(message);
346 }
347 }
348
349 @Override
350 public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
351 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
352 if (srinfo != null) {
353 log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
354 return srinfo.ipv6Loopback;
355 } else {
356 String message = "getRouterIpv6 fails for device: " + deviceId + ".";
Charles Chan0b4e6182015-11-03 10:42:14 -0800357 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700358 }
sanghob35a6192015-04-01 13:05:26 -0700359 }
360
pierf8e328d2019-06-28 22:17:31 +0200361 /**
362 * Gets router ip address based on the destination ip address.
363 *
364 * @param destIpAddress the destination ip address
365 * @param routerDeviceId the device id
366 * @return the ip address of the routes
367 */
368 public IpAddress getRouterIpAddress(IpAddress destIpAddress, DeviceId routerDeviceId) {
369 IpAddress routerIpAddress;
370 try {
371 routerIpAddress = destIpAddress.isIp4() ? getRouterIpv4(routerDeviceId) :
372 getRouterIpv6(routerDeviceId);
373 } catch (DeviceConfigNotFoundException e) {
374 routerIpAddress = null;
375 }
376 return routerIpAddress;
377 }
378
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700379 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800380 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700381 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
382 if (srinfo != null) {
383 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
384 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700385 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800386 String message = "isEdgeDevice fails for device: " + deviceId + ".";
387 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700388 }
389 }
390
sanghob35a6192015-04-01 13:05:26 -0700391 @Override
392 public List<Integer> getAllDeviceSegmentIds() {
393 return allSegmentIds;
394 }
395
Charles Chanc42e84e2015-10-20 16:24:19 -0700396 @Override
Pier Ventre10bd8d12016-11-26 21:05:22 -0800397 public Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
Saurav Das7a1ffca2016-03-28 19:00:18 -0700398 throws DeviceConfigNotFoundException {
399 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
400 if (srinfo == null) {
401 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
402 throw new DeviceConfigNotFoundException(message);
403 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700404 // Construct subnet-port mapping from port-subnet mapping
Pier Ventre10bd8d12016-11-26 21:05:22 -0800405 SetMultimap<PortNumber, IpPrefix> portSubnetMap = srinfo.subnets;
406 Map<IpPrefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -0800407
408 portSubnetMap.entries().forEach(entry -> {
409 PortNumber port = entry.getKey();
Pier Ventre10bd8d12016-11-26 21:05:22 -0800410 IpPrefix subnet = entry.getValue();
Charles Chan5270ed02016-01-30 23:22:37 -0800411
Pier Ventre10bd8d12016-11-26 21:05:22 -0800412 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
413 subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
Charles Chand0fd5dc2016-02-16 23:14:49 -0800414 return;
415 }
416
Charles Chanc42e84e2015-10-20 16:24:19 -0700417 if (subnetPortMap.containsKey(subnet)) {
418 subnetPortMap.get(subnet).add(port);
419 } else {
420 ArrayList<PortNumber> ports = new ArrayList<>();
421 ports.add(port);
422 subnetPortMap.put(subnet, ports);
423 }
424 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700425 return subnetPortMap;
426 }
427
sanghob35a6192015-04-01 13:05:26 -0700428 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700429 * Returns the device identifier or data plane identifier (dpid)
430 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700431 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700432 * @param sid segment id
433 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700434 */
435 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700436 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
437 deviceConfigMap.entrySet()) {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800438 if (entry.getValue().ipv4NodeSid == sid ||
439 entry.getValue().ipv6NodeSid == sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700440 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700441 }
442 }
443
444 return null;
445 }
446
447 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700448 * Returns the device identifier or data plane identifier (dpid)
449 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700450 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700451 * @param ipAddress router ip address
452 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700453 */
454 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700455 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
456 deviceConfigMap.entrySet()) {
Pier Ventree0ae7a32016-11-23 09:57:42 -0800457 if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
458 return entry.getValue().deviceId;
459 }
460 }
461
462 return null;
463 }
464
465 /**
466 * Returns the device identifier or data plane identifier (dpid)
467 * of a segment router given its router ipv6 address.
468 *
469 * @param ipAddress router ipv6 address
470 * @return deviceId device identifier
471 */
472 public DeviceId getDeviceId(Ip6Address ipAddress) {
473 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
474 deviceConfigMap.entrySet()) {
475 if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700476 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700477 }
478 }
479
480 return null;
481 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700482
483 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700484 * Returns the configured port ip addresses for a segment router.
485 * These addresses serve as gateway IP addresses for the subnets configured
486 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700487 *
488 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700489 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700490 */
Pier Ventre10bd8d12016-11-26 21:05:22 -0800491 public Set<IpAddress> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700492 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
493 if (srinfo != null) {
494 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
495 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700496 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700497 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700498 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700499 }
500
501 /**
Charles Chan61eb99e2019-03-22 10:04:27 -0700502 * Returns configured subnets for a segment router.
503 *
504 * @param deviceId device identifier
505 * @return list of ip prefixes or null if not found
506 */
507 public Set<IpPrefix> getConfiguredSubnets(DeviceId deviceId) {
508 Set<IpPrefix> subnets = srManager.interfaceService.getInterfaces().stream()
509 .filter(intf -> Objects.equals(deviceId, intf.connectPoint().deviceId()))
510 .flatMap(intf -> intf.ipAddressesList().stream())
511 .map(InterfaceIpAddress::subnetAddress)
512 .collect(Collectors.toSet());
513
514 if (subnets.isEmpty()) {
515 log.debug(NO_SUBNET, deviceId);
516 return Collections.emptySet();
517 }
518 return subnets;
519 }
520
521 /**
522 * Returns all subnets for a segment router, including subnets learnt from route service.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700523 *
524 * @param deviceId device identifier
Charles Chan411beb22019-04-17 14:20:26 -0700525 * @return set of ip prefixes or null if not found
526 * @deprecated use getBatchedSubnets(DeviceId deviceId) instead
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700527 */
Charles Chan411beb22019-04-17 14:20:26 -0700528 @Deprecated
Pier Ventre10bd8d12016-11-26 21:05:22 -0800529 public Set<IpPrefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700530 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chanf2f8ef02018-06-18 14:42:17 -0700531 if (srinfo != null && srinfo.subnets != null) {
532 // Note: ImmutableSet.Builder.addAll calls the iterator of parameter internally,
533 // which is not protected by SynchronizedCollection mutex.
Pier Ventre10bd8d12016-11-26 21:05:22 -0800534 ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
Charles Chanf2f8ef02018-06-18 14:42:17 -0700535 srinfo.subnets.forEach((k, v) -> builder.add(v));
536 return builder.build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700537 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700538 return null;
539 }
540
Charles Chan411beb22019-04-17 14:20:26 -0700541 /**
Charles Chan72ff3d92019-04-18 14:30:41 -0700542 * Returns batches of all subnets reachable via given next hop
543 * <p>
544 * First batch includes FPM and STATIC routes
545 * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
546 *
547 * @param hostId next hop host id
548 * @return list of subnet batches, each batch includes a set of prefixes.
549 */
550 // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
551 public List<Set<IpPrefix>> getBatchedSubnets(HostId hostId) {
552 Set<IpPrefix> high = Sets.newHashSet();
553 Set<IpPrefix> low = Sets.newHashSet();
554
555 srManager.routeService.getRouteTables().stream()
556 .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
557 .flatMap(Collection::stream)
558 .forEach(resolvedRoute -> {
559 // Continue if next hop is not what we are looking for
560 if (!Objects.equals(hostId.mac(), resolvedRoute.nextHopMac()) ||
561 !Objects.equals(hostId.vlanId(), resolvedRoute.nextHopVlan())) {
562 return;
563 }
564 // Prioritize STATIC and FPM among others
565 if (resolvedRoute.route().source() == Route.Source.STATIC ||
566 resolvedRoute.route().source() == Route.Source.FPM) {
567 high.add(resolvedRoute.prefix());
568 } else {
569 low.add(resolvedRoute.prefix());
570 }
571 });
572 return Stream.of(high, low).filter(set -> !set.isEmpty()).collect(Collectors.toList());
573 }
574
575 /**
Charles Chan411beb22019-04-17 14:20:26 -0700576 * Returns batches of all subnets reachable on the given device.
577 * <p>
578 * First batch includes configured subnets, FPM and STATIC routes
579 * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
580 *
581 * @param deviceId device identifier
582 * @return list of subnet batches, each batch includes a set of prefixes.
583 */
584 // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
585 public List<Set<IpPrefix>> getBatchedSubnets(DeviceId deviceId) {
586 Set<IpPrefix> high = Sets.newHashSet();
587 Set<IpPrefix> low = Sets.newHashSet();
588
589 high.addAll(getConfiguredSubnets(deviceId));
590 srManager.routeService.getRouteTables().stream()
591 .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
592 .flatMap(Collection::stream)
593 .forEach(resolvedRoute -> {
594 // Continue to next resolved route if none of the next hop attaches to given device
595 if (srManager.nextHopLocations(resolvedRoute).stream()
596 .noneMatch(cp -> Objects.equals(deviceId, cp.deviceId()))) {
597 return;
598 }
599 // Prioritize STATIC and FPM among others
600 if (resolvedRoute.route().source() == Route.Source.STATIC ||
601 resolvedRoute.route().source() == Route.Source.FPM) {
602 high.add(resolvedRoute.prefix());
603 } else {
604 low.add(resolvedRoute.prefix());
605 }
606 });
607 return Lists.newArrayList(high, low);
608 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800609
Saurav Das0e99e2b2015-10-28 12:39:42 -0700610 /**
Charles Chan2c15aca2016-11-09 20:51:44 -0800611 * Returns the subnet configuration of given device and port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700612 *
Charles Chan2c15aca2016-11-09 20:51:44 -0800613 * @param deviceId Device ID
614 * @param port Port number
Pier Ventre10bd8d12016-11-26 21:05:22 -0800615 * @return The subnets configured on given port or empty set if
Charles Chanc53d6172017-04-24 16:21:01 -0700616 * the port is unconfigured or suppressed.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700617 */
Pier Ventre10bd8d12016-11-26 21:05:22 -0800618 public Set<IpPrefix> getPortSubnets(DeviceId deviceId, PortNumber port) {
Charles Chan2c15aca2016-11-09 20:51:44 -0800619 ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
620
621 if (isSuppressedPort(connectPoint)) {
Pier Ventre10bd8d12016-11-26 21:05:22 -0800622 return Collections.emptySet();
Saurav Das0e99e2b2015-10-28 12:39:42 -0700623 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800624
Charles Chan61eb99e2019-03-22 10:04:27 -0700625 Set<IpPrefix> subnets = srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
626 .flatMap(intf -> intf.ipAddressesList().stream())
627 .map(InterfaceIpAddress::subnetAddress)
628 .collect(Collectors.toSet());
Charles Chan2c15aca2016-11-09 20:51:44 -0800629
Jon Hallcbd1b392017-01-18 20:15:44 -0800630 if (subnets.isEmpty()) {
Saurav Das018605f2017-02-18 14:05:44 -0800631 log.debug(NO_SUBNET, connectPoint);
Pier Ventre10bd8d12016-11-26 21:05:22 -0800632 return Collections.emptySet();
Charles Chan2c15aca2016-11-09 20:51:44 -0800633 }
Charles Chanc53d6172017-04-24 16:21:01 -0700634 return subnets;
Pier Ventre10bd8d12016-11-26 21:05:22 -0800635 }
636
637 /**
Charles Chan47933752017-11-30 15:37:50 -0800638 * Returns all ports that has a subnet that contains any of the given IP addresses.
639 *
640 * @param ips a set of IP addresses
641 * @return a set of connect point that has a subnet that contains any of the given IP addresses
642 */
643 public Set<ConnectPoint> getPortByIps(Set<IpAddress> ips) {
644 return srManager.interfaceService.getInterfaces().stream()
645 .filter(intf -> intf.ipAddressesList().stream().anyMatch(intfAddress ->
646 ips.stream().anyMatch(ip -> intfAddress.subnetAddress().contains(ip))))
647 .map(Interface::connectPoint)
648 .collect(Collectors.toSet());
649 }
650
651 /**
pierf8e328d2019-06-28 22:17:31 +0200652 * Returns all the connect points of the segment routers that have the
653 * specified ip address in their subnets.
654 *
655 * @param destIpAddress target ip address
656 * @return connect points of the segment routers
657 */
658 public Set<ConnectPoint> getConnectPointsForASubnetHost(IpAddress destIpAddress) {
659 return srManager.interfaceService.getMatchingInterfaces(destIpAddress).stream()
660 .map(Interface::connectPoint)
661 .collect(Collectors.toSet());
662 }
663
664 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700665 * Returns the router ip address of segment router that has the
666 * specified ip address in its subnets.
667 *
668 * @param destIpAddress target ip address
669 * @return router ip address
670 */
671 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
Charles Chan68aaad52016-12-09 12:54:49 -0800672 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
673
674 if (matchIntf == null) {
675 log.debug("No router was found for {}", destIpAddress);
676 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700677 }
678
Charles Chan68aaad52016-12-09 12:54:49 -0800679 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
680 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
681 if (srInfo == null) {
682 log.debug("No device config was found for {}", routerDeviceId);
683 return null;
684 }
685
Pier Ventree0ae7a32016-11-23 09:57:42 -0800686 return srInfo.ipv4Loopback;
687 }
688
689 /**
690 * Returns the router ipv6 address of segment router that has the
691 * specified ip address in its subnets.
692 *
693 * @param destIpAddress target ip address
694 * @return router ip address
695 */
696 public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
697 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
698
699 if (matchIntf == null) {
700 log.debug("No router was found for {}", destIpAddress);
701 return null;
702 }
703
704 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
705 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
706 if (srInfo == null) {
707 log.debug("No device config was found for {}", routerDeviceId);
708 return null;
709 }
710
711 return srInfo.ipv6Loopback;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700712 }
713
714 /**
715 * Returns the router mac address of segment router that has the
716 * specified ip address as one of its subnet gateway ip address.
717 *
718 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700719 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700720 */
Pier Ventre10bd8d12016-11-26 21:05:22 -0800721 public MacAddress getRouterMacForAGatewayIp(IpAddress gatewayIpAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700722 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
723 deviceConfigMap.entrySet()) {
724 if (entry.getValue().gatewayIps.
725 values().contains(gatewayIpAddress)) {
726 return entry.getValue().mac;
727 }
728 }
729
730 log.debug("Cannot find a router for {}", gatewayIpAddress);
731 return null;
732 }
sangho666cd6d2015-04-14 16:27:13 -0700733
sangho666cd6d2015-04-14 16:27:13 -0700734 /**
Charles Chana9519af2017-06-26 18:30:18 -0700735 * Checks if the host IP is in any of the subnet defined in the router with the
sangho666cd6d2015-04-14 16:27:13 -0700736 * device ID given.
737 *
738 * @param deviceId device identification of the router
739 * @param hostIp host IP address to check
Charles Chana9519af2017-06-26 18:30:18 -0700740 * @return true if the given IP is within any of the subnet defined in the router,
741 * false if no subnet is defined in the router or if the host is not
742 * within any subnet defined in the router
sangho666cd6d2015-04-14 16:27:13 -0700743 */
Pier Ventre10bd8d12016-11-26 21:05:22 -0800744 public boolean inSameSubnet(DeviceId deviceId, IpAddress hostIp) {
Charles Chan61eb99e2019-03-22 10:04:27 -0700745 Set<IpPrefix> subnets = getConfiguredSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700746 if (subnets == null) {
747 return false;
748 }
749
Pier Ventre10bd8d12016-11-26 21:05:22 -0800750 for (IpPrefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800751 // Exclude /0 since it is a special case used for default route
752 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700753 return true;
754 }
755 }
sangho666cd6d2015-04-14 16:27:13 -0700756 return false;
757 }
sangho1e575652015-05-14 00:39:53 -0700758
759 /**
Charles Chan03a73e02016-10-24 14:52:01 -0700760 * Checks if the IP is in the subnet defined on given connect point.
761 *
762 * @param connectPoint Connect point
763 * @param ip The IP address to check
764 * @return True if the IP belongs to the subnet.
765 * False if the IP does not belong to the subnet, or
766 * there is no subnet configuration on given connect point.
767 */
768 public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
Charles Chana9519af2017-06-26 18:30:18 -0700769 return getPortSubnets(connectPoint.deviceId(), connectPoint.port()).stream()
770 .anyMatch(ipPrefix -> ipPrefix.contains(ip));
Charles Chan03a73e02016-10-24 14:52:01 -0700771 }
772
773 /**
sangho1e575652015-05-14 00:39:53 -0700774 * Returns the ports corresponding to the adjacency Sid given.
775 *
776 * @param deviceId device identification of the router
777 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800778 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700779 */
Charles Chan531a78b2015-12-01 10:00:51 -0800780 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700781 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800782 return srinfo != null ?
783 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
784 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700785 }
786
787 /**
788 * Check if the Sid given is whether adjacency Sid of the router device or not.
789 *
790 * @param deviceId device identification of the router
791 * @param sid Sid to check
792 * @return true if the Sid given is the adjacency Sid of the device,
793 * otherwise false
794 */
795 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700796 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800797 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700798 }
Charles Chanf2565a92016-02-10 20:46:58 -0800799
Charles Chand55e84d2016-03-30 17:54:24 -0700800 /**
Charles Chan93e71ba2016-04-29 14:38:22 -0700801 * Add subnet to specific connect point.
802 *
803 * @param cp connect point
Pier Ventre10bd8d12016-11-26 21:05:22 -0800804 * @param ipPrefix subnet being added to the device
Charles Chan93e71ba2016-04-29 14:38:22 -0700805 */
Pier Ventre10bd8d12016-11-26 21:05:22 -0800806 public void addSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
Charles Chan93e71ba2016-04-29 14:38:22 -0700807 checkNotNull(cp);
Pier Ventre10bd8d12016-11-26 21:05:22 -0800808 checkNotNull(ipPrefix);
Charles Chan93e71ba2016-04-29 14:38:22 -0700809 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
810 if (srinfo == null) {
811 log.warn("Device {} is not configured. Abort.", cp.deviceId());
812 return;
813 }
Pier Ventre10bd8d12016-11-26 21:05:22 -0800814 srinfo.subnets.put(cp.port(), ipPrefix);
Charles Chan93e71ba2016-04-29 14:38:22 -0700815 }
816
817 /**
818 * Remove subnet from specific connect point.
819 *
820 * @param cp connect point
Pier Ventre10bd8d12016-11-26 21:05:22 -0800821 * @param ipPrefix subnet being removed to the device
Charles Chan93e71ba2016-04-29 14:38:22 -0700822 */
Pier Ventre10bd8d12016-11-26 21:05:22 -0800823 public void removeSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
Charles Chan93e71ba2016-04-29 14:38:22 -0700824 checkNotNull(cp);
Pier Ventre10bd8d12016-11-26 21:05:22 -0800825 checkNotNull(ipPrefix);
Charles Chan93e71ba2016-04-29 14:38:22 -0700826 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
827 if (srinfo == null) {
828 log.warn("Device {} is not configured. Abort.", cp.deviceId());
829 return;
830 }
Pier Ventre10bd8d12016-11-26 21:05:22 -0800831 srinfo.subnets.remove(cp.port(), ipPrefix);
Charles Chan93e71ba2016-04-29 14:38:22 -0700832 }
Charles Chan2c15aca2016-11-09 20:51:44 -0800833
834 private boolean isSuppressedPort(ConnectPoint connectPoint) {
835 SegmentRoutingAppConfig appConfig = srManager.cfgService
Ray Milkeye4afdb52017-04-05 09:42:04 -0700836 .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
Charles Chan2c15aca2016-11-09 20:51:44 -0800837 if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
Charles Chan03a73e02016-10-24 14:52:01 -0700838 log.info("Interface configuration on port {} is ignored", connectPoint);
Charles Chan2c15aca2016-11-09 20:51:44 -0800839 return true;
840 }
841 return false;
842 }
Saurav Das7bcbe702017-06-13 15:35:54 -0700843
844 public boolean isPairedEdge(DeviceId deviceId) throws DeviceConfigNotFoundException {
845 if (!isEdgeDevice(deviceId)) {
846 return false;
847 }
848 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
849 return (srinfo.pairDeviceId == null) ? false : true;
850 }
851
852 public DeviceId getPairDeviceId(DeviceId deviceId) throws DeviceConfigNotFoundException {
853 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
854 if (srinfo != null) {
855 return srinfo.pairDeviceId;
856 } else {
857 String message = "getPairDeviceId fails for device: " + deviceId + ".";
858 throw new DeviceConfigNotFoundException(message);
859 }
860 }
861
862 public PortNumber getPairLocalPort(DeviceId deviceId)
863 throws DeviceConfigNotFoundException {
864 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
865 if (srinfo != null) {
866 return srinfo.pairLocalPort;
867 } else {
868 String message = "getPairLocalPort fails for device: " + deviceId + ".";
869 throw new DeviceConfigNotFoundException(message);
870 }
871 }
872
Saurav Das9a554292018-04-27 18:42:30 -0700873 public boolean isPairLocalPort(DeviceId devId, PortNumber pnum) {
874 return pnum.equals(srManager.getPairLocalPort(devId).orElse(null));
875 }
Jonathan Hart00cddda2016-02-16 10:30:37 -0800876}