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