2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.forwardingrulesmanager;
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;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import javax.xml.bind.annotation.XmlAccessType;
21 import javax.xml.bind.annotation.XmlAccessorType;
22 import javax.xml.bind.annotation.XmlElement;
23 import javax.xml.bind.annotation.XmlRootElement;
25 import org.opendaylight.controller.sal.action.Action;
26 import org.opendaylight.controller.sal.action.ActionType;
27 import org.opendaylight.controller.sal.action.Controller;
28 import org.opendaylight.controller.sal.action.Drop;
29 import org.opendaylight.controller.sal.action.Flood;
30 import org.opendaylight.controller.sal.action.HwPath;
31 import org.opendaylight.controller.sal.action.Loopback;
32 import org.opendaylight.controller.sal.action.Output;
33 import org.opendaylight.controller.sal.action.PopVlan;
34 import org.opendaylight.controller.sal.action.SetDlDst;
35 import org.opendaylight.controller.sal.action.SetDlSrc;
36 import org.opendaylight.controller.sal.action.SetNextHop;
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.Status;
59 import org.opendaylight.controller.sal.utils.StatusCode;
60 import org.opendaylight.controller.switchmanager.ISwitchManager;
61 import org.opendaylight.controller.switchmanager.Switch;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
66 * Configuration Java Object which represents a flow configuration information
67 * for Forwarding Rules Manager.
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 NAMEREGEX = "^[a-zA-Z0-9]+$";
75 public static final String STATICFLOWGROUP = "__StaticFlows__";
76 public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
77 public static final String INTERNALSTATICFLOWBEGIN = "__";
78 public static final String INTERNALSTATICFLOWEND = "__";
79 private boolean dynamic;
80 private String status;
83 * The order of the object data defined below is used directly in the UI
84 * built using JSP. Hence try to keep the order in a more logical way.
87 private String installInHw;
93 private String ingressPort;
94 private String portGroup;
96 private String priority;
98 private String etherType;
100 private String vlanId;
102 private String vlanPriority;
104 private String dlSrc;
106 private String dlDst;
108 private String nwSrc;
110 private String nwDst;
112 private String protocol;
114 private String tosBits;
116 private String tpSrc;
118 private String tpDst;
120 private String cookie;
122 private String idleTimeout;
124 private String hardTimeout;
126 private List<String> actions;
128 private enum EtherIPType {
132 public FlowConfig() {
135 public FlowConfig(String installInHw, String name, Node node, String priority, String cookie, String ingressPort,
136 String portGroup, String vlanId, String vlanPriority, String etherType, String srcMac, String dstMac,
137 String protocol, String tosBits, String srcIP, String dstIP, String tpSrc, String tpDst,
138 String idleTimeout, String hardTimeout, List<String> actions) {
140 this.installInHw = installInHw;
143 this.priority = priority;
144 this.cookie = cookie;
145 this.ingressPort = ingressPort;
146 this.portGroup = portGroup;
147 this.vlanId = vlanId;
148 this.vlanPriority = vlanPriority;
149 this.etherType = etherType;
152 this.protocol = protocol;
153 this.tosBits = tosBits;
158 this.idleTimeout = idleTimeout;
159 this.hardTimeout = hardTimeout;
160 this.actions = actions;
161 this.status = StatusCode.SUCCESS.toString();
164 public FlowConfig(FlowConfig from) {
165 this.installInHw = from.installInHw;
166 this.name = from.name;
167 this.node = from.node;
168 this.priority = from.priority;
169 this.cookie = from.cookie;
170 this.ingressPort = from.ingressPort;
171 this.portGroup = from.portGroup;
172 this.vlanId = from.vlanId;
173 this.vlanPriority = from.vlanPriority;
174 this.etherType = from.etherType;
175 this.dlSrc = from.dlSrc;
176 this.dlDst = from.dlDst;
177 this.protocol = from.protocol;
178 this.tosBits = from.tosBits;
179 this.nwSrc = from.nwSrc;
180 this.nwDst = from.nwDst;
181 this.tpSrc = from.tpSrc;
182 this.tpDst = from.tpDst;
183 this.idleTimeout = from.idleTimeout;
184 this.hardTimeout = from.hardTimeout;
185 this.actions = new ArrayList<String>(from.actions);
188 public boolean installInHw() {
189 if (installInHw == null) {
190 // backward compatibility
191 installInHw = "true";
193 return installInHw.equals("true");
196 public void setInstallInHw(boolean inHw) {
197 installInHw = inHw ? "true" : "false";
200 public String getInstallInHw() {
204 public boolean isInternalFlow() {
205 return (this.name != null &&
206 this.name.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN) &&
207 this.name.endsWith(FlowConfig.INTERNALSTATICFLOWEND));
210 public String getName() {
214 public void setName(String name) {
221 public Node getNode() {
225 public void setNode(Node node) {
229 public String getPriority() {
233 public void setPriority(String priority) {
234 this.priority = priority;
237 public String getCookie() {
241 public void setCookie(String cookie) {
242 this.cookie = cookie;
245 public String getIngressPort() {
249 public void setIngressPort(String ingressPort) {
250 this.ingressPort = ingressPort;
253 public String getPortGroup() {
258 public String toString() {
259 return "FlowConfig [dynamic=" + dynamic + ", status=" + status + ", installInHw=" + installInHw + ", name="
260 + name + ", switchId=" + node + ", ingressPort=" + ingressPort + ", portGroup=" + portGroup
261 + ", etherType=" + etherType + ", priority=" + priority + ", vlanId=" + vlanId + ", vlanPriority="
262 + vlanPriority + ", dlSrc=" + dlSrc + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
263 + ", protocol=" + protocol + ", tosBits=" + tosBits + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst
264 + ", cookie=" + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" + hardTimeout + ", actions="
268 public void setPortGroup(String portGroup) {
269 this.portGroup = portGroup;
272 public String getVlanId() {
276 public void setVlanId(String vlanId) {
277 this.vlanId = vlanId;
280 public String getVlanPriority() {
284 public void setVlanPriority(String vlanPriority) {
285 this.vlanPriority = vlanPriority;
288 public String getEtherType() {
292 public void setEtherType(String etherType) {
293 this.etherType = etherType;
296 public String getSrcMac() {
300 public void setSrcMac(String srcMac) {
304 public String getDstMac() {
308 public void setDstMac(String dstMac) {
312 public String getProtocol() {
316 public void setProtocol(String protocol) {
317 this.protocol = protocol;
320 public String getTosBits() {
324 public void setTosBits(String tos_bits) {
325 this.tosBits = tos_bits;
328 public String getSrcIp() {
332 public void setSrcIp(String src_ip) {
336 public String getDstIp() {
340 public void setDstIp(String dst_ip) {
344 public String getSrcPort() {
348 public void setSrcPort(String src_port) {
349 this.tpSrc = src_port;
352 public String getDstPort() {
356 public void setDstPort(String dst_port) {
357 this.tpDst = dst_port;
360 public String getIdleTimeout() {
364 public void setIdleTimeout(String idleTimeout) {
365 this.idleTimeout = idleTimeout;
368 public String getHardTimeout() {
372 public void setHardTimeout(String hardTimeout) {
373 this.hardTimeout = hardTimeout;
376 public boolean isIPv6() {
377 return NetUtils.isIPv6AddressValid(this.getSrcIp()) || NetUtils.isIPv6AddressValid(this.getDstIp());
380 public List<String> getActions() {
384 public void setActions(List<String> actions) {
385 this.actions = actions;
388 public boolean isPortGroupEnabled() {
389 return (portGroup != null);
392 public boolean isDynamic() {
396 public void setDynamic(boolean dynamic) {
397 this.dynamic = dynamic;
400 public String getStatus() {
404 public void setStatus(String status) {
405 this.status = status;
408 public boolean isStatusSuccessful() {
409 return status.equals(StatusCode.SUCCESS.toString());
413 public int hashCode() {
414 final int prime = 31;
416 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
417 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
418 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
419 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
420 result = prime * result + (dynamic ? 1231 : 1237);
421 result = prime * result + ((etherType == null) ? 0 : etherType.hashCode());
422 result = prime * result + ((ingressPort == null) ? 0 : ingressPort.hashCode());
423 result = prime * result + ((name == null) ? 0 : name.hashCode());
424 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
425 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
426 result = prime * result + ((portGroup == null) ? 0 : portGroup.hashCode());
427 result = prime * result + ((priority == null) ? 0 : priority.hashCode());
428 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
429 result = prime * result + ((node == null) ? 0 : node.hashCode());
430 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
431 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
432 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
433 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
434 result = prime * result + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
435 result = prime * result + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
436 result = prime * result + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
441 public boolean equals(Object obj) {
448 if (getClass() != obj.getClass()) {
451 FlowConfig other = (FlowConfig) obj;
452 if (actions == null) {
453 if (other.actions != null) {
456 } else if (!actions.equals(other.actions)) {
459 if (cookie == null) {
460 if (other.cookie != null) {
463 } else if (!cookie.equals(other.cookie)) {
467 if (other.dlDst != null) {
470 } else if (!dlDst.equals(other.dlDst)) {
474 if (other.dlSrc != null) {
477 } else if (!dlSrc.equals(other.dlSrc)) {
480 if (dynamic != other.dynamic) {
483 if (etherType == null) {
484 if (other.etherType != null) {
487 } else if (!etherType.equals(other.etherType)) {
490 if (ingressPort == null) {
491 if (other.ingressPort != null) {
494 } else if (!ingressPort.equals(other.ingressPort)) {
498 if (other.name != null) {
501 } else if (!name.equals(other.name)) {
505 if (other.nwDst != null) {
508 } else if (!nwDst.equals(other.nwDst)) {
512 if (other.nwSrc != null) {
515 } else if (!nwSrc.equals(other.nwSrc)) {
518 if (portGroup == null) {
519 if (other.portGroup != null) {
522 } else if (!portGroup.equals(other.portGroup)) {
525 if (priority == null) {
526 if (other.priority != null) {
529 } else if (!priority.equals(other.priority)) {
532 if (protocol == null) {
533 if (other.protocol != null) {
536 } else if (!protocol.equals(other.protocol)) {
540 if (other.node != null) {
543 } else if (!node.equals(other.node)) {
546 if (tosBits == null) {
547 if (other.tosBits != null) {
550 } else if (!tosBits.equals(other.tosBits)) {
554 if (other.tpDst != null) {
557 } else if (!tpDst.equals(other.tpDst)) {
561 if (other.tpSrc != null) {
564 } else if (!tpSrc.equals(other.tpSrc)) {
567 if (vlanId == null) {
568 if (other.vlanId != null) {
571 } else if (!vlanId.equals(other.vlanId)) {
574 if (vlanPriority == null) {
575 if (other.vlanPriority != null) {
578 } else if (!vlanPriority.equals(other.vlanPriority)) {
581 if (idleTimeout == null) {
582 if (other.idleTimeout != null) {
585 } else if (!idleTimeout.equals(other.idleTimeout)) {
588 if (hardTimeout == null) {
589 if (other.hardTimeout != null) {
592 } else if (!hardTimeout.equals(other.hardTimeout)) {
598 public boolean isL2AddressValid(String mac) {
603 Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
604 Matcher mm = macPattern.matcher(mac);
606 log.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
612 public boolean isPortValid(Switch sw, Short port) {
614 log.debug("port {} is not valid", port);
619 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
623 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
624 for (NodeConnector nodeConnector : nodeConnectorSet) {
625 if (((Short) nodeConnector.getID()).equals(port)) {
629 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
633 public boolean isVlanIdValid(String vlanId) {
634 int vlan = Integer.decode(vlanId);
635 return ((vlan >= 0) && (vlan < 4096));
638 public boolean isVlanPriorityValid(String vlanPriority) {
639 int pri = Integer.decode(vlanPriority);
640 return ((pri >= 0) && (pri < 8));
643 public boolean isTOSBitsValid(String tosBits) {
644 int tos = Integer.decode(tosBits);
645 return ((tos >= 0) && (tos < 64));
648 public boolean isTpPortValid(String tpPort) {
649 int port = Integer.decode(tpPort);
650 return ((port >= 0) && (port <= 0xffff));
653 public boolean isTimeoutValid(String timeout) {
654 int to = Integer.decode(timeout);
655 return ((to >= 0) && (to <= 0xffff));
658 private Status conflictWithContainerFlow(IContainer container) {
659 // Return true if it's default container
660 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
661 return new Status(StatusCode.SUCCESS);
664 // No container flow = no conflict
665 List<ContainerFlow> cFlowList = container.getContainerFlows();
666 if (((cFlowList == null)) || cFlowList.isEmpty()) {
667 return new Status(StatusCode.SUCCESS);
670 // Check against each container's flow
671 Flow flow = this.getFlow();
673 // Configuration is rejected if it conflicts with _all_ the container
675 for (ContainerFlow cFlow : cFlowList) {
676 if (cFlow.allowsFlow(flow)) {
677 log.trace("Config is congruent with at least one container flow");
678 return new Status(StatusCode.SUCCESS);
681 String msg = "Flow Config conflicts with all existing container flows";
684 return new Status(StatusCode.BADREQUEST, msg);
687 public Status validate(IContainer container) {
688 EtherIPType etype = EtherIPType.ANY;
689 EtherIPType ipsrctype = EtherIPType.ANY;
690 EtherIPType ipdsttype = EtherIPType.ANY;
692 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
693 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
698 if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
699 return new Status(StatusCode.BADREQUEST, "Invalid name");
703 return new Status(StatusCode.BADREQUEST, "Node is null");
706 if (switchManager != null) {
707 for (Switch device : switchManager.getNetworkDevices()) {
708 if (device.getNode().equals(node)) {
714 return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
717 log.debug("switchmanager is not set yet");
720 if (priority != null) {
721 if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
722 return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
727 // make sure it's a valid number
728 if (cookie != null) {
732 if (ingressPort != null) {
733 Short port = Short.decode(ingressPort);
734 if (isPortValid(sw, port) == false) {
735 String msg = String.format("Ingress port %d is not valid for the Switch", port);
736 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
737 msg += " in Container " + containerName;
739 return new Status(StatusCode.BADREQUEST, msg);
743 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
744 return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095",
748 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
749 return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7",
752 if (etherType != null) {
753 int type = Integer.decode(etherType);
754 if ((type < 0) || (type > 0xffff)) {
755 return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType));
758 etype = EtherIPType.V4;
759 } else if (type == 0x86dd) {
760 etype = EtherIPType.V6;
765 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
766 return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
770 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
771 return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc));
774 if ((tpDst != null) && !isTpPortValid(tpDst)) {
775 return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid",
779 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
780 return new Status(StatusCode.BADREQUEST, String.format(
781 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc));
784 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
785 return new Status(StatusCode.BADREQUEST, String.format(
786 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst));
790 if (NetUtils.isIPv4AddressValid(nwSrc)) {
791 ipsrctype = EtherIPType.V4;
792 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
793 ipsrctype = EtherIPType.V6;
795 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc));
800 if (NetUtils.isIPv4AddressValid(nwDst)) {
801 ipdsttype = EtherIPType.V4;
802 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
803 ipdsttype = EtherIPType.V6;
805 return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid",
810 if (etype != EtherIPType.ANY) {
811 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
812 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP"));
814 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
815 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP"));
818 if (ipsrctype != ipdsttype) {
819 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
820 return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch"));
824 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
825 return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid",
829 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
830 return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid",
835 if (actions != null && !actions.isEmpty()) {
836 for (String actiongrp : actions) {
837 // check output ports
838 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
839 if (sstr.matches()) {
840 for (String t : sstr.group(1).split(",")) {
841 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
843 if (n.group(1) != null) {
844 Short port = Short.parseShort(n.group(1));
845 if (isPortValid(sw, port) == false) {
846 String msg = String.format("Output port %d is not valid for this switch", port);
847 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
848 msg += " in Container " + containerName;
850 return new Status(StatusCode.BADREQUEST, msg);
858 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
859 if (sstr.matches()) {
860 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
861 return new Status(StatusCode.BADREQUEST, String.format(
862 "flood is not allowed in container %s", containerName));
867 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
868 if (sstr.matches()) {
869 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
870 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
876 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
877 if (sstr.matches()) {
878 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
879 return new Status(StatusCode.BADREQUEST, String.format(
880 "IP destination address %s is not valid", sstr.group(1)));
885 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
886 if (sstr.matches()) {
887 if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
888 return new Status(StatusCode.BADREQUEST, String.format(
889 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
894 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
895 if (sstr.matches()) {
896 if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
897 return new Status(StatusCode.BADREQUEST, String.format(
898 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
903 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
904 if (sstr.matches()) {
905 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
906 return new Status(StatusCode.BADREQUEST, String.format(
907 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
912 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
913 if (sstr.matches()) {
914 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
915 return new Status(StatusCode.BADREQUEST, String.format(
916 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
922 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
923 if (sstr.matches()) {
924 if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
925 return new Status(StatusCode.BADREQUEST, String.format(
926 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
931 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
932 if (sstr.matches()) {
933 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
934 return new Status(StatusCode.BADREQUEST, String.format(
935 "Transport source port %s is not valid", sstr.group(1)));
940 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
941 if (sstr.matches()) {
942 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
943 return new Status(StatusCode.BADREQUEST, String.format(
944 "Transport destination port %s is not valid", sstr.group(1)));
948 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
949 if (sstr.matches()) {
950 if (!NetUtils.isIPAddressValid(sstr.group(1))) {
951 return new Status(StatusCode.BADREQUEST, String.format(
952 "IP destination address %s is not valid", sstr.group(1)));
958 // Check against the container flow
960 if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
963 } catch (NumberFormatException e) {
964 return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
967 return new Status(StatusCode.SUCCESS);
970 public FlowEntry getFlowEntry() {
971 String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
972 return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
975 public Flow getFlow() {
976 Match match = new Match();
978 if (this.ingressPort != null) {
979 match.setField(MatchType.IN_PORT,
980 NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode()));
982 if (this.dlSrc != null) {
983 match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
985 if (this.dlDst != null) {
986 match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
988 if (this.etherType != null) {
989 match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
991 if (this.vlanId != null) {
992 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
994 if (this.vlanPriority != null) {
995 match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
997 if (this.nwSrc != null) {
998 String parts[] = this.nwSrc.split("/");
999 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1000 InetAddress mask = null;
1002 if (parts.length > 1) {
1003 maskLen = Integer.parseInt(parts[1]);
1005 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1007 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1008 match.setField(MatchType.NW_SRC, ip, mask);
1010 if (this.nwDst != null) {
1011 String parts[] = this.nwDst.split("/");
1012 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1013 InetAddress mask = null;
1015 if (parts.length > 1) {
1016 maskLen = Integer.parseInt(parts[1]);
1018 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1020 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1021 match.setField(MatchType.NW_DST, ip, mask);
1023 if (this.protocol != null) {
1024 match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
1026 if (this.tosBits != null) {
1027 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1029 if (this.tpSrc != null) {
1030 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
1032 if (this.tpDst != null) {
1033 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1036 Flow flow = new Flow(match, getActionList());
1037 if (this.cookie != null) {
1038 flow.setId(Long.parseLong(cookie));
1040 if (this.hardTimeout != null) {
1041 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1043 if (this.idleTimeout != null) {
1044 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1046 if (this.priority != null) {
1047 flow.setPriority(Integer.decode(this.priority).shortValue());
1052 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1053 return (this.name.equals(that.name) && this.node.equals(that.node));
1056 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1057 return (this.name.equals(name) && this.node.equals(node));
1060 public boolean onNode(Node node) {
1061 return this.node.equals(node);
1064 public void toggleInstallation() {
1065 installInHw = (installInHw == null) ? "true" : (installInHw.equals("true")) ? "false" : "true";
1069 * Parses the actions string and return the List of SAL Action No syntax
1070 * check run, as this function will be called when the config validation
1071 * check has already been performed
1073 private List<Action> getActionList() {
1074 List<Action> actionList = new ArrayList<Action>();
1076 if (actions != null) {
1078 for (String actiongrp : actions) {
1079 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1080 if (sstr.matches()) {
1081 for (String t : sstr.group(1).split(",")) {
1082 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1084 if (n.group(1) != null) {
1085 short ofPort = Short.parseShort(n.group(1));
1086 actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort,
1094 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1095 if (sstr.matches()) {
1096 actionList.add(new Drop());
1100 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1101 if (sstr.matches()) {
1102 actionList.add(new Loopback());
1106 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1107 if (sstr.matches()) {
1108 actionList.add(new Flood());
1112 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1113 if (sstr.matches()) {
1114 actionList.add(new SwPath());
1118 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1119 if (sstr.matches()) {
1120 actionList.add(new HwPath());
1124 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1125 if (sstr.matches()) {
1126 actionList.add(new Controller());
1130 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1131 if (sstr.matches()) {
1132 actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1136 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1137 if (sstr.matches()) {
1138 actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1142 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1143 if (sstr.matches()) {
1144 actionList.add(new PopVlan());
1148 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1149 if (sstr.matches()) {
1150 actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1154 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1155 if (sstr.matches()) {
1156 actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1159 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1160 if (sstr.matches()) {
1161 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1164 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1165 if (sstr.matches()) {
1166 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1170 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1171 if (sstr.matches()) {
1172 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1176 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1177 if (sstr.matches()) {
1178 actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1182 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1183 if (sstr.matches()) {
1184 actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1188 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1189 if (sstr.matches()) {
1190 actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));