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 public static final String staticFlowsGroup = "**StaticFlows";
75 public static final String internalStaticFlowsGroup = "**InternalStaticFlows";
76 public static final String internalStaticFlowBegin = "**";
77 private boolean dynamic;
78 private String status;
81 * The order of the object data defined below is used directly in the UI
82 * built using JSP. Hence try to keep the order in a more logical way.
85 private String installInHw;
91 private String ingressPort;
92 private String portGroup;
94 private String priority;
96 private String etherType;
98 private String vlanId;
100 private String vlanPriority;
102 private String dlSrc;
104 private String dlDst;
106 private String nwSrc;
108 private String nwDst;
110 private String protocol;
112 private String tosBits;
114 private String tpSrc;
116 private String tpDst;
118 private String cookie;
120 private String idleTimeout;
122 private String hardTimeout;
124 private List<String> actions;
126 private enum EtherIPType {
130 public FlowConfig() {
133 public FlowConfig(String installInHw, String name, Node node, String priority, String cookie, String ingressPort,
134 String portGroup, String vlanId, String vlanPriority, String etherType, String srcMac, String dstMac,
135 String protocol, String tosBits, String srcIP, String dstIP, String tpSrc, String tpDst,
136 String idleTimeout, String hardTimeout, List<String> actions) {
138 this.installInHw = installInHw;
141 this.priority = priority;
142 this.cookie = cookie;
143 this.ingressPort = ingressPort;
144 this.portGroup = portGroup;
145 this.vlanId = vlanId;
146 this.vlanPriority = vlanPriority;
147 this.etherType = etherType;
150 this.protocol = protocol;
151 this.tosBits = tosBits;
156 this.idleTimeout = idleTimeout;
157 this.hardTimeout = hardTimeout;
158 this.actions = actions;
159 this.status = StatusCode.SUCCESS.toString();
162 public FlowConfig(FlowConfig from) {
163 this.installInHw = from.installInHw;
164 this.name = from.name;
165 this.node = from.node;
166 this.priority = from.priority;
167 this.cookie = from.cookie;
168 this.ingressPort = from.ingressPort;
169 this.portGroup = from.portGroup;
170 this.vlanId = from.vlanId;
171 this.vlanPriority = from.vlanPriority;
172 this.etherType = from.etherType;
173 this.dlSrc = from.dlSrc;
174 this.dlDst = from.dlDst;
175 this.protocol = from.protocol;
176 this.tosBits = from.tosBits;
177 this.nwSrc = from.nwSrc;
178 this.nwDst = from.nwDst;
179 this.tpSrc = from.tpSrc;
180 this.tpDst = from.tpDst;
181 this.idleTimeout = from.idleTimeout;
182 this.hardTimeout = from.hardTimeout;
183 this.actions = new ArrayList<String>(from.actions);
186 public boolean installInHw() {
187 if (installInHw == null) {
188 // backward compatibility
189 installInHw = "true";
191 return installInHw.equals("true");
194 public void setInstallInHw(boolean inHw) {
195 installInHw = inHw ? "true" : "false";
198 public String getInstallInHw() {
202 public boolean isInternalFlow() {
203 // Controller generated static flows have name starting with "**"
204 return (this.name != null && this.name.startsWith(FlowConfig.internalStaticFlowBegin));
207 public String getName() {
211 public void setName(String name) {
218 public Node getNode() {
222 public void setNode(Node node) {
226 public String getPriority() {
230 public void setPriority(String priority) {
231 this.priority = priority;
234 public String getCookie() {
238 public void setCookie(String cookie) {
239 this.cookie = cookie;
242 public String getIngressPort() {
246 public void setIngressPort(String ingressPort) {
247 this.ingressPort = ingressPort;
250 public String getPortGroup() {
255 public String toString() {
256 return "FlowConfig [dynamic=" + dynamic + ", status=" + status + ", installInHw=" + installInHw + ", name="
257 + name + ", switchId=" + node + ", ingressPort=" + ingressPort + ", portGroup=" + portGroup
258 + ", etherType=" + etherType + ", priority=" + priority + ", vlanId=" + vlanId + ", vlanPriority="
259 + vlanPriority + ", dlSrc=" + dlSrc + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
260 + ", protocol=" + protocol + ", tosBits=" + tosBits + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst
261 + ", cookie=" + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" + hardTimeout + ", actions="
265 public void setPortGroup(String portGroup) {
266 this.portGroup = portGroup;
269 public String getVlanId() {
273 public void setVlanId(String vlanId) {
274 this.vlanId = vlanId;
277 public String getVlanPriority() {
281 public void setVlanPriority(String vlanPriority) {
282 this.vlanPriority = vlanPriority;
285 public String getEtherType() {
289 public void setEtherType(String etherType) {
290 this.etherType = etherType;
293 public String getSrcMac() {
297 public void setSrcMac(String srcMac) {
301 public String getDstMac() {
305 public void setDstMac(String dstMac) {
309 public String getProtocol() {
313 public void setProtocol(String protocol) {
314 this.protocol = protocol;
317 public String getTosBits() {
321 public void setTosBits(String tos_bits) {
322 this.tosBits = tos_bits;
325 public String getSrcIp() {
329 public void setSrcIp(String src_ip) {
333 public String getDstIp() {
337 public void setDstIp(String dst_ip) {
341 public String getSrcPort() {
345 public void setSrcPort(String src_port) {
346 this.tpSrc = src_port;
349 public String getDstPort() {
353 public void setDstPort(String dst_port) {
354 this.tpDst = dst_port;
357 public String getIdleTimeout() {
361 public void setIdleTimeout(String idleTimeout) {
362 this.idleTimeout = idleTimeout;
365 public String getHardTimeout() {
369 public void setHardTimeout(String hardTimeout) {
370 this.hardTimeout = hardTimeout;
373 public boolean isIPv6() {
374 return NetUtils.isIPv6AddressValid(this.getSrcIp()) || NetUtils.isIPv6AddressValid(this.getDstIp());
377 public List<String> getActions() {
381 public void setActions(List<String> actions) {
382 this.actions = actions;
385 public boolean isPortGroupEnabled() {
386 return (portGroup != null);
389 public boolean isDynamic() {
393 public void setDynamic(boolean dynamic) {
394 this.dynamic = dynamic;
397 public String getStatus() {
401 public void setStatus(String status) {
402 this.status = status;
405 public boolean isStatusSuccessful() {
406 return status.equals(StatusCode.SUCCESS.toString());
410 public int hashCode() {
411 final int prime = 31;
413 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
414 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
415 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
416 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
417 result = prime * result + (dynamic ? 1231 : 1237);
418 result = prime * result + ((etherType == null) ? 0 : etherType.hashCode());
419 result = prime * result + ((ingressPort == null) ? 0 : ingressPort.hashCode());
420 result = prime * result + ((name == null) ? 0 : name.hashCode());
421 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
422 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
423 result = prime * result + ((portGroup == null) ? 0 : portGroup.hashCode());
424 result = prime * result + ((priority == null) ? 0 : priority.hashCode());
425 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
426 result = prime * result + ((node == null) ? 0 : node.hashCode());
427 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
428 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
429 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
430 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
431 result = prime * result + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
432 result = prime * result + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
433 result = prime * result + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
438 public boolean equals(Object obj) {
445 if (getClass() != obj.getClass()) {
448 FlowConfig other = (FlowConfig) obj;
449 if (actions == null) {
450 if (other.actions != null) {
453 } else if (!actions.equals(other.actions)) {
456 if (cookie == null) {
457 if (other.cookie != null) {
460 } else if (!cookie.equals(other.cookie)) {
464 if (other.dlDst != null) {
467 } else if (!dlDst.equals(other.dlDst)) {
471 if (other.dlSrc != null) {
474 } else if (!dlSrc.equals(other.dlSrc)) {
477 if (dynamic != other.dynamic) {
480 if (etherType == null) {
481 if (other.etherType != null) {
484 } else if (!etherType.equals(other.etherType)) {
487 if (ingressPort == null) {
488 if (other.ingressPort != null) {
491 } else if (!ingressPort.equals(other.ingressPort)) {
495 if (other.name != null) {
498 } else if (!name.equals(other.name)) {
502 if (other.nwDst != null) {
505 } else if (!nwDst.equals(other.nwDst)) {
509 if (other.nwSrc != null) {
512 } else if (!nwSrc.equals(other.nwSrc)) {
515 if (portGroup == null) {
516 if (other.portGroup != null) {
519 } else if (!portGroup.equals(other.portGroup)) {
522 if (priority == null) {
523 if (other.priority != null) {
526 } else if (!priority.equals(other.priority)) {
529 if (protocol == null) {
530 if (other.protocol != null) {
533 } else if (!protocol.equals(other.protocol)) {
537 if (other.node != null) {
540 } else if (!node.equals(other.node)) {
543 if (tosBits == null) {
544 if (other.tosBits != null) {
547 } else if (!tosBits.equals(other.tosBits)) {
551 if (other.tpDst != null) {
554 } else if (!tpDst.equals(other.tpDst)) {
558 if (other.tpSrc != null) {
561 } else if (!tpSrc.equals(other.tpSrc)) {
564 if (vlanId == null) {
565 if (other.vlanId != null) {
568 } else if (!vlanId.equals(other.vlanId)) {
571 if (vlanPriority == null) {
572 if (other.vlanPriority != null) {
575 } else if (!vlanPriority.equals(other.vlanPriority)) {
578 if (idleTimeout == null) {
579 if (other.idleTimeout != null) {
582 } else if (!idleTimeout.equals(other.idleTimeout)) {
585 if (hardTimeout == null) {
586 if (other.hardTimeout != null) {
589 } else if (!hardTimeout.equals(other.hardTimeout)) {
595 public boolean isL2AddressValid(String mac) {
600 Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
601 Matcher mm = macPattern.matcher(mac);
603 log.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
609 public boolean isPortValid(Switch sw, Short port) {
611 log.debug("port {} is not valid", port);
616 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
620 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
621 for (NodeConnector nodeConnector : nodeConnectorSet) {
622 if (((Short) nodeConnector.getID()).equals(port)) {
626 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
630 public boolean isVlanIdValid(String vlanId) {
631 int vlan = Integer.decode(vlanId);
632 return ((vlan >= 0) && (vlan < 4096));
635 public boolean isVlanPriorityValid(String vlanPriority) {
636 int pri = Integer.decode(vlanPriority);
637 return ((pri >= 0) && (pri < 8));
640 public boolean isTOSBitsValid(String tosBits) {
641 int tos = Integer.decode(tosBits);
642 return ((tos >= 0) && (tos < 64));
645 public boolean isTpPortValid(String tpPort) {
646 int port = Integer.decode(tpPort);
647 return ((port > 0) && (port <= 0xffff));
650 public boolean isTimeoutValid(String timeout) {
651 int to = Integer.decode(timeout);
652 return ((to >= 0) && (to <= 0xffff));
655 private Status conflictWithContainerFlow(IContainer container) {
656 // Return true if it's default container
657 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
658 return new Status(StatusCode.SUCCESS);
661 // No container flow = no conflict
662 List<ContainerFlow> cFlowList = container.getContainerFlows();
663 if (((cFlowList == null)) || cFlowList.isEmpty()) {
664 return new Status(StatusCode.SUCCESS);
667 // Check against each container's flow
668 Flow flow = this.getFlow();
670 // Configuration is rejected if it conflicts with _all_ the container
672 for (ContainerFlow cFlow : cFlowList) {
673 if (cFlow.allowsFlow(flow)) {
674 log.trace("Config is congruent with at least one container flow");
675 return new Status(StatusCode.SUCCESS);
678 String msg = "Flow Config conflicts with all existing container flows";
681 return new Status(StatusCode.BADREQUEST, msg);
684 public Status validate(IContainer container) {
685 EtherIPType etype = EtherIPType.ANY;
686 EtherIPType ipsrctype = EtherIPType.ANY;
687 EtherIPType ipdsttype = EtherIPType.ANY;
689 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
690 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
695 if (name == null || name.trim().isEmpty()) {
696 return new Status(StatusCode.BADREQUEST, "Invalid name");
700 return new Status(StatusCode.BADREQUEST, "Node is null");
703 if (switchManager != null) {
704 for (Switch device : switchManager.getNetworkDevices()) {
705 if (device.getNode().equals(node)) {
711 return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
714 log.debug("switchmanager is not set yet");
717 if (priority != null) {
718 if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
719 return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
724 // make sure it's a valid number
725 if (cookie != null) {
729 if (ingressPort != null) {
730 Short port = Short.decode(ingressPort);
731 if (isPortValid(sw, port) == false) {
732 String msg = String.format("Ingress port %d is not valid for the Switch", port);
733 if ((container != null) && !container.getName().equals(GlobalConstants.DEFAULT.toString())) {
734 msg += " in Container " + container.getName();
736 return new Status(StatusCode.BADREQUEST, msg);
740 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
741 return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095",
745 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
746 return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7",
749 if (etherType != null) {
750 int type = Integer.decode(etherType);
751 if ((type < 0) || (type > 0xffff)) {
752 return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType));
755 etype = EtherIPType.V4;
756 } else if (type == 0x86dd) {
757 etype = EtherIPType.V6;
762 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
763 return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
767 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
768 return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc));
771 if ((tpDst != null) && !isTpPortValid(tpDst)) {
772 return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid",
776 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
777 return new Status(StatusCode.BADREQUEST, String.format(
778 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc));
781 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
782 return new Status(StatusCode.BADREQUEST, String.format(
783 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst));
787 if (NetUtils.isIPv4AddressValid(nwSrc)) {
788 ipsrctype = EtherIPType.V4;
789 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
790 ipsrctype = EtherIPType.V6;
792 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc));
797 if (NetUtils.isIPv4AddressValid(nwDst)) {
798 ipdsttype = EtherIPType.V4;
799 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
800 ipdsttype = EtherIPType.V6;
802 return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid",
807 if (etype != EtherIPType.ANY) {
808 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
809 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP"));
811 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
812 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP"));
815 if (ipsrctype != ipdsttype) {
816 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
817 return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch"));
821 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
822 return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid",
826 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
827 return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid",
832 if (actions != null && !actions.isEmpty()) {
833 for (String actiongrp : actions) {
834 // check output ports
835 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
836 if (sstr.matches()) {
837 for (String t : sstr.group(1).split(",")) {
838 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
840 if (n.group(1) != null) {
841 Short port = Short.parseShort(n.group(1));
842 if (isPortValid(sw, port) == false) {
843 String msg = String.format("Output port %d is not valid for this switch", port);
844 if ((container != null)
845 && !container.getName().equals(GlobalConstants.DEFAULT.toString())) {
846 msg += " in Container " + container.getName();
848 return new Status(StatusCode.BADREQUEST, msg);
856 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
857 if (sstr.matches()) {
858 if (container != null) {
859 return new Status(StatusCode.BADREQUEST, String.format(
860 "flood is not allowed in container %s", container.getName()));
865 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
866 if (sstr.matches()) {
867 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
868 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
874 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
875 if (sstr.matches()) {
876 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
877 return new Status(StatusCode.BADREQUEST, String.format(
878 "IP destination address %s is not valid", sstr.group(1)));
883 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
884 if (sstr.matches()) {
885 if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
886 return new Status(StatusCode.BADREQUEST, String.format(
887 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
892 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
893 if (sstr.matches()) {
894 if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
895 return new Status(StatusCode.BADREQUEST, String.format(
896 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
901 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
902 if (sstr.matches()) {
903 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
904 return new Status(StatusCode.BADREQUEST, String.format(
905 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
910 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
911 if (sstr.matches()) {
912 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
913 return new Status(StatusCode.BADREQUEST, String.format(
914 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
920 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
921 if (sstr.matches()) {
922 if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
923 return new Status(StatusCode.BADREQUEST, String.format(
924 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
929 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
930 if (sstr.matches()) {
931 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
932 return new Status(StatusCode.BADREQUEST, String.format(
933 "Transport source port %s is not valid", sstr.group(1)));
938 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
939 if (sstr.matches()) {
940 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
941 return new Status(StatusCode.BADREQUEST, String.format(
942 "Transport destination port %s is not valid", sstr.group(1)));
946 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
947 if (sstr.matches()) {
948 if (!NetUtils.isIPAddressValid(sstr.group(1))) {
949 return new Status(StatusCode.BADREQUEST, String.format(
950 "IP destination address %s is not valid", sstr.group(1)));
956 // Check against the container flow
958 if ((container != null) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
961 } catch (NumberFormatException e) {
962 return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
965 return new Status(StatusCode.SUCCESS);
968 public FlowEntry getFlowEntry() {
969 return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this.getFlow(), this.getNode());
972 public Flow getFlow() {
973 Match match = new Match();
975 if (this.ingressPort != null) {
976 match.setField(MatchType.IN_PORT,
977 NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode()));
979 if (this.dlSrc != null) {
980 match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
982 if (this.dlDst != null) {
983 match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
985 if (this.etherType != null) {
986 match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
988 if (this.vlanId != null) {
989 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
991 if (this.vlanPriority != null) {
992 match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
994 if (this.nwSrc != null) {
995 String parts[] = this.nwSrc.split("/");
996 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
997 InetAddress mask = null;
999 if (parts.length > 1) {
1000 maskLen = Integer.parseInt(parts[1]);
1002 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1004 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1005 match.setField(MatchType.NW_SRC, ip, mask);
1007 if (this.nwDst != null) {
1008 String parts[] = this.nwDst.split("/");
1009 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1010 InetAddress mask = null;
1012 if (parts.length > 1) {
1013 maskLen = Integer.parseInt(parts[1]);
1015 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1017 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1018 match.setField(MatchType.NW_DST, ip, mask);
1020 if (this.protocol != null) {
1021 match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
1023 if (this.tosBits != null) {
1024 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1026 if (this.tpSrc != null) {
1027 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
1029 if (this.tpDst != null) {
1030 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1033 Flow flow = new Flow(match, getActionList());
1034 if (this.cookie != null) {
1035 flow.setId(Long.parseLong(cookie));
1037 if (this.hardTimeout != null) {
1038 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1040 if (this.idleTimeout != null) {
1041 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1043 if (this.priority != null) {
1044 flow.setPriority(Integer.decode(this.priority).shortValue());
1049 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1050 return (this.name.equals(that.name) && this.node.equals(that.node));
1053 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1054 return (this.name.equals(name) && this.node.equals(node));
1057 public boolean onNode(Node node) {
1058 return this.node.equals(node);
1061 public void toggleInstallation() {
1062 installInHw = (installInHw == null) ? "true" : (installInHw.equals("true")) ? "false" : "true";
1066 * Parses the actions string and return the List of SAL Action No syntax
1067 * check run, as this function will be called when the config validation
1068 * check has already been performed
1070 private List<Action> getActionList() {
1071 List<Action> actionList = new ArrayList<Action>();
1073 if (actions != null) {
1075 for (String actiongrp : actions) {
1076 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1077 if (sstr.matches()) {
1078 for (String t : sstr.group(1).split(",")) {
1079 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1081 if (n.group(1) != null) {
1082 short ofPort = Short.parseShort(n.group(1));
1083 actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort,
1091 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1092 if (sstr.matches()) {
1093 actionList.add(new Drop());
1097 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1098 if (sstr.matches()) {
1099 actionList.add(new Loopback());
1103 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1104 if (sstr.matches()) {
1105 actionList.add(new Flood());
1109 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1110 if (sstr.matches()) {
1111 actionList.add(new SwPath());
1115 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1116 if (sstr.matches()) {
1117 actionList.add(new HwPath());
1121 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1122 if (sstr.matches()) {
1123 actionList.add(new Controller());
1127 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1128 if (sstr.matches()) {
1129 actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1133 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1134 if (sstr.matches()) {
1135 actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1139 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1140 if (sstr.matches()) {
1141 actionList.add(new PopVlan());
1145 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1146 if (sstr.matches()) {
1147 actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1151 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1152 if (sstr.matches()) {
1153 actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1156 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1157 if (sstr.matches()) {
1158 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1161 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1162 if (sstr.matches()) {
1163 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1167 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1168 if (sstr.matches()) {
1169 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1173 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1174 if (sstr.matches()) {
1175 actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1179 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1180 if (sstr.matches()) {
1181 actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1185 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1186 if (sstr.matches()) {
1187 actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));