Merge "Do not catch Throwables, but rather Exceptions"
[controller.git] / opendaylight / forwardingrulesmanager / api / src / main / java / org / opendaylight / controller / forwardingrulesmanager / FlowConfig.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.forwardingrulesmanager;
10
11 import java.io.Serializable;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
18
19 import javax.xml.bind.annotation.XmlAccessType;
20 import javax.xml.bind.annotation.XmlAccessorType;
21 import javax.xml.bind.annotation.XmlElement;
22 import javax.xml.bind.annotation.XmlRootElement;
23
24 import org.opendaylight.controller.configuration.ConfigurationObject;
25 import org.opendaylight.controller.sal.action.Action;
26 import org.opendaylight.controller.sal.action.ActionType;
27 import org.opendaylight.controller.sal.action.Controller;
28 import org.opendaylight.controller.sal.action.Drop;
29 import org.opendaylight.controller.sal.action.Enqueue;
30 import org.opendaylight.controller.sal.action.Flood;
31 import org.opendaylight.controller.sal.action.FloodAll;
32 import org.opendaylight.controller.sal.action.HwPath;
33 import org.opendaylight.controller.sal.action.Loopback;
34 import org.opendaylight.controller.sal.action.Output;
35 import org.opendaylight.controller.sal.action.PopVlan;
36 import org.opendaylight.controller.sal.action.SetDlDst;
37 import org.opendaylight.controller.sal.action.SetDlSrc;
38 import org.opendaylight.controller.sal.action.SetNextHop;
39 import org.opendaylight.controller.sal.action.SetNwDst;
40 import org.opendaylight.controller.sal.action.SetNwSrc;
41 import org.opendaylight.controller.sal.action.SetNwTos;
42 import org.opendaylight.controller.sal.action.SetTpDst;
43 import org.opendaylight.controller.sal.action.SetTpSrc;
44 import org.opendaylight.controller.sal.action.SetVlanId;
45 import org.opendaylight.controller.sal.action.SetVlanPcp;
46 import org.opendaylight.controller.sal.action.SwPath;
47 import org.opendaylight.controller.sal.core.Node;
48 import org.opendaylight.controller.sal.core.NodeConnector;
49 import org.opendaylight.controller.sal.flowprogrammer.Flow;
50 import org.opendaylight.controller.sal.match.Match;
51 import org.opendaylight.controller.sal.match.MatchType;
52 import org.opendaylight.controller.sal.utils.HexEncode;
53 import org.opendaylight.controller.sal.utils.IPProtocols;
54 import org.opendaylight.controller.sal.utils.NetUtils;
55 import org.opendaylight.controller.sal.utils.Status;
56 import org.opendaylight.controller.sal.utils.StatusCode;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60 /**
61  * Configuration Java Object which represents a flow configuration information
62  * for Forwarding Rules Manager.
63  */
64 @XmlRootElement
65 @XmlAccessorType(XmlAccessType.NONE)
66 public class FlowConfig extends ConfigurationObject implements Serializable {
67     private static final long serialVersionUID = 1L;
68     private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
69     public static final String STATICFLOWGROUP = "__StaticFlows__";
70     public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
71     public static final String INTERNALSTATICFLOWBEGIN = "__";
72     public static final String INTERNALSTATICFLOWEND = "__";
73     private boolean dynamic;
74     private String status;
75
76     /*
77      * The order of the object data defined below is used directly in the UI
78      * built using JSP. Hence try to keep the order in a more logical way.
79      */
80     @XmlElement
81     private String installInHw;
82     @XmlElement
83     private String name;
84     @XmlElement
85     private Node node;
86     @XmlElement
87     private String ingressPort;
88     private String portGroup;
89     @XmlElement
90     private String priority;
91     @XmlElement
92     private String etherType;
93     @XmlElement
94     private String vlanId;
95     @XmlElement
96     private String vlanPriority;
97     @XmlElement
98     private String dlSrc;
99     @XmlElement
100     private String dlDst;
101     @XmlElement
102     private String nwSrc;
103     @XmlElement
104     private String nwDst;
105     @XmlElement
106     private String protocol;
107     @XmlElement
108     private String tosBits;
109     @XmlElement
110     private String tpSrc;
111     @XmlElement
112     private String tpDst;
113     @XmlElement
114     private String cookie;
115     @XmlElement
116     private String idleTimeout;
117     @XmlElement
118     private String hardTimeout;
119     @XmlElement
120     private List<String> actions;
121
122     private enum EtherIPType {
123         ANY, V4, V6;
124     };
125
126     public FlowConfig() {
127     }
128
129     public FlowConfig(String installInHw, String name, Node node, String priority, String cookie, String ingressPort,
130             String portGroup, String vlanId, String vlanPriority, String etherType, String srcMac, String dstMac,
131             String protocol, String tosBits, String srcIP, String dstIP, String tpSrc, String tpDst,
132             String idleTimeout, String hardTimeout, List<String> actions) {
133         super();
134         this.installInHw = installInHw;
135         this.name = name;
136         this.node = node;
137         this.priority = priority;
138         this.cookie = cookie;
139         this.ingressPort = ingressPort;
140         this.portGroup = portGroup;
141         this.vlanId = vlanId;
142         this.vlanPriority = vlanPriority;
143         this.etherType = etherType;
144         this.dlSrc = srcMac;
145         this.dlDst = dstMac;
146         this.protocol = protocol;
147         this.tosBits = tosBits;
148         this.nwSrc = srcIP;
149         this.nwDst = dstIP;
150         this.tpSrc = tpSrc;
151         this.tpDst = tpDst;
152         this.idleTimeout = idleTimeout;
153         this.hardTimeout = hardTimeout;
154         this.actions = actions;
155         this.status = StatusCode.SUCCESS.toString();
156     }
157
158     public FlowConfig(FlowConfig from) {
159         this.installInHw = from.installInHw;
160         this.name = from.name;
161         this.node = from.node;
162         this.priority = from.priority;
163         this.cookie = from.cookie;
164         this.ingressPort = from.ingressPort;
165         this.portGroup = from.portGroup;
166         this.vlanId = from.vlanId;
167         this.vlanPriority = from.vlanPriority;
168         this.etherType = from.etherType;
169         this.dlSrc = from.dlSrc;
170         this.dlDst = from.dlDst;
171         this.protocol = from.protocol;
172         this.tosBits = from.tosBits;
173         this.nwSrc = from.nwSrc;
174         this.nwDst = from.nwDst;
175         this.tpSrc = from.tpSrc;
176         this.tpDst = from.tpDst;
177         this.idleTimeout = from.idleTimeout;
178         this.hardTimeout = from.hardTimeout;
179         this.actions = new ArrayList<String>(from.actions);
180     }
181
182     public boolean installInHw() {
183         if (installInHw == null) {
184             // backward compatibility
185             installInHw = Boolean.toString(true);
186         }
187         return Boolean.valueOf(installInHw);
188     }
189
190     public void setInstallInHw(boolean inHw) {
191         installInHw = String.valueOf(inHw);
192     }
193
194     public String getInstallInHw() {
195         return installInHw;
196     }
197
198     public boolean isInternalFlow() {
199         return (this.name != null &&
200                 this.name.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN) &&
201                 this.name.endsWith(FlowConfig.INTERNALSTATICFLOWEND));
202     }
203
204     public String getName() {
205         return name;
206     }
207
208     public void setName(String name) {
209         if (name == null) {
210             return;
211         }
212         this.name = name;
213     }
214
215     public Node getNode() {
216         return this.node;
217     }
218
219     public void setNode(Node node) {
220         this.node = node;
221     }
222
223     public String getPriority() {
224         return priority;
225     }
226
227     public void setPriority(String priority) {
228         this.priority = priority;
229     }
230
231     public String getCookie() {
232         return cookie;
233     }
234
235     public void setCookie(String cookie) {
236         this.cookie = cookie;
237     }
238
239     public String getIngressPort() {
240         return ingressPort;
241     }
242
243     public void setIngressPort(String ingressPort) {
244         this.ingressPort = ingressPort;
245     }
246
247     public String getPortGroup() {
248         return portGroup;
249     }
250
251     @Override
252     public String toString() {
253         return "FlowConfig [dynamic=" + dynamic + ", status=" + status + ", installInHw=" + installInHw + ", name="
254                 + name + ", switchId=" + node + ", ingressPort=" + ingressPort + ", portGroup=" + portGroup
255                 + ", etherType=" + etherType + ", priority=" + priority + ", vlanId=" + vlanId + ", vlanPriority="
256                 + vlanPriority + ", dlSrc=" + dlSrc + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
257                 + ", protocol=" + protocol + ", tosBits=" + tosBits + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst
258                 + ", cookie=" + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" + hardTimeout + ", actions="
259                 + actions + "]";
260     }
261
262     public void setPortGroup(String portGroup) {
263         this.portGroup = portGroup;
264     }
265
266     public String getVlanId() {
267         return vlanId;
268     }
269
270     public void setVlanId(String vlanId) {
271         this.vlanId = vlanId;
272     }
273
274     public String getVlanPriority() {
275         return vlanPriority;
276     }
277
278     public void setVlanPriority(String vlanPriority) {
279         this.vlanPriority = vlanPriority;
280     }
281
282     public String getEtherType() {
283         return etherType;
284     }
285
286     public void setEtherType(String etherType) {
287         this.etherType = etherType;
288     }
289
290     public String getSrcMac() {
291         return dlSrc;
292     }
293
294     public void setSrcMac(String srcMac) {
295         this.dlSrc = srcMac;
296     }
297
298     public String getDstMac() {
299         return dlDst;
300     }
301
302     public void setDstMac(String dstMac) {
303         this.dlDst = dstMac;
304     }
305
306     public String getProtocol() {
307         return protocol;
308     }
309
310     public void setProtocol(String protocol) {
311         this.protocol = protocol;
312     }
313
314     public String getTosBits() {
315         return tosBits;
316     }
317
318     public void setTosBits(String tos_bits) {
319         this.tosBits = tos_bits;
320     }
321
322     public String getSrcIp() {
323         return nwSrc;
324     }
325
326     public void setSrcIp(String src_ip) {
327         this.nwSrc = src_ip;
328     }
329
330     public String getDstIp() {
331         return nwDst;
332     }
333
334     public void setDstIp(String dst_ip) {
335         this.nwDst = dst_ip;
336     }
337
338     public String getSrcPort() {
339         return tpSrc;
340     }
341
342     public void setSrcPort(String src_port) {
343         this.tpSrc = src_port;
344     }
345
346     public String getDstPort() {
347         return tpDst;
348     }
349
350     public void setDstPort(String dst_port) {
351         this.tpDst = dst_port;
352     }
353
354     public String getIdleTimeout() {
355         return idleTimeout;
356     }
357
358     public void setIdleTimeout(String idleTimeout) {
359         this.idleTimeout = idleTimeout;
360     }
361
362     public String getHardTimeout() {
363         return hardTimeout;
364     }
365
366     public void setHardTimeout(String hardTimeout) {
367         this.hardTimeout = hardTimeout;
368     }
369
370     public boolean isIPv6() {
371         return NetUtils.isIPv6AddressValid(this.getSrcIp()) || NetUtils.isIPv6AddressValid(this.getDstIp());
372     }
373
374     public List<String> getActions() {
375         return actions;
376     }
377
378     public void setActions(List<String> actions) {
379         this.actions = actions;
380     }
381
382     public boolean isPortGroupEnabled() {
383         return (portGroup != null);
384     }
385
386     public boolean isDynamic() {
387         return dynamic;
388     }
389
390     public void setDynamic(boolean dynamic) {
391         this.dynamic = dynamic;
392     }
393
394     public String getStatus() {
395         return status;
396     }
397
398     public void setStatus(String status) {
399         this.status = status;
400     }
401
402     public boolean isStatusSuccessful() {
403         return status.equals(StatusCode.SUCCESS.toString());
404     }
405
406     @Override
407     public int hashCode() {
408         final int prime = 31;
409         int result = 1;
410         result = prime * result + ((actions == null) ? 0 : actions.hashCode());
411         result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
412         result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
413         result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
414         result = prime * result + (dynamic ? 1231 : 1237);
415         result = prime * result + ((etherType == null) ? 0 : etherType.hashCode());
416         result = prime * result + ((ingressPort == null) ? 0 : ingressPort.hashCode());
417         result = prime * result + ((name == null) ? 0 : name.hashCode());
418         result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
419         result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
420         result = prime * result + ((portGroup == null) ? 0 : portGroup.hashCode());
421         result = prime * result + ((priority == null) ? 0 : priority.hashCode());
422         result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
423         result = prime * result + ((node == null) ? 0 : node.hashCode());
424         result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
425         result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
426         result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
427         result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
428         result = prime * result + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
429         result = prime * result + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
430         result = prime * result + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
431         return result;
432     }
433
434     @Override
435     public boolean equals(Object obj) {
436         if (this == obj) {
437             return true;
438         }
439         if (obj == null) {
440             return false;
441         }
442         if (getClass() != obj.getClass()) {
443             return false;
444         }
445         FlowConfig other = (FlowConfig) obj;
446         if (actions == null) {
447             if (other.actions != null) {
448                 return false;
449             }
450         } else if (!actions.equals(other.actions)) {
451             return false;
452         }
453         if (cookie == null) {
454             if (other.cookie != null) {
455                 return false;
456             }
457         } else if (!cookie.equals(other.cookie)) {
458             return false;
459         }
460         if (dlDst == null) {
461             if (other.dlDst != null) {
462                 return false;
463             }
464         } else if (!dlDst.equals(other.dlDst)) {
465             return false;
466         }
467         if (dlSrc == null) {
468             if (other.dlSrc != null) {
469                 return false;
470             }
471         } else if (!dlSrc.equals(other.dlSrc)) {
472             return false;
473         }
474         if (dynamic != other.dynamic) {
475             return false;
476         }
477         if (etherType == null) {
478             if (other.etherType != null) {
479                 return false;
480             }
481         } else if (!etherType.equals(other.etherType)) {
482             return false;
483         }
484         if (ingressPort == null) {
485             if (other.ingressPort != null) {
486                 return false;
487             }
488         } else if (!ingressPort.equals(other.ingressPort)) {
489             return false;
490         }
491         if (name == null) {
492             if (other.name != null) {
493                 return false;
494             }
495         } else if (!name.equals(other.name)) {
496             return false;
497         }
498         if (nwDst == null) {
499             if (other.nwDst != null) {
500                 return false;
501             }
502         } else if (!nwDst.equals(other.nwDst)) {
503             return false;
504         }
505         if (nwSrc == null) {
506             if (other.nwSrc != null) {
507                 return false;
508             }
509         } else if (!nwSrc.equals(other.nwSrc)) {
510             return false;
511         }
512         if (portGroup == null) {
513             if (other.portGroup != null) {
514                 return false;
515             }
516         } else if (!portGroup.equals(other.portGroup)) {
517             return false;
518         }
519         if (priority == null) {
520             if (other.priority != null) {
521                 return false;
522             }
523         } else if (!priority.equals(other.priority)) {
524             return false;
525         }
526         if (protocol == null) {
527             if (other.protocol != null) {
528                 return false;
529             }
530         } else if (!protocol.equals(other.protocol)) {
531             return false;
532         }
533         if (node == null) {
534             if (other.node != null) {
535                 return false;
536             }
537         } else if (!node.equals(other.node)) {
538             return false;
539         }
540         if (tosBits == null) {
541             if (other.tosBits != null) {
542                 return false;
543             }
544         } else if (!tosBits.equals(other.tosBits)) {
545             return false;
546         }
547         if (tpDst == null) {
548             if (other.tpDst != null) {
549                 return false;
550             }
551         } else if (!tpDst.equals(other.tpDst)) {
552             return false;
553         }
554         if (tpSrc == null) {
555             if (other.tpSrc != null) {
556                 return false;
557             }
558         } else if (!tpSrc.equals(other.tpSrc)) {
559             return false;
560         }
561         if (vlanId == null) {
562             if (other.vlanId != null) {
563                 return false;
564             }
565         } else if (!vlanId.equals(other.vlanId)) {
566             return false;
567         }
568         if (vlanPriority == null) {
569             if (other.vlanPriority != null) {
570                 return false;
571             }
572         } else if (!vlanPriority.equals(other.vlanPriority)) {
573             return false;
574         }
575         if (idleTimeout == null) {
576             if (other.idleTimeout != null) {
577                 return false;
578             }
579         } else if (!idleTimeout.equals(other.idleTimeout)) {
580             return false;
581         }
582         if (hardTimeout == null) {
583             if (other.hardTimeout != null) {
584                 return false;
585             }
586         } else if (!hardTimeout.equals(other.hardTimeout)) {
587             return false;
588         }
589         return true;
590     }
591
592     public boolean isL2AddressValid(String mac) {
593         if (mac == null) {
594             return false;
595         }
596
597         Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
598         Matcher mm = macPattern.matcher(mac);
599         if (!mm.matches()) {
600             log.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
601             return false;
602         }
603         return true;
604     }
605
606     public boolean isVlanIdValid(String vlanId) {
607         int vlan = Integer.decode(vlanId);
608         return ((vlan >= 0) && (vlan < 4096));
609     }
610
611     public boolean isVlanPriorityValid(String vlanPriority) {
612         int pri = Integer.decode(vlanPriority);
613         return ((pri >= 0) && (pri < 8));
614     }
615
616     public boolean isTOSBitsValid(String tosBits) {
617         int tos = Integer.decode(tosBits);
618         return ((tos >= 0) && (tos < 64));
619     }
620
621     public boolean isTpPortValid(String tpPort) {
622         int port = Integer.decode(tpPort);
623         return ((port >= 0) && (port <= 0xffff));
624     }
625
626     public boolean isTimeoutValid(String timeout) {
627         int to = Integer.decode(timeout);
628         return ((to >= 0) && (to <= 0xffff));
629     }
630
631     public boolean isProtocolValid(String protocol) {
632         IPProtocols proto = IPProtocols.fromString(protocol);
633         return (proto != null);
634     }
635
636     public Status validate() {
637         EtherIPType etype = EtherIPType.ANY;
638         EtherIPType ipsrctype = EtherIPType.ANY;
639         EtherIPType ipdsttype = EtherIPType.ANY;
640
641         try {
642             // Flow name cannot be internal flow signature
643             if (!isValidResourceName(name) || isInternalFlow()) {
644                 return new Status(StatusCode.BADREQUEST, "Invalid name");
645             }
646
647             if (node == null) {
648                 return new Status(StatusCode.BADREQUEST, "Node is null");
649             }
650
651             if (priority != null) {
652                 if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
653                     return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
654                             priority));
655                 }
656             }
657
658             // make sure it's a valid number
659             if (cookie != null) {
660                 Long.decode(cookie);
661             }
662
663             if (ingressPort != null && ingressPort.isEmpty()) {
664                 return new Status(StatusCode.BADREQUEST, "Invalid ingress port");
665             }
666
667             if ((vlanId != null) && !isVlanIdValid(vlanId)) {
668                 return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095",
669                         vlanId));
670             }
671
672             if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
673                 return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7",
674                         vlanPriority));
675             }
676             if (etherType != null) {
677                 int type = Integer.decode(etherType);
678                 if ((type < 0) || (type > 0xffff)) {
679                     return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType));
680                 } else {
681                     if (type == 0x800) {
682                         etype = EtherIPType.V4;
683                     } else if (type == 0x86dd) {
684                         etype = EtherIPType.V6;
685                     }
686                 }
687             }
688
689             if ((protocol != null) && !isProtocolValid(protocol)) {
690                 return new Status(StatusCode.BADREQUEST, String.format("Protocol %s is not valid", protocol));
691             }
692
693             if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
694                 return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
695                         tosBits));
696             }
697
698             if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
699                 return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc));
700             }
701
702             if ((tpDst != null) && !isTpPortValid(tpDst)) {
703                 return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid",
704                         tpDst));
705             }
706
707             if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
708                 return new Status(StatusCode.BADREQUEST, String.format(
709                         "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc));
710             }
711
712             if ((dlDst != null) && !isL2AddressValid(dlDst)) {
713                 return new Status(StatusCode.BADREQUEST, String.format(
714                         "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst));
715             }
716
717             if (nwSrc != null) {
718                 if (NetUtils.isIPv4AddressValid(nwSrc)) {
719                     ipsrctype = EtherIPType.V4;
720                 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
721                     ipsrctype = EtherIPType.V6;
722                 } else {
723                     return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc));
724                 }
725             }
726
727             if (nwDst != null) {
728                 if (NetUtils.isIPv4AddressValid(nwDst)) {
729                     ipdsttype = EtherIPType.V4;
730                 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
731                     ipdsttype = EtherIPType.V6;
732                 } else {
733                     return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid",
734                             nwDst));
735                 }
736             }
737
738             if (etype != EtherIPType.ANY) {
739                 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
740                     return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP"));
741                 }
742                 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
743                     return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP"));
744                 }
745             }
746             if (ipsrctype != ipdsttype) {
747                 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
748                     return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch"));
749                 }
750             }
751
752             if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
753                 return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid",
754                         idleTimeout));
755             }
756
757             if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
758                 return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid",
759                         hardTimeout));
760             }
761
762             Matcher sstr;
763             if (actions == null || actions.isEmpty()) {
764                 return new Status(StatusCode.BADREQUEST, "Actions value is null or empty");
765             }
766             for (String actiongrp : actions) {
767                 // Check src IP
768                 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
769                 if (sstr.matches()) {
770                     if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
771                         return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
772                                 sstr.group(1)));
773                     }
774                     continue;
775                 }
776                 // Check dst IP
777                 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
778                 if (sstr.matches()) {
779                     if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
780                         return new Status(StatusCode.BADREQUEST, String.format(
781                                 "IP destination address %s is not valid", sstr.group(1)));
782                     }
783                     continue;
784                 }
785
786                 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
787                 if (sstr.matches()) {
788                     if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
789                         return new Status(StatusCode.BADREQUEST, String.format(
790                                 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
791                     }
792                     continue;
793                 }
794
795                 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
796                 if (sstr.matches()) {
797                     if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
798                         return new Status(StatusCode.BADREQUEST, String.format(
799                                 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
800                     }
801                     continue;
802                 }
803
804                 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
805                 if (sstr.matches()) {
806                     if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
807                         return new Status(StatusCode.BADREQUEST, String.format(
808                                 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
809                                 sstr.group(1)));
810                     }
811                     continue;
812                 }
813                 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
814                 if (sstr.matches()) {
815                     if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
816                         return new Status(StatusCode.BADREQUEST, String.format(
817                                 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
818                                 sstr.group(1)));
819                     }
820                     continue;
821                 }
822
823                 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
824                 if (sstr.matches()) {
825                     if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
826                         return new Status(StatusCode.BADREQUEST, String.format(
827                                 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
828                     }
829                     continue;
830                 }
831
832                 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
833                 if (sstr.matches()) {
834                     if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
835                         return new Status(StatusCode.BADREQUEST, String.format(
836                                 "Transport source port %s is not valid", sstr.group(1)));
837                     }
838                     continue;
839                 }
840
841                 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
842                 if (sstr.matches()) {
843                     if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
844                         return new Status(StatusCode.BADREQUEST, String.format(
845                                 "Transport destination port %s is not valid", sstr.group(1)));
846                     }
847                     continue;
848                 }
849                 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
850                 if (sstr.matches()) {
851                     if (!NetUtils.isIPAddressValid(sstr.group(1))) {
852                         return new Status(StatusCode.BADREQUEST, String.format(
853                                 "IP destination address %s is not valid", sstr.group(1)));
854                     }
855                     continue;
856                 }
857             }
858         } catch (NumberFormatException e) {
859             return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
860         }
861
862         return new Status(StatusCode.SUCCESS);
863     }
864
865     public FlowEntry getFlowEntry() {
866         String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
867         return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
868     }
869
870     public Flow getFlow() {
871         Match match = new Match();
872
873         if (this.ingressPort != null) {
874             match.setField(MatchType.IN_PORT,
875                     NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
876         }
877         if (this.dlSrc != null) {
878             match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
879         }
880         if (this.dlDst != null) {
881             match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
882         }
883         if (this.etherType != null) {
884             match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
885         }
886         if (this.vlanId != null) {
887             match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
888         }
889         if (this.vlanPriority != null) {
890             match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
891         }
892         if (this.nwSrc != null) {
893             String parts[] = this.nwSrc.split("/");
894             InetAddress ip = NetUtils.parseInetAddress(parts[0]);
895             InetAddress mask = null;
896             int maskLen = 0;
897             if (parts.length > 1) {
898                 maskLen = Integer.parseInt(parts[1]);
899             } else {
900                 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
901             }
902             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
903             match.setField(MatchType.NW_SRC, ip, mask);
904         }
905         if (this.nwDst != null) {
906             String parts[] = this.nwDst.split("/");
907             InetAddress ip = NetUtils.parseInetAddress(parts[0]);
908             InetAddress mask = null;
909             int maskLen = 0;
910             if (parts.length > 1) {
911                 maskLen = Integer.parseInt(parts[1]);
912             } else {
913                 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
914             }
915             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
916             match.setField(MatchType.NW_DST, ip, mask);
917         }
918         if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
919             match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
920         }
921         if (this.tosBits != null) {
922             match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
923         }
924         if (this.tpSrc != null) {
925             match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
926         }
927         if (this.tpDst != null) {
928             match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
929         }
930
931         Flow flow = new Flow(match, getActionList());
932
933         if (this.cookie != null) {
934             flow.setId(Long.parseLong(cookie));
935         }
936         if (this.hardTimeout != null) {
937             flow.setHardTimeout(Short.parseShort(this.hardTimeout));
938         }
939         if (this.idleTimeout != null) {
940             flow.setIdleTimeout(Short.parseShort(idleTimeout));
941         }
942         if (this.priority != null) {
943             flow.setPriority(Integer.decode(this.priority).shortValue());
944         }
945
946
947         return flow;
948     }
949
950     public boolean isByNameAndNodeIdEqual(FlowConfig that) {
951         return (this.name.equals(that.name) && this.node.equals(that.node));
952     }
953
954     public boolean isByNameAndNodeIdEqual(String name, Node node) {
955         return (this.name.equals(name) && this.node.equals(node));
956     }
957
958     public boolean onNode(Node node) {
959         return this.node.equals(node);
960     }
961
962     public void toggleInstallation() {
963         installInHw = (installInHw == null) ? Boolean.toString(false) : Boolean.toString(!Boolean.valueOf(installInHw));
964     }
965
966     /*
967      * Parses the actions string and return the List of SAL Action No syntax
968      * check run, as this function will be called when the config validation
969      * check has already been performed
970      */
971     private List<Action> getActionList() {
972         List<Action> actionList = new ArrayList<Action>();
973
974         if (actions != null) {
975             Matcher sstr;
976             for (String actiongrp : actions) {
977                 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
978                 if (sstr.matches()) {
979                     for (String t : sstr.group(1).split(",")) {
980                         if (t != null) {
981                             String nc = String.format("%s|%s@%s", node.getType(), t, node.toString());
982                             actionList.add(new Output(NodeConnector.fromString(nc)));
983                         }
984                     }
985                     continue;
986                 }
987
988                 sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
989                 if (sstr.matches()) {
990                     for (String t : sstr.group(1).split(",")) {
991                         if (t != null) {
992                             String parts[] = t.split(":");
993                             String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
994                             if (parts.length == 1) {
995                                 actionList.add(new Enqueue(NodeConnector.fromString(nc)));
996                             } else {
997                                 actionList
998                                 .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
999                             }
1000                         }
1001                     }
1002                     continue;
1003                 }
1004
1005                 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1006                 if (sstr.matches()) {
1007                     actionList.add(new Drop());
1008                     continue;
1009                 }
1010
1011                 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1012                 if (sstr.matches()) {
1013                     actionList.add(new Loopback());
1014                     continue;
1015                 }
1016
1017                 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1018                 if (sstr.matches()) {
1019                     actionList.add(new Flood());
1020                     continue;
1021                 }
1022
1023                 sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp);
1024                 if (sstr.matches()) {
1025                     actionList.add(new FloodAll());
1026                     continue;
1027                 }
1028
1029                 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1030                 if (sstr.matches()) {
1031                     actionList.add(new SwPath());
1032                     continue;
1033                 }
1034
1035                 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1036                 if (sstr.matches()) {
1037                     actionList.add(new HwPath());
1038                     continue;
1039                 }
1040
1041                 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1042                 if (sstr.matches()) {
1043                     actionList.add(new Controller());
1044                     continue;
1045                 }
1046
1047                 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1048                 if (sstr.matches()) {
1049                     actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1050                     continue;
1051                 }
1052
1053                 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1054                 if (sstr.matches()) {
1055                     actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1056                     continue;
1057                 }
1058
1059                 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1060                 if (sstr.matches()) {
1061                     actionList.add(new PopVlan());
1062                     continue;
1063                 }
1064
1065                 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1066                 if (sstr.matches()) {
1067                     actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1068                     continue;
1069                 }
1070
1071                 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1072                 if (sstr.matches()) {
1073                     actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1074                     continue;
1075                 }
1076                 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1077                 if (sstr.matches()) {
1078                     actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1079                     continue;
1080                 }
1081                 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1082                 if (sstr.matches()) {
1083                     actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1084                     continue;
1085                 }
1086
1087                 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1088                 if (sstr.matches()) {
1089                     actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1090                     continue;
1091                 }
1092
1093                 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1094                 if (sstr.matches()) {
1095                     actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1096                     continue;
1097                 }
1098
1099                 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1100                 if (sstr.matches()) {
1101                     actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1102                     continue;
1103                 }
1104
1105                 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1106                 if (sstr.matches()) {
1107                     actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));
1108                     continue;
1109                 }
1110             }
1111         }
1112         return actionList;
1113     }
1114
1115 }