blob: d95efd2b96f34414b11349a41fb647b371f61159 [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska58de4162015-09-10 16:15:33 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Charles Chan0b4e6182015-11-03 10:42:14 -080016package org.onosproject.segmentrouting.config;
sanghob35a6192015-04-01 13:05:26 -070017
Charles Chan5270ed02016-01-30 23:22:37 -080018import com.google.common.collect.HashMultimap;
Charles Chan9f676b62015-10-29 14:58:10 -070019import com.google.common.collect.ImmutableSet;
Charles Chan5270ed02016-01-30 23:22:37 -080020import com.google.common.collect.SetMultimap;
sanghob35a6192015-04-01 13:05:26 -070021import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070022import org.onlab.packet.Ip4Prefix;
Charles Chan5270ed02016-01-30 23:22:37 -080023import org.onlab.packet.IpPrefix;
sanghob35a6192015-04-01 13:05:26 -070024import org.onlab.packet.MacAddress;
Charles Chane849c192016-01-11 18:28:54 -080025import org.onlab.packet.VlanId;
Charles Chanf2565a92016-02-10 20:46:58 -080026import org.onosproject.core.ApplicationId;
Charles Chan4636be02015-10-07 14:21:45 -070027import org.onosproject.incubator.net.config.basics.ConfigException;
28import org.onosproject.incubator.net.config.basics.InterfaceConfig;
29import org.onosproject.incubator.net.intf.Interface;
30import org.onosproject.net.ConnectPoint;
Charles Chand6832882015-10-05 17:50:33 -070031import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chand9681e72016-02-22 19:27:29 -080032import org.onosproject.net.config.NetworkConfigService;
Charles Chan4636be02015-10-07 14:21:45 -070033import org.onosproject.net.host.InterfaceIpAddress;
sanghob35a6192015-04-01 13:05:26 -070034import org.onosproject.net.DeviceId;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070035import org.onosproject.net.PortNumber;
sanghob35a6192015-04-01 13:05:26 -070036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070039import java.util.ArrayList;
sanghob35a6192015-04-01 13:05:26 -070040import java.util.HashMap;
Charles Chan531a78b2015-12-01 10:00:51 -080041import java.util.HashSet;
Charles Chane849c192016-01-11 18:28:54 -080042import java.util.LinkedList;
sanghob35a6192015-04-01 13:05:26 -070043import java.util.List;
44import java.util.Map;
Charles Chan5270ed02016-01-30 23:22:37 -080045import java.util.Optional;
Charles Chand6832882015-10-05 17:50:33 -070046import java.util.Set;
Saurav Das0e99e2b2015-10-28 12:39:42 -070047import java.util.concurrent.ConcurrentHashMap;
sanghob35a6192015-04-01 13:05:26 -070048
Charles Chan93e71ba2016-04-29 14:38:22 -070049import static com.google.common.base.Preconditions.checkNotNull;
50
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070051/**
52 * Segment Routing configuration component that reads the
53 * segment routing related configuration from Network Configuration Manager
54 * component and organizes in more accessible formats.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070055 */
sanghob35a6192015-04-01 13:05:26 -070056public class DeviceConfiguration implements DeviceProperties {
57
Charles Chanf2565a92016-02-10 20:46:58 -080058 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU6cfc02d2015-09-11 11:19:11 -070059 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chane849c192016-01-11 18:28:54 -080060 private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
61 private final Map<VlanId, List<ConnectPoint>> xConnects = new ConcurrentHashMap<>();
Charles Chand9681e72016-02-22 19:27:29 -080062 private ApplicationId appId;
63 private NetworkConfigService cfgService;
sanghob35a6192015-04-01 13:05:26 -070064
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070065 private class SegmentRouterInfo {
66 int nodeSid;
67 DeviceId deviceId;
68 Ip4Address ip;
69 MacAddress mac;
70 boolean isEdge;
Charles Chan5270ed02016-01-30 23:22:37 -080071 Map<PortNumber, Ip4Address> gatewayIps;
72 SetMultimap<PortNumber, Ip4Prefix> subnets;
Charles Chan531a78b2015-12-01 10:00:51 -080073 Map<Integer, Set<Integer>> adjacencySids;
Charles Chanb8e10c82015-10-14 11:24:40 -070074
75 public SegmentRouterInfo() {
Charles Chane849c192016-01-11 18:28:54 -080076 gatewayIps = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -080077 subnets = HashMultimap.create();
Charles Chanb8e10c82015-10-14 11:24:40 -070078 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070079 }
sanghob35a6192015-04-01 13:05:26 -070080
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070081 /**
Charles Chane849c192016-01-11 18:28:54 -080082 * Constructs device configuration for all Segment Router devices,
83 * organizing the data into various maps for easier access.
Brian O'Connor52515622015-10-09 17:03:44 -070084 *
Charles Chanf2565a92016-02-10 20:46:58 -080085 * @param appId application id
Brian O'Connor52515622015-10-09 17:03:44 -070086 * @param cfgService config service
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070087 */
Charles Chanf2565a92016-02-10 20:46:58 -080088 public DeviceConfiguration(ApplicationId appId,
89 NetworkConfigRegistry cfgService) {
Charles Chand9681e72016-02-22 19:27:29 -080090 this.appId = appId;
91 this.cfgService = cfgService;
92
Charles Chan4636be02015-10-07 14:21:45 -070093 // Read config from device subject, excluding gatewayIps and subnets.
94 Set<DeviceId> deviceSubjects =
Charles Chan5270ed02016-01-30 23:22:37 -080095 cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chan4636be02015-10-07 14:21:45 -070096 deviceSubjects.forEach(subject -> {
Charles Chan5270ed02016-01-30 23:22:37 -080097 SegmentRoutingDeviceConfig config =
98 cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070099 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chand6832882015-10-05 17:50:33 -0700100 info.deviceId = subject;
Charles Chan531a78b2015-12-01 10:00:51 -0800101 info.nodeSid = config.nodeSid();
102 info.ip = config.routerIp();
103 info.mac = config.routerMac();
Charles Chand6832882015-10-05 17:50:33 -0700104 info.isEdge = config.isEdgeRouter();
Charles Chan531a78b2015-12-01 10:00:51 -0800105 info.adjacencySids = config.adjacencySids();
Charles Chane849c192016-01-11 18:28:54 -0800106 deviceConfigMap.put(info.deviceId, info);
Saurav Das59232cf2016-04-27 18:35:50 -0700107 log.info("Read device config for device: {}", info.deviceId);
Charles Chane849c192016-01-11 18:28:54 -0800108 allSegmentIds.add(info.nodeSid);
Charles Chand6832882015-10-05 17:50:33 -0700109 });
Charles Chan4636be02015-10-07 14:21:45 -0700110
111 // Read gatewayIps and subnets from port subject.
112 Set<ConnectPoint> portSubjects =
113 cfgService.getSubjects(ConnectPoint.class, InterfaceConfig.class);
114 portSubjects.forEach(subject -> {
Charles Chand9681e72016-02-22 19:27:29 -0800115 // Do not process excluded ports
116 if (suppressSubnet().contains(subject)) {
117 return;
118 }
119
Charles Chan4636be02015-10-07 14:21:45 -0700120 InterfaceConfig config =
121 cfgService.getConfig(subject, InterfaceConfig.class);
122 Set<Interface> networkInterfaces;
123 try {
124 networkInterfaces = config.getInterfaces();
125 } catch (ConfigException e) {
126 log.error("Error loading port configuration");
127 return;
128 }
129 networkInterfaces.forEach(networkInterface -> {
Charles Chane849c192016-01-11 18:28:54 -0800130 VlanId vlanId = networkInterface.vlan();
131 ConnectPoint connectPoint = networkInterface.connectPoint();
132 DeviceId dpid = connectPoint.deviceId();
133 PortNumber port = connectPoint.port();
134 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chan4636be02015-10-07 14:21:45 -0700135
Charles Chanb8e10c82015-10-14 11:24:40 -0700136 // skip if there is no corresponding device for this ConenctPoint
137 if (info != null) {
Charles Chane849c192016-01-11 18:28:54 -0800138 // Extract subnet information
Jonathan Hart00cddda2016-02-16 10:30:37 -0800139 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chanb8e10c82015-10-14 11:24:40 -0700140 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan5270ed02016-01-30 23:22:37 -0800141 // Do not add /0 and /32 to gateway IP list
142 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
143 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
144 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
145 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700146 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
147 });
Charles Chane849c192016-01-11 18:28:54 -0800148
149 // Extract VLAN cross-connect information
150 // Do not setup cross-connect if VLAN is NONE
151 if (vlanId.equals(VlanId.NONE)) {
152 return;
153 }
154 List<ConnectPoint> connectPoints = xConnects.get(vlanId);
155 if (connectPoints != null) {
156 if (connectPoints.size() != 1) {
157 log.warn("Cross-connect should only have two endpoints. Aborting.");
158 return;
159 }
160 if (!connectPoints.get(0).deviceId().equals(connectPoint.deviceId())) {
161 log.warn("Cross-connect endpoints must be on the same switch. Aborting.");
162 return;
163 }
164 connectPoints.add(connectPoint);
165 } else {
166 connectPoints = new LinkedList<>();
167 connectPoints.add(connectPoint);
168 xConnects.put(vlanId, connectPoints);
169 }
Charles Chanb8e10c82015-10-14 11:24:40 -0700170 }
Charles Chan4636be02015-10-07 14:21:45 -0700171 });
Charles Chan4636be02015-10-07 14:21:45 -0700172 });
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700173 }
174
sanghob35a6192015-04-01 13:05:26 -0700175 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800176 public boolean isConfigured(DeviceId deviceId) {
177 return deviceConfigMap.get(deviceId) != null;
178 }
179
180 @Override
181 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700182 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
183 if (srinfo != null) {
184 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
185 return srinfo.nodeSid;
sanghob35a6192015-04-01 13:05:26 -0700186 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800187 String message = "getSegmentId fails for device: " + deviceId + ".";
188 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700189 }
190 }
191
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700192 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700193 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700194 *
195 * @param routerMac router mac address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700196 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700197 */
198 public int getSegmentId(MacAddress routerMac) {
199 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
200 deviceConfigMap.entrySet()) {
201 if (entry.getValue().mac.equals(routerMac)) {
202 return entry.getValue().nodeSid;
203 }
204 }
sanghob35a6192015-04-01 13:05:26 -0700205
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700206 return -1;
207 }
208
209 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700210 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700211 *
212 * @param routerAddress router ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700213 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700214 */
215 public int getSegmentId(Ip4Address routerAddress) {
216 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
217 deviceConfigMap.entrySet()) {
218 if (entry.getValue().ip.equals(routerAddress)) {
219 return entry.getValue().nodeSid;
220 }
221 }
222
223 return -1;
224 }
225
sanghob35a6192015-04-01 13:05:26 -0700226 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800227 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700228 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
229 if (srinfo != null) {
230 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
231 return srinfo.mac;
sanghob35a6192015-04-01 13:05:26 -0700232 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800233 String message = "getDeviceMac fails for device: " + deviceId + ".";
234 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700235 }
236 }
237
Charles Chan0b4e6182015-11-03 10:42:14 -0800238 @Override
239 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700240 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
241 if (srinfo != null) {
242 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
243 return srinfo.ip;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700244 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800245 String message = "getRouterIp fails for device: " + deviceId + ".";
246 throw new DeviceConfigNotFoundException(message);
sanghob35a6192015-04-01 13:05:26 -0700247 }
sanghob35a6192015-04-01 13:05:26 -0700248 }
249
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700250 @Override
Charles Chan0b4e6182015-11-03 10:42:14 -0800251 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700252 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
253 if (srinfo != null) {
254 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
255 return srinfo.isEdge;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700256 } else {
Charles Chan0b4e6182015-11-03 10:42:14 -0800257 String message = "isEdgeDevice fails for device: " + deviceId + ".";
258 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700259 }
260 }
261
sanghob35a6192015-04-01 13:05:26 -0700262 @Override
263 public List<Integer> getAllDeviceSegmentIds() {
264 return allSegmentIds;
265 }
266
Charles Chanc42e84e2015-10-20 16:24:19 -0700267 @Override
Saurav Das7a1ffca2016-03-28 19:00:18 -0700268 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
269 throws DeviceConfigNotFoundException {
270 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
271 if (srinfo == null) {
272 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
273 throw new DeviceConfigNotFoundException(message);
274 }
Charles Chanc42e84e2015-10-20 16:24:19 -0700275 // Construct subnet-port mapping from port-subnet mapping
Saurav Das7a1ffca2016-03-28 19:00:18 -0700276 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
277 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan5270ed02016-01-30 23:22:37 -0800278
279 portSubnetMap.entries().forEach(entry -> {
280 PortNumber port = entry.getKey();
281 Ip4Prefix subnet = entry.getValue();
282
Charles Chand0fd5dc2016-02-16 23:14:49 -0800283 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
284 return;
285 }
286
Charles Chanc42e84e2015-10-20 16:24:19 -0700287 if (subnetPortMap.containsKey(subnet)) {
288 subnetPortMap.get(subnet).add(port);
289 } else {
290 ArrayList<PortNumber> ports = new ArrayList<>();
291 ports.add(port);
292 subnetPortMap.put(subnet, ports);
293 }
294 });
Charles Chanc42e84e2015-10-20 16:24:19 -0700295 return subnetPortMap;
296 }
297
Charles Chane849c192016-01-11 18:28:54 -0800298 @Override
299 public Map<VlanId, List<ConnectPoint>> getXConnects() {
300 return xConnects;
301 }
302
sanghob35a6192015-04-01 13:05:26 -0700303 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700304 * Returns the device identifier or data plane identifier (dpid)
305 * of a segment router given its segment id.
sanghob35a6192015-04-01 13:05:26 -0700306 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700307 * @param sid segment id
308 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700309 */
310 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700311 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
312 deviceConfigMap.entrySet()) {
313 if (entry.getValue().nodeSid == sid) {
314 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700315 }
316 }
317
318 return null;
319 }
320
321 /**
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700322 * Returns the device identifier or data plane identifier (dpid)
323 * of a segment router given its router ip address.
sanghob35a6192015-04-01 13:05:26 -0700324 *
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700325 * @param ipAddress router ip address
326 * @return deviceId device identifier
sanghob35a6192015-04-01 13:05:26 -0700327 */
328 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700329 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
330 deviceConfigMap.entrySet()) {
331 if (entry.getValue().ip.equals(ipAddress)) {
332 return entry.getValue().deviceId;
sanghob35a6192015-04-01 13:05:26 -0700333 }
334 }
335
336 return null;
337 }
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700338
339 /**
Saurav Das822c4e22015-10-23 10:51:11 -0700340 * Returns the configured port ip addresses for a segment router.
341 * These addresses serve as gateway IP addresses for the subnets configured
342 * on those ports.
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700343 *
344 * @param deviceId device identifier
Saurav Das837e0bb2015-10-30 17:45:38 -0700345 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700346 */
Saurav Das837e0bb2015-10-30 17:45:38 -0700347 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700348 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
349 if (srinfo != null) {
350 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
351 srinfo.gatewayIps.values());
Saurav Das837e0bb2015-10-30 17:45:38 -0700352 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700353 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700354 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700355 }
356
357 /**
358 * Returns the configured subnet prefixes for a segment router.
359 *
360 * @param deviceId device identifier
Saurav Das0e99e2b2015-10-28 12:39:42 -0700361 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700362 */
Charles Chan9f676b62015-10-29 14:58:10 -0700363 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700364 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
365 if (srinfo != null) {
366 log.trace("getSubnets for device{} is {}", deviceId,
367 srinfo.subnets.values());
Charles Chanf2565a92016-02-10 20:46:58 -0800368
369 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
370 builder.addAll(srinfo.subnets.values());
Charles Chan2196a922016-03-07 00:49:33 -0800371 SegmentRoutingAppConfig appConfig =
372 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
373 if (appConfig != null) {
374 if (deviceId.equals(appConfig.vRouterId().orElse(null))) {
375 builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
376 }
Charles Chanf2565a92016-02-10 20:46:58 -0800377 }
378 return builder.build();
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700379 }
Saurav Das0e99e2b2015-10-28 12:39:42 -0700380 return null;
381 }
382
383 /**
Charles Chan5270ed02016-01-30 23:22:37 -0800384 * Returns the configured non-/32 and non-/0 subnet on the given port,
385 * or null if no subnet has been configured on the port.
Saurav Das0e99e2b2015-10-28 12:39:42 -0700386 *
387 * @param deviceId device identifier
388 * @param pnum port identifier
389 * @return configured subnet on port, or null
390 */
391 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) {
392 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
393 if (srinfo != null) {
Charles Chan5270ed02016-01-30 23:22:37 -0800394 Optional<Ip4Prefix> result = srinfo.subnets.get(pnum).stream()
395 .filter(subnet ->
396 subnet.getIp4Prefix().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH &&
397 subnet.getIp4Prefix().prefixLength() != 0)
398 .findFirst();
399 return (result.isPresent()) ? result.get() : null;
Saurav Das0e99e2b2015-10-28 12:39:42 -0700400 }
401 return null;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700402 }
403
404 /**
405 * Returns the router ip address of segment router that has the
406 * specified ip address in its subnets.
407 *
408 * @param destIpAddress target ip address
409 * @return router ip address
410 */
411 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
412 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
413 deviceConfigMap.entrySet()) {
Charles Chan5270ed02016-01-30 23:22:37 -0800414 for (Ip4Prefix prefix : entry.getValue().subnets.values()) {
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700415 if (prefix.contains(destIpAddress)) {
416 return entry.getValue().ip;
417 }
418 }
419 }
420
421 log.debug("No router was found for {}", destIpAddress);
422 return null;
423 }
424
425 /**
426 * Returns the router mac address of segment router that has the
427 * specified ip address as one of its subnet gateway ip address.
428 *
429 * @param gatewayIpAddress router gateway ip address
Saurav Das0e99e2b2015-10-28 12:39:42 -0700430 * @return router mac address or null if not found
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700431 */
432 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
433 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
434 deviceConfigMap.entrySet()) {
435 if (entry.getValue().gatewayIps.
436 values().contains(gatewayIpAddress)) {
437 return entry.getValue().mac;
438 }
439 }
440
441 log.debug("Cannot find a router for {}", gatewayIpAddress);
442 return null;
443 }
sangho666cd6d2015-04-14 16:27:13 -0700444
445
446 /**
447 * Checks if the host is in the subnet defined in the router with the
448 * device ID given.
449 *
450 * @param deviceId device identification of the router
451 * @param hostIp host IP address to check
452 * @return true if the host is within the subnet of the router,
453 * false if no subnet is defined under the router or if the host is not
454 * within the subnet defined in the router
455 */
456 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
457
Charles Chan9f676b62015-10-29 14:58:10 -0700458 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho666cd6d2015-04-14 16:27:13 -0700459 if (subnets == null) {
460 return false;
461 }
462
463 for (Ip4Prefix subnet: subnets) {
Charles Chan5270ed02016-01-30 23:22:37 -0800464 // Exclude /0 since it is a special case used for default route
465 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho666cd6d2015-04-14 16:27:13 -0700466 return true;
467 }
468 }
469
470 return false;
471 }
sangho1e575652015-05-14 00:39:53 -0700472
473 /**
474 * Returns the ports corresponding to the adjacency Sid given.
475 *
476 * @param deviceId device identification of the router
477 * @param sid adjacency Sid
Charles Chan531a78b2015-12-01 10:00:51 -0800478 * @return set of port numbers
sangho1e575652015-05-14 00:39:53 -0700479 */
Charles Chan531a78b2015-12-01 10:00:51 -0800480 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700481 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800482 return srinfo != null ?
483 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
484 ImmutableSet.copyOf(new HashSet<>());
sangho1e575652015-05-14 00:39:53 -0700485 }
486
487 /**
488 * Check if the Sid given is whether adjacency Sid of the router device or not.
489 *
490 * @param deviceId device identification of the router
491 * @param sid Sid to check
492 * @return true if the Sid given is the adjacency Sid of the device,
493 * otherwise false
494 */
495 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das0e99e2b2015-10-28 12:39:42 -0700496 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan531a78b2015-12-01 10:00:51 -0800497 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho1e575652015-05-14 00:39:53 -0700498 }
Charles Chanf2565a92016-02-10 20:46:58 -0800499
Charles Chand55e84d2016-03-30 17:54:24 -0700500 /**
501 * Gets connect points for which segment routing does not install subnet rules.
502 *
503 * @return set of connect points
504 */
Charles Chand9681e72016-02-22 19:27:29 -0800505 public Set<ConnectPoint> suppressSubnet() {
Charles Chan2196a922016-03-07 00:49:33 -0800506 SegmentRoutingAppConfig appConfig =
507 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
Charles Chand9681e72016-02-22 19:27:29 -0800508 return (appConfig != null) ? appConfig.suppressSubnet() : ImmutableSet.of();
509 }
510
Charles Chand55e84d2016-03-30 17:54:24 -0700511 /**
512 * Gets connect points for which segment routing does not install host rules.
513 *
514 * @return set of connect points
515 */
Charles Chand9681e72016-02-22 19:27:29 -0800516 public Set<ConnectPoint> suppressHost() {
Charles Chan2196a922016-03-07 00:49:33 -0800517 SegmentRoutingAppConfig appConfig =
518 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
Charles Chand9681e72016-02-22 19:27:29 -0800519 return (appConfig != null) ? appConfig.suppressHost() : ImmutableSet.of();
Charles Chanf2565a92016-02-10 20:46:58 -0800520 }
Charles Chan93e71ba2016-04-29 14:38:22 -0700521
522 /**
523 * Add subnet to specific connect point.
524 *
525 * @param cp connect point
526 * @param ip4Prefix subnet being added to the device
527 */
528 public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
529 checkNotNull(cp);
530 checkNotNull(ip4Prefix);
531 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
532 if (srinfo == null) {
533 log.warn("Device {} is not configured. Abort.", cp.deviceId());
534 return;
535 }
536 srinfo.subnets.put(cp.port(), ip4Prefix);
537 }
538
539 /**
540 * Remove subnet from specific connect point.
541 *
542 * @param cp connect point
543 * @param ip4Prefix subnet being removed to the device
544 */
545 public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
546 checkNotNull(cp);
547 checkNotNull(ip4Prefix);
548 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
549 if (srinfo == null) {
550 log.warn("Device {} is not configured. Abort.", cp.deviceId());
551 return;
552 }
553 srinfo.subnets.remove(cp.port(), ip4Prefix);
554 }
Jonathan Hart00cddda2016-02-16 10:30:37 -0800555}