Merge "Fixed for bug 1168 : Issue while update subnet"
[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
871                 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
872                 if (sstr.matches()) {
873                     if (!NetUtils.isIPAddressValid(sstr.group(1))) {
874                         return new Status(StatusCode.BADREQUEST, String.format(
875                                 "IP destination address %s is not valid", sstr.group(1)));
876                     }
877                     continue;
878                 }
879
880                 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
881                 if (sstr.matches()) {
882                     continue;
883                 }
884
885                 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
886                 if (sstr.matches()) {
887                     continue;
888                 }
889
890                 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
891                 if (sstr.matches()) {
892                     continue;
893                 }
894
895                 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
896                 if (sstr.matches()) {
897                     continue;
898                 }
899
900                 sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp);
901                 if (sstr.matches()) {
902                     continue;
903                 }
904
905                 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
906                 if (sstr.matches()) {
907                     continue;
908                 }
909
910                 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
911                 if (sstr.matches()) {
912                     continue;
913                 }
914
915                 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
916                 if (sstr.matches()) {
917                     continue;
918                 }
919
920                 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
921                 if (sstr.matches()) {
922                     continue;
923                 }
924
925                 // If execution reached here, it means there is an Action
926                 // which is not recognized by the controller. Return error
927
928                 return new Status(StatusCode.BADREQUEST, String.format("%s is an UnSupported Action", actiongrp));
929            }
930         } catch (NumberFormatException e) {
931             return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
932         }
933
934         return new Status(StatusCode.SUCCESS);
935     }
936
937     public FlowEntry getFlowEntry() {
938         String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
939         return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
940     }
941
942     public Flow getFlow() {
943         Match match = new Match();
944
945         if (this.ingressPort != null) {
946             match.setField(MatchType.IN_PORT,
947                     NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
948         }
949         if (this.dlSrc != null) {
950             match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
951         }
952         if (this.dlDst != null) {
953             match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
954         }
955         if (this.etherType != null) {
956             match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
957         }
958         if (this.vlanId != null) {
959             match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
960         }
961         if (this.vlanPriority != null) {
962             match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
963         }
964         if (this.nwSrc != null) {
965             String parts[] = this.nwSrc.split("/");
966             InetAddress ip = NetUtils.parseInetAddress(parts[0]);
967             InetAddress mask = null;
968             int maskLen = 0;
969             if (parts.length > 1) {
970                 maskLen = Integer.parseInt(parts[1]);
971             } else {
972                 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
973             }
974             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
975             match.setField(MatchType.NW_SRC, ip, mask);
976         }
977         if (this.nwDst != null) {
978             String parts[] = this.nwDst.split("/");
979             InetAddress ip = NetUtils.parseInetAddress(parts[0]);
980             InetAddress mask = null;
981             int maskLen = 0;
982             if (parts.length > 1) {
983                 maskLen = Integer.parseInt(parts[1]);
984             } else {
985                 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
986             }
987             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
988             match.setField(MatchType.NW_DST, ip, mask);
989         }
990         if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
991             match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
992         }
993         if (this.tosBits != null) {
994             match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
995         }
996         if (this.tpSrc != null) {
997             match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
998         }
999         if (this.tpDst != null) {
1000             match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1001         }
1002
1003         Flow flow = new Flow(match, getActionList());
1004
1005         if (this.cookie != null) {
1006             flow.setId(Long.parseLong(cookie));
1007         }
1008         if (this.hardTimeout != null) {
1009             flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1010         }
1011         if (this.idleTimeout != null) {
1012             flow.setIdleTimeout(Short.parseShort(idleTimeout));
1013         }
1014         if (this.priority != null) {
1015             flow.setPriority(Integer.decode(this.priority).shortValue());
1016         }
1017
1018
1019         return flow;
1020     }
1021
1022     public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1023         return (this.name.equals(that.name) && this.node.equals(that.node));
1024     }
1025
1026     public boolean isByNameAndNodeIdEqual(String name, Node node) {
1027         return (this.name.equals(name) && this.node.equals(node));
1028     }
1029
1030     public boolean onNode(Node node) {
1031         return this.node.equals(node);
1032     }
1033
1034     public void toggleInstallation() {
1035         installInHw = (installInHw == null) ? Boolean.toString(false) : Boolean.toString(!Boolean.valueOf(installInHw));
1036     }
1037
1038     /*
1039      * Parses the actions string and return the List of SAL Action No syntax
1040      * check run, as this function will be called when the config validation
1041      * check has already been performed
1042      */
1043     private List<Action> getActionList() {
1044         List<Action> actionList = new ArrayList<Action>();
1045
1046         if (actions != null) {
1047             Matcher sstr;
1048             for (String actiongrp : actions) {
1049                 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1050                 if (sstr.matches()) {
1051                     for (String t : sstr.group(1).split(",")) {
1052                         if (t != null) {
1053                             String nc = String.format("%s|%s@%s", node.getType(), t, node.toString());
1054                             actionList.add(new Output(NodeConnector.fromString(nc)));
1055                         }
1056                     }
1057                     continue;
1058                 }
1059
1060                 sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
1061                 if (sstr.matches()) {
1062                     for (String t : sstr.group(1).split(",")) {
1063                         if (t != null) {
1064                             String parts[] = t.split(":");
1065                             String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
1066                             if (parts.length == 1) {
1067                                 actionList.add(new Enqueue(NodeConnector.fromString(nc)));
1068                             } else {
1069                                 actionList
1070                                 .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
1071                             }
1072                         }
1073                     }
1074                     continue;
1075                 }
1076
1077                 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1078                 if (sstr.matches()) {
1079                     actionList.add(new Drop());
1080                     continue;
1081                 }
1082
1083                 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1084                 if (sstr.matches()) {
1085                     actionList.add(new Loopback());
1086                     continue;
1087                 }
1088
1089                 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1090                 if (sstr.matches()) {
1091                     actionList.add(new Flood());
1092                     continue;
1093                 }
1094
1095                 sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp);
1096                 if (sstr.matches()) {
1097                     actionList.add(new FloodAll());
1098                     continue;
1099                 }
1100
1101                 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1102                 if (sstr.matches()) {
1103                     actionList.add(new SwPath());
1104                     continue;
1105                 }
1106
1107                 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1108                 if (sstr.matches()) {
1109                     actionList.add(new HwPath());
1110                     continue;
1111                 }
1112
1113                 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1114                 if (sstr.matches()) {
1115                     actionList.add(new Controller());
1116                     continue;
1117                 }
1118
1119                 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1120                 if (sstr.matches()) {
1121                     actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1122                     continue;
1123                 }
1124
1125                 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1126                 if (sstr.matches()) {
1127                     actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1128                     continue;
1129                 }
1130
1131                 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1132                 if (sstr.matches()) {
1133                     actionList.add(new PopVlan());
1134                     continue;
1135                 }
1136
1137                 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1138                 if (sstr.matches()) {
1139                     actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1140                     continue;
1141                 }
1142
1143                 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1144                 if (sstr.matches()) {
1145                     actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1146                     continue;
1147                 }
1148                 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1149                 if (sstr.matches()) {
1150                     actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1151                     continue;
1152                 }
1153                 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1154                 if (sstr.matches()) {
1155                     actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1156                     continue;
1157                 }
1158
1159                 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1160                 if (sstr.matches()) {
1161                     actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1162                     continue;
1163                 }
1164
1165                 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1166                 if (sstr.matches()) {
1167                     actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1168                     continue;
1169                 }
1170
1171                 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1172                 if (sstr.matches()) {
1173                     actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1174                     continue;
1175                 }
1176
1177                 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1178                 if (sstr.matches()) {
1179                     actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));
1180                     continue;
1181                 }
1182             }
1183         }
1184         return actionList;
1185     }
1186
1187 }