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.sal.action.Action;
12 import org.opendaylight.controller.sal.action.ActionType;
13 import org.opendaylight.controller.sal.action.Controller;
14 import org.opendaylight.controller.sal.action.Drop;
15 import org.opendaylight.controller.sal.action.Enqueue;
16 import org.opendaylight.controller.sal.action.Flood;
17 import org.opendaylight.controller.sal.action.HwPath;
18 import org.opendaylight.controller.sal.action.Loopback;
19 import org.opendaylight.controller.sal.action.Output;
20 import org.opendaylight.controller.sal.action.PopVlan;
21 import org.opendaylight.controller.sal.action.SetDlDst;
22 import org.opendaylight.controller.sal.action.SetDlSrc;
23 import org.opendaylight.controller.sal.action.SetNextHop;
24 import org.opendaylight.controller.sal.action.SetNwDst;
25 import org.opendaylight.controller.sal.action.SetNwSrc;
26 import org.opendaylight.controller.sal.action.SetNwTos;
27 import org.opendaylight.controller.sal.action.SetTpDst;
28 import org.opendaylight.controller.sal.action.SetTpSrc;
29 import org.opendaylight.controller.sal.action.SetVlanId;
30 import org.opendaylight.controller.sal.action.SetVlanPcp;
31 import org.opendaylight.controller.sal.action.SwPath;
32 import org.opendaylight.controller.sal.core.ContainerFlow;
33 import org.opendaylight.controller.sal.core.IContainer;
34 import org.opendaylight.controller.sal.core.Node;
35 import org.opendaylight.controller.sal.core.NodeConnector;
36 import org.opendaylight.controller.sal.flowprogrammer.Flow;
37 import org.opendaylight.controller.sal.match.Match;
38 import org.opendaylight.controller.sal.match.MatchType;
39 import org.opendaylight.controller.sal.utils.GlobalConstants;
40 import org.opendaylight.controller.sal.utils.HexEncode;
41 import org.opendaylight.controller.sal.utils.IPProtocols;
42 import org.opendaylight.controller.sal.utils.NetUtils;
43 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
44 import org.opendaylight.controller.sal.utils.ServiceHelper;
45 import org.opendaylight.controller.sal.utils.Status;
46 import org.opendaylight.controller.sal.utils.StatusCode;
47 import org.opendaylight.controller.switchmanager.ISwitchManager;
48 import org.opendaylight.controller.switchmanager.Switch;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 import javax.xml.bind.annotation.XmlAccessType;
53 import javax.xml.bind.annotation.XmlAccessorType;
54 import javax.xml.bind.annotation.XmlElement;
55 import javax.xml.bind.annotation.XmlRootElement;
56 import java.io.Serializable;
57 import java.net.Inet6Address;
58 import java.net.InetAddress;
59 import java.util.ArrayList;
60 import java.util.List;
61 import java.util.regex.Matcher;
62 import java.util.regex.Pattern;
65 * Configuration Java Object which represents a flow configuration information
66 * for Forwarding Rules Manager.
69 @XmlAccessorType(XmlAccessType.NONE)
70 public class FlowConfig implements Serializable {
71 private static final long serialVersionUID = 1L;
72 private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
73 private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
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 if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
691 return new Status(StatusCode.BADREQUEST, "Invalid name");
695 return new Status(StatusCode.BADREQUEST, "Node is null");
698 if (switchManager != null) {
699 for (Switch device : switchManager.getNetworkDevices()) {
700 if (device.getNode().equals(node)) {
706 return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
709 log.debug("switchmanager is not set yet");
712 if (priority != null) {
713 if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
714 return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
719 // make sure it's a valid number
720 if (cookie != null) {
724 if (ingressPort != null) {
725 if (!isPortValid(sw, ingressPort)) {
726 String msg = String.format("Ingress port %s is not valid for the Switch", ingressPort);
727 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
728 msg += " in Container " + containerName;
730 return new Status(StatusCode.BADREQUEST, msg);
734 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
735 return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095",
739 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
740 return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7",
743 if (etherType != null) {
744 int type = Integer.decode(etherType);
745 if ((type < 0) || (type > 0xffff)) {
746 return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType));
749 etype = EtherIPType.V4;
750 } else if (type == 0x86dd) {
751 etype = EtherIPType.V6;
756 if ((protocol != null) && !isProtocolValid(protocol)) {
757 return new Status(StatusCode.BADREQUEST, String.format("Protocol %s is not valid", protocol));
760 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
761 return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
765 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
766 return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc));
769 if ((tpDst != null) && !isTpPortValid(tpDst)) {
770 return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid",
774 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
775 return new Status(StatusCode.BADREQUEST, String.format(
776 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc));
779 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
780 return new Status(StatusCode.BADREQUEST, String.format(
781 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst));
785 if (NetUtils.isIPv4AddressValid(nwSrc)) {
786 ipsrctype = EtherIPType.V4;
787 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
788 ipsrctype = EtherIPType.V6;
790 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc));
795 if (NetUtils.isIPv4AddressValid(nwDst)) {
796 ipdsttype = EtherIPType.V4;
797 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
798 ipdsttype = EtherIPType.V6;
800 return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid",
805 if (etype != EtherIPType.ANY) {
806 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
807 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP"));
809 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
810 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP"));
813 if (ipsrctype != ipdsttype) {
814 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
815 return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch"));
819 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
820 return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid",
824 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
825 return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid",
830 if (actions == null || actions.isEmpty()) {
831 return new Status(StatusCode.BADREQUEST, "Actions value is null or empty");
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(",")) {
839 if (!isPortValid(sw, t)) {
840 String msg = String.format("Output port %s is not valid for this switch", t);
841 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
842 msg += " in Container " + containerName;
844 return new Status(StatusCode.BADREQUEST, msg);
851 sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
852 if (sstr.matches()) {
853 for (String t : sstr.group(1).split(",")) {
855 String port = t.split(":")[0];
856 if (!isPortValid(sw, port)) {
857 String msg = String.format("Output port %d is not valid for this switch", port);
858 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
859 msg += " in Container " + containerName;
861 return new Status(StatusCode.BADREQUEST, msg);
868 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
869 if (sstr.matches()) {
870 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
871 return new Status(StatusCode.BADREQUEST, String.format(
872 "flood is not allowed in container %s", containerName));
877 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
878 if (sstr.matches()) {
879 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
880 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
886 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
887 if (sstr.matches()) {
888 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
889 return new Status(StatusCode.BADREQUEST, String.format(
890 "IP destination address %s is not valid", sstr.group(1)));
895 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
896 if (sstr.matches()) {
897 if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
898 return new Status(StatusCode.BADREQUEST, String.format(
899 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
904 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
905 if (sstr.matches()) {
906 if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
907 return new Status(StatusCode.BADREQUEST, String.format(
908 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
913 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
914 if (sstr.matches()) {
915 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
916 return new Status(StatusCode.BADREQUEST, String.format(
917 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
922 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
923 if (sstr.matches()) {
924 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
925 return new Status(StatusCode.BADREQUEST, String.format(
926 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
932 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
933 if (sstr.matches()) {
934 if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
935 return new Status(StatusCode.BADREQUEST, String.format(
936 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
941 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
942 if (sstr.matches()) {
943 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
944 return new Status(StatusCode.BADREQUEST, String.format(
945 "Transport source port %s is not valid", sstr.group(1)));
950 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
951 if (sstr.matches()) {
952 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
953 return new Status(StatusCode.BADREQUEST, String.format(
954 "Transport destination port %s is not valid", sstr.group(1)));
958 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
959 if (sstr.matches()) {
960 if (!NetUtils.isIPAddressValid(sstr.group(1))) {
961 return new Status(StatusCode.BADREQUEST, String.format(
962 "IP destination address %s is not valid", sstr.group(1)));
967 // Check against the container flow
969 if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
972 } catch (NumberFormatException e) {
973 return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
976 return new Status(StatusCode.SUCCESS);
979 public FlowEntry getFlowEntry() {
980 String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
981 return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
984 public Flow getFlow() {
985 Match match = new Match();
987 if (this.ingressPort != null) {
988 match.setField(MatchType.IN_PORT,
989 NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
991 if (this.dlSrc != null) {
992 match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
994 if (this.dlDst != null) {
995 match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
997 if (this.etherType != null) {
998 match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
1000 if (this.vlanId != null) {
1001 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1003 if (this.vlanPriority != null) {
1004 match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
1006 if (this.nwSrc != null) {
1007 String parts[] = this.nwSrc.split("/");
1008 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1009 InetAddress mask = null;
1011 if (parts.length > 1) {
1012 maskLen = Integer.parseInt(parts[1]);
1014 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1016 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1017 match.setField(MatchType.NW_SRC, ip, mask);
1019 if (this.nwDst != null) {
1020 String parts[] = this.nwDst.split("/");
1021 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1022 InetAddress mask = null;
1024 if (parts.length > 1) {
1025 maskLen = Integer.parseInt(parts[1]);
1027 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1029 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1030 match.setField(MatchType.NW_DST, ip, mask);
1032 if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
1033 match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
1035 if (this.tosBits != null) {
1036 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1038 if (this.tpSrc != null) {
1039 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
1041 if (this.tpDst != null) {
1042 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1045 Flow flow = new Flow(match, getActionList());
1047 if (this.cookie != null) {
1048 flow.setId(Long.parseLong(cookie));
1050 if (this.hardTimeout != null) {
1051 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1053 if (this.idleTimeout != null) {
1054 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1056 if (this.priority != null) {
1057 flow.setPriority(Integer.decode(this.priority).shortValue());
1064 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1065 return (this.name.equals(that.name) && this.node.equals(that.node));
1068 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1069 return (this.name.equals(name) && this.node.equals(node));
1072 public boolean onNode(Node node) {
1073 return this.node.equals(node);
1076 public void toggleInstallation() {
1077 installInHw = (installInHw == null) ? Boolean.toString(false) : Boolean.toString(!Boolean.valueOf(installInHw));
1081 * Parses the actions string and return the List of SAL Action No syntax
1082 * check run, as this function will be called when the config validation
1083 * check has already been performed
1085 private List<Action> getActionList() {
1086 List<Action> actionList = new ArrayList<Action>();
1088 if (actions != null) {
1090 for (String actiongrp : actions) {
1091 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1092 if (sstr.matches()) {
1093 for (String t : sstr.group(1).split(",")) {
1095 String nc = String.format("%s|%s@%s", node.getType(), t, node.toString());
1096 actionList.add(new Output(NodeConnector.fromString(nc)));
1102 sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
1103 if (sstr.matches()) {
1104 for (String t : sstr.group(1).split(",")) {
1106 String parts[] = t.split(":");
1107 String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
1108 if (parts.length == 1) {
1109 actionList.add(new Enqueue(NodeConnector.fromString(nc)));
1112 .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
1119 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1120 if (sstr.matches()) {
1121 actionList.add(new Drop());
1125 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1126 if (sstr.matches()) {
1127 actionList.add(new Loopback());
1131 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1132 if (sstr.matches()) {
1133 actionList.add(new Flood());
1137 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1138 if (sstr.matches()) {
1139 actionList.add(new SwPath());
1143 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1144 if (sstr.matches()) {
1145 actionList.add(new HwPath());
1149 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1150 if (sstr.matches()) {
1151 actionList.add(new Controller());
1155 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1156 if (sstr.matches()) {
1157 actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1161 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1162 if (sstr.matches()) {
1163 actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1167 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1168 if (sstr.matches()) {
1169 actionList.add(new PopVlan());
1173 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1174 if (sstr.matches()) {
1175 actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1179 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1180 if (sstr.matches()) {
1181 actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1184 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1185 if (sstr.matches()) {
1186 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1189 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1190 if (sstr.matches()) {
1191 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1195 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1196 if (sstr.matches()) {
1197 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1201 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1202 if (sstr.matches()) {
1203 actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1207 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1208 if (sstr.matches()) {
1209 actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1213 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1214 if (sstr.matches()) {
1215 actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));