3cf45b11c8246fd9ab4c2d8e2feb9fc1c58507cf
[controller.git] / opendaylight / forwarding / staticrouting / src / main / java / org / opendaylight / controller / forwarding / staticrouting / StaticRoute.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.forwarding.staticrouting;
11
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.nio.ByteBuffer;
16 import java.util.Map;
17
18 import org.opendaylight.controller.sal.core.Node;
19 import org.opendaylight.controller.sal.core.NodeConnector;
20 import org.opendaylight.controller.sal.packet.BitBufferHelper;
21 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
22 import org.opendaylight.controller.sal.utils.NodeCreator;
23
24 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * This class defines a static route object.
30  */
31 public class StaticRoute {
32     protected static final Logger logger = LoggerFactory
33     .getLogger(StaticRoute.class);
34
35     /**
36      * This Enum defines the possible types for the next hop address.
37      */
38     public enum NextHopType {
39         IPADDRESS("nexthop-ip"), SWITCHPORT("nexthop-interface");
40         private NextHopType(String name) {
41             this.name = name;
42         }
43
44         private String name;
45
46         public String toString() {
47             return name;
48         }
49
50         public static NextHopType fromString(String str) {
51             if (str == null)
52                 return IPADDRESS;
53             if (str.equals(IPADDRESS.toString()))
54                 return IPADDRESS;
55             if (str.equals(SWITCHPORT.toString()))
56                 return SWITCHPORT;
57             return IPADDRESS;
58         }
59     }
60
61     InetAddress networkAddress;
62     InetAddress mask;
63     NextHopType type;
64     InetAddress nextHopAddress;
65     Node node;
66     NodeConnector port;
67     HostNodeConnector host;
68
69     /**
70      * Create a static route object with no specific information.
71      */
72     public StaticRoute() {
73
74     }
75
76     /**
77      * Create a static route object from the StaticRouteConfig.
78      * @param: config: StaticRouteConfig
79      */
80     public StaticRoute(StaticRouteConfig config) {
81         networkAddress = config.getStaticRouteIP();
82         mask = StaticRoute.getV4AddressMaskFromDecimal(config
83                 .getStaticRouteMask());
84         type = NextHopType.fromString(config.getNextHopType());
85         nextHopAddress = config.getNextHopIP();
86         Map<Long, Short> switchPort = config.getNextHopSwitchPorts();
87         if ((switchPort != null) && (switchPort.size() == 1)) {
88             node = NodeCreator.createOFNode((Long) switchPort.keySet()
89                     .toArray()[0]);
90             port = NodeConnectorCreator.createOFNodeConnector(
91                     (Short) switchPort.values().toArray()[0], node);
92         }
93     }
94
95     /**
96      * Get the IP address portion of the sub-network of the static route.
97      * @return InetAddress: the IP address portion of the sub-network of the static route
98      */
99     public InetAddress getNetworkAddress() {
100         return networkAddress;
101     }
102
103     /**
104      * Set the IP address portion of the sub-network of the static route.
105      * @param networkAddress The IP address (InetAddress) to be set
106      */
107     public void setNetworkAddress(InetAddress networkAddress) {
108         this.networkAddress = networkAddress;
109     }
110
111     /**
112      * Get the mask of the sub-network of the static route.
113      * @return mask: the mask  (InetAddress) of the sub-network of the static route
114      */
115     public InetAddress getMask() {
116         return mask;
117     }
118
119     /**
120      * Set the sub-network's mask of the static route.
121      * @param mask The mask (InetAddress) to be set
122      */
123     public void setMask(InetAddress mask) {
124         this.mask = mask;
125     }
126
127     /**
128      * Get the NextHopeType of the static route.
129      * @return type: NextHopeType
130      */
131     public NextHopType getType() {
132         return type;
133     }
134
135     /**
136      * Set the nextHopType.
137      * @param type The NextHopType to be set
138      */
139     public void setType(NextHopType type) {
140         this.type = type;
141     }
142
143     /**
144      * Get the next hop IP address.
145      * @return: nextHopAddress (InetAddress)
146      */
147     public InetAddress getNextHopAddress() {
148         return nextHopAddress;
149     }
150
151     /**
152      * Set the next hop IP address.
153      * @param nextHopAddress The IP address (InetAddress) to be set
154      */
155     public void setNextHopAddress(InetAddress nextHopAddress) {
156         this.nextHopAddress = nextHopAddress;
157     }
158
159     /**
160      * Get the Node associated with the static route.
161      * @return: Node
162      */
163     public Node getNode() {
164         return node;
165     }
166
167     /**
168      * Set the node associated to the static route.
169      * @param node: The node to be set
170      */
171     public void setNode(Node node) {
172         this.node = node;
173     }
174
175     /**
176      * Set the port associated to the static route.
177      * @param port The port (NodeConnector) to be set
178      */
179     public void setPort(NodeConnector port) {
180         this.port = port;
181     }
182
183     /**
184      * Get the port associated to the static route.
185      * @return port: The port (NodeConnector)
186      */
187     public NodeConnector getPort() {
188         return port;
189     }
190
191     /**
192      * Get the Host associated to static route.
193      * @return host:  The host (HostNodeConnector)
194      */
195     public HostNodeConnector getHost() {
196         return host;
197     }
198
199     /**
200      * Set the host associated to the static route.
201      * @param host: (HostNodeConnector) to be set
202      */
203     public void setHost(HostNodeConnector host) {
204         this.host = host;
205     }
206
207     @Override
208     public int hashCode() {
209         final int prime = 31;
210         int result = 1;
211         result = prime * result + ((host == null) ? 0 : host.hashCode());
212         result = prime * result + ((mask == null) ? 0 : mask.hashCode());
213         result = prime * result
214                 + ((networkAddress == null) ? 0 : networkAddress.hashCode());
215         result = prime * result
216                 + ((nextHopAddress == null) ? 0 : nextHopAddress.hashCode());
217         result = prime * result + ((port == null) ? 0 : port.hashCode());
218         result = prime * result + ((node == null) ? 0 : node.hashCode());
219         result = prime * result + ((type == null) ? 0 : type.hashCode());
220         return result;
221     }
222
223     @Override
224     public String toString() {
225         return "StaticRoute [networkAddress=" + networkAddress + ", mask="
226                 + mask + ", type=" + type.toString() + ", nextHopAddress="
227                 + nextHopAddress + ", swid=" + node + ", port=" + port
228                 + ", host=" + host + "]";
229     }
230
231     @Override
232     public boolean equals(Object obj) {
233         if (this == obj)
234             return true;
235         if (obj == null)
236             return false;
237         if (getClass() != obj.getClass())
238             return false;
239         StaticRoute other = (StaticRoute) obj;
240         if (!networkAddress.equals(other.networkAddress))
241             return false;
242         if (!mask.equals(other.mask))
243             return false;
244         return true;
245     }
246
247     private static InetAddress getV4AddressMaskFromDecimal(int mask) {
248         int netmask = 0;
249         for (int i = 0; i < mask; i++) {
250             netmask |= (1 << 31 - i);
251         }
252
253         try {
254             return InetAddress.getByAddress(BitBufferHelper
255                     .toByteArray(netmask));
256         } catch (Exception e) {
257             logger.error("",e);
258             return null;
259         }
260     }
261
262     private void applyV4MaskOnByteBuffer(ByteBuffer bb, ByteBuffer bbMask) {
263         for (int i = 0; i < bb.array().length; i++) {
264             bb.put(i, (byte) (bb.get(i) & bbMask.get(i)));
265         }
266     }
267
268     /**
269      * Compute and return the IP address  with longest prefix match from the static route based on the
270      *  destNetworkAddress. Currently it only take IPv4 address format (Inet4Address)
271      * @param destNetworkAddress: the IP address to be based on
272      * @return: InetAddress: the IPv4 address with the longest prefix matching the static route.
273      * If the destNetworkkAddress is not IPv4 format, it will return null.
274      */
275     public InetAddress longestPrefixMatch(InetAddress destNetworkAddress) {
276         if (destNetworkAddress instanceof Inet4Address) {
277             ByteBuffer bbdest = ByteBuffer
278                     .wrap(destNetworkAddress.getAddress());
279             ByteBuffer bbself = ByteBuffer.wrap(networkAddress.getAddress());
280
281             ByteBuffer bbMask = ByteBuffer.wrap(mask.getAddress());
282
283             applyV4MaskOnByteBuffer(bbdest, bbMask);
284             applyV4MaskOnByteBuffer(bbself, bbMask);
285
286             if (bbdest.equals(bbself)) {
287                 try {
288                     return InetAddress.getByAddress(bbself.array());
289                 } catch (Exception e) {
290                     logger.error("",e);
291                 }
292             }
293         }
294         return null;
295     }
296
297     /**
298      * Compare the static route with another static route. It only handles(for now) IPv4Address.
299      * @param s: the other StaticRoute
300      * @return: 0 if they are the same
301      */
302     public int compareTo(StaticRoute s) {
303         if (s == null)
304             return 1;
305         if ((networkAddress instanceof Inet6Address)
306                 || (s.getNetworkAddress() instanceof Inet6Address)) {
307             // HANDLE IPv6 Later
308             return 1;
309         }
310
311         ByteBuffer bbchallenger = ByteBuffer.wrap(s.getNetworkAddress()
312                 .getAddress());
313         ByteBuffer bbself = ByteBuffer.wrap(networkAddress.getAddress());
314         ByteBuffer bbChallengerMask = ByteBuffer.wrap(s.getMask().getAddress());
315         ByteBuffer bbSelfMask = ByteBuffer.wrap(getMask().getAddress());
316
317         applyV4MaskOnByteBuffer(bbchallenger, bbChallengerMask);
318         applyV4MaskOnByteBuffer(bbself, bbSelfMask);
319         return bbself.compareTo(bbchallenger);
320     }
321 }