3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
10 package org.opendaylight.controller.forwarding.staticrouting;
12 import java.io.Serializable;
13 import java.lang.reflect.Field;
14 import java.net.InetAddress;
15 import java.net.UnknownHostException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
21 import org.opendaylight.controller.configuration.ConfigurationObject;
22 import org.opendaylight.controller.sal.utils.GUIField;
23 import org.opendaylight.controller.sal.utils.Status;
24 import org.opendaylight.controller.sal.utils.StatusCode;
27 * This class defines all the necessary configuration information for a static route.
29 public class StaticRouteConfig extends ConfigurationObject implements Serializable {
30 private static final long serialVersionUID = 1L;
31 private static final String regexSubnet = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
32 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
33 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
34 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])[/](\\d|[12]\\d|3[0-2])$";
35 private static final String regexIP = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
36 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
37 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
38 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
39 private static final String regexDatapathID = "^([0-9a-fA-F]{1,2}[:-]){7}[0-9a-fA-F]{1,2}$";
40 private static final String regexDatapathIDLong = "^[0-9a-fA-F]{1,16}$";
41 private static final String prettyFields[] = { GUIField.NAME.toString(),
42 GUIField.STATICROUTE.toString(), GUIField.NEXTHOP.toString() };
43 private transient String nextHopType; // Ignoring NextHopType for now. Supporting just the next-hop IP-Address feature for now.
44 // Order matters: JSP file expects following fields in the following order
46 private String staticRoute; // A.B.C.D/MM Where A.B.C.D is the Default Gateway IP (L3) or ARP Querier IP (L2)
47 private String nextHop; // NextHop IP-Address (or) datapath ID/port list: xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
50 * Create a static route configuration with no specific information.
52 public StaticRouteConfig() {
54 nextHopType = StaticRoute.NextHopType.IPADDRESS.toString();
58 * Create a static route configuration with all the information.
59 * @param name The name (String) of the static route config
60 * @param staticRoute The string representation of the route. e.g. 192.168.1.1/24
61 * @param nextHop The string representation of the next hop IP address. e.g. 10.10.1.1
63 public StaticRouteConfig(String name, String staticRoute, String nextHop) {
66 this.staticRoute = staticRoute;
67 this.nextHop = nextHop;
71 * Get the name of the StaticRouteConfig.
74 public String getName() {
79 * Set the name of the StaticRouteConfig.
80 * @param name The name to set
82 public void setName(String name) {
87 * Get the string representation of the static route.
88 * @return The string representation of the static route
90 public String getStaticRoute() {
95 * Set the static route of the StaticRouteConfig.
96 * @param staticRoute The string representation of the static route
98 public void setStaticRoute(String staticRoute) {
99 this.staticRoute = staticRoute;
103 * Get the string representation of the next hop address type.
104 * @return The string representation of the next hop address type
106 public String getNextHopType() {
107 if (nextHopType == null) {
108 return StaticRoute.NextHopType.IPADDRESS.toString();
114 * Set the next hop address type.
115 * @param nextHopType The string representation of the next hop address type
117 public void setNextHopType(String nextHopType) {
118 this.nextHopType = nextHopType;
122 * Get all the supported next hop address types.
123 * @return The list of supported next hop address types
125 public static List<String> getSupportedNextHopTypes() {
126 List<String> s = new ArrayList<String>();
127 for (StaticRoute.NextHopType nh : StaticRoute.NextHopType.values()) {
128 s.add(nh.toString());
134 * Get the next hop address
135 * @return The string represenation of the next hop address
137 public String getNextHop() {
142 * Set the next hop address.
143 * @param nextHop: The string representation of the next hop address to be set
145 public void setNextHop(String nextHop) {
146 this.nextHop = nextHop;
150 * Return a string with text indicating if the config is valid.
151 * @return SUCCESS if the config is valid
153 public Status isValid() {
154 if (!isValidResourceName(name)) {
155 return new Status(StatusCode.BADREQUEST,
156 "Invalid Static Route name");
158 if (!isValidStaticRouteEntry()) {
159 return new Status(StatusCode.BADREQUEST,
160 "Invalid Static Route entry. Please use the " +
161 "IPAddress/mask format. Default gateway " +
162 "(0.0.0.0/0) is NOT supported.");
164 if (!isValidNextHop()) {
165 return new Status(StatusCode.BADREQUEST,
166 "Invalid NextHop IP Address configuration. " +
167 "Please use the X.X.X.X format.");
170 return new Status(StatusCode.SUCCESS, null);
173 private boolean isValidAddress(String address) {
174 if ((address != null) && address.matches(regexIP)) {
180 private boolean isValidStaticRouteEntry() {
181 if ((staticRoute != null) && staticRoute.matches(regexSubnet)) {
187 private boolean isValidNextHop() {
188 if (getNextHopType().equalsIgnoreCase(
189 StaticRoute.NextHopType.IPADDRESS.toString())) {
190 return isValidNextHopIP();
191 } else if (getNextHopType().equalsIgnoreCase(
192 StaticRoute.NextHopType.SWITCHPORT.toString())) {
193 return isValidSwitchId();
198 private boolean isValidNextHopIP() {
199 return isValidAddress(nextHop);
202 private boolean isValidSwitchId(String switchId) {
203 return (switchId != null && (switchId.matches(regexDatapathID) || switchId
204 .matches(regexDatapathIDLong)));
207 private boolean isValidSwitchId() {
208 if (getNextHopType().equalsIgnoreCase(
209 StaticRoute.NextHopType.SWITCHPORT.toString())) {
210 String pieces[] = nextHop.split("/");
211 if (pieces.length < 2) {
214 return isValidSwitchId(pieces[0]);
220 * Return the IP address of the static route.
221 * @return The IP address
223 public InetAddress getStaticRouteIP() {
224 if (!isValidStaticRouteEntry()) {
227 InetAddress ip = null;
229 ip = InetAddress.getByName(staticRoute.split("/")[0]);
230 } catch (UnknownHostException e1) {
237 * Return the bit-mask length of the static route.
238 * @return The bit-mask length
240 public Short getStaticRouteMask() {
242 if (isValidStaticRouteEntry()) {
243 String[] s = staticRoute.split("/");
244 maskLen = (s.length == 2) ? Short.valueOf(s[1]) : 32;
250 * Return the IP address of the next hop.
251 * @return the IP address
253 public InetAddress getNextHopIP() {
254 if ((getNextHopType()
255 .equalsIgnoreCase(StaticRoute.NextHopType.IPADDRESS.toString()))
256 && isValidNextHopIP()) {
257 InetAddress ip = null;
259 ip = InetAddress.getByName(nextHop);
260 } catch (UnknownHostException e1) {
269 * Return the switch ID and the port ID of the next hop address.
270 * @return The switchID (Long) and PortID (Short) in the map
272 public Map<Long, Short> getNextHopSwitchPorts() {
273 // codedSwitchPorts = xx:xx:xx:xx:xx:xx:xx:xx/port-number
274 if (getNextHopType().equalsIgnoreCase(
275 StaticRoute.NextHopType.SWITCHPORT.toString())) {
276 Map<Long, Short> sp = new HashMap<Long, Short>(1);
277 String pieces[] = nextHop.split("/");
278 sp.put(getSwitchIDLong(pieces[0]), Short.valueOf(pieces[1]));
284 private long getSwitchIDLong(String switchId) {
286 String switchString = "0";
288 if (isValidSwitchId(switchId)) {
289 if (switchId.contains(":")) {
290 // Handle the 00:00:AA:BB:CC:DD:EE:FF notation
291 switchString = switchId.replace(":", "");
292 } else if (switchId.contains("-")) {
293 // Handle the 00-00-AA-BB-CC-DD-EE-FF notation
294 switchString = switchId.replace("-", "");
296 // Handle the 0123456789ABCDEF notation
297 switchString = switchId;
300 return Long.parseLong(switchString, radix);
304 * Return all the field names of the config.
305 * @return The list containing all the field names
307 public static List<String> getFieldsNames() {
308 List<String> fieldList = new ArrayList<String>();
309 for (Field fld : StaticRouteConfig.class.getDeclaredFields()) {
310 fieldList.add(fld.getName());
312 //remove the 6 static fields + NextHopType
313 for (short i = 0; i < 7; i++) {
320 * Return all the GUI field names of the config.
321 * @return The list containing all the GUI field names
323 public static List<String> getGuiFieldsNames() {
324 List<String> fieldList = new ArrayList<String>();
325 for (String str : prettyFields) {
332 public int hashCode() {
333 final int prime = 31;
335 result = prime * result + ((name == null) ? 0 : name.hashCode());
336 result = prime * result + ((nextHop == null) ? 0 : nextHop.hashCode());
337 result = prime * result
338 + ((staticRoute == null) ? 0 : staticRoute.hashCode());
343 public boolean equals(Object obj) {
350 if (getClass() != obj.getClass()) {
353 StaticRouteConfig other = (StaticRouteConfig) obj;
355 if (other.name != null) {
358 } else if (!name.equals(other.name)) {
361 if (nextHop == null) {
362 if (other.nextHop != null) {
365 } else if (!nextHop.equals(other.nextHop)) {
368 if (staticRoute == null) {
369 if (other.staticRoute != null) {
372 } else if (!staticRoute.equals(other.staticRoute)) {
379 public String toString() {
380 return "StaticRouteConfig [name=" + name + ", staticRoute="
381 + staticRoute + ", nextHopType=" + nextHopType + ", nextHop="