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