ef9d444afdcc96120083efffdf641be6356fe0d2
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
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  */
16 package org.onosproject.segmentrouting;
17
18 import com.google.common.collect.Lists;
19 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.Ip4Prefix;
21 import org.onlab.packet.IpPrefix;
22 import org.onlab.packet.MacAddress;
23 import org.onosproject.segmentrouting.grouphandler.DeviceProperties;
24 import org.onosproject.net.DeviceId;
25 import org.onosproject.net.PortNumber;
26 import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig;
27 import org.onosproject.segmentrouting.config.NetworkConfigManager;
28 import org.onosproject.segmentrouting.config.SegmentRouterConfig;
29 import org.onosproject.segmentrouting.config.SegmentRouterConfig.Subnet;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import static com.google.common.base.Preconditions.checkNotNull;
34
35 import java.util.ArrayList;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39
40 /**
41  * Segment Routing configuration component that reads the
42  * segment routing related configuration from Network Configuration Manager
43  * component and organizes in more accessible formats.
44  *
45  * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
46  */
47 public class DeviceConfiguration implements DeviceProperties {
48
49     private static final Logger log = LoggerFactory
50             .getLogger(DeviceConfiguration.class);
51     private final List<Integer> allSegmentIds = new ArrayList<>();
52     private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
53     private final NetworkConfigManager configService;
54
55     private class SegmentRouterInfo {
56         int nodeSid;
57         DeviceId deviceId;
58         Ip4Address ip;
59         MacAddress mac;
60         boolean isEdge;
61         HashMap<PortNumber, Ip4Address> gatewayIps;
62         HashMap<PortNumber, Ip4Prefix> subnets;
63         List<SegmentRouterConfig.AdjacencySid> adjacencySids;
64     }
65
66     /**
67      * Constructor. Reads all the configuration for all devices of type
68      * Segment Router and organizes into various maps for easier access.
69      *
70      * @param configService handle to network configuration manager
71      * component from where the relevant configuration is retrieved.
72      */
73     public DeviceConfiguration(NetworkConfigManager configService) {
74         this.configService = checkNotNull(configService);
75         List<SwitchConfig> allSwitchCfg =
76                 this.configService.getConfiguredAllowedSwitches();
77         for (SwitchConfig cfg : allSwitchCfg) {
78             if (!(cfg instanceof SegmentRouterConfig)) {
79                 continue;
80             }
81             SegmentRouterInfo info = new SegmentRouterInfo();
82             info.nodeSid = ((SegmentRouterConfig) cfg).getNodeSid();
83             info.deviceId = ((SegmentRouterConfig) cfg).getDpid();
84             info.mac = MacAddress.valueOf(((
85                     SegmentRouterConfig) cfg).getRouterMac());
86             String routerIp = ((SegmentRouterConfig) cfg).getRouterIp();
87             Ip4Prefix prefix = checkNotNull(IpPrefix.valueOf(routerIp).getIp4Prefix());
88             info.ip = prefix.address();
89             info.isEdge = ((SegmentRouterConfig) cfg).isEdgeRouter();
90             info.subnets = new HashMap<>();
91             info.gatewayIps = new HashMap<>();
92             for (Subnet s: ((SegmentRouterConfig) cfg).getSubnets()) {
93                 info.subnets.put(PortNumber.portNumber(s.getPortNo()),
94                                  Ip4Prefix.valueOf(s.getSubnetIp()));
95                 String gatewayIp = s.getSubnetIp().
96                         substring(0, s.getSubnetIp().indexOf('/'));
97                 info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()),
98                                     Ip4Address.valueOf(gatewayIp));
99             }
100             info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids();
101             this.deviceConfigMap.put(info.deviceId, info);
102             this.allSegmentIds.add(info.nodeSid);
103
104         }
105     }
106
107     /**
108      * Returns the segment id of a segment router.
109      *
110      * @param deviceId device identifier
111      * @return segment id
112      */
113     @Override
114     public int getSegmentId(DeviceId deviceId) {
115         if (deviceConfigMap.get(deviceId) != null) {
116             log.debug("getSegmentId for device{} is {}",
117                     deviceId,
118                     deviceConfigMap.get(deviceId).nodeSid);
119             return deviceConfigMap.get(deviceId).nodeSid;
120         } else {
121             log.warn("getSegmentId for device {} "
122                     + "throwing IllegalStateException "
123                     + "because device does not exist in config", deviceId);
124             throw new IllegalStateException();
125         }
126     }
127
128     /**
129      * Returns the segment id of a segment router given its mac address.
130      *
131      * @param routerMac router mac address
132      * @return segment id
133      */
134     public int getSegmentId(MacAddress routerMac) {
135         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
136                     deviceConfigMap.entrySet()) {
137             if (entry.getValue().mac.equals(routerMac)) {
138                 return entry.getValue().nodeSid;
139             }
140         }
141
142         return -1;
143     }
144
145     /**
146      * Returns the segment id of a segment router given its router ip address.
147      *
148      * @param routerAddress router ip address
149      * @return segment id
150      */
151     public int getSegmentId(Ip4Address routerAddress) {
152         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
153             deviceConfigMap.entrySet()) {
154             if (entry.getValue().ip.equals(routerAddress)) {
155                 return entry.getValue().nodeSid;
156             }
157         }
158
159         return -1;
160     }
161
162     /**
163      * Returns the router mac of a segment router.
164      *
165      * @param deviceId device identifier
166      * @return router mac address
167      */
168     @Override
169     public MacAddress getDeviceMac(DeviceId deviceId) {
170         if (deviceConfigMap.get(deviceId) != null) {
171             log.debug("getDeviceMac for device{} is {}",
172                     deviceId,
173                     deviceConfigMap.get(deviceId).mac);
174             return deviceConfigMap.get(deviceId).mac;
175         } else {
176             log.warn("getDeviceMac for device {} "
177                     + "throwing IllegalStateException "
178                     + "because device does not exist in config", deviceId);
179             throw new IllegalStateException();
180         }
181     }
182
183     /**
184      * Returns the router ip address of a segment router.
185      *
186      * @param deviceId device identifier
187      * @return router ip address
188      */
189     public Ip4Address getRouterIp(DeviceId deviceId) {
190         if (deviceConfigMap.get(deviceId) != null) {
191             log.debug("getDeviceIp for device{} is {}",
192                     deviceId,
193                     deviceConfigMap.get(deviceId).ip);
194             return deviceConfigMap.get(deviceId).ip;
195         } else {
196             log.warn("getRouterIp for device {} "
197                     + "throwing IllegalStateException "
198                     + "because device does not exist in config", deviceId);
199             throw new IllegalStateException();
200         }
201     }
202
203     /**
204      * Indicates if the segment router is a edge router or
205      * a transit/back bone router.
206      *
207      * @param deviceId device identifier
208      * @return boolean
209      */
210     @Override
211     public boolean isEdgeDevice(DeviceId deviceId) {
212         if (deviceConfigMap.get(deviceId) != null) {
213             log.debug("isEdgeDevice for device{} is {}",
214                     deviceId,
215                     deviceConfigMap.get(deviceId).isEdge);
216             return deviceConfigMap.get(deviceId).isEdge;
217         } else {
218             log.warn("isEdgeDevice for device {} "
219                     + "throwing IllegalStateException "
220                     + "because device does not exist in config", deviceId);
221             throw new IllegalStateException();
222         }
223     }
224
225     /**
226      * Returns the segment ids of all configured segment routers.
227      *
228      * @return list of segment ids
229      */
230     @Override
231     public List<Integer> getAllDeviceSegmentIds() {
232         return allSegmentIds;
233     }
234
235     /**
236      * Returns the device identifier or data plane identifier (dpid)
237      * of a segment router given its segment id.
238      *
239      * @param sid segment id
240      * @return deviceId device identifier
241      */
242     public DeviceId getDeviceId(int sid) {
243         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
244             deviceConfigMap.entrySet()) {
245             if (entry.getValue().nodeSid == sid) {
246                 return entry.getValue().deviceId;
247             }
248         }
249
250         return null;
251     }
252
253     /**
254      * Returns the device identifier or data plane identifier (dpid)
255      * of a segment router given its router ip address.
256      *
257      * @param ipAddress router ip address
258      * @return deviceId device identifier
259      */
260     public DeviceId getDeviceId(Ip4Address ipAddress) {
261         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
262             deviceConfigMap.entrySet()) {
263             if (entry.getValue().ip.equals(ipAddress)) {
264                 return entry.getValue().deviceId;
265             }
266         }
267
268         return null;
269     }
270
271     /**
272      * Returns the configured subnet gateway ip addresses for a segment router.
273      *
274      * @param deviceId device identifier
275      * @return list of ip addresses
276      */
277     public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
278         if (deviceConfigMap.get(deviceId) != null) {
279             log.debug("getSubnetGatewayIps for device{} is {}",
280                     deviceId,
281                     deviceConfigMap.get(deviceId).gatewayIps.values());
282             return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
283         } else {
284             return null;
285         }
286     }
287
288     /**
289      * Returns the configured subnet prefixes for a segment router.
290      *
291      * @param deviceId device identifier
292      * @return list of ip prefixes
293      */
294     public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
295         if (deviceConfigMap.get(deviceId) != null) {
296             log.debug("getSubnets for device{} is {}",
297                     deviceId,
298                     deviceConfigMap.get(deviceId).subnets.values());
299             return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
300         } else {
301             return null;
302         }
303     }
304
305     /**
306      * Returns the router ip address of segment router that has the
307      * specified ip address in its subnets.
308      *
309      * @param destIpAddress target ip address
310      * @return router ip address
311      */
312     public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) {
313         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
314                     deviceConfigMap.entrySet()) {
315             for (Ip4Prefix prefix:entry.getValue().subnets.values()) {
316                 if (prefix.contains(destIpAddress)) {
317                     return entry.getValue().ip;
318                 }
319             }
320         }
321
322         log.debug("No router was found for {}", destIpAddress);
323         return null;
324     }
325
326     /**
327      * Returns the router mac address of segment router that has the
328      * specified ip address as one of its subnet gateway ip address.
329      *
330      * @param gatewayIpAddress router gateway ip address
331      * @return router mac address
332      */
333     public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
334         for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
335                 deviceConfigMap.entrySet()) {
336             if (entry.getValue().gatewayIps.
337                     values().contains(gatewayIpAddress)) {
338                 return entry.getValue().mac;
339             }
340         }
341
342         log.debug("Cannot find a router for {}", gatewayIpAddress);
343         return null;
344     }
345
346
347     /**
348      * Checks if the host is in the subnet defined in the router with the
349      * device ID given.
350      *
351      * @param deviceId device identification of the router
352      * @param hostIp   host IP address to check
353      * @return true if the host is within the subnet of the router,
354      * false if no subnet is defined under the router or if the host is not
355      * within the subnet defined in the router
356      */
357     public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
358
359         List<Ip4Prefix> subnets = getSubnets(deviceId);
360         if (subnets == null) {
361             return false;
362         }
363
364         for (Ip4Prefix subnet: subnets) {
365             if (subnet.contains(hostIp)) {
366                 return true;
367             }
368         }
369
370         return false;
371     }
372
373     /**
374      * Returns the ports corresponding to the adjacency Sid given.
375      *
376      * @param deviceId device identification of the router
377      * @param sid adjacency Sid
378      * @return list of port numbers
379      */
380     public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
381         if (deviceConfigMap.get(deviceId) != null) {
382             for (SegmentRouterConfig.AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
383                 if (asid.getAdjSid() == sid) {
384                     return asid.getPorts();
385                 }
386             }
387         }
388
389         return Lists.newArrayList();
390     }
391
392     /**
393      * Check if the Sid given is whether adjacency Sid of the router device or not.
394      *
395      * @param deviceId device identification of the router
396      * @param sid Sid to check
397      * @return true if the Sid given is the adjacency Sid of the device,
398      * otherwise false
399      */
400     public boolean isAdjacencySid(DeviceId deviceId, int sid) {
401         if (deviceConfigMap.get(deviceId) != null) {
402             if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
403                 return false;
404             } else {
405                 for (SegmentRouterConfig.AdjacencySid asid:
406                         deviceConfigMap.get(deviceId).adjacencySids) {
407                     if (asid.getAdjSid() == sid) {
408                         return true;
409                     }
410                 }
411                 return false;
412             }
413         }
414
415         return false;
416     }
417 }