blob: 123da370b125ca499cc55f640b09cdf9b06fe163 [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;
38import org.onosproject.net.config.basics.InterfaceConfig;
39import org.onosproject.net.host.InterfaceIpAddress;
40import org.onosproject.net.intf.Interface;
Charles Chan19b70032019-04-17 14:20:26 -070041import org.onosproject.routeservice.Route;
Charles Chan46fdfaf2016-11-09 20:51:44 -080042import org.onosproject.segmentrouting.SegmentRoutingManager;
sangho80f11cb2015-04-01 13:05:26 -070043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070046import java.util.ArrayList;
Jonathan Hart61e24e12017-11-30 18:23:42 -080047import java.util.Collection;
Pier Ventreb6a7f342016-11-26 21:05:22 -080048import java.util.Collections;
sangho80f11cb2015-04-01 13:05:26 -070049import java.util.HashMap;
Charles Chan9bec8a32015-12-01 10:00:51 -080050import java.util.HashSet;
sangho80f11cb2015-04-01 13:05:26 -070051import java.util.List;
52import java.util.Map;
Charles Chancf789822019-03-22 10:04:27 -070053import java.util.Objects;
Charles Chan72f556a2015-10-05 17:50:33 -070054import java.util.Set;
Saurav Das7c305372015-10-28 12:39:42 -070055import java.util.concurrent.ConcurrentHashMap;
Charles Chan46fdfaf2016-11-09 20:51:44 -080056import java.util.stream.Collectors;
Charles Chan5eec3b12019-04-18 14:30:41 -070057import java.util.stream.Stream;
sangho80f11cb2015-04-01 13:05:26 -070058
Charles Chanc22cef32016-04-29 14:38:22 -070059import static com.google.common.base.Preconditions.checkNotNull;
60
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070061/**
62 * Segment Routing configuration component that reads the
63 * segment routing related configuration from Network Configuration Manager
64 * component and organizes in more accessible formats.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070065 */
sangho80f11cb2015-04-01 13:05:26 -070066public class DeviceConfiguration implements DeviceProperties {
67
Charles Chan46fdfaf2016-11-09 20:51:44 -080068 private static final String NO_SUBNET = "No subnet configured on {}";
69
Charles Chan43547ca2016-02-10 20:46:58 -080070 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -070071 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chanb7f75ac2016-01-11 18:28:54 -080072 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
Charles Chan46fdfaf2016-11-09 20:51:44 -080073 private SegmentRoutingManager srManager;
sangho80f11cb2015-04-01 13:05:26 -070074
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070075 private class SegmentRouterInfo {
Charles Chan3d35a542018-10-02 12:52:29 -070076 int ipv4NodeSid = -1;
77 int ipv6NodeSid = -1;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070078 DeviceId deviceId;
Pier Ventreadb4ae62016-11-23 09:57:42 -080079 Ip4Address ipv4Loopback;
80 Ip6Address ipv6Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070081 MacAddress mac;
82 boolean isEdge;
Pier Ventreb6a7f342016-11-26 21:05:22 -080083 SetMultimap<PortNumber, IpAddress> gatewayIps;
84 SetMultimap<PortNumber, IpPrefix> subnets;
Charles Chan9bec8a32015-12-01 10:00:51 -080085 Map<Integer, Set<Integer>> adjacencySids;
Saurav Das261c3002017-06-13 15:35:54 -070086 DeviceId pairDeviceId;
87 PortNumber pairLocalPort;
Andreas Pantelopoulos5e7be3d2017-10-23 12:18:25 -070088 int pwRoutingLabel;
Charles Chan2b078ae2015-10-14 11:24:40 -070089
90 public SegmentRouterInfo() {
Charles Chandc7d6f92018-03-20 13:30:38 -070091 gatewayIps = Multimaps.synchronizedSetMultimap(HashMultimap.create());
92 subnets = Multimaps.synchronizedSetMultimap(HashMultimap.create());
Charles Chan2b078ae2015-10-14 11:24:40 -070093 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070094 }
sangho80f11cb2015-04-01 13:05:26 -070095
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070096 /**
Charles Chanb7f75ac2016-01-11 18:28:54 -080097 * Constructs device configuration for all Segment Router devices,
98 * organizing the data into various maps for easier access.
Brian O'Connor65eeb572015-10-09 17:03:44 -070099 *
Charles Chan46fdfaf2016-11-09 20:51:44 -0800100 * @param srManager Segment Routing Manager
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700101 */
Charles Chan46fdfaf2016-11-09 20:51:44 -0800102 public DeviceConfiguration(SegmentRoutingManager srManager) {
103 this.srManager = srManager;
Saurav Das261c3002017-06-13 15:35:54 -0700104 updateConfig();
105 }
Charles Chan57bd98c2016-02-22 19:27:29 -0800106
Saurav Das261c3002017-06-13 15:35:54 -0700107 public void updateConfig() {
Charles Chane7c61022015-10-07 14:21:45 -0700108 // Read config from device subject, excluding gatewayIps and subnets.
109 Set<DeviceId> deviceSubjects =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800110 srManager.cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -0700111 deviceSubjects.forEach(subject -> {
Charles Chan82ab1932016-01-30 23:22:37 -0800112 SegmentRoutingDeviceConfig config =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800113 srManager.cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700114 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chan72f556a2015-10-05 17:50:33 -0700115 info.deviceId = subject;
Pier Ventreadb4ae62016-11-23 09:57:42 -0800116 info.ipv4NodeSid = config.nodeSidIPv4();
117 info.ipv6NodeSid = config.nodeSidIPv6();
118 info.ipv4Loopback = config.routerIpv4();
119 info.ipv6Loopback = config.routerIpv6();
Charles Chan9bec8a32015-12-01 10:00:51 -0800120 info.mac = config.routerMac();
Charles Chan72f556a2015-10-05 17:50:33 -0700121 info.isEdge = config.isEdgeRouter();
Charles Chan9bec8a32015-12-01 10:00:51 -0800122 info.adjacencySids = config.adjacencySids();
Saurav Das261c3002017-06-13 15:35:54 -0700123 info.pairDeviceId = config.pairDeviceId();
124 info.pairLocalPort = config.pairLocalPort();
Andreas Pantelopoulos5e7be3d2017-10-23 12:18:25 -0700125 info.pwRoutingLabel = info.ipv4NodeSid + 1000;
Charles Chanb7f75ac2016-01-11 18:28:54 -0800126 deviceConfigMap.put(info.deviceId, info);
Charles Chan68363b12017-06-26 15:25:09 -0700127 log.debug("Read device config for device: {}", info.deviceId);
Pier Ventreadb4ae62016-11-23 09:57:42 -0800128 /*
129 * IPv6 sid is not inserted. this part of the code is not used for now.
130 */
131 allSegmentIds.add(info.ipv4NodeSid);
Charles Chan72f556a2015-10-05 17:50:33 -0700132 });
Charles Chane7c61022015-10-07 14:21:45 -0700133
Charles Chan46fdfaf2016-11-09 20:51:44 -0800134 // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
135 Set<ConnectPoint> portSubjects = srManager.cfgService
136 .getSubjects(ConnectPoint.class, InterfaceConfig.class);
Jonathan Hart61e24e12017-11-30 18:23:42 -0800137 portSubjects.stream()
138 .filter(subject -> deviceConfigMap.containsKey(subject.deviceId()))
139 .filter(subject -> !isSuppressedPort(subject)).forEach(subject -> {
Charles Chane7c61022015-10-07 14:21:45 -0700140 InterfaceConfig config =
Charles Chan46fdfaf2016-11-09 20:51:44 -0800141 srManager.cfgService.getConfig(subject, InterfaceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -0700142 Set<Interface> networkInterfaces;
143 try {
144 networkInterfaces = config.getInterfaces();
145 } catch (ConfigException e) {
146 log.error("Error loading port configuration");
147 return;
148 }
149 networkInterfaces.forEach(networkInterface -> {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800150 VlanId vlanId = networkInterface.vlan();
151 ConnectPoint connectPoint = networkInterface.connectPoint();
152 DeviceId dpid = connectPoint.deviceId();
153 PortNumber port = connectPoint.port();
Charles Chan6191aca2017-09-12 12:09:22 -0700154 MacAddress mac = networkInterface.mac();
Charles Chanb7f75ac2016-01-11 18:28:54 -0800155 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chane7c61022015-10-07 14:21:45 -0700156
Charles Chan2b078ae2015-10-14 11:24:40 -0700157 // skip if there is no corresponding device for this ConenctPoint
158 if (info != null) {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800159 // Extract subnet information
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800160 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chan2b078ae2015-10-14 11:24:40 -0700161 interfaceAddresses.forEach(interfaceAddress -> {
Pier Ventreb6a7f342016-11-26 21:05:22 -0800162 // Do not add /0, /32 and /128 to gateway IP list
Charles Chan82ab1932016-01-30 23:22:37 -0800163 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
Pier Ventreb6a7f342016-11-26 21:05:22 -0800164 IpPrefix ipPrefix = interfaceAddress.subnetAddress();
165 if (ipPrefix.isIp4()) {
166 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
167 info.gatewayIps.put(port, interfaceAddress.ipAddress());
168 }
169 info.subnets.put(port, interfaceAddress.subnetAddress());
170 } else {
171 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET6_MASK_LENGTH) {
172 info.gatewayIps.put(port, interfaceAddress.ipAddress());
173 }
174 info.subnets.put(port, interfaceAddress.subnetAddress());
Charles Chan82ab1932016-01-30 23:22:37 -0800175 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700176 });
Charles Chan6191aca2017-09-12 12:09:22 -0700177
178 // Override interface mac with router mac
179 if (!mac.equals(info.mac)) {
180 ArrayNode array = (ArrayNode) config.node();
181 for (JsonNode intfNode : array) {
182 ObjectNode objNode = (ObjectNode) intfNode;
183 objNode.put(InterfaceConfig.MAC, info.mac.toString());
184 }
185 srManager.cfgService.applyConfig(connectPoint, InterfaceConfig.class, array);
186 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700187 }
Charles Chane7c61022015-10-07 14:21:45 -0700188 });
Pier Luigi6a2643a2017-01-31 09:35:05 -0800189 // We register the connect point with the NRS.
Pier Ventreb6a7f342016-11-26 21:05:22 -0800190 srManager.registerConnectPoint(subject);
Charles Chane7c61022015-10-07 14:21:45 -0700191 });
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700192 }
193
Jonathan Hart61e24e12017-11-30 18:23:42 -0800194 public Collection<DeviceId> getRouters() {
195 return deviceConfigMap.keySet();
196 }
Saurav Das261c3002017-06-13 15:35:54 -0700197
sangho80f11cb2015-04-01 13:05:26 -0700198 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800199 public boolean isConfigured(DeviceId deviceId) {
200 return deviceConfigMap.get(deviceId) != null;
201 }
202
203 @Override
Pier Ventreadb4ae62016-11-23 09:57:42 -0800204 public int getIPv4SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700205 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
206 if (srinfo != null) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800207 log.trace("getIPv4SegmentId for device{} is {}", deviceId, srinfo.ipv4NodeSid);
208 return srinfo.ipv4NodeSid;
sangho80f11cb2015-04-01 13:05:26 -0700209 } else {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800210 String message = "getIPv4SegmentId fails for device: " + deviceId + ".";
211 throw new DeviceConfigNotFoundException(message);
212 }
213 }
214
215 @Override
216 public int getIPv6SegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
217 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
218 if (srinfo != null) {
219 log.trace("getIPv6SegmentId for device{} is {}", deviceId, srinfo.ipv6NodeSid);
220 return srinfo.ipv6NodeSid;
221 } else {
222 String message = "getIPv6SegmentId fails for device: " + deviceId + ".";
Charles Chan319d1a22015-11-03 10:42:14 -0800223 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700224 }
225 }
226
Andreas Pantelopoulos5e7be3d2017-10-23 12:18:25 -0700227 @Override
228 public int getPWRoutingLabel(DeviceId deviceId) throws DeviceConfigNotFoundException {
229 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
230 if (srinfo != null) {
231 log.trace("pwRoutingLabel for device{} is {}", deviceId, srinfo.pwRoutingLabel);
232 return srinfo.pwRoutingLabel;
233 } else {
234 String message = "getPWRoutingLabel fails for device: " + deviceId + ".";
235 throw new DeviceConfigNotFoundException(message);
236 }
237 }
238
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700239 /**
Pier Ventreadb4ae62016-11-23 09:57:42 -0800240 * Returns the IPv4 Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700241 *
242 * @param routerMac router mac address
Saurav Das7c305372015-10-28 12:39:42 -0700243 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700244 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800245 public int getIPv4SegmentId(MacAddress routerMac) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700246 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
247 deviceConfigMap.entrySet()) {
248 if (entry.getValue().mac.equals(routerMac)) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800249 return entry.getValue().ipv4NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700250 }
251 }
sangho80f11cb2015-04-01 13:05:26 -0700252
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700253 return -1;
254 }
255
256 /**
Pier Ventreadb4ae62016-11-23 09:57:42 -0800257 * Returns the IPv6 Node segment id of a segment router given its Router mac address.
258 *
259 * @param routerMac router mac address
260 * @return node segment id, or -1 if not found in config
261 */
262 public int getIPv6SegmentId(MacAddress routerMac) {
263 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
264 deviceConfigMap.entrySet()) {
265 if (entry.getValue().mac.equals(routerMac)) {
266 return entry.getValue().ipv6NodeSid;
267 }
268 }
269
270 return -1;
271 }
272
273 /**
274 * Returns the IPv4 Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700275 *
276 * @param routerAddress router ip address
Saurav Das7c305372015-10-28 12:39:42 -0700277 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700278 */
Pier Ventreadb4ae62016-11-23 09:57:42 -0800279 public int getIPv4SegmentId(Ip4Address routerAddress) {
Charles Chan3d35a542018-10-02 12:52:29 -0700280 for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
281 Ip4Address ipv4Loopback = entry.getValue().ipv4Loopback;
282 if (ipv4Loopback == null) {
283 continue;
284 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800285 if (entry.getValue().ipv4Loopback.equals(routerAddress)) {
Charles Chan3d35a542018-10-02 12:52:29 -0700286 if (entry.getValue().ipv4NodeSid == -1) {
287 continue;
288 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800289 return entry.getValue().ipv4NodeSid;
290 }
291 }
292
293 return -1;
294 }
295
296 /**
297 * Returns the IPv6 Node segment id of a segment router given its Router ip address.
298 *
299 * @param routerAddress router ip address
300 * @return node segment id, or -1 if not found in config
301 */
302 public int getIPv6SegmentId(Ip6Address routerAddress) {
Charles Chan3d35a542018-10-02 12:52:29 -0700303 for (Map.Entry<DeviceId, SegmentRouterInfo> entry: deviceConfigMap.entrySet()) {
304 Ip6Address ipv6Loopback = entry.getValue().ipv6Loopback;
305 if (ipv6Loopback == null) {
306 continue;
307 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800308 if (entry.getValue().ipv6Loopback.equals(routerAddress)) {
Charles Chan3d35a542018-10-02 12:52:29 -0700309 if (entry.getValue().ipv6NodeSid == -1) {
310 continue;
311 }
Pier Ventreadb4ae62016-11-23 09:57:42 -0800312 return entry.getValue().ipv6NodeSid;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700313 }
314 }
315
316 return -1;
317 }
318
sangho80f11cb2015-04-01 13:05:26 -0700319 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800320 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700321 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
322 if (srinfo != null) {
Saurav Das7c305372015-10-28 12:39:42 -0700323 return srinfo.mac;
sangho80f11cb2015-04-01 13:05:26 -0700324 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800325 String message = "getDeviceMac fails for device: " + deviceId + ".";
326 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700327 }
328 }
329
Charles Chan319d1a22015-11-03 10:42:14 -0800330 @Override
Pier Ventreadb4ae62016-11-23 09:57:42 -0800331 public Ip4Address getRouterIpv4(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700332 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
333 if (srinfo != null) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800334 log.trace("getRouterIpv4 for device{} is {}", deviceId, srinfo.ipv4Loopback);
335 return srinfo.ipv4Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700336 } else {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800337 String message = "getRouterIpv4 fails for device: " + deviceId + ".";
338 throw new DeviceConfigNotFoundException(message);
339 }
340 }
341
342 @Override
343 public Ip6Address getRouterIpv6(DeviceId deviceId) throws DeviceConfigNotFoundException {
344 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
345 if (srinfo != null) {
346 log.trace("getRouterIpv6 for device{} is {}", deviceId, srinfo.ipv6Loopback);
347 return srinfo.ipv6Loopback;
348 } else {
349 String message = "getRouterIpv6 fails for device: " + deviceId + ".";
Charles Chan319d1a22015-11-03 10:42:14 -0800350 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700351 }
sangho80f11cb2015-04-01 13:05:26 -0700352 }
353
pier6a2052b2019-06-28 22:17:31 +0200354 /**
355 * Gets router ip address based on the destination ip address.
356 *
357 * @param destIpAddress the destination ip address
358 * @param routerDeviceId the device id
359 * @return the ip address of the routes
360 */
361 public IpAddress getRouterIpAddress(IpAddress destIpAddress, DeviceId routerDeviceId) {
362 IpAddress routerIpAddress;
363 try {
364 routerIpAddress = destIpAddress.isIp4() ? getRouterIpv4(routerDeviceId) :
365 getRouterIpv6(routerDeviceId);
366 } catch (DeviceConfigNotFoundException e) {
367 routerIpAddress = null;
368 }
369 return routerIpAddress;
370 }
371
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700372 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800373 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700374 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
375 if (srinfo != null) {
376 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
377 return srinfo.isEdge;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700378 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800379 String message = "isEdgeDevice fails for device: " + deviceId + ".";
380 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700381 }
382 }
383
sangho80f11cb2015-04-01 13:05:26 -0700384 @Override
385 public List<Integer> getAllDeviceSegmentIds() {
386 return allSegmentIds;
387 }
388
Charles Chan77277672015-10-20 16:24:19 -0700389 @Override
Pier Ventreb6a7f342016-11-26 21:05:22 -0800390 public Map<IpPrefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
Saurav Das52d4ed72016-03-28 19:00:18 -0700391 throws DeviceConfigNotFoundException {
392 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
393 if (srinfo == null) {
394 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
395 throw new DeviceConfigNotFoundException(message);
396 }
Charles Chan77277672015-10-20 16:24:19 -0700397 // Construct subnet-port mapping from port-subnet mapping
Pier Ventreb6a7f342016-11-26 21:05:22 -0800398 SetMultimap<PortNumber, IpPrefix> portSubnetMap = srinfo.subnets;
399 Map<IpPrefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan82ab1932016-01-30 23:22:37 -0800400
401 portSubnetMap.entries().forEach(entry -> {
402 PortNumber port = entry.getKey();
Pier Ventreb6a7f342016-11-26 21:05:22 -0800403 IpPrefix subnet = entry.getValue();
Charles Chan82ab1932016-01-30 23:22:37 -0800404
Pier Ventreb6a7f342016-11-26 21:05:22 -0800405 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH ||
406 subnet.prefixLength() == IpPrefix.MAX_INET6_MASK_LENGTH) {
Charles Chanbbd004c2016-02-16 23:14:49 -0800407 return;
408 }
409
Charles Chan77277672015-10-20 16:24:19 -0700410 if (subnetPortMap.containsKey(subnet)) {
411 subnetPortMap.get(subnet).add(port);
412 } else {
413 ArrayList<PortNumber> ports = new ArrayList<>();
414 ports.add(port);
415 subnetPortMap.put(subnet, ports);
416 }
417 });
Charles Chan77277672015-10-20 16:24:19 -0700418 return subnetPortMap;
419 }
420
sangho80f11cb2015-04-01 13:05:26 -0700421 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700422 * Returns the device identifier or data plane identifier (dpid)
423 * of a segment router given its segment id.
sangho80f11cb2015-04-01 13:05:26 -0700424 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700425 * @param sid segment id
426 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700427 */
428 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700429 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
430 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800431 if (entry.getValue().ipv4NodeSid == sid ||
432 entry.getValue().ipv6NodeSid == sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700433 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700434 }
435 }
436
437 return null;
438 }
439
440 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700441 * Returns the device identifier or data plane identifier (dpid)
442 * of a segment router given its router ip address.
sangho80f11cb2015-04-01 13:05:26 -0700443 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700444 * @param ipAddress router ip address
445 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700446 */
447 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700448 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
449 deviceConfigMap.entrySet()) {
Pier Ventreadb4ae62016-11-23 09:57:42 -0800450 if (entry.getValue().ipv4Loopback.equals(ipAddress)) {
451 return entry.getValue().deviceId;
452 }
453 }
454
455 return null;
456 }
457
458 /**
459 * Returns the device identifier or data plane identifier (dpid)
460 * of a segment router given its router ipv6 address.
461 *
462 * @param ipAddress router ipv6 address
463 * @return deviceId device identifier
464 */
465 public DeviceId getDeviceId(Ip6Address ipAddress) {
466 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
467 deviceConfigMap.entrySet()) {
468 if (entry.getValue().ipv6Loopback.equals(ipAddress)) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700469 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700470 }
471 }
472
473 return null;
474 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700475
476 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700477 * Returns the configured port ip addresses for a segment router.
478 * These addresses serve as gateway IP addresses for the subnets configured
479 * on those ports.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700480 *
481 * @param deviceId device identifier
Saurav Dasc28b3432015-10-30 17:45:38 -0700482 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700483 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800484 public Set<IpAddress> getPortIPs(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700485 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
486 if (srinfo != null) {
487 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
488 srinfo.gatewayIps.values());
Saurav Dasc28b3432015-10-30 17:45:38 -0700489 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700490 }
Saurav Das7c305372015-10-28 12:39:42 -0700491 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700492 }
493
494 /**
Charles Chancf789822019-03-22 10:04:27 -0700495 * Returns configured subnets for a segment router.
496 *
497 * @param deviceId device identifier
498 * @return list of ip prefixes or null if not found
499 */
500 public Set<IpPrefix> getConfiguredSubnets(DeviceId deviceId) {
501 Set<IpPrefix> subnets = srManager.interfaceService.getInterfaces().stream()
502 .filter(intf -> Objects.equals(deviceId, intf.connectPoint().deviceId()))
503 .flatMap(intf -> intf.ipAddressesList().stream())
504 .map(InterfaceIpAddress::subnetAddress)
505 .collect(Collectors.toSet());
506
507 if (subnets.isEmpty()) {
508 log.debug(NO_SUBNET, deviceId);
509 return Collections.emptySet();
510 }
511 return subnets;
512 }
513
514 /**
515 * Returns all subnets for a segment router, including subnets learnt from route service.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700516 *
517 * @param deviceId device identifier
Charles Chan19b70032019-04-17 14:20:26 -0700518 * @return set of ip prefixes or null if not found
519 * @deprecated use getBatchedSubnets(DeviceId deviceId) instead
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700520 */
Charles Chan19b70032019-04-17 14:20:26 -0700521 @Deprecated
Pier Ventreb6a7f342016-11-26 21:05:22 -0800522 public Set<IpPrefix> getSubnets(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700523 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan5eb66042018-06-18 14:42:17 -0700524 if (srinfo != null && srinfo.subnets != null) {
525 // Note: ImmutableSet.Builder.addAll calls the iterator of parameter internally,
526 // which is not protected by SynchronizedCollection mutex.
Pier Ventreb6a7f342016-11-26 21:05:22 -0800527 ImmutableSet.Builder<IpPrefix> builder = ImmutableSet.builder();
Charles Chan5eb66042018-06-18 14:42:17 -0700528 srinfo.subnets.forEach((k, v) -> builder.add(v));
529 return builder.build();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700530 }
Saurav Das7c305372015-10-28 12:39:42 -0700531 return null;
532 }
533
Charles Chan19b70032019-04-17 14:20:26 -0700534 /**
Charles Chan5eec3b12019-04-18 14:30:41 -0700535 * Returns batches of all subnets reachable via given next hop
536 * <p>
537 * First batch includes FPM and STATIC routes
538 * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
539 *
540 * @param hostId next hop host id
541 * @return list of subnet batches, each batch includes a set of prefixes.
542 */
543 // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
544 public List<Set<IpPrefix>> getBatchedSubnets(HostId hostId) {
545 Set<IpPrefix> high = Sets.newHashSet();
546 Set<IpPrefix> low = Sets.newHashSet();
547
548 srManager.routeService.getRouteTables().stream()
549 .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
550 .flatMap(Collection::stream)
551 .forEach(resolvedRoute -> {
552 // Continue if next hop is not what we are looking for
553 if (!Objects.equals(hostId.mac(), resolvedRoute.nextHopMac()) ||
554 !Objects.equals(hostId.vlanId(), resolvedRoute.nextHopVlan())) {
555 return;
556 }
557 // Prioritize STATIC and FPM among others
558 if (resolvedRoute.route().source() == Route.Source.STATIC ||
559 resolvedRoute.route().source() == Route.Source.FPM) {
560 high.add(resolvedRoute.prefix());
561 } else {
562 low.add(resolvedRoute.prefix());
563 }
564 });
565 return Stream.of(high, low).filter(set -> !set.isEmpty()).collect(Collectors.toList());
566 }
567
568 /**
Charles Chan19b70032019-04-17 14:20:26 -0700569 * Returns batches of all subnets reachable on the given device.
570 * <p>
571 * First batch includes configured subnets, FPM and STATIC routes
572 * Second batch includes all other type of routes obtained from routeService, including DHCP routes.
573 *
574 * @param deviceId device identifier
575 * @return list of subnet batches, each batch includes a set of prefixes.
576 */
577 // TODO Querying routeService directly may be expensive. Some kind of reverse lookup cache should be developed.
578 public List<Set<IpPrefix>> getBatchedSubnets(DeviceId deviceId) {
579 Set<IpPrefix> high = Sets.newHashSet();
580 Set<IpPrefix> low = Sets.newHashSet();
581
582 high.addAll(getConfiguredSubnets(deviceId));
583 srManager.routeService.getRouteTables().stream()
584 .map(tableId -> srManager.routeService.getResolvedRoutes(tableId))
585 .flatMap(Collection::stream)
586 .forEach(resolvedRoute -> {
587 // Continue to next resolved route if none of the next hop attaches to given device
588 if (srManager.nextHopLocations(resolvedRoute).stream()
589 .noneMatch(cp -> Objects.equals(deviceId, cp.deviceId()))) {
590 return;
591 }
592 // Prioritize STATIC and FPM among others
593 if (resolvedRoute.route().source() == Route.Source.STATIC ||
594 resolvedRoute.route().source() == Route.Source.FPM) {
595 high.add(resolvedRoute.prefix());
596 } else {
597 low.add(resolvedRoute.prefix());
598 }
599 });
600 return Lists.newArrayList(high, low);
601 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800602
Saurav Das7c305372015-10-28 12:39:42 -0700603 /**
Charles Chan46fdfaf2016-11-09 20:51:44 -0800604 * Returns the subnet configuration of given device and port.
Saurav Das7c305372015-10-28 12:39:42 -0700605 *
Charles Chan46fdfaf2016-11-09 20:51:44 -0800606 * @param deviceId Device ID
607 * @param port Port number
Pier Ventreb6a7f342016-11-26 21:05:22 -0800608 * @return The subnets configured on given port or empty set if
Charles Chan2f4d2bc2017-04-24 16:21:01 -0700609 * the port is unconfigured or suppressed.
Saurav Das7c305372015-10-28 12:39:42 -0700610 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800611 public Set<IpPrefix> getPortSubnets(DeviceId deviceId, PortNumber port) {
Charles Chan46fdfaf2016-11-09 20:51:44 -0800612 ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
613
614 if (isSuppressedPort(connectPoint)) {
Pier Ventreb6a7f342016-11-26 21:05:22 -0800615 return Collections.emptySet();
Saurav Das7c305372015-10-28 12:39:42 -0700616 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800617
Charles Chancf789822019-03-22 10:04:27 -0700618 Set<IpPrefix> subnets = srManager.interfaceService.getInterfacesByPort(connectPoint).stream()
619 .flatMap(intf -> intf.ipAddressesList().stream())
620 .map(InterfaceIpAddress::subnetAddress)
621 .collect(Collectors.toSet());
Charles Chan46fdfaf2016-11-09 20:51:44 -0800622
Jon Hall31d84782017-01-18 20:15:44 -0800623 if (subnets.isEmpty()) {
Saurav Dasf9332192017-02-18 14:05:44 -0800624 log.debug(NO_SUBNET, connectPoint);
Pier Ventreb6a7f342016-11-26 21:05:22 -0800625 return Collections.emptySet();
Charles Chan46fdfaf2016-11-09 20:51:44 -0800626 }
Charles Chan2f4d2bc2017-04-24 16:21:01 -0700627 return subnets;
Pier Ventreb6a7f342016-11-26 21:05:22 -0800628 }
629
630 /**
Charles Chan873661e2017-11-30 15:37:50 -0800631 * Returns all ports that has a subnet that contains any of the given IP addresses.
632 *
633 * @param ips a set of IP addresses
634 * @return a set of connect point that has a subnet that contains any of the given IP addresses
635 */
636 public Set<ConnectPoint> getPortByIps(Set<IpAddress> ips) {
637 return srManager.interfaceService.getInterfaces().stream()
638 .filter(intf -> intf.ipAddressesList().stream().anyMatch(intfAddress ->
639 ips.stream().anyMatch(ip -> intfAddress.subnetAddress().contains(ip))))
640 .map(Interface::connectPoint)
641 .collect(Collectors.toSet());
642 }
643
644 /**
pier6a2052b2019-06-28 22:17:31 +0200645 * Returns all the connect points of the segment routers that have the
646 * specified ip address in their subnets.
647 *
648 * @param destIpAddress target ip address
649 * @return connect points of the segment routers
650 */
651 public Set<ConnectPoint> getConnectPointsForASubnetHost(IpAddress destIpAddress) {
652 return srManager.interfaceService.getMatchingInterfaces(destIpAddress).stream()
653 .map(Interface::connectPoint)
654 .collect(Collectors.toSet());
655 }
656
657 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700658 * Returns the router ip address of segment router that has the
659 * specified ip address in its subnets.
660 *
661 * @param destIpAddress target ip address
662 * @return router ip address
663 */
664 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
Charles Chan70661362016-12-09 12:54:49 -0800665 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
666
667 if (matchIntf == null) {
668 log.debug("No router was found for {}", destIpAddress);
669 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700670 }
671
Charles Chan70661362016-12-09 12:54:49 -0800672 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
673 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
674 if (srInfo == null) {
675 log.debug("No device config was found for {}", routerDeviceId);
676 return null;
677 }
678
Pier Ventreadb4ae62016-11-23 09:57:42 -0800679 return srInfo.ipv4Loopback;
680 }
681
682 /**
683 * Returns the router ipv6 address of segment router that has the
684 * specified ip address in its subnets.
685 *
686 * @param destIpAddress target ip address
687 * @return router ip address
688 */
689 public Ip6Address getRouterIpAddressForASubnetHost(Ip6Address destIpAddress) {
690 Interface matchIntf = srManager.interfaceService.getMatchingInterface(destIpAddress);
691
692 if (matchIntf == null) {
693 log.debug("No router was found for {}", destIpAddress);
694 return null;
695 }
696
697 DeviceId routerDeviceId = matchIntf.connectPoint().deviceId();
698 SegmentRouterInfo srInfo = deviceConfigMap.get(routerDeviceId);
699 if (srInfo == null) {
700 log.debug("No device config was found for {}", routerDeviceId);
701 return null;
702 }
703
704 return srInfo.ipv6Loopback;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700705 }
706
707 /**
708 * Returns the router mac address of segment router that has the
709 * specified ip address as one of its subnet gateway ip address.
710 *
711 * @param gatewayIpAddress router gateway ip address
Saurav Das7c305372015-10-28 12:39:42 -0700712 * @return router mac address or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700713 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800714 public MacAddress getRouterMacForAGatewayIp(IpAddress gatewayIpAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700715 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
716 deviceConfigMap.entrySet()) {
717 if (entry.getValue().gatewayIps.
718 values().contains(gatewayIpAddress)) {
719 return entry.getValue().mac;
720 }
721 }
722
723 log.debug("Cannot find a router for {}", gatewayIpAddress);
724 return null;
725 }
sangho9b169e32015-04-14 16:27:13 -0700726
sangho9b169e32015-04-14 16:27:13 -0700727 /**
Charles Chan35f21e42017-06-26 18:30:18 -0700728 * Checks if the host IP is in any of the subnet defined in the router with the
sangho9b169e32015-04-14 16:27:13 -0700729 * device ID given.
730 *
731 * @param deviceId device identification of the router
732 * @param hostIp host IP address to check
Charles Chan35f21e42017-06-26 18:30:18 -0700733 * @return true if the given IP is within any of the subnet defined in the router,
734 * false if no subnet is defined in the router or if the host is not
735 * within any subnet defined in the router
sangho9b169e32015-04-14 16:27:13 -0700736 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800737 public boolean inSameSubnet(DeviceId deviceId, IpAddress hostIp) {
Charles Chancf789822019-03-22 10:04:27 -0700738 Set<IpPrefix> subnets = getConfiguredSubnets(deviceId);
sangho9b169e32015-04-14 16:27:13 -0700739 if (subnets == null) {
740 return false;
741 }
742
Pier Ventreb6a7f342016-11-26 21:05:22 -0800743 for (IpPrefix subnet: subnets) {
Charles Chan82ab1932016-01-30 23:22:37 -0800744 // Exclude /0 since it is a special case used for default route
745 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho9b169e32015-04-14 16:27:13 -0700746 return true;
747 }
748 }
sangho9b169e32015-04-14 16:27:13 -0700749 return false;
750 }
sangho27462c62015-05-14 00:39:53 -0700751
752 /**
Charles Chandebfea32016-10-24 14:52:01 -0700753 * Checks if the IP is in the subnet defined on given connect point.
754 *
755 * @param connectPoint Connect point
756 * @param ip The IP address to check
757 * @return True if the IP belongs to the subnet.
758 * False if the IP does not belong to the subnet, or
759 * there is no subnet configuration on given connect point.
760 */
761 public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
Charles Chan35f21e42017-06-26 18:30:18 -0700762 return getPortSubnets(connectPoint.deviceId(), connectPoint.port()).stream()
763 .anyMatch(ipPrefix -> ipPrefix.contains(ip));
Charles Chandebfea32016-10-24 14:52:01 -0700764 }
765
766 /**
sangho27462c62015-05-14 00:39:53 -0700767 * Returns the ports corresponding to the adjacency Sid given.
768 *
769 * @param deviceId device identification of the router
770 * @param sid adjacency Sid
Charles Chan9bec8a32015-12-01 10:00:51 -0800771 * @return set of port numbers
sangho27462c62015-05-14 00:39:53 -0700772 */
Charles Chan9bec8a32015-12-01 10:00:51 -0800773 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700774 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800775 return srinfo != null ?
776 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
777 ImmutableSet.copyOf(new HashSet<>());
sangho27462c62015-05-14 00:39:53 -0700778 }
779
780 /**
781 * Check if the Sid given is whether adjacency Sid of the router device or not.
782 *
783 * @param deviceId device identification of the router
784 * @param sid Sid to check
785 * @return true if the Sid given is the adjacency Sid of the device,
786 * otherwise false
787 */
788 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700789 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800790 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho27462c62015-05-14 00:39:53 -0700791 }
Charles Chan43547ca2016-02-10 20:46:58 -0800792
Charles Chanc91c8782016-03-30 17:54:24 -0700793 /**
Charles Chanc22cef32016-04-29 14:38:22 -0700794 * Add subnet to specific connect point.
795 *
796 * @param cp connect point
Pier Ventreb6a7f342016-11-26 21:05:22 -0800797 * @param ipPrefix subnet being added to the device
Charles Chanc22cef32016-04-29 14:38:22 -0700798 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800799 public void addSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
Charles Chanc22cef32016-04-29 14:38:22 -0700800 checkNotNull(cp);
Pier Ventreb6a7f342016-11-26 21:05:22 -0800801 checkNotNull(ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700802 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
803 if (srinfo == null) {
804 log.warn("Device {} is not configured. Abort.", cp.deviceId());
805 return;
806 }
Pier Ventreb6a7f342016-11-26 21:05:22 -0800807 srinfo.subnets.put(cp.port(), ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700808 }
809
810 /**
811 * Remove subnet from specific connect point.
812 *
813 * @param cp connect point
Pier Ventreb6a7f342016-11-26 21:05:22 -0800814 * @param ipPrefix subnet being removed to the device
Charles Chanc22cef32016-04-29 14:38:22 -0700815 */
Pier Ventreb6a7f342016-11-26 21:05:22 -0800816 public void removeSubnet(ConnectPoint cp, IpPrefix ipPrefix) {
Charles Chanc22cef32016-04-29 14:38:22 -0700817 checkNotNull(cp);
Pier Ventreb6a7f342016-11-26 21:05:22 -0800818 checkNotNull(ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700819 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
820 if (srinfo == null) {
821 log.warn("Device {} is not configured. Abort.", cp.deviceId());
822 return;
823 }
Pier Ventreb6a7f342016-11-26 21:05:22 -0800824 srinfo.subnets.remove(cp.port(), ipPrefix);
Charles Chanc22cef32016-04-29 14:38:22 -0700825 }
Charles Chan46fdfaf2016-11-09 20:51:44 -0800826
827 private boolean isSuppressedPort(ConnectPoint connectPoint) {
828 SegmentRoutingAppConfig appConfig = srManager.cfgService
Ray Milkeyb85de082017-04-05 09:42:04 -0700829 .getConfig(srManager.appId(), SegmentRoutingAppConfig.class);
Charles Chan46fdfaf2016-11-09 20:51:44 -0800830 if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
Charles Chandebfea32016-10-24 14:52:01 -0700831 log.info("Interface configuration on port {} is ignored", connectPoint);
Charles Chan46fdfaf2016-11-09 20:51:44 -0800832 return true;
833 }
834 return false;
835 }
Saurav Das261c3002017-06-13 15:35:54 -0700836
837 public boolean isPairedEdge(DeviceId deviceId) throws DeviceConfigNotFoundException {
838 if (!isEdgeDevice(deviceId)) {
839 return false;
840 }
841 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
842 return (srinfo.pairDeviceId == null) ? false : true;
843 }
844
845 public DeviceId getPairDeviceId(DeviceId deviceId) throws DeviceConfigNotFoundException {
846 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
847 if (srinfo != null) {
848 return srinfo.pairDeviceId;
849 } else {
850 String message = "getPairDeviceId fails for device: " + deviceId + ".";
851 throw new DeviceConfigNotFoundException(message);
852 }
853 }
854
855 public PortNumber getPairLocalPort(DeviceId deviceId)
856 throws DeviceConfigNotFoundException {
857 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
858 if (srinfo != null) {
859 return srinfo.pairLocalPort;
860 } else {
861 String message = "getPairLocalPort fails for device: " + deviceId + ".";
862 throw new DeviceConfigNotFoundException(message);
863 }
864 }
865
Saurav Dasec683dc2018-04-27 18:42:30 -0700866 public boolean isPairLocalPort(DeviceId devId, PortNumber pnum) {
867 return pnum.equals(srManager.getPairLocalPort(devId).orElse(null));
868 }
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800869}