blob: d161f63ea1557fdd2149282798d7602d7b403e1b [file] [log] [blame]
Thomas Vachuska8fd25052015-09-10 16:15:33 -07001/*
Brian O'Connor0947d7e2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska8fd25052015-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 Chan319d1a22015-11-03 10:42:14 -080016package org.onosproject.segmentrouting.config;
sangho80f11cb2015-04-01 13:05:26 -070017
Charles Chan6191aca2017-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 Chan82ab1932016-01-30 23:22:37 -080021import com.google.common.collect.HashMultimap;
Charles Chanc6ad7752015-10-29 14:58:10 -070022import com.google.common.collect.ImmutableSet;
Charles Chan19b70032019-04-17 14:20:26 -070023import com.google.common.collect.Lists;
Charles Chandc7d6f92018-03-20 13:30:38 -070024import com.google.common.collect.Multimaps;
Charles Chan82ab1932016-01-30 23:22:37 -080025import com.google.common.collect.SetMultimap;
Charles Chan19b70032019-04-17 14:20:26 -070026import com.google.common.collect.Sets;
sangho80f11cb2015-04-01 13:05:26 -070027import org.onlab.packet.Ip4Address;
Pier Ventreadb4ae62016-11-23 09:57:42 -080028import org.onlab.packet.Ip6Address;
Charles Chandebfea32016-10-24 14:52:01 -070029import org.onlab.packet.IpAddress;
Charles Chan82ab1932016-01-30 23:22:37 -080030import org.onlab.packet.IpPrefix;
sangho80f11cb2015-04-01 13:05:26 -070031import org.onlab.packet.MacAddress;
Charles Chanb7f75ac2016-01-11 18:28:54 -080032import org.onlab.packet.VlanId;
Charles Chane7c61022015-10-07 14:21:45 -070033import org.onosproject.net.ConnectPoint;
sangho80f11cb2015-04-01 13:05:26 -070034import org.onosproject.net.DeviceId;
Charles Chan5eec3b12019-04-18 14:30:41 -070035import org.onosproject.net.HostId;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070036import org.onosproject.net.PortNumber;
Jonathan Hart61e24e12017-11-30 18:23:42 -080037import org.onosproject.net.config.ConfigException;
Andrea Campanella09943842020-03-27 12:53:46 +010038import org.onosproject.net.config.basics.BasicDeviceConfig;
Jonathan Hart61e24e12017-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 Chan19b70032019-04-17 14:20:26 -070042import org.onosproject.routeservice.Route;
Charles Chan46fdfaf2016-11-09 20:51:44 -080043import org.onosproject.segmentrouting.SegmentRoutingManager;
sangho80f11cb2015-04-01 13:05:26 -070044import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070047import java.util.ArrayList;
Jonathan Hart61e24e12017-11-30 18:23:42 -080048import java.util.Collection;
Pier Ventreb6a7f342016-11-26 21:05:22 -080049import java.util.Collections;
sangho80f11cb2015-04-01 13:05:26 -070050import java.util.HashMap;
Charles Chan9bec8a32015-12-01 10:00:51 -080051import java.util.HashSet;
sangho80f11cb2015-04-01 13:05:26 -070052import java.util.List;
53import java.util.Map;
Charles Chancf789822019-03-22 10:04:27 -070054import java.util.Objects;
Charles Chan72f556a2015-10-05 17:50:33 -070055import java.util.Set;
Saurav Das7c305372015-10-28 12:39:42 -070056import java.util.concurrent.ConcurrentHashMap;
Charles Chan46fdfaf2016-11-09 20:51:44 -080057import java.util.stream.Collectors;
Charles Chan5eec3b12019-04-18 14:30:41 -070058import java.util.stream.Stream;
sangho80f11cb2015-04-01 13:05:26 -070059
Charles Chanc22cef32016-04-29 14:38:22 -070060import static com.google.common.base.Preconditions.checkNotNull;
61
Srikanth Vavilapalli37a461b2015-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 Vavilapalli37a461b2015-04-07 15:12:32 -070066 */
sangho80f11cb2015-04-01 13:05:26 -070067public class DeviceConfiguration implements DeviceProperties {
68
Charles Chan46fdfaf2016-11-09 20:51:44 -080069 private static final String NO_SUBNET = "No subnet configured on {}";
70
Charles Chan43547ca2016-02-10 20:46:58 -080071 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -070072 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chanb7f75ac2016-01-11 18:28:54 -080073 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chan46fdfaf2016-11-09 20:51:44 -080074 private SegmentRoutingManager srManager;
sangho80f11cb2015-04-01 13:05:26 -070075
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070076 private class SegmentRouterInfo {
Charles Chan3d35a542018-10-02 12:52:29 -070077 int ipv4NodeSid = -1;
78 int ipv6NodeSid = -1;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070079 DeviceId deviceId;
Pier Ventreadb4ae62016-11-23 09:57:42 -080080 Ip4Address ipv4Loopback;
81 Ip6Address ipv6Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070082 MacAddress mac;
83 boolean isEdge;
Pier Ventreb6a7f342016-11-26 21:05:22 -080084 SetMultimap<PortNumber, IpAddress> gatewayIps;
85 SetMultimap<PortNumber, IpPrefix> subnets;
Charles Chan9bec8a32015-12-01 10:00:51 -080086 Map<Integer, Set<Integer>> adjacencySids;
Saurav Das261c3002017-06-13 15:35:54 -070087 DeviceId pairDeviceId;
88 PortNumber pairLocalPort;
Andreas Pantelopoulos5e7be3d2017-10-23 12:18:25 -070089 int pwRoutingLabel;
Charles Chan2b078ae2015-10-14 11:24:40 -070090
91 public SegmentRouterInfo() {
Charles Chandc7d6f92018-03-20 13:30:38 -070092 gatewayIps = Multimaps.synchronizedSetMultimap(HashMultimap.create());
93 subnets = Multimaps.synchronizedSetMultimap(HashMultimap.create());
Charles Chan2b078ae2015-10-14 11:24:40 -070094 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070095 }
sangho80f11cb2015-04-01 13:05:26 -070096
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070097 /**
Charles Chanb7f75ac2016-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'Connor65eeb572015-10-09 17:03:44 -0700100 *
Charles Chan46fdfaf2016-11-09 20:51:44 -0800101 * @param srManager Segment Routing Manager
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700102 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800103 public DeviceConfiguration(SegmentRoutingManager srManager) {
104 this.srManager = srManager;
Saurav Das261c3002017-06-13 15:35:54 -0700105 updateConfig();
106 }
Charles Chan57bd98c2016-02-22 19:27:29 -0800107
Saurav Das261c3002017-06-13 15:35:54 -0700108 public void updateConfig() {
Charles Chane7c61022015-10-07 14:21:45 -0700109 // Read config from device subject, excluding gatewayIps and subnets.
110 Set<DeviceId> deviceSubjects =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800111 srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -0700112 deviceSubjects.forEach(subject -> {
Andrea Campanella09943842020-03-27 12:53:46 +0100113 BasicDeviceConfig basicDeviceConfig = srManager.cfgService.addConfig(subject, BasicDeviceConfig.class);
pierc81188f2020-04-15 22:48:36 +0200114 if (!basicDeviceConfig.purgeOnDisconnection()) {
115 // Setting purge on disconnection flag for the device SR has control over.
116 // addConfig returns a config if it exists or creates a new one.
117 log.info("PurgeOnDisconnection set to true for device {}", subject);
118 basicDeviceConfig.purgeOnDisconnection(true);
119 srManager.cfgService.applyConfig(subject, BasicDeviceConfig.class, basicDeviceConfig.node());
120 }
Charles Chan82ab1932016-01-30 23:22:37 -0800121 SegmentRoutingDeviceConfig config =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800122 srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700123 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chan72f556a2015-10-05 17:50:33 -0700124 info.deviceId = subject;
Pier Ventreadb4ae62016-11-23 09:57:42 -0800125 info.ipv4NodeSid = config.nodeSidIPv4();
126 info.ipv6NodeSid = config.nodeSidIPv6();
127 info.ipv4Loopback = config.routerIpv4();
128 info.ipv6Loopback = config.routerIpv6();
Charles Chan9bec8a32015-12-01 10:00:51 -0800129 info.mac = config.routerMac();
Charles Chan72f556a2015-10-05 17:50:33 -0700130 info.isEdge = config.isEdgeRouter();
Charles Chan9bec8a32015-12-01 10:00:51 -0800131 info.adjacencySids = config.adjacencySids();
Saurav Das261c3002017-06-13 15:35:54 -0700132 info.pairDeviceId = config.pairDeviceId();
133 info.pairLocalPort = config.pairLocalPort();
Andreas Pantelopoulos5e7be3d2017-10-23 12:18:25 -0700134 info.pwRoutingLabel = info.ipv4NodeSid + 1000;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800135 deviceConfigMap.put(info.deviceId, info);
Charles Chan68363b12017-06-26 15:25:09 -0700136 log.debug("Read device config for device: {}", info.deviceId);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800137 /*
138 * IPv6 sid is not inserted. this part of the code is not used for now.
139 */
140 allSegmentIds.add(info.ipv4NodeSid);
Charles Chan72f556a2015-10-05 17:50:33 -0700141 });
Charles Chane7c61022015-10-07 14:21:45 -0700142
Charles Chan46fdfaf2016-11-09 20:51:44 -0800143 // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
144 Set<ConnectPoint> portSubjects = srManager.cfgService
145 .getSubjects(ConnectPoint.class, InterfaceConfig.class);
Jonathan Hart61e24e12017-11-30 18:23:42 -0800146 portSubjects.stream()
147 .filter(subject -> deviceConfigMap.containsKey(subject.deviceId()))
148 .filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
Charles Chane7c61022015-10-07 14:21:45 -0700149 InterfaceConfig config =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800150 srManager.cfgService.getConfig(subject, InterfaceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -0700151 Set<Interface> networkInterfaces;
152 try {
153 networkInterfaces = config.getInterfaces();
154 } catch (ConfigException e) {
155 log.error("Error loading port configuration");
156 return;
157 }
158 networkInterfaces.forEach(networkInterface -> {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800159 VlanId vlanId = networkInterface.vlan();
160 ConnectPoint connectPoint = networkInterface.connectPoint();
161 DeviceId dpid = connectPoint.deviceId();
162 PortNumber port = connectPoint.port();
Charles Chan6191aca2017-09-12 12:09:22 -0700163 MacAddress mac = networkInterface.mac();
Charles Chanb7f75ac2016-01-11 18:28:54 -0800164 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chane7c61022015-10-07 14:21:45 -0700165
Charles Chan2b078ae2015-10-14 11:24:40 -0700166 // skip if there is no corresponding device for this ConenctPoint
167 if (info != null) {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800168 // Extract subnet information
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800169 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chan2b078ae2015-10-14 11:24:40 -0700170 interfaceAddresses.forEach(interfaceAddress -> {
Pier Ventreb6a7f342016-11-26 21:05:22 -0800171 // Do not add /0, /32 and /128 to gateway IP list
Charles Chan82ab1932016-01-30 23:22:37 -0800172 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
Pier Ventreb6a7f342016-11-26 21:05:22 -0800173 IpPrefix ipPrefix = interfaceAddress.subnetAddress();
174 if (ipPrefix.isIp4()) {
175 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
176 info.gatewayIps.put(port, interfaceAddress.ipAddress());
177 }
178 info.subnets.put(port, interfaceAddress.subnetAddress());
179 } else {
180 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET6_MASK_LENGTH) {
181 info.gatewayIps.put(port, interfaceAddress.ipAddress());
182 }
183 info.subnets.put(port, interfaceAddress.subnetAddress());
Charles Chan82ab1932016-01-30 23:22:37 -0800184 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700185 });
Charles Chan6191aca2017-09-12 12:09:22 -0700186
187 // Override interface mac with router mac
188 if (!mac.equals(info.mac)) {
189 ArrayNode array = (ArrayNode) config.node();
190 for (JsonNode intfNode : array) {
191 ObjectNode objNode = (ObjectNode) intfNode;
192 objNode.put(InterfaceConfig.MAC, info.mac.toString());
193 }
194 srManager.cfgService.applyConfig(connectPoint, InterfaceConfig.class, array);
195 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700196 }
Charles Chane7c61022015-10-07 14:21:45 -0700197 });
Pier Luigi6a2643a2017-01-31 09:35:05 -0800198 // We register the connect point with the NRS.
Pier Ventreb6a7f342016-11-26 21:05:22 -0800199 srManager.registerConnectPoint(subject);
Charles Chane7c61022015-10-07 14:21:45 -0700200 });
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700201 }
202
Jonathan Hart61e24e12017-11-30 18:23:42 -0800203 public Collection<DeviceId> getRouters() {
204 return deviceConfigMap.keySet();
205 }
Saurav Das261c3002017-06-13 15:35:54 -0700206
sangho80f11cb2015-04-01 13:05:26 -0700207 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800208 public boolean isConfigured(DeviceId deviceId) {
209 return deviceConfigMap.get(deviceId) != null;
210 }
211
212 @Override
Pier Ventreadb4ae62016-11-23 09:57:42 -0800213 public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700214 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
215 if (srinfo != null) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800216 log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
217 return srinfo.ipv4NodeSid;
sangho80f11cb2015-04-01 13:05:26 -0700218 } else {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800219 String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
220 throw new DeviceConfigNotFoundException(message);
221 }
222 }
223
224 @Override
225 public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
226 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
227 if (srinfo != null) {
228 log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
229 return srinfo.ipv6NodeSid;
230 } else {
231 String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
Charles Chan319d1a22015-11-03 10:42:14 -0800232 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700233 }
234 }
235
Andreas Pantelopoulos5e7be3d2017-10-23 12:18:25 -0700236 @Override
237 public int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException {
238 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
239 if (srinfo != null) {
240 log.trace("pwRoutingLabel for device{} is {}", deviceId, srinfo.pwRoutingLabel);
241 return srinfo.pwRoutingLabel;
242 } else {
243 String message = "getPWRoutingLabel fails for device: " + deviceId + ".";
244 throw new DeviceConfigNotFoundException(message);
245 }
246 }
247
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700248 /**
Pier Ventreadb4ae62016-11-23 09:57:42 -0800249 * Returns the IPv4 Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700250 *
251 * @param routerMac router mac address
Saurav Das7c305372015-10-28 12:39:42 -0700252 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700253 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800254 public int getIPv4SegmentId(MacAddress routerMac) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700255 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
256 deviceConfigMap.entrySet()) {
257 if (entry.getValue().mac.equals(routerMac)) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800258 return entry.getValue().ipv4NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700259 }
260 }
sangho80f11cb2015-04-01 13:05:26 -0700261
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700262 return -1;
263 }
264
265 /**
Pier Ventreadb4ae62016-11-23 09:57:42 -0800266 * Returns the IPv6 Node segment id of a segment router given its Router mac address.
267 *
268 * @param routerMac router mac address
269 * @return node segment id, or -1 if not found in config
270 */
271 public int getIPv6SegmentId(MacAddress routerMac) {
272 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
273 deviceConfigMap.entrySet()) {
274 if (entry.getValue().mac.equals(routerMac)) {
275 return entry.getValue().ipv6NodeSid;
276 }
277 }
278
279 return -1;
280 }
281
282 /**
283 * Returns the IPv4 Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700284 *
285 * @param routerAddress router ip address
Saurav Das7c305372015-10-28 12:39:42 -0700286 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700287 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800288 public int getIPv4SegmentId(Ip4Address routerAddress) {
Charles Chan3d35a542018-10-02 12:52:29 -0700289 for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
290 Ip4Address ipv4Loopback = entry.getValue().ipv4Loopback;
291 if (ipv4Loopback == null) {
292 continue;
293 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800294 if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
Charles Chan3d35a542018-10-02 12:52:29 -0700295 if (entry.getValue().ipv4NodeSid == -1) {
296 continue;
297 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800298 return entry.getValue().ipv4NodeSid;
299 }
300 }
301
302 return -1;
303 }
304
305 /**
306 * Returns the IPv6 Node segment id of a segment router given its Router ip address.
307 *
308 * @param routerAddress router ip address
309 * @return node segment id, or -1 if not found in config
310 */
311 public int getIPv6SegmentId(Ip6Address routerAddress) {
Charles Chan3d35a542018-10-02 12:52:29 -0700312 for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
313 Ip6Address ipv6Loopback = entry.getValue().ipv6Loopback;
314 if (ipv6Loopback == null) {
315 continue;
316 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800317 if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
Charles Chan3d35a542018-10-02 12:52:29 -0700318 if (entry.getValue().ipv6NodeSid == -1) {
319 continue;
320 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800321 return entry.getValue().ipv6NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700322 }
323 }
324
325 return -1;
326 }
327
sangho80f11cb2015-04-01 13:05:26 -0700328 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800329 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700330 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
331 if (srinfo != null) {
Saurav Das7c305372015-10-28 12:39:42 -0700332 return srinfo.mac;
sangho80f11cb2015-04-01 13:05:26 -0700333 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800334 String message = "getDeviceMac fails for device: " + deviceId + ".";
335 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700336 }
337 }
338
Charles Chan319d1a22015-11-03 10:42:14 -0800339 @Override
Pier Ventreadb4ae62016-11-23 09:57:42 -0800340 public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700341 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
342 if (srinfo != null) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800343 log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
344 return srinfo.ipv4Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700345 } else {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800346 String message = "getRouterIpv4 fails for device: " + deviceId + ".";
347 throw new DeviceConfigNotFoundException(message);
348 }
349 }
350
351 @Override
352 public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
353 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
354 if (srinfo != null) {
355 log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
356 return srinfo.ipv6Loopback;
357 } else {
358 String message = "getRouterIpv6 fails for device: " + deviceId + ".";
Charles Chan319d1a22015-11-03 10:42:14 -0800359 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700360 }
sangho80f11cb2015-04-01 13:05:26 -0700361 }
362
pier6a2052b2019-06-28 22:17:31 +0200363 /**
364 * Gets router ip address based on the destination ip address.
365 *
366 * @param destIpAddress the destination ip address
367 * @param routerDeviceId the device id
368 * @return the ip address of the routes
369 */
370 public IpAddress getRouterIpAddress(IpAddress destIpAddress, DeviceId routerDeviceId) {
371 IpAddress routerIpAddress;
372 try {
373 routerIpAddress = destIpAddress.isIp4() ? getRouterIpv4(routerDeviceId) :
374 getRouterIpv6(routerDeviceId);
375 } catch (DeviceConfigNotFoundException e) {
376 routerIpAddress = null;
377 }
378 return routerIpAddress;
379 }
380
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700381 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800382 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700383 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
384 if (srinfo != null) {
385 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
386 return srinfo.isEdge;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700387 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800388 String message = "isEdgeDevice fails for device: " + deviceId + ".";
389 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700390 }
391 }
392
sangho80f11cb2015-04-01 13:05:26 -0700393 @Override
394 public List<Integer> getAllDeviceSegmentIds() {
395 return allSegmentIds;
396 }
397
Charles Chan77277672015-10-20 16:24:19 -0700398 @Override
Pier Ventreb6a7f342016-11-26 21:05:22 -0800399 public Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
Saurav Das52d4ed72016-03-28 19:00:18 -0700400 throws DeviceConfigNotFoundException {
401 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
402 if (srinfo == null) {
403 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
404 throw new DeviceConfigNotFoundException(message);
405 }
Charles Chan77277672015-10-20 16:24:19 -0700406 // Construct subnet-port mapping from port-subnet mapping
Pier Ventreb6a7f342016-11-26 21:05:22 -0800407 SetMultimap<PortNumber, IpPrefix> portSubnetMap = srinfo.subnets;
408 Map<IpPrefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan82ab1932016-01-30 23:22:37 -0800409
410 portSubnetMap.entries().forEach(entry -> {
411 PortNumber port = entry.getKey();
Pier Ventreb6a7f342016-11-26 21:05:22 -0800412 IpPrefix subnet = entry.getValue();
Charles Chan82ab1932016-01-30 23:22:37 -0800413
Pier Ventreb6a7f342016-11-26 21:05:22 -0800414 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
415 subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
Charles Chanbbd004c2016-02-16 23:14:49 -0800416 return;
417 }
418
Charles Chan77277672015-10-20 16:24:19 -0700419 if (subnetPortMap.containsKey(subnet)) {
420 subnetPortMap.get(subnet).add(port);
421 } else {
422 ArrayList<PortNumber> ports = new ArrayList<>();
423 ports.add(port);
424 subnetPortMap.put(subnet, ports);
425 }
426 });
Charles Chan77277672015-10-20 16:24:19 -0700427 return subnetPortMap;
428 }
429
sangho80f11cb2015-04-01 13:05:26 -0700430 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700431 * Returns the device identifier or data plane identifier (dpid)
432 * of a segment router given its segment id.
sangho80f11cb2015-04-01 13:05:26 -0700433 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700434 * @param sid segment id
435 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700436 */
437 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700438 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
439 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800440 if (entry.getValue().ipv4NodeSid == sid ||
441 entry.getValue().ipv6NodeSid == sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700442 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700443 }
444 }
445
446 return null;
447 }
448
449 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700450 * Returns the device identifier or data plane identifier (dpid)
451 * of a segment router given its router ip address.
sangho80f11cb2015-04-01 13:05:26 -0700452 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700453 * @param ipAddress router ip address
454 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700455 */
456 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700457 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
458 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800459 if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
460 return entry.getValue().deviceId;
461 }
462 }
463
464 return null;
465 }
466
467 /**
468 * Returns the device identifier or data plane identifier (dpid)
469 * of a segment router given its router ipv6 address.
470 *
471 * @param ipAddress router ipv6 address
472 * @return deviceId device identifier
473 */
474 public DeviceId getDeviceId(Ip6Address ipAddress) {
475 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
476 deviceConfigMap.entrySet()) {
477 if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700478 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700479 }
480 }
481
482 return null;
483 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700484
485 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700486 * Returns the configured port ip addresses for a segment router.
487 * These addresses serve as gateway IP addresses for the subnets configured
488 * on those ports.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700489 *
490 * @param deviceId device identifier
Saurav Dasc28b3432015-10-30 17:45:38 -0700491 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700492 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800493 public Set<IpAddress> getPortIPs(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700494 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
495 if (srinfo != null) {
496 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
497 srinfo.gatewayIps.values());
Saurav Dasc28b3432015-10-30 17:45:38 -0700498 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700499 }
Saurav Das7c305372015-10-28 12:39:42 -0700500 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700501 }
502
503 /**
Charles Chancf789822019-03-22 10:04:27 -0700504 * Returns configured subnets for a segment router.
505 *
506 * @param deviceId device identifier
507 * @return list of ip prefixes or null if not found
508 */
509 public Set<IpPrefix> getConfiguredSubnets(DeviceId deviceId) {
510 Set<IpPrefix> subnets = srManager.interfaceService.getInterfaces().stream()
511 .filter(intf -> Objects.equals(deviceId, intf.connectPoint().deviceId()))
512 .flatMap(intf -> intf.ipAddressesList().stream())
513 .map(InterfaceIpAddress::subnetAddress)
514 .collect(Collectors.toSet());
515
516 if (subnets.isEmpty()) {
517 log.debug(NO_SUBNET, deviceId);
518 return Collections.emptySet();
519 }
520 return subnets;
521 }
522
523 /**
524 * Returns all subnets for a segment router, including subnets learnt from route service.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700525 *
526 * @param deviceId device identifier
Charles Chan19b70032019-04-17 14:20:26 -0700527 * @return set of ip prefixes or null if not found
528 * @deprecated use getBatchedSubnets(DeviceId deviceId) instead
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700529 */
Charles Chan19b70032019-04-17 14:20:26 -0700530 @Deprecated
Pier Ventreb6a7f342016-11-26 21:05:22 -0800531 public Set<IpPrefix> getSubnets(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700532 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan5eb66042018-06-18 14:42:17 -0700533 if (srinfo != null && srinfo.subnets != null) {
534 // Note: ImmutableSet.Builder.addAll calls the iterator of parameter internally,
535 // which is not protected by SynchronizedCollection mutex.
Pier Ventreb6a7f342016-11-26 21:05:22 -0800536 ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
Charles Chan5eb66042018-06-18 14:42:17 -0700537 srinfo.subnets.forEach((k, v) -> builder.add(v));
538 return builder.build();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700539 }
Saurav Das7c305372015-10-28 12:39:42 -0700540 return null;
541 }
542
Charles Chan19b70032019-04-17 14:20:26 -0700543 /**
Charles Chan5eec3b12019-04-18 14:30:41 -0700544 * Returns batches of all subnets reachable via given next hop
545 * <p>
546 * First batch includes FPM and STATIC routes
547 * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
548 *
549 * @param hostId next hop host id
550 * @return list of subnet batches, each batch includes a set of prefixes.
551 */
552 // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
553 public List<Set<IpPrefix>> getBatchedSubnets(HostId hostId) {
554 Set<IpPrefix> high = Sets.newHashSet();
555 Set<IpPrefix> low = Sets.newHashSet();
556
557 srManager.routeService.getRouteTables().stream()
558 .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
559 .flatMap(Collection::stream)
560 .forEach(resolvedRoute -> {
561 // Continue if next hop is not what we are looking for
562 if (!Objects.equals(hostId.mac(), resolvedRoute.nextHopMac()) ||
563 !Objects.equals(hostId.vlanId(), resolvedRoute.nextHopVlan())) {
564 return;
565 }
566 // Prioritize STATIC and FPM among others
567 if (resolvedRoute.route().source() == Route.Source.STATIC ||
568 resolvedRoute.route().source() == Route.Source.FPM) {
569 high.add(resolvedRoute.prefix());
570 } else {
571 low.add(resolvedRoute.prefix());
572 }
573 });
574 return Stream.of(high, low).filter(set -> !set.isEmpty()).collect(Collectors.toList());
575 }
576
577 /**
Charles Chan19b70032019-04-17 14:20:26 -0700578 * Returns batches of all subnets reachable on the given device.
579 * <p>
580 * First batch includes configured subnets, FPM and STATIC routes
581 * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
582 *
583 * @param deviceId device identifier
584 * @return list of subnet batches, each batch includes a set of prefixes.
585 */
586 // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
587 public List<Set<IpPrefix>> getBatchedSubnets(DeviceId deviceId) {
588 Set<IpPrefix> high = Sets.newHashSet();
589 Set<IpPrefix> low = Sets.newHashSet();
590
591 high.addAll(getConfiguredSubnets(deviceId));
592 srManager.routeService.getRouteTables().stream()
593 .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
594 .flatMap(Collection::stream)
595 .forEach(resolvedRoute -> {
596 // Continue to next resolved route if none of the next hop attaches to given device
597 if (srManager.nextHopLocations(resolvedRoute).stream()
598 .noneMatch(cp -> Objects.equals(deviceId, cp.deviceId()))) {
599 return;
600 }
601 // Prioritize STATIC and FPM among others
602 if (resolvedRoute.route().source() == Route.Source.STATIC ||
603 resolvedRoute.route().source() == Route.Source.FPM) {
604 high.add(resolvedRoute.prefix());
605 } else {
606 low.add(resolvedRoute.prefix());
607 }
608 });
609 return Lists.newArrayList(high, low);
610 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800611
Saurav Das7c305372015-10-28 12:39:42 -0700612 /**
Charles Chan46fdfaf2016-11-09 20:51:44 -0800613 * Returns the subnet configuration of given device and port.
Saurav Das7c305372015-10-28 12:39:42 -0700614 *
Charles Chan46fdfaf2016-11-09 20:51:44 -0800615 * @param deviceId Device ID
616 * @param port Port number
Pier Ventreb6a7f342016-11-26 21:05:22 -0800617 * @return The subnets configured on given port or empty set if
Charles Chan2f4d2bc2017-04-24 16:21:01 -0700618 * the port is unconfigured or suppressed.
Saurav Das7c305372015-10-28 12:39:42 -0700619 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800620 public Set<IpPrefix> getPortSubnets(DeviceId deviceId, PortNumber port) {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800621 ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
622
623 if (isSuppressedPort(connectPoint)) {
Pier Ventreb6a7f342016-11-26 21:05:22 -0800624 return Collections.emptySet();
Saurav Das7c305372015-10-28 12:39:42 -0700625 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800626
Charles Chancf789822019-03-22 10:04:27 -0700627 Set<IpPrefix> subnets = srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
628 .flatMap(intf -> intf.ipAddressesList().stream())
629 .map(InterfaceIpAddress::subnetAddress)
630 .collect(Collectors.toSet());
Charles Chan46fdfaf2016-11-09 20:51:44 -0800631
Jon Hall31d84782017-01-18 20:15:44 -0800632 if (subnets.isEmpty()) {
Saurav Dasf9332192017-02-18 14:05:44 -0800633 log.debug(NO_SUBNET, connectPoint);
Pier Ventreb6a7f342016-11-26 21:05:22 -0800634 return Collections.emptySet();
Charles Chan46fdfaf2016-11-09 20:51:44 -0800635 }
Charles Chan2f4d2bc2017-04-24 16:21:01 -0700636 return subnets;
Pier Ventreb6a7f342016-11-26 21:05:22 -0800637 }
638
639 /**
Charles Chan873661e2017-11-30 15:37:50 -0800640 * Returns all ports that has a subnet that contains any of the given IP addresses.
641 *
642 * @param ips a set of IP addresses
643 * @return a set of connect point that has a subnet that contains any of the given IP addresses
644 */
645 public Set<ConnectPoint> getPortByIps(Set<IpAddress> ips) {
646 return srManager.interfaceService.getInterfaces().stream()
647 .filter(intf -> intf.ipAddressesList().stream().anyMatch(intfAddress ->
648 ips.stream().anyMatch(ip -> intfAddress.subnetAddress().contains(ip))))
649 .map(Interface::connectPoint)
650 .collect(Collectors.toSet());
651 }
652
653 /**
pier6a2052b2019-06-28 22:17:31 +0200654 * Returns all the connect points of the segment routers that have the
655 * specified ip address in their subnets.
656 *
657 * @param destIpAddress target ip address
658 * @return connect points of the segment routers
659 */
660 public Set<ConnectPoint> getConnectPointsForASubnetHost(IpAddress destIpAddress) {
661 return srManager.interfaceService.getMatchingInterfaces(destIpAddress).stream()
662 .map(Interface::connectPoint)
663 .collect(Collectors.toSet());
664 }
665
666 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700667 * Returns the router ip address of segment router that has the
668 * specified ip address in its subnets.
669 *
670 * @param destIpAddress target ip address
671 * @return router ip address
672 */
673 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
Charles Chan70661362016-12-09 12:54:49 -0800674 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
675
676 if (matchIntf == null) {
677 log.debug("No router was found for {}", destIpAddress);
678 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700679 }
680
Charles Chan70661362016-12-09 12:54:49 -0800681 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
682 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
683 if (srInfo == null) {
684 log.debug("No device config was found for {}", routerDeviceId);
685 return null;
686 }
687
Pier Ventreadb4ae62016-11-23 09:57:42 -0800688 return srInfo.ipv4Loopback;
689 }
690
691 /**
692 * Returns the router ipv6 address of segment router that has the
693 * specified ip address in its subnets.
694 *
695 * @param destIpAddress target ip address
696 * @return router ip address
697 */
698 public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
699 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
700
701 if (matchIntf == null) {
702 log.debug("No router was found for {}", destIpAddress);
703 return null;
704 }
705
706 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
707 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
708 if (srInfo == null) {
709 log.debug("No device config was found for {}", routerDeviceId);
710 return null;
711 }
712
713 return srInfo.ipv6Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700714 }
715
716 /**
717 * Returns the router mac address of segment router that has the
718 * specified ip address as one of its subnet gateway ip address.
719 *
720 * @param gatewayIpAddress router gateway ip address
Saurav Das7c305372015-10-28 12:39:42 -0700721 * @return router mac address or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700722 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800723 public MacAddress getRouterMacForAGatewayIp(IpAddress gatewayIpAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700724 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
725 deviceConfigMap.entrySet()) {
726 if (entry.getValue().gatewayIps.
727 values().contains(gatewayIpAddress)) {
728 return entry.getValue().mac;
729 }
730 }
731
732 log.debug("Cannot find a router for {}", gatewayIpAddress);
733 return null;
734 }
sangho9b169e32015-04-14 16:27:13 -0700735
sangho9b169e32015-04-14 16:27:13 -0700736 /**
Charles Chan35f21e42017-06-26 18:30:18 -0700737 * Checks if the host IP is in any of the subnet defined in the router with the
sangho9b169e32015-04-14 16:27:13 -0700738 * device ID given.
739 *
740 * @param deviceId device identification of the router
741 * @param hostIp host IP address to check
Charles Chan35f21e42017-06-26 18:30:18 -0700742 * @return true if the given IP is within any of the subnet defined in the router,
743 * false if no subnet is defined in the router or if the host is not
744 * within any subnet defined in the router
sangho9b169e32015-04-14 16:27:13 -0700745 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800746 public boolean inSameSubnet(DeviceId deviceId, IpAddress hostIp) {
Charles Chancf789822019-03-22 10:04:27 -0700747 Set<IpPrefix> subnets = getConfiguredSubnets(deviceId);
sangho9b169e32015-04-14 16:27:13 -0700748 if (subnets == null) {
749 return false;
750 }
751
Pier Ventreb6a7f342016-11-26 21:05:22 -0800752 for (IpPrefix subnet: subnets) {
Charles Chan82ab1932016-01-30 23:22:37 -0800753 // Exclude /0 since it is a special case used for default route
754 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho9b169e32015-04-14 16:27:13 -0700755 return true;
756 }
757 }
sangho9b169e32015-04-14 16:27:13 -0700758 return false;
759 }
sangho27462c62015-05-14 00:39:53 -0700760
761 /**
Charles Chandebfea32016-10-24 14:52:01 -0700762 * Checks if the IP is in the subnet defined on given connect point.
763 *
764 * @param connectPoint Connect point
765 * @param ip The IP address to check
766 * @return True if the IP belongs to the subnet.
767 * False if the IP does not belong to the subnet, or
768 * there is no subnet configuration on given connect point.
769 */
770 public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
Charles Chan35f21e42017-06-26 18:30:18 -0700771 return getPortSubnets(connectPoint.deviceId(), connectPoint.port()).stream()
772 .anyMatch(ipPrefix -> ipPrefix.contains(ip));
Charles Chandebfea32016-10-24 14:52:01 -0700773 }
774
775 /**
sangho27462c62015-05-14 00:39:53 -0700776 * Returns the ports corresponding to the adjacency Sid given.
777 *
778 * @param deviceId device identification of the router
779 * @param sid adjacency Sid
Charles Chan9bec8a32015-12-01 10:00:51 -0800780 * @return set of port numbers
sangho27462c62015-05-14 00:39:53 -0700781 */
Charles Chan9bec8a32015-12-01 10:00:51 -0800782 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700783 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800784 return srinfo != null ?
785 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
786 ImmutableSet.copyOf(new HashSet<>());
sangho27462c62015-05-14 00:39:53 -0700787 }
788
789 /**
790 * Check if the Sid given is whether adjacency Sid of the router device or not.
791 *
792 * @param deviceId device identification of the router
793 * @param sid Sid to check
794 * @return true if the Sid given is the adjacency Sid of the device,
795 * otherwise false
796 */
797 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700798 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800799 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho27462c62015-05-14 00:39:53 -0700800 }
Charles Chan43547ca2016-02-10 20:46:58 -0800801
Charles Chanc91c8782016-03-30 17:54:24 -0700802 /**
Charles Chanc22cef32016-04-29 14:38:22 -0700803 * Add subnet to specific connect point.
804 *
805 * @param cp connect point
Pier Ventreb6a7f342016-11-26 21:05:22 -0800806 * @param ipPrefix subnet being added to the device
Charles Chanc22cef32016-04-29 14:38:22 -0700807 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800808 public void addSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
Charles Chanc22cef32016-04-29 14:38:22 -0700809 checkNotNull(cp);
Pier Ventreb6a7f342016-11-26 21:05:22 -0800810 checkNotNull(ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700811 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
812 if (srinfo == null) {
813 log.warn("Device {} is not configured. Abort.", cp.deviceId());
814 return;
815 }
Pier Ventreb6a7f342016-11-26 21:05:22 -0800816 srinfo.subnets.put(cp.port(), ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700817 }
818
819 /**
820 * Remove subnet from specific connect point.
821 *
822 * @param cp connect point
Pier Ventreb6a7f342016-11-26 21:05:22 -0800823 * @param ipPrefix subnet being removed to the device
Charles Chanc22cef32016-04-29 14:38:22 -0700824 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800825 public void removeSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
Charles Chanc22cef32016-04-29 14:38:22 -0700826 checkNotNull(cp);
Pier Ventreb6a7f342016-11-26 21:05:22 -0800827 checkNotNull(ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700828 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
829 if (srinfo == null) {
830 log.warn("Device {} is not configured. Abort.", cp.deviceId());
831 return;
832 }
Pier Ventreb6a7f342016-11-26 21:05:22 -0800833 srinfo.subnets.remove(cp.port(), ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700834 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800835
836 private boolean isSuppressedPort(ConnectPoint connectPoint) {
837 SegmentRoutingAppConfig appConfig = srManager.cfgService
Ray Milkeyb85de082017-04-05 09:42:04 -0700838 .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
Charles Chan46fdfaf2016-11-09 20:51:44 -0800839 if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
Charles Chandebfea32016-10-24 14:52:01 -0700840 log.info("Interface configuration on port {} is ignored", connectPoint);
Charles Chan46fdfaf2016-11-09 20:51:44 -0800841 return true;
842 }
843 return false;
844 }
Saurav Das261c3002017-06-13 15:35:54 -0700845
846 public boolean isPairedEdge(DeviceId deviceId) throws DeviceConfigNotFoundException {
847 if (!isEdgeDevice(deviceId)) {
848 return false;
849 }
850 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
851 return (srinfo.pairDeviceId == null) ? false : true;
852 }
853
854 public DeviceId getPairDeviceId(DeviceId deviceId) throws DeviceConfigNotFoundException {
855 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
856 if (srinfo != null) {
857 return srinfo.pairDeviceId;
858 } else {
859 String message = "getPairDeviceId fails for device: " + deviceId + ".";
860 throw new DeviceConfigNotFoundException(message);
861 }
862 }
863
864 public PortNumber getPairLocalPort(DeviceId deviceId)
865 throws DeviceConfigNotFoundException {
866 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
867 if (srinfo != null) {
868 return srinfo.pairLocalPort;
869 } else {
870 String message = "getPairLocalPort fails for device: " + deviceId + ".";
871 throw new DeviceConfigNotFoundException(message);
872 }
873 }
874
Saurav Dasec683dc2018-04-27 18:42:30 -0700875 public boolean isPairLocalPort(DeviceId devId, PortNumber pnum) {
876 return pnum.equals(srManager.getPairLocalPort(devId).orElse(null));
877 }
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800878}