Optimization - calculate the subnet prefix only once.
[controller.git] / opendaylight / switchmanager / api / src / main / java / org / opendaylight / controller / switchmanager / Subnet.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.switchmanager;
11
12 import java.io.Serializable;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.HashSet;
16 import java.util.Set;
17
18 import org.opendaylight.controller.sal.core.NodeConnector;
19
20 /**
21  * The class describes subnet information including L3 address, vlan and set of
22  * ports associated with the subnet.
23  */
24 public class Subnet implements Cloneable, Serializable {
25     private static final long serialVersionUID = 1L;
26     // Key fields
27     private InetAddress networkAddress;
28     private transient InetAddress subnetPrefix;
29     private short subnetMaskLength;
30     // Property fields
31     private short vlan;
32     private final Set<NodeConnector> nodeConnectors;
33
34     public Subnet(InetAddress ip, short maskLen, short vlan) {
35         this.networkAddress = ip;
36         this.subnetMaskLength = maskLen;
37         this.vlan = vlan;
38         this.nodeConnectors = new HashSet<NodeConnector>();
39     }
40
41     public Subnet(SubnetConfig conf) {
42         networkAddress = conf.getIPAddress();
43         subnetMaskLength = conf.getIPMaskLen();
44         nodeConnectors = conf.getNodeConnectors();
45     }
46
47     public Subnet(Subnet subnet) {
48         networkAddress = subnet.networkAddress;
49         subnetMaskLength = subnet.subnetMaskLength;
50         vlan = subnet.vlan;
51         nodeConnectors = new HashSet<NodeConnector>(subnet.nodeConnectors);
52     }
53
54     /**
55      * Add NodeConnectors to a subnet
56      *
57      * @param sp Set of NodeConnectors to add to the subnet
58      */
59     public void addNodeConnectors(Set<NodeConnector> sp) {
60         if (sp != null) {
61             this.nodeConnectors.addAll(sp);
62         }
63     }
64
65     /**
66      * Delete NodeConnectors from subnet
67      *
68      * @param sp Set of NodeConnectors to add to the subnet
69      */
70     public void deleteNodeConnectors(Set<NodeConnector> sp) {
71         if (sp == null) {
72             return;
73         }
74         for (NodeConnector p : sp) {
75             this.nodeConnectors.remove(p);
76         }
77     }
78
79     /**
80      * Return the list of NodeConnectors configured for this subnet,
81      * could be also an empty set in case of all the known
82      * nodeconnectors.
83      *
84      *
85      * @return The list of NodeConnectors attached to the subnet
86      */
87     public Set<NodeConnector> getNodeConnectors() {
88         return this.nodeConnectors;
89     }
90
91     /**
92      * If the subnet has no node connectors attached to it then it
93      * means that is a whole L2 flat domain
94      *
95      *
96      * @return true if there are no node connectors configured for the
97      * subnet else false
98      */
99     public boolean isFlatLayer2() {
100         return nodeConnectors.isEmpty();
101     }
102
103     /**
104      * getter method
105      *
106      *
107      * @return the Network Address part of the subnet
108      */
109     public InetAddress getNetworkAddress() {
110         return networkAddress;
111     }
112
113     /**
114      * @param networkAddress the networkAddress to set
115      */
116     public Subnet setNetworkAddress(InetAddress networkAddress) {
117         this.networkAddress = networkAddress;
118         this.subnetPrefix = null;
119         return this;
120     }
121
122     /**
123      * getter method
124      *
125      *
126      * @return the subnet mask length
127      */
128     public short getSubnetMaskLength() {
129         return this.subnetMaskLength;
130     }
131
132     public Subnet setSubnetMaskLength(short m) {
133         this.subnetMaskLength = m;
134         return this;
135     }
136
137     /*
138      * returns the prefix of a given IP by applying this subnet's mask
139      */
140     private InetAddress getPrefixForAddress(InetAddress ip) {
141         int bytes = this.subnetMaskLength / 8;
142         int bits = this.subnetMaskLength % 8;
143         byte modifiedByte;
144         byte[] sn = ip.getAddress();
145         if (bits > 0) {
146             modifiedByte = (byte) (sn[bytes] >> (8 - bits));
147             sn[bytes] = (byte) (modifiedByte << (8 - bits));
148             bytes++;
149         }
150         for (; bytes < sn.length; bytes++) {
151             sn[bytes] = (byte) (0);
152         }
153         try {
154             return InetAddress.getByAddress(sn);
155         } catch (UnknownHostException e) {
156             return null;
157         }
158     }
159
160     public boolean isSubnetOf(InetAddress ip) {
161         if (ip == null) {
162             return false;
163         }
164         if(subnetPrefix == null) {
165             subnetPrefix = getPrefixForAddress(this.networkAddress);
166         }
167         InetAddress otherPrefix = getPrefixForAddress(ip);
168         boolean isSubnetOf = true;
169         if (((subnetPrefix == null) || (otherPrefix == null)) || (!subnetPrefix.equals(otherPrefix)) ) {
170             isSubnetOf = false;
171         }
172         return isSubnetOf;
173     }
174
175     public short getVlan() {
176         return this.vlan;
177     }
178
179     public Subnet setVlan(short i) {
180         this.vlan = i;
181         return this;
182     }
183
184     @Override
185     public int hashCode() {
186         final int prime = 31;
187         int result = 1;
188         result = prime * result
189                 + ((networkAddress == null) ? 0 : networkAddress.hashCode());
190         result = prime * result
191                 + ((nodeConnectors == null) ? 0 : nodeConnectors.hashCode());
192         result = prime * result + subnetMaskLength;
193         result = prime * result + vlan;
194         return result;
195     }
196
197     @Override
198     public boolean equals(Object obj) {
199         if (this == obj) {
200             return true;
201         }
202         if (obj == null) {
203             return false;
204         }
205         if (getClass() != obj.getClass()) {
206             return false;
207         }
208         Subnet other = (Subnet) obj;
209         if (networkAddress == null) {
210             if (other.networkAddress != null) {
211                 return false;
212             }
213         } else if (!networkAddress.equals(other.networkAddress)) {
214             return false;
215         }
216         if (nodeConnectors == null) {
217             if (other.nodeConnectors != null) {
218                 return false;
219             }
220         } else if (!nodeConnectors.equals(other.nodeConnectors)) {
221             return false;
222         }
223         if (subnetMaskLength != other.subnetMaskLength) {
224             return false;
225         }
226         if (vlan != other.vlan) {
227             return false;
228         }
229         return true;
230     }
231
232     /* (non-Javadoc)
233      * @see java.lang.Object#toString()
234      */
235     @Override
236     public String toString() {
237         return ("Subnet [networkAddress=" + networkAddress.getHostAddress()
238                 + "/" + subnetMaskLength
239                 + ((vlan == 0) ? "" : (", vlan=" + vlan)) + ", "
240                 + ((isFlatLayer2()) ? "{[*, *]}" : nodeConnectors.toString()) + "]");
241     }
242
243     public boolean hasNodeConnector(NodeConnector p) {
244         if (p == null) {
245             return false;
246         }
247         return isFlatLayer2() || nodeConnectors.contains(p);
248     }
249
250     public boolean isMutualExclusive(Subnet otherSubnet) {
251         return !(isSubnetOf(otherSubnet.getNetworkAddress()) || otherSubnet.isSubnetOf(getNetworkAddress()));
252     }
253
254     /**
255      * Implement clonable interface
256      */
257     @Override
258     public Subnet clone() {
259         return new Subnet(this);
260     }
261
262 }