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