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 org.opendaylight.controller.configuration.ConfigurationObject;
12 import org.opendaylight.controller.sal.action.Action;
13 import org.opendaylight.controller.sal.action.ActionType;
14 import org.opendaylight.controller.sal.action.Controller;
15 import org.opendaylight.controller.sal.action.Drop;
16 import org.opendaylight.controller.sal.action.Enqueue;
17 import org.opendaylight.controller.sal.action.Flood;
18 import org.opendaylight.controller.sal.action.HwPath;
19 import org.opendaylight.controller.sal.action.Loopback;
20 import org.opendaylight.controller.sal.action.Output;
21 import org.opendaylight.controller.sal.action.PopVlan;
22 import org.opendaylight.controller.sal.action.SetDlDst;
23 import org.opendaylight.controller.sal.action.SetDlSrc;
24 import org.opendaylight.controller.sal.action.SetNextHop;
25 import org.opendaylight.controller.sal.action.SetNwDst;
26 import org.opendaylight.controller.sal.action.SetNwSrc;
27 import org.opendaylight.controller.sal.action.SetNwTos;
28 import org.opendaylight.controller.sal.action.SetTpDst;
29 import org.opendaylight.controller.sal.action.SetTpSrc;
30 import org.opendaylight.controller.sal.action.SetVlanId;
31 import org.opendaylight.controller.sal.action.SetVlanPcp;
32 import org.opendaylight.controller.sal.action.SwPath;
33 import org.opendaylight.controller.sal.core.ContainerFlow;
34 import org.opendaylight.controller.sal.core.IContainer;
35 import org.opendaylight.controller.sal.core.Node;
36 import org.opendaylight.controller.sal.core.NodeConnector;
37 import org.opendaylight.controller.sal.flowprogrammer.Flow;
38 import org.opendaylight.controller.sal.match.Match;
39 import org.opendaylight.controller.sal.match.MatchType;
40 import org.opendaylight.controller.sal.utils.GlobalConstants;
41 import org.opendaylight.controller.sal.utils.HexEncode;
42 import org.opendaylight.controller.sal.utils.IPProtocols;
43 import org.opendaylight.controller.sal.utils.NetUtils;
44 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
45 import org.opendaylight.controller.sal.utils.ServiceHelper;
46 import org.opendaylight.controller.sal.utils.Status;
47 import org.opendaylight.controller.sal.utils.StatusCode;
48 import org.opendaylight.controller.switchmanager.ISwitchManager;
49 import org.opendaylight.controller.switchmanager.Switch;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 import javax.xml.bind.annotation.XmlAccessType;
54 import javax.xml.bind.annotation.XmlAccessorType;
55 import javax.xml.bind.annotation.XmlElement;
56 import javax.xml.bind.annotation.XmlRootElement;
57 import java.io.Serializable;
58 import java.net.Inet6Address;
59 import java.net.InetAddress;
60 import java.util.ArrayList;
61 import java.util.List;
62 import java.util.regex.Matcher;
63 import java.util.regex.Pattern;
66 * Configuration Java Object which represents a flow configuration information
67 * for Forwarding Rules Manager.
70 @XmlAccessorType(XmlAccessType.NONE)
71 public class FlowConfig extends ConfigurationObject implements Serializable {
72 private static final long serialVersionUID = 1L;
73 private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
74 public static final String STATICFLOWGROUP = "__StaticFlows__";
75 public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
76 public static final String INTERNALSTATICFLOWBEGIN = "__";
77 public static final String INTERNALSTATICFLOWEND = "__";
78 private boolean dynamic;
79 private String status;
82 * The order of the object data defined below is used directly in the UI
83 * built using JSP. Hence try to keep the order in a more logical way.
86 private String installInHw;
92 private String ingressPort;
93 private String portGroup;
95 private String priority;
97 private String etherType;
99 private String vlanId;
101 private String vlanPriority;
103 private String dlSrc;
105 private String dlDst;
107 private String nwSrc;
109 private String nwDst;
111 private String protocol;
113 private String tosBits;
115 private String tpSrc;
117 private String tpDst;
119 private String cookie;
121 private String idleTimeout;
123 private String hardTimeout;
125 private List<String> actions;
127 private enum EtherIPType {
131 public FlowConfig() {
134 public FlowConfig(String installInHw, String name, Node node, String priority, String cookie, String ingressPort,
135 String portGroup, String vlanId, String vlanPriority, String etherType, String srcMac, String dstMac,
136 String protocol, String tosBits, String srcIP, String dstIP, String tpSrc, String tpDst,
137 String idleTimeout, String hardTimeout, List<String> actions) {
139 this.installInHw = installInHw;
142 this.priority = priority;
143 this.cookie = cookie;
144 this.ingressPort = ingressPort;
145 this.portGroup = portGroup;
146 this.vlanId = vlanId;
147 this.vlanPriority = vlanPriority;
148 this.etherType = etherType;
151 this.protocol = protocol;
152 this.tosBits = tosBits;
157 this.idleTimeout = idleTimeout;
158 this.hardTimeout = hardTimeout;
159 this.actions = actions;
160 this.status = StatusCode.SUCCESS.toString();
163 public FlowConfig(FlowConfig from) {
164 this.installInHw = from.installInHw;
165 this.name = from.name;
166 this.node = from.node;
167 this.priority = from.priority;
168 this.cookie = from.cookie;
169 this.ingressPort = from.ingressPort;
170 this.portGroup = from.portGroup;
171 this.vlanId = from.vlanId;
172 this.vlanPriority = from.vlanPriority;
173 this.etherType = from.etherType;
174 this.dlSrc = from.dlSrc;
175 this.dlDst = from.dlDst;
176 this.protocol = from.protocol;
177 this.tosBits = from.tosBits;
178 this.nwSrc = from.nwSrc;
179 this.nwDst = from.nwDst;
180 this.tpSrc = from.tpSrc;
181 this.tpDst = from.tpDst;
182 this.idleTimeout = from.idleTimeout;
183 this.hardTimeout = from.hardTimeout;
184 this.actions = new ArrayList<String>(from.actions);
187 public boolean installInHw() {
188 if (installInHw == null) {
189 // backward compatibility
190 installInHw = Boolean.toString(true);
192 return Boolean.valueOf(installInHw);
195 public void setInstallInHw(boolean inHw) {
196 installInHw = String.valueOf(inHw);
199 public String getInstallInHw() {
203 public boolean isInternalFlow() {
204 return (this.name != null &&
205 this.name.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN) &&
206 this.name.endsWith(FlowConfig.INTERNALSTATICFLOWEND));
209 public String getName() {
213 public void setName(String name) {
220 public Node getNode() {
224 public void setNode(Node node) {
228 public String getPriority() {
232 public void setPriority(String priority) {
233 this.priority = priority;
236 public String getCookie() {
240 public void setCookie(String cookie) {
241 this.cookie = cookie;
244 public String getIngressPort() {
248 public void setIngressPort(String ingressPort) {
249 this.ingressPort = ingressPort;
252 public String getPortGroup() {
257 public String toString() {
258 return "FlowConfig [dynamic=" + dynamic + ", status=" + status + ", installInHw=" + installInHw + ", name="
259 + name + ", switchId=" + node + ", ingressPort=" + ingressPort + ", portGroup=" + portGroup
260 + ", etherType=" + etherType + ", priority=" + priority + ", vlanId=" + vlanId + ", vlanPriority="
261 + vlanPriority + ", dlSrc=" + dlSrc + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
262 + ", protocol=" + protocol + ", tosBits=" + tosBits + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst
263 + ", cookie=" + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" + hardTimeout + ", actions="
267 public void setPortGroup(String portGroup) {
268 this.portGroup = portGroup;
271 public String getVlanId() {
275 public void setVlanId(String vlanId) {
276 this.vlanId = vlanId;
279 public String getVlanPriority() {
283 public void setVlanPriority(String vlanPriority) {
284 this.vlanPriority = vlanPriority;
287 public String getEtherType() {
291 public void setEtherType(String etherType) {
292 this.etherType = etherType;
295 public String getSrcMac() {
299 public void setSrcMac(String srcMac) {
303 public String getDstMac() {
307 public void setDstMac(String dstMac) {
311 public String getProtocol() {
315 public void setProtocol(String protocol) {
316 this.protocol = protocol;
319 public String getTosBits() {
323 public void setTosBits(String tos_bits) {
324 this.tosBits = tos_bits;
327 public String getSrcIp() {
331 public void setSrcIp(String src_ip) {
335 public String getDstIp() {
339 public void setDstIp(String dst_ip) {
343 public String getSrcPort() {
347 public void setSrcPort(String src_port) {
348 this.tpSrc = src_port;
351 public String getDstPort() {
355 public void setDstPort(String dst_port) {
356 this.tpDst = dst_port;
359 public String getIdleTimeout() {
363 public void setIdleTimeout(String idleTimeout) {
364 this.idleTimeout = idleTimeout;
367 public String getHardTimeout() {
371 public void setHardTimeout(String hardTimeout) {
372 this.hardTimeout = hardTimeout;
375 public boolean isIPv6() {
376 return NetUtils.isIPv6AddressValid(this.getSrcIp()) || NetUtils.isIPv6AddressValid(this.getDstIp());
379 public List<String> getActions() {
383 public void setActions(List<String> actions) {
384 this.actions = actions;
387 public boolean isPortGroupEnabled() {
388 return (portGroup != null);
391 public boolean isDynamic() {
395 public void setDynamic(boolean dynamic) {
396 this.dynamic = dynamic;
399 public String getStatus() {
403 public void setStatus(String status) {
404 this.status = status;
407 public boolean isStatusSuccessful() {
408 return status.equals(StatusCode.SUCCESS.toString());
412 public int hashCode() {
413 final int prime = 31;
415 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
416 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
417 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
418 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
419 result = prime * result + (dynamic ? 1231 : 1237);
420 result = prime * result + ((etherType == null) ? 0 : etherType.hashCode());
421 result = prime * result + ((ingressPort == null) ? 0 : ingressPort.hashCode());
422 result = prime * result + ((name == null) ? 0 : name.hashCode());
423 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
424 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
425 result = prime * result + ((portGroup == null) ? 0 : portGroup.hashCode());
426 result = prime * result + ((priority == null) ? 0 : priority.hashCode());
427 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
428 result = prime * result + ((node == null) ? 0 : node.hashCode());
429 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
430 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
431 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
432 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
433 result = prime * result + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
434 result = prime * result + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
435 result = prime * result + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
440 public boolean equals(Object obj) {
447 if (getClass() != obj.getClass()) {
450 FlowConfig other = (FlowConfig) obj;
451 if (actions == null) {
452 if (other.actions != null) {
455 } else if (!actions.equals(other.actions)) {
458 if (cookie == null) {
459 if (other.cookie != null) {
462 } else if (!cookie.equals(other.cookie)) {
466 if (other.dlDst != null) {
469 } else if (!dlDst.equals(other.dlDst)) {
473 if (other.dlSrc != null) {
476 } else if (!dlSrc.equals(other.dlSrc)) {
479 if (dynamic != other.dynamic) {
482 if (etherType == null) {
483 if (other.etherType != null) {
486 } else if (!etherType.equals(other.etherType)) {
489 if (ingressPort == null) {
490 if (other.ingressPort != null) {
493 } else if (!ingressPort.equals(other.ingressPort)) {
497 if (other.name != null) {
500 } else if (!name.equals(other.name)) {
504 if (other.nwDst != null) {
507 } else if (!nwDst.equals(other.nwDst)) {
511 if (other.nwSrc != null) {
514 } else if (!nwSrc.equals(other.nwSrc)) {
517 if (portGroup == null) {
518 if (other.portGroup != null) {
521 } else if (!portGroup.equals(other.portGroup)) {
524 if (priority == null) {
525 if (other.priority != null) {
528 } else if (!priority.equals(other.priority)) {
531 if (protocol == null) {
532 if (other.protocol != null) {
535 } else if (!protocol.equals(other.protocol)) {
539 if (other.node != null) {
542 } else if (!node.equals(other.node)) {
545 if (tosBits == null) {
546 if (other.tosBits != null) {
549 } else if (!tosBits.equals(other.tosBits)) {
553 if (other.tpDst != null) {
556 } else if (!tpDst.equals(other.tpDst)) {
560 if (other.tpSrc != null) {
563 } else if (!tpSrc.equals(other.tpSrc)) {
566 if (vlanId == null) {
567 if (other.vlanId != null) {
570 } else if (!vlanId.equals(other.vlanId)) {
573 if (vlanPriority == null) {
574 if (other.vlanPriority != null) {
577 } else if (!vlanPriority.equals(other.vlanPriority)) {
580 if (idleTimeout == null) {
581 if (other.idleTimeout != null) {
584 } else if (!idleTimeout.equals(other.idleTimeout)) {
587 if (hardTimeout == null) {
588 if (other.hardTimeout != null) {
591 } else if (!hardTimeout.equals(other.hardTimeout)) {
597 public boolean isL2AddressValid(String mac) {
602 Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
603 Matcher mm = macPattern.matcher(mac);
605 log.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
611 public boolean isPortValid(Switch sw, String port) {
613 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
616 NodeConnector nc = NodeConnectorCreator.createNodeConnector(port, sw.getNode());
617 return sw.getNodeConnectors().contains(nc);
620 public boolean isVlanIdValid(String vlanId) {
621 int vlan = Integer.decode(vlanId);
622 return ((vlan >= 0) && (vlan < 4096));
625 public boolean isVlanPriorityValid(String vlanPriority) {
626 int pri = Integer.decode(vlanPriority);
627 return ((pri >= 0) && (pri < 8));
630 public boolean isTOSBitsValid(String tosBits) {
631 int tos = Integer.decode(tosBits);
632 return ((tos >= 0) && (tos < 64));
635 public boolean isTpPortValid(String tpPort) {
636 int port = Integer.decode(tpPort);
637 return ((port >= 0) && (port <= 0xffff));
640 public boolean isTimeoutValid(String timeout) {
641 int to = Integer.decode(timeout);
642 return ((to >= 0) && (to <= 0xffff));
645 public boolean isProtocolValid(String protocol) {
646 IPProtocols proto = IPProtocols.fromString(protocol);
647 return (proto != null);
650 private Status conflictWithContainerFlow(IContainer container) {
651 // Return true if it's default container
652 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
653 return new Status(StatusCode.SUCCESS);
656 // No container flow = no conflict
657 List<ContainerFlow> cFlowList = container.getContainerFlows();
658 if (((cFlowList == null)) || cFlowList.isEmpty()) {
659 return new Status(StatusCode.SUCCESS);
662 // Check against each container's flow
663 Flow flow = this.getFlow();
665 // Configuration is rejected if it conflicts with _all_ the container
667 for (ContainerFlow cFlow : cFlowList) {
668 if (cFlow.allowsFlow(flow)) {
669 log.trace("Config is congruent with at least one container flow");
670 return new Status(StatusCode.SUCCESS);
673 String msg = "Flow Config conflicts with all existing container flows";
676 return new Status(StatusCode.BADREQUEST, msg);
679 public Status validate(IContainer container) {
680 EtherIPType etype = EtherIPType.ANY;
681 EtherIPType ipsrctype = EtherIPType.ANY;
682 EtherIPType ipdsttype = EtherIPType.ANY;
684 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
685 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
690 // Flow name cannot be internal flow signature
691 if (!isValidResourceName(name) || isInternalFlow()) {
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(",")) {
840 if (!isPortValid(sw, t)) {
841 String msg = String.format("Output port %s is not valid for this switch", t);
842 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
843 msg += " in Container " + containerName;
845 return new Status(StatusCode.BADREQUEST, msg);
852 sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
853 if (sstr.matches()) {
854 for (String t : sstr.group(1).split(",")) {
856 String port = t.split(":")[0];
857 if (!isPortValid(sw, port)) {
858 String msg = String.format("Output port %d is not valid for this switch", port);
859 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
860 msg += " in Container " + containerName;
862 return new Status(StatusCode.BADREQUEST, msg);
869 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
870 if (sstr.matches()) {
871 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
872 return new Status(StatusCode.BADREQUEST, String.format(
873 "flood is not allowed in container %s", containerName));
878 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
879 if (sstr.matches()) {
880 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
881 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
887 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
888 if (sstr.matches()) {
889 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
890 return new Status(StatusCode.BADREQUEST, String.format(
891 "IP destination address %s is not valid", sstr.group(1)));
896 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
897 if (sstr.matches()) {
898 if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
899 return new Status(StatusCode.BADREQUEST, String.format(
900 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
905 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
906 if (sstr.matches()) {
907 if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
908 return new Status(StatusCode.BADREQUEST, String.format(
909 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
914 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
915 if (sstr.matches()) {
916 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
917 return new Status(StatusCode.BADREQUEST, String.format(
918 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
923 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
924 if (sstr.matches()) {
925 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
926 return new Status(StatusCode.BADREQUEST, String.format(
927 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
933 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
934 if (sstr.matches()) {
935 if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
936 return new Status(StatusCode.BADREQUEST, String.format(
937 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
942 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
943 if (sstr.matches()) {
944 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
945 return new Status(StatusCode.BADREQUEST, String.format(
946 "Transport source port %s is not valid", sstr.group(1)));
951 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
952 if (sstr.matches()) {
953 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
954 return new Status(StatusCode.BADREQUEST, String.format(
955 "Transport destination port %s is not valid", sstr.group(1)));
959 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
960 if (sstr.matches()) {
961 if (!NetUtils.isIPAddressValid(sstr.group(1))) {
962 return new Status(StatusCode.BADREQUEST, String.format(
963 "IP destination address %s is not valid", sstr.group(1)));
968 // Check against the container flow
970 if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
973 } catch (NumberFormatException e) {
974 return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
977 return new Status(StatusCode.SUCCESS);
980 public FlowEntry getFlowEntry() {
981 String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
982 return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
985 public Flow getFlow() {
986 Match match = new Match();
988 if (this.ingressPort != null) {
989 match.setField(MatchType.IN_PORT,
990 NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
992 if (this.dlSrc != null) {
993 match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
995 if (this.dlDst != null) {
996 match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
998 if (this.etherType != null) {
999 match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
1001 if (this.vlanId != null) {
1002 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1004 if (this.vlanPriority != null) {
1005 match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
1007 if (this.nwSrc != null) {
1008 String parts[] = this.nwSrc.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_SRC, ip, mask);
1020 if (this.nwDst != null) {
1021 String parts[] = this.nwDst.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_DST, ip, mask);
1033 if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
1034 match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
1036 if (this.tosBits != null) {
1037 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1039 if (this.tpSrc != null) {
1040 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
1042 if (this.tpDst != null) {
1043 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1046 Flow flow = new Flow(match, getActionList());
1048 if (this.cookie != null) {
1049 flow.setId(Long.parseLong(cookie));
1051 if (this.hardTimeout != null) {
1052 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1054 if (this.idleTimeout != null) {
1055 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1057 if (this.priority != null) {
1058 flow.setPriority(Integer.decode(this.priority).shortValue());
1065 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1066 return (this.name.equals(that.name) && this.node.equals(that.node));
1069 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1070 return (this.name.equals(name) && this.node.equals(node));
1073 public boolean onNode(Node node) {
1074 return this.node.equals(node);
1077 public void toggleInstallation() {
1078 installInHw = (installInHw == null) ? Boolean.toString(false) : Boolean.toString(!Boolean.valueOf(installInHw));
1082 * Parses the actions string and return the List of SAL Action No syntax
1083 * check run, as this function will be called when the config validation
1084 * check has already been performed
1086 private List<Action> getActionList() {
1087 List<Action> actionList = new ArrayList<Action>();
1089 if (actions != null) {
1091 for (String actiongrp : actions) {
1092 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1093 if (sstr.matches()) {
1094 for (String t : sstr.group(1).split(",")) {
1096 String nc = String.format("%s|%s@%s", node.getType(), t, node.toString());
1097 actionList.add(new Output(NodeConnector.fromString(nc)));
1103 sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
1104 if (sstr.matches()) {
1105 for (String t : sstr.group(1).split(",")) {
1107 String parts[] = t.split(":");
1108 String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
1109 if (parts.length == 1) {
1110 actionList.add(new Enqueue(NodeConnector.fromString(nc)));
1113 .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
1120 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1121 if (sstr.matches()) {
1122 actionList.add(new Drop());
1126 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1127 if (sstr.matches()) {
1128 actionList.add(new Loopback());
1132 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1133 if (sstr.matches()) {
1134 actionList.add(new Flood());
1138 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1139 if (sstr.matches()) {
1140 actionList.add(new SwPath());
1144 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1145 if (sstr.matches()) {
1146 actionList.add(new HwPath());
1150 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1151 if (sstr.matches()) {
1152 actionList.add(new Controller());
1156 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1157 if (sstr.matches()) {
1158 actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1162 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1163 if (sstr.matches()) {
1164 actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1168 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1169 if (sstr.matches()) {
1170 actionList.add(new PopVlan());
1174 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1175 if (sstr.matches()) {
1176 actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1180 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1181 if (sstr.matches()) {
1182 actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1185 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1186 if (sstr.matches()) {
1187 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1190 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1191 if (sstr.matches()) {
1192 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1196 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1197 if (sstr.matches()) {
1198 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1202 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1203 if (sstr.matches()) {
1204 actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1208 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1209 if (sstr.matches()) {
1210 actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1214 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1215 if (sstr.matches()) {
1216 actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));