blob: 4474fb240f312923032fb4e56fea21e8e8d03a1f [file] [log] [blame]
Thomas Vachuska8fd25052015-09-10 16:15:33 -07001/*
Brian O'Connor43b53542016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
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 Chan82ab1932016-01-30 23:22:37 -080018import com.google.common.collect.HashMultimap;
Charles Chanc6ad7752015-10-29 14:58:10 -070019import com.google.common.collect.ImmutableSet;
Charles Chan82ab1932016-01-30 23:22:37 -080020import com.google.common.collect.SetMultimap;
sangho80f11cb2015-04-01 13:05:26 -070021import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070022import org.onlab.packet.Ip4Prefix;
Charles Chan82ab1932016-01-30 23:22:37 -080023import org.onlab.packet.IpPrefix;
sangho80f11cb2015-04-01 13:05:26 -070024import org.onlab.packet.MacAddress;
Charles Chanb7f75ac2016-01-11 18:28:54 -080025import org.onlab.packet.VlanId;
Charles Chan43547ca2016-02-10 20:46:58 -080026import org.onosproject.core.ApplicationId;
Charles Chane7c61022015-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 Chan72f556a2015-10-05 17:50:33 -070031import org.onosproject.net.config.NetworkConfigRegistry;
Charles Chan57bd98c2016-02-22 19:27:29 -080032import org.onosproject.net.config.NetworkConfigService;
Charles Chane7c61022015-10-07 14:21:45 -070033import org.onosproject.net.host.InterfaceIpAddress;
sangho80f11cb2015-04-01 13:05:26 -070034import org.onosproject.net.DeviceId;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070035import org.onosproject.net.PortNumber;
sangho80f11cb2015-04-01 13:05:26 -070036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070039import java.util.ArrayList;
sangho80f11cb2015-04-01 13:05:26 -070040import java.util.HashMap;
Charles Chan9bec8a32015-12-01 10:00:51 -080041import java.util.HashSet;
Charles Chanb7f75ac2016-01-11 18:28:54 -080042import java.util.LinkedList;
sangho80f11cb2015-04-01 13:05:26 -070043import java.util.List;
44import java.util.Map;
Charles Chan82ab1932016-01-30 23:22:37 -080045import java.util.Optional;
Charles Chan72f556a2015-10-05 17:50:33 -070046import java.util.Set;
Saurav Das7c305372015-10-28 12:39:42 -070047import java.util.concurrent.ConcurrentHashMap;
sangho80f11cb2015-04-01 13:05:26 -070048
Charles Chanc22cef32016-04-29 14:38:22 -070049import static com.google.common.base.Preconditions.checkNotNull;
50
Srikanth Vavilapalli37a461b2015-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 Vavilapalli37a461b2015-04-07 15:12:32 -070055 */
sangho80f11cb2015-04-01 13:05:26 -070056public class DeviceConfiguration implements DeviceProperties {
57
Charles Chan43547ca2016-02-10 20:46:58 -080058 private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
Sho SHIMIZU47b8aa22015-09-11 11:19:11 -070059 private final List<Integer> allSegmentIds = new ArrayList<>();
Charles Chanb7f75ac2016-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 Chan57bd98c2016-02-22 19:27:29 -080062 private ApplicationId appId;
63 private NetworkConfigService cfgService;
sangho80f11cb2015-04-01 13:05:26 -070064
Srikanth Vavilapalli37a461b2015-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 Chan82ab1932016-01-30 23:22:37 -080071 Map<PortNumber, Ip4Address> gatewayIps;
72 SetMultimap<PortNumber, Ip4Prefix> subnets;
Charles Chan9bec8a32015-12-01 10:00:51 -080073 Map<Integer, Set<Integer>> adjacencySids;
Charles Chan2b078ae2015-10-14 11:24:40 -070074
75 public SegmentRouterInfo() {
Charles Chanb7f75ac2016-01-11 18:28:54 -080076 gatewayIps = new HashMap<>();
Charles Chan82ab1932016-01-30 23:22:37 -080077 subnets = HashMultimap.create();
Charles Chan2b078ae2015-10-14 11:24:40 -070078 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070079 }
sangho80f11cb2015-04-01 13:05:26 -070080
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070081 /**
Charles Chanb7f75ac2016-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'Connor65eeb572015-10-09 17:03:44 -070084 *
Charles Chan43547ca2016-02-10 20:46:58 -080085 * @param appId application id
Brian O'Connor65eeb572015-10-09 17:03:44 -070086 * @param cfgService config service
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070087 */
Charles Chan43547ca2016-02-10 20:46:58 -080088 public DeviceConfiguration(ApplicationId appId,
89 NetworkConfigRegistry cfgService) {
Charles Chan57bd98c2016-02-22 19:27:29 -080090 this.appId = appId;
91 this.cfgService = cfgService;
92
Charles Chane7c61022015-10-07 14:21:45 -070093 // Read config from device subject, excluding gatewayIps and subnets.
94 Set<DeviceId> deviceSubjects =
Charles Chan82ab1932016-01-30 23:22:37 -080095 cfgService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class);
Charles Chane7c61022015-10-07 14:21:45 -070096 deviceSubjects.forEach(subject -> {
Charles Chan82ab1932016-01-30 23:22:37 -080097 SegmentRoutingDeviceConfig config =
98 cfgService.getConfig(subject, SegmentRoutingDeviceConfig.class);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -070099 SegmentRouterInfo info = new SegmentRouterInfo();
Charles Chan72f556a2015-10-05 17:50:33 -0700100 info.deviceId = subject;
Charles Chan9bec8a32015-12-01 10:00:51 -0800101 info.nodeSid = config.nodeSid();
102 info.ip = config.routerIp();
103 info.mac = config.routerMac();
Charles Chan72f556a2015-10-05 17:50:33 -0700104 info.isEdge = config.isEdgeRouter();
Charles Chan9bec8a32015-12-01 10:00:51 -0800105 info.adjacencySids = config.adjacencySids();
Charles Chanb7f75ac2016-01-11 18:28:54 -0800106 deviceConfigMap.put(info.deviceId, info);
Saurav Das07c74602016-04-27 18:35:50 -0700107 log.info("Read device config for device: {}", info.deviceId);
Charles Chanb7f75ac2016-01-11 18:28:54 -0800108 allSegmentIds.add(info.nodeSid);
Charles Chan72f556a2015-10-05 17:50:33 -0700109 });
Charles Chane7c61022015-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 Chan57bd98c2016-02-22 19:27:29 -0800115 // Do not process excluded ports
Charles Chan370a65b2016-05-10 17:29:47 -0700116 SegmentRoutingAppConfig appConfig =
117 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
118 if (appConfig != null && appConfig.suppressSubnet().contains(subject)) {
119 log.info("Ignore suppressed port {}", subject);
Charles Chan57bd98c2016-02-22 19:27:29 -0800120 return;
121 }
122
Charles Chane7c61022015-10-07 14:21:45 -0700123 InterfaceConfig config =
124 cfgService.getConfig(subject, InterfaceConfig.class);
125 Set<Interface> networkInterfaces;
126 try {
127 networkInterfaces = config.getInterfaces();
128 } catch (ConfigException e) {
129 log.error("Error loading port configuration");
130 return;
131 }
132 networkInterfaces.forEach(networkInterface -> {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800133 VlanId vlanId = networkInterface.vlan();
134 ConnectPoint connectPoint = networkInterface.connectPoint();
135 DeviceId dpid = connectPoint.deviceId();
136 PortNumber port = connectPoint.port();
137 SegmentRouterInfo info = deviceConfigMap.get(dpid);
Charles Chane7c61022015-10-07 14:21:45 -0700138
Charles Chan2b078ae2015-10-14 11:24:40 -0700139 // skip if there is no corresponding device for this ConenctPoint
140 if (info != null) {
Charles Chanb7f75ac2016-01-11 18:28:54 -0800141 // Extract subnet information
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800142 List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
Charles Chan2b078ae2015-10-14 11:24:40 -0700143 interfaceAddresses.forEach(interfaceAddress -> {
Charles Chan82ab1932016-01-30 23:22:37 -0800144 // Do not add /0 and /32 to gateway IP list
145 int prefixLength = interfaceAddress.subnetAddress().prefixLength();
146 if (prefixLength != 0 && prefixLength != IpPrefix.MAX_INET_MASK_LENGTH) {
147 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
148 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700149 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
150 });
Charles Chanb7f75ac2016-01-11 18:28:54 -0800151
152 // Extract VLAN cross-connect information
153 // Do not setup cross-connect if VLAN is NONE
154 if (vlanId.equals(VlanId.NONE)) {
155 return;
156 }
157 List<ConnectPoint> connectPoints = xConnects.get(vlanId);
158 if (connectPoints != null) {
159 if (connectPoints.size() != 1) {
160 log.warn("Cross-connect should only have two endpoints. Aborting.");
161 return;
162 }
163 if (!connectPoints.get(0).deviceId().equals(connectPoint.deviceId())) {
164 log.warn("Cross-connect endpoints must be on the same switch. Aborting.");
165 return;
166 }
167 connectPoints.add(connectPoint);
168 } else {
169 connectPoints = new LinkedList<>();
170 connectPoints.add(connectPoint);
171 xConnects.put(vlanId, connectPoints);
172 }
Charles Chan2b078ae2015-10-14 11:24:40 -0700173 }
Charles Chane7c61022015-10-07 14:21:45 -0700174 });
Charles Chane7c61022015-10-07 14:21:45 -0700175 });
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700176 }
177
sangho80f11cb2015-04-01 13:05:26 -0700178 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800179 public boolean isConfigured(DeviceId deviceId) {
180 return deviceConfigMap.get(deviceId) != null;
181 }
182
183 @Override
184 public int getSegmentId(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700185 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
186 if (srinfo != null) {
187 log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
188 return srinfo.nodeSid;
sangho80f11cb2015-04-01 13:05:26 -0700189 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800190 String message = "getSegmentId fails for device: " + deviceId + ".";
191 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700192 }
193 }
194
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700195 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700196 * Returns the Node segment id of a segment router given its Router mac address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700197 *
198 * @param routerMac router mac address
Saurav Das7c305372015-10-28 12:39:42 -0700199 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700200 */
201 public int getSegmentId(MacAddress routerMac) {
202 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
203 deviceConfigMap.entrySet()) {
204 if (entry.getValue().mac.equals(routerMac)) {
205 return entry.getValue().nodeSid;
206 }
207 }
sangho80f11cb2015-04-01 13:05:26 -0700208
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700209 return -1;
210 }
211
212 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700213 * Returns the Node segment id of a segment router given its Router ip address.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700214 *
215 * @param routerAddress router ip address
Saurav Das7c305372015-10-28 12:39:42 -0700216 * @return node segment id, or -1 if not found in config
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700217 */
218 public int getSegmentId(Ip4Address routerAddress) {
219 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
220 deviceConfigMap.entrySet()) {
221 if (entry.getValue().ip.equals(routerAddress)) {
222 return entry.getValue().nodeSid;
223 }
224 }
225
226 return -1;
227 }
228
sangho80f11cb2015-04-01 13:05:26 -0700229 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800230 public MacAddress getDeviceMac(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700231 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
232 if (srinfo != null) {
233 log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
234 return srinfo.mac;
sangho80f11cb2015-04-01 13:05:26 -0700235 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800236 String message = "getDeviceMac fails for device: " + deviceId + ".";
237 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700238 }
239 }
240
Charles Chan319d1a22015-11-03 10:42:14 -0800241 @Override
242 public Ip4Address getRouterIp(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700243 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
244 if (srinfo != null) {
245 log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
246 return srinfo.ip;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700247 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800248 String message = "getRouterIp fails for device: " + deviceId + ".";
249 throw new DeviceConfigNotFoundException(message);
sangho80f11cb2015-04-01 13:05:26 -0700250 }
sangho80f11cb2015-04-01 13:05:26 -0700251 }
252
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700253 @Override
Charles Chan319d1a22015-11-03 10:42:14 -0800254 public boolean isEdgeDevice(DeviceId deviceId) throws DeviceConfigNotFoundException {
Saurav Das7c305372015-10-28 12:39:42 -0700255 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
256 if (srinfo != null) {
257 log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
258 return srinfo.isEdge;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700259 } else {
Charles Chan319d1a22015-11-03 10:42:14 -0800260 String message = "isEdgeDevice fails for device: " + deviceId + ".";
261 throw new DeviceConfigNotFoundException(message);
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700262 }
263 }
264
sangho80f11cb2015-04-01 13:05:26 -0700265 @Override
266 public List<Integer> getAllDeviceSegmentIds() {
267 return allSegmentIds;
268 }
269
Charles Chan77277672015-10-20 16:24:19 -0700270 @Override
Saurav Das52d4ed72016-03-28 19:00:18 -0700271 public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId)
272 throws DeviceConfigNotFoundException {
273 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
274 if (srinfo == null) {
275 String message = "getSubnetPortsMap fails for device: " + deviceId + ".";
276 throw new DeviceConfigNotFoundException(message);
277 }
Charles Chan77277672015-10-20 16:24:19 -0700278 // Construct subnet-port mapping from port-subnet mapping
Saurav Das52d4ed72016-03-28 19:00:18 -0700279 SetMultimap<PortNumber, Ip4Prefix> portSubnetMap = srinfo.subnets;
280 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
Charles Chan82ab1932016-01-30 23:22:37 -0800281
282 portSubnetMap.entries().forEach(entry -> {
283 PortNumber port = entry.getKey();
284 Ip4Prefix subnet = entry.getValue();
285
Charles Chanbbd004c2016-02-16 23:14:49 -0800286 if (subnet.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) {
287 return;
288 }
289
Charles Chan77277672015-10-20 16:24:19 -0700290 if (subnetPortMap.containsKey(subnet)) {
291 subnetPortMap.get(subnet).add(port);
292 } else {
293 ArrayList<PortNumber> ports = new ArrayList<>();
294 ports.add(port);
295 subnetPortMap.put(subnet, ports);
296 }
297 });
Charles Chan77277672015-10-20 16:24:19 -0700298 return subnetPortMap;
299 }
300
Charles Chanb7f75ac2016-01-11 18:28:54 -0800301 @Override
302 public Map<VlanId, List<ConnectPoint>> getXConnects() {
303 return xConnects;
304 }
305
sangho80f11cb2015-04-01 13:05:26 -0700306 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700307 * Returns the device identifier or data plane identifier (dpid)
308 * of a segment router given its segment id.
sangho80f11cb2015-04-01 13:05:26 -0700309 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700310 * @param sid segment id
311 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700312 */
313 public DeviceId getDeviceId(int sid) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700314 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
315 deviceConfigMap.entrySet()) {
316 if (entry.getValue().nodeSid == sid) {
317 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700318 }
319 }
320
321 return null;
322 }
323
324 /**
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700325 * Returns the device identifier or data plane identifier (dpid)
326 * of a segment router given its router ip address.
sangho80f11cb2015-04-01 13:05:26 -0700327 *
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700328 * @param ipAddress router ip address
329 * @return deviceId device identifier
sangho80f11cb2015-04-01 13:05:26 -0700330 */
331 public DeviceId getDeviceId(Ip4Address ipAddress) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700332 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
333 deviceConfigMap.entrySet()) {
334 if (entry.getValue().ip.equals(ipAddress)) {
335 return entry.getValue().deviceId;
sangho80f11cb2015-04-01 13:05:26 -0700336 }
337 }
338
339 return null;
340 }
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700341
342 /**
Saurav Das9f1c42e2015-10-23 10:51:11 -0700343 * Returns the configured port ip addresses for a segment router.
344 * These addresses serve as gateway IP addresses for the subnets configured
345 * on those ports.
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700346 *
347 * @param deviceId device identifier
Saurav Dasc28b3432015-10-30 17:45:38 -0700348 * @return immutable set of ip addresses configured on the ports or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700349 */
Saurav Dasc28b3432015-10-30 17:45:38 -0700350 public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700351 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
352 if (srinfo != null) {
353 log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
354 srinfo.gatewayIps.values());
Saurav Dasc28b3432015-10-30 17:45:38 -0700355 return ImmutableSet.copyOf(srinfo.gatewayIps.values());
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700356 }
Saurav Das7c305372015-10-28 12:39:42 -0700357 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700358 }
359
360 /**
361 * Returns the configured subnet prefixes for a segment router.
362 *
363 * @param deviceId device identifier
Saurav Das7c305372015-10-28 12:39:42 -0700364 * @return list of ip prefixes or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700365 */
Charles Chanc6ad7752015-10-29 14:58:10 -0700366 public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
Saurav Das7c305372015-10-28 12:39:42 -0700367 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
368 if (srinfo != null) {
369 log.trace("getSubnets for device{} is {}", deviceId,
370 srinfo.subnets.values());
Charles Chan43547ca2016-02-10 20:46:58 -0800371
372 ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
373 builder.addAll(srinfo.subnets.values());
Charles Chan1dd21a52016-03-07 00:49:33 -0800374 SegmentRoutingAppConfig appConfig =
375 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
376 if (appConfig != null) {
377 if (deviceId.equals(appConfig.vRouterId().orElse(null))) {
378 builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
379 }
Charles Chan43547ca2016-02-10 20:46:58 -0800380 }
381 return builder.build();
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700382 }
Saurav Das7c305372015-10-28 12:39:42 -0700383 return null;
384 }
385
386 /**
Charles Chan82ab1932016-01-30 23:22:37 -0800387 * Returns the configured non-/32 and non-/0 subnet on the given port,
388 * or null if no subnet has been configured on the port.
Saurav Das7c305372015-10-28 12:39:42 -0700389 *
390 * @param deviceId device identifier
391 * @param pnum port identifier
392 * @return configured subnet on port, or null
393 */
394 public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) {
395 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
396 if (srinfo != null) {
Charles Chan82ab1932016-01-30 23:22:37 -0800397 Optional<Ip4Prefix> result = srinfo.subnets.get(pnum).stream()
398 .filter(subnet ->
399 subnet.getIp4Prefix().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH &&
400 subnet.getIp4Prefix().prefixLength() != 0)
401 .findFirst();
402 return (result.isPresent()) ? result.get() : null;
Saurav Das7c305372015-10-28 12:39:42 -0700403 }
404 return null;
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700405 }
406
407 /**
408 * Returns the router ip address of segment router that has the
409 * specified ip address in its subnets.
410 *
411 * @param destIpAddress target ip address
412 * @return router ip address
413 */
414 public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
415 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
416 deviceConfigMap.entrySet()) {
Charles Chan82ab1932016-01-30 23:22:37 -0800417 for (Ip4Prefix prefix : entry.getValue().subnets.values()) {
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700418 if (prefix.contains(destIpAddress)) {
419 return entry.getValue().ip;
420 }
421 }
422 }
423
424 log.debug("No router was found for {}", destIpAddress);
425 return null;
426 }
427
428 /**
429 * Returns the router mac address of segment router that has the
430 * specified ip address as one of its subnet gateway ip address.
431 *
432 * @param gatewayIpAddress router gateway ip address
Saurav Das7c305372015-10-28 12:39:42 -0700433 * @return router mac address or null if not found
Srikanth Vavilapalli37a461b2015-04-07 15:12:32 -0700434 */
435 public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
436 for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
437 deviceConfigMap.entrySet()) {
438 if (entry.getValue().gatewayIps.
439 values().contains(gatewayIpAddress)) {
440 return entry.getValue().mac;
441 }
442 }
443
444 log.debug("Cannot find a router for {}", gatewayIpAddress);
445 return null;
446 }
sangho9b169e32015-04-14 16:27:13 -0700447
448
449 /**
450 * Checks if the host is in the subnet defined in the router with the
451 * device ID given.
452 *
453 * @param deviceId device identification of the router
454 * @param hostIp host IP address to check
455 * @return true if the host is within the subnet of the router,
456 * false if no subnet is defined under the router or if the host is not
457 * within the subnet defined in the router
458 */
459 public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
460
Charles Chanc6ad7752015-10-29 14:58:10 -0700461 Set<Ip4Prefix> subnets = getSubnets(deviceId);
sangho9b169e32015-04-14 16:27:13 -0700462 if (subnets == null) {
463 return false;
464 }
465
466 for (Ip4Prefix subnet: subnets) {
Charles Chan82ab1932016-01-30 23:22:37 -0800467 // Exclude /0 since it is a special case used for default route
468 if (subnet.prefixLength() != 0 && subnet.contains(hostIp)) {
sangho9b169e32015-04-14 16:27:13 -0700469 return true;
470 }
471 }
472
473 return false;
474 }
sangho27462c62015-05-14 00:39:53 -0700475
476 /**
477 * Returns the ports corresponding to the adjacency Sid given.
478 *
479 * @param deviceId device identification of the router
480 * @param sid adjacency Sid
Charles Chan9bec8a32015-12-01 10:00:51 -0800481 * @return set of port numbers
sangho27462c62015-05-14 00:39:53 -0700482 */
Charles Chan9bec8a32015-12-01 10:00:51 -0800483 public Set<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700484 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800485 return srinfo != null ?
486 ImmutableSet.copyOf(srinfo.adjacencySids.get(sid)) :
487 ImmutableSet.copyOf(new HashSet<>());
sangho27462c62015-05-14 00:39:53 -0700488 }
489
490 /**
491 * Check if the Sid given is whether adjacency Sid of the router device or not.
492 *
493 * @param deviceId device identification of the router
494 * @param sid Sid to check
495 * @return true if the Sid given is the adjacency Sid of the device,
496 * otherwise false
497 */
498 public boolean isAdjacencySid(DeviceId deviceId, int sid) {
Saurav Das7c305372015-10-28 12:39:42 -0700499 SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
Charles Chan9bec8a32015-12-01 10:00:51 -0800500 return srinfo != null && srinfo.adjacencySids.containsKey(sid);
sangho27462c62015-05-14 00:39:53 -0700501 }
Charles Chan43547ca2016-02-10 20:46:58 -0800502
Charles Chanc91c8782016-03-30 17:54:24 -0700503 /**
Charles Chanc22cef32016-04-29 14:38:22 -0700504 * Add subnet to specific connect point.
505 *
506 * @param cp connect point
507 * @param ip4Prefix subnet being added to the device
508 */
509 public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
510 checkNotNull(cp);
511 checkNotNull(ip4Prefix);
512 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
513 if (srinfo == null) {
514 log.warn("Device {} is not configured. Abort.", cp.deviceId());
515 return;
516 }
517 srinfo.subnets.put(cp.port(), ip4Prefix);
518 }
519
520 /**
521 * Remove subnet from specific connect point.
522 *
523 * @param cp connect point
524 * @param ip4Prefix subnet being removed to the device
525 */
526 public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
527 checkNotNull(cp);
528 checkNotNull(ip4Prefix);
529 SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
530 if (srinfo == null) {
531 log.warn("Device {} is not configured. Abort.", cp.deviceId());
532 return;
533 }
534 srinfo.subnets.remove(cp.port(), ip4Prefix);
535 }
Jonathan Hart8fa9ec52016-02-16 10:30:37 -0800536}