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