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