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