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