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;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
19 import javax.xml.bind.annotation.XmlAccessType;
20 import javax.xml.bind.annotation.XmlAccessorType;
21 import javax.xml.bind.annotation.XmlElement;
22 import javax.xml.bind.annotation.XmlRootElement;
24 import org.opendaylight.controller.sal.action.Action;
25 import org.opendaylight.controller.sal.action.ActionType;
26 import org.opendaylight.controller.sal.action.Controller;
27 import org.opendaylight.controller.sal.action.Drop;
28 import org.opendaylight.controller.sal.action.Enqueue;
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 = Boolean.toString(true);
193 return Boolean.valueOf(installInHw);
196 public void setInstallInHw(boolean inHw) {
197 installInHw = String.valueOf(inHw);
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, String port) {
614 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
617 NodeConnector nc = NodeConnectorCreator.createNodeConnector(port, sw.getNode());
618 return sw.getNodeConnectors().contains(nc);
621 public boolean isVlanIdValid(String vlanId) {
622 int vlan = Integer.decode(vlanId);
623 return ((vlan >= 0) && (vlan < 4096));
626 public boolean isVlanPriorityValid(String vlanPriority) {
627 int pri = Integer.decode(vlanPriority);
628 return ((pri >= 0) && (pri < 8));
631 public boolean isTOSBitsValid(String tosBits) {
632 int tos = Integer.decode(tosBits);
633 return ((tos >= 0) && (tos < 64));
636 public boolean isTpPortValid(String tpPort) {
637 int port = Integer.decode(tpPort);
638 return ((port >= 0) && (port <= 0xffff));
641 public boolean isTimeoutValid(String timeout) {
642 int to = Integer.decode(timeout);
643 return ((to >= 0) && (to <= 0xffff));
646 public boolean isProtocolValid(String protocol) {
647 IPProtocols proto = IPProtocols.fromString(protocol);
648 return (proto != null);
651 private Status conflictWithContainerFlow(IContainer container) {
652 // Return true if it's default container
653 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
654 return new Status(StatusCode.SUCCESS);
657 // No container flow = no conflict
658 List<ContainerFlow> cFlowList = container.getContainerFlows();
659 if (((cFlowList == null)) || cFlowList.isEmpty()) {
660 return new Status(StatusCode.SUCCESS);
663 // Check against each container's flow
664 Flow flow = this.getFlow();
666 // Configuration is rejected if it conflicts with _all_ the container
668 for (ContainerFlow cFlow : cFlowList) {
669 if (cFlow.allowsFlow(flow)) {
670 log.trace("Config is congruent with at least one container flow");
671 return new Status(StatusCode.SUCCESS);
674 String msg = "Flow Config conflicts with all existing container flows";
677 return new Status(StatusCode.BADREQUEST, msg);
680 public Status validate(IContainer container) {
681 EtherIPType etype = EtherIPType.ANY;
682 EtherIPType ipsrctype = EtherIPType.ANY;
683 EtherIPType ipdsttype = EtherIPType.ANY;
685 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
686 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
691 if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
692 return new Status(StatusCode.BADREQUEST, "Invalid name");
696 return new Status(StatusCode.BADREQUEST, "Node is null");
699 if (switchManager != null) {
700 for (Switch device : switchManager.getNetworkDevices()) {
701 if (device.getNode().equals(node)) {
707 return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
710 log.debug("switchmanager is not set yet");
713 if (priority != null) {
714 if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
715 return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
720 // make sure it's a valid number
721 if (cookie != null) {
725 if (ingressPort != null) {
726 if (!isPortValid(sw, ingressPort)) {
727 String msg = String.format("Ingress port %s is not valid for the Switch", ingressPort);
728 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
729 msg += " in Container " + containerName;
731 return new Status(StatusCode.BADREQUEST, msg);
735 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
736 return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095",
740 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
741 return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7",
744 if (etherType != null) {
745 int type = Integer.decode(etherType);
746 if ((type < 0) || (type > 0xffff)) {
747 return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType));
750 etype = EtherIPType.V4;
751 } else if (type == 0x86dd) {
752 etype = EtherIPType.V6;
757 if ((protocol != null) && !isProtocolValid(protocol)) {
758 return new Status(StatusCode.BADREQUEST, String.format("Protocol %s is not valid", protocol));
761 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
762 return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
766 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
767 return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc));
770 if ((tpDst != null) && !isTpPortValid(tpDst)) {
771 return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid",
775 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
776 return new Status(StatusCode.BADREQUEST, String.format(
777 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc));
780 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
781 return new Status(StatusCode.BADREQUEST, String.format(
782 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst));
786 if (NetUtils.isIPv4AddressValid(nwSrc)) {
787 ipsrctype = EtherIPType.V4;
788 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
789 ipsrctype = EtherIPType.V6;
791 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc));
796 if (NetUtils.isIPv4AddressValid(nwDst)) {
797 ipdsttype = EtherIPType.V4;
798 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
799 ipdsttype = EtherIPType.V6;
801 return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid",
806 if (etype != EtherIPType.ANY) {
807 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
808 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP"));
810 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
811 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP"));
814 if (ipsrctype != ipdsttype) {
815 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
816 return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch"));
820 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
821 return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid",
825 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
826 return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid",
831 if (actions == null || actions.isEmpty()) {
832 return new Status(StatusCode.BADREQUEST, "Actions value is null or empty");
834 for (String actiongrp : actions) {
835 // check output ports
836 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
837 if (sstr.matches()) {
838 for (String t : sstr.group(1).split(",")) {
839 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
841 String port = n.group(1);
843 if (!isPortValid(sw, port)) {
844 String msg = String.format("Output port %s is not valid for this switch", port);
845 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
846 msg += " in Container " + containerName;
848 return new Status(StatusCode.BADREQUEST, msg);
852 String msg = String.format("Output port %s is not valid", t);
853 return new Status(StatusCode.BADREQUEST, msg);
859 sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
860 if (sstr.matches()) {
861 for (String t : sstr.group(1).split(",")) {
862 Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
864 if (n.group(1) != null) {
865 String port = n.group(1).split(":")[0];
866 if (!isPortValid(sw, port)) {
867 String msg = String.format("Output port %d is not valid for this switch", port);
868 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
869 msg += " in Container " + containerName;
871 return new Status(StatusCode.BADREQUEST, msg);
875 String msg = String.format("Enqueue port %s is not valid", t);
876 return new Status(StatusCode.BADREQUEST, msg);
882 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
883 if (sstr.matches()) {
884 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
885 return new Status(StatusCode.BADREQUEST, String.format(
886 "flood is not allowed in container %s", containerName));
891 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
892 if (sstr.matches()) {
893 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
894 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
900 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
901 if (sstr.matches()) {
902 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
903 return new Status(StatusCode.BADREQUEST, String.format(
904 "IP destination address %s is not valid", sstr.group(1)));
909 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
910 if (sstr.matches()) {
911 if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
912 return new Status(StatusCode.BADREQUEST, String.format(
913 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
918 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
919 if (sstr.matches()) {
920 if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
921 return new Status(StatusCode.BADREQUEST, String.format(
922 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
927 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
928 if (sstr.matches()) {
929 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
930 return new Status(StatusCode.BADREQUEST, String.format(
931 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
936 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
937 if (sstr.matches()) {
938 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
939 return new Status(StatusCode.BADREQUEST, String.format(
940 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
946 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
947 if (sstr.matches()) {
948 if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
949 return new Status(StatusCode.BADREQUEST, String.format(
950 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
955 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
956 if (sstr.matches()) {
957 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
958 return new Status(StatusCode.BADREQUEST, String.format(
959 "Transport source port %s is not valid", sstr.group(1)));
964 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
965 if (sstr.matches()) {
966 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
967 return new Status(StatusCode.BADREQUEST, String.format(
968 "Transport destination port %s is not valid", sstr.group(1)));
972 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
973 if (sstr.matches()) {
974 if (!NetUtils.isIPAddressValid(sstr.group(1))) {
975 return new Status(StatusCode.BADREQUEST, String.format(
976 "IP destination address %s is not valid", sstr.group(1)));
981 // Check against the container flow
983 if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
986 } catch (NumberFormatException e) {
987 return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
990 return new Status(StatusCode.SUCCESS);
993 public FlowEntry getFlowEntry() {
994 String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
995 return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
998 public Flow getFlow() {
999 Match match = new Match();
1001 if (this.ingressPort != null) {
1002 match.setField(MatchType.IN_PORT,
1003 NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
1005 if (this.dlSrc != null) {
1006 match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
1008 if (this.dlDst != null) {
1009 match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
1011 if (this.etherType != null) {
1012 match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
1014 if (this.vlanId != null) {
1015 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1017 if (this.vlanPriority != null) {
1018 match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
1020 if (this.nwSrc != null) {
1021 String parts[] = this.nwSrc.split("/");
1022 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1023 InetAddress mask = null;
1025 if (parts.length > 1) {
1026 maskLen = Integer.parseInt(parts[1]);
1028 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1030 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1031 match.setField(MatchType.NW_SRC, ip, mask);
1033 if (this.nwDst != null) {
1034 String parts[] = this.nwDst.split("/");
1035 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1036 InetAddress mask = null;
1038 if (parts.length > 1) {
1039 maskLen = Integer.parseInt(parts[1]);
1041 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1043 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1044 match.setField(MatchType.NW_DST, ip, mask);
1046 if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
1047 match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
1049 if (this.tosBits != null) {
1050 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1052 if (this.tpSrc != null) {
1053 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
1055 if (this.tpDst != null) {
1056 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1059 Flow flow = new Flow(match, getActionList());
1060 if (this.cookie != null) {
1061 flow.setId(Long.parseLong(cookie));
1063 if (this.hardTimeout != null) {
1064 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1066 if (this.idleTimeout != null) {
1067 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1069 if (this.priority != null) {
1070 flow.setPriority(Integer.decode(this.priority).shortValue());
1075 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1076 return (this.name.equals(that.name) && this.node.equals(that.node));
1079 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1080 return (this.name.equals(name) && this.node.equals(node));
1083 public boolean onNode(Node node) {
1084 return this.node.equals(node);
1087 public void toggleInstallation() {
1088 installInHw = (installInHw == null) ? Boolean.toString(false) : Boolean.toString(!Boolean.valueOf(installInHw));
1092 * Parses the actions string and return the List of SAL Action No syntax
1093 * check run, as this function will be called when the config validation
1094 * check has already been performed
1096 private List<Action> getActionList() {
1097 List<Action> actionList = new ArrayList<Action>();
1099 if (actions != null) {
1101 for (String actiongrp : actions) {
1102 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1103 if (sstr.matches()) {
1104 for (String t : sstr.group(1).split(",")) {
1105 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1107 if (n.group(1) != null) {
1108 String nc = String.format("%s|%s@%s", node.getType(), n.group(1), node.toString());
1109 actionList.add(new Output(NodeConnector.fromString(nc)));
1116 sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
1117 if (sstr.matches()) {
1118 for (String t : sstr.group(1).split(",")) {
1119 Matcher n = Pattern.compile("(?:(\\d+:\\d+))").matcher(t);
1121 if (n.group(1) != null) {
1122 String parts[] = n.group(1).split(":");
1123 String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
1124 if (parts.length == 1) {
1125 actionList.add(new Enqueue(NodeConnector.fromString(nc)));
1128 .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
1136 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1137 if (sstr.matches()) {
1138 actionList.add(new Drop());
1142 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1143 if (sstr.matches()) {
1144 actionList.add(new Loopback());
1148 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1149 if (sstr.matches()) {
1150 actionList.add(new Flood());
1154 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1155 if (sstr.matches()) {
1156 actionList.add(new SwPath());
1160 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1161 if (sstr.matches()) {
1162 actionList.add(new HwPath());
1166 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1167 if (sstr.matches()) {
1168 actionList.add(new Controller());
1172 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1173 if (sstr.matches()) {
1174 actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1178 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1179 if (sstr.matches()) {
1180 actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1184 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1185 if (sstr.matches()) {
1186 actionList.add(new PopVlan());
1190 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1191 if (sstr.matches()) {
1192 actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1196 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1197 if (sstr.matches()) {
1198 actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1201 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1202 if (sstr.matches()) {
1203 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1206 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1207 if (sstr.matches()) {
1208 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1212 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1213 if (sstr.matches()) {
1214 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1218 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1219 if (sstr.matches()) {
1220 actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1224 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1225 if (sstr.matches()) {
1226 actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1230 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1231 if (sstr.matches()) {
1232 actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));