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