2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.forwardingrulesmanager;
11 import java.io.Serializable;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import javax.xml.bind.annotation.XmlAccessType;
21 import javax.xml.bind.annotation.XmlAccessorType;
22 import javax.xml.bind.annotation.XmlElement;
23 import javax.xml.bind.annotation.XmlRootElement;
25 import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
26 import org.opendaylight.controller.sal.action.Action;
27 import org.opendaylight.controller.sal.action.ActionType;
28 import org.opendaylight.controller.sal.action.Controller;
29 import org.opendaylight.controller.sal.action.Drop;
30 import org.opendaylight.controller.sal.action.Flood;
31 import org.opendaylight.controller.sal.action.HwPath;
32 import org.opendaylight.controller.sal.action.Loopback;
33 import org.opendaylight.controller.sal.action.Output;
34 import org.opendaylight.controller.sal.action.PopVlan;
35 import org.opendaylight.controller.sal.action.SetDlDst;
36 import org.opendaylight.controller.sal.action.SetDlSrc;
37 import org.opendaylight.controller.sal.action.SetNextHop;
38 import org.opendaylight.controller.sal.action.SetNwDst;
39 import org.opendaylight.controller.sal.action.SetNwSrc;
40 import org.opendaylight.controller.sal.action.SetNwTos;
41 import org.opendaylight.controller.sal.action.SetTpDst;
42 import org.opendaylight.controller.sal.action.SetTpSrc;
43 import org.opendaylight.controller.sal.action.SetVlanId;
44 import org.opendaylight.controller.sal.action.SetVlanPcp;
45 import org.opendaylight.controller.sal.action.SwPath;
46 import org.opendaylight.controller.sal.core.ContainerFlow;
47 import org.opendaylight.controller.sal.core.IContainer;
48 import org.opendaylight.controller.sal.core.Node;
49 import org.opendaylight.controller.sal.core.NodeConnector;
50 import org.opendaylight.controller.sal.flowprogrammer.Flow;
51 import org.opendaylight.controller.sal.match.Match;
52 import org.opendaylight.controller.sal.match.MatchType;
53 import org.opendaylight.controller.sal.utils.GlobalConstants;
54 import org.opendaylight.controller.sal.utils.HexEncode;
55 import org.opendaylight.controller.sal.utils.IPProtocols;
56 import org.opendaylight.controller.sal.utils.NetUtils;
57 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
58 import org.opendaylight.controller.sal.utils.ServiceHelper;
59 import org.opendaylight.controller.sal.utils.Status;
60 import org.opendaylight.controller.sal.utils.StatusCode;
61 import org.opendaylight.controller.switchmanager.ISwitchManager;
62 import org.opendaylight.controller.switchmanager.Switch;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
67 * Configuration Java Object which represents a flow configuration information
68 * for Forwarding Rules Manager.
71 @XmlAccessorType(XmlAccessType.NONE)
72 public class FlowConfig implements Serializable {
73 private static final long serialVersionUID = 1L;
74 private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
75 private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
76 public static final String STATICFLOWGROUP = "__StaticFlows__";
77 public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
78 public static final String INTERNALSTATICFLOWBEGIN = "__";
79 public static final String INTERNALSTATICFLOWEND = "__";
80 private boolean dynamic;
81 private String status;
84 * The order of the object data defined below is used directly in the UI
85 * built using JSP. Hence try to keep the order in a more logical way.
88 private String installInHw;
94 private String ingressPort;
95 private String portGroup;
97 private String priority;
99 private String etherType;
101 private String vlanId;
103 private String vlanPriority;
105 private String dlSrc;
107 private String dlDst;
109 private String nwSrc;
111 private String nwDst;
113 private String protocol;
115 private String tosBits;
117 private String tpSrc;
119 private String tpDst;
121 private String cookie;
123 private String idleTimeout;
125 private String hardTimeout;
127 private List<String> actions;
129 private enum EtherIPType {
133 public FlowConfig() {
136 public FlowConfig(String installInHw, String name, Node node, String priority, String cookie, String ingressPort,
137 String portGroup, String vlanId, String vlanPriority, String etherType, String srcMac, String dstMac,
138 String protocol, String tosBits, String srcIP, String dstIP, String tpSrc, String tpDst,
139 String idleTimeout, String hardTimeout, List<String> actions) {
141 this.installInHw = installInHw;
144 this.priority = priority;
145 this.cookie = cookie;
146 this.ingressPort = ingressPort;
147 this.portGroup = portGroup;
148 this.vlanId = vlanId;
149 this.vlanPriority = vlanPriority;
150 this.etherType = etherType;
153 this.protocol = protocol;
154 this.tosBits = tosBits;
159 this.idleTimeout = idleTimeout;
160 this.hardTimeout = hardTimeout;
161 this.actions = actions;
162 this.status = StatusCode.SUCCESS.toString();
165 public FlowConfig(FlowConfig from) {
166 this.installInHw = from.installInHw;
167 this.name = from.name;
168 this.node = from.node;
169 this.priority = from.priority;
170 this.cookie = from.cookie;
171 this.ingressPort = from.ingressPort;
172 this.portGroup = from.portGroup;
173 this.vlanId = from.vlanId;
174 this.vlanPriority = from.vlanPriority;
175 this.etherType = from.etherType;
176 this.dlSrc = from.dlSrc;
177 this.dlDst = from.dlDst;
178 this.protocol = from.protocol;
179 this.tosBits = from.tosBits;
180 this.nwSrc = from.nwSrc;
181 this.nwDst = from.nwDst;
182 this.tpSrc = from.tpSrc;
183 this.tpDst = from.tpDst;
184 this.idleTimeout = from.idleTimeout;
185 this.hardTimeout = from.hardTimeout;
186 this.actions = new ArrayList<String>(from.actions);
189 public boolean installInHw() {
190 if (installInHw == null) {
191 // backward compatibility
192 installInHw = Boolean.toString(true);
194 return Boolean.valueOf(installInHw);
197 public void setInstallInHw(boolean inHw) {
198 installInHw = String.valueOf(inHw);
201 public String getInstallInHw() {
205 public boolean isInternalFlow() {
206 return (this.name != null &&
207 this.name.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN) &&
208 this.name.endsWith(FlowConfig.INTERNALSTATICFLOWEND));
211 public String getName() {
215 public void setName(String name) {
222 public Node getNode() {
226 public void setNode(Node node) {
230 public String getPriority() {
234 public void setPriority(String priority) {
235 this.priority = priority;
238 public String getCookie() {
242 public void setCookie(String cookie) {
243 this.cookie = cookie;
246 public String getIngressPort() {
250 public void setIngressPort(String ingressPort) {
251 this.ingressPort = ingressPort;
254 public String getPortGroup() {
259 public String toString() {
260 return "FlowConfig [dynamic=" + dynamic + ", status=" + status + ", installInHw=" + installInHw + ", name="
261 + name + ", switchId=" + node + ", ingressPort=" + ingressPort + ", portGroup=" + portGroup
262 + ", etherType=" + etherType + ", priority=" + priority + ", vlanId=" + vlanId + ", vlanPriority="
263 + vlanPriority + ", dlSrc=" + dlSrc + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
264 + ", protocol=" + protocol + ", tosBits=" + tosBits + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst
265 + ", cookie=" + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" + hardTimeout + ", actions="
269 public void setPortGroup(String portGroup) {
270 this.portGroup = portGroup;
273 public String getVlanId() {
277 public void setVlanId(String vlanId) {
278 this.vlanId = vlanId;
281 public String getVlanPriority() {
285 public void setVlanPriority(String vlanPriority) {
286 this.vlanPriority = vlanPriority;
289 public String getEtherType() {
293 public void setEtherType(String etherType) {
294 this.etherType = etherType;
297 public String getSrcMac() {
301 public void setSrcMac(String srcMac) {
305 public String getDstMac() {
309 public void setDstMac(String dstMac) {
313 public String getProtocol() {
317 public void setProtocol(String protocol) {
318 this.protocol = protocol;
321 public String getTosBits() {
325 public void setTosBits(String tos_bits) {
326 this.tosBits = tos_bits;
329 public String getSrcIp() {
333 public void setSrcIp(String src_ip) {
337 public String getDstIp() {
341 public void setDstIp(String dst_ip) {
345 public String getSrcPort() {
349 public void setSrcPort(String src_port) {
350 this.tpSrc = src_port;
353 public String getDstPort() {
357 public void setDstPort(String dst_port) {
358 this.tpDst = dst_port;
361 public String getIdleTimeout() {
365 public void setIdleTimeout(String idleTimeout) {
366 this.idleTimeout = idleTimeout;
369 public String getHardTimeout() {
373 public void setHardTimeout(String hardTimeout) {
374 this.hardTimeout = hardTimeout;
377 public boolean isIPv6() {
378 return NetUtils.isIPv6AddressValid(this.getSrcIp()) || NetUtils.isIPv6AddressValid(this.getDstIp());
381 public List<String> getActions() {
385 public void setActions(List<String> actions) {
386 this.actions = actions;
389 public boolean isPortGroupEnabled() {
390 return (portGroup != null);
393 public boolean isDynamic() {
397 public void setDynamic(boolean dynamic) {
398 this.dynamic = dynamic;
401 public String getStatus() {
405 public void setStatus(String status) {
406 this.status = status;
409 public boolean isStatusSuccessful() {
410 return status.equals(StatusCode.SUCCESS.toString());
414 public int hashCode() {
415 final int prime = 31;
417 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
418 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
419 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
420 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
421 result = prime * result + (dynamic ? 1231 : 1237);
422 result = prime * result + ((etherType == null) ? 0 : etherType.hashCode());
423 result = prime * result + ((ingressPort == null) ? 0 : ingressPort.hashCode());
424 result = prime * result + ((name == null) ? 0 : name.hashCode());
425 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
426 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
427 result = prime * result + ((portGroup == null) ? 0 : portGroup.hashCode());
428 result = prime * result + ((priority == null) ? 0 : priority.hashCode());
429 result = prime * result + ((protocol == null) ? 0 : protocol.hashCode());
430 result = prime * result + ((node == null) ? 0 : node.hashCode());
431 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
432 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
433 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
434 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
435 result = prime * result + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
436 result = prime * result + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
437 result = prime * result + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
442 public boolean equals(Object obj) {
449 if (getClass() != obj.getClass()) {
452 FlowConfig other = (FlowConfig) obj;
453 if (actions == null) {
454 if (other.actions != null) {
457 } else if (!actions.equals(other.actions)) {
460 if (cookie == null) {
461 if (other.cookie != null) {
464 } else if (!cookie.equals(other.cookie)) {
468 if (other.dlDst != null) {
471 } else if (!dlDst.equals(other.dlDst)) {
475 if (other.dlSrc != null) {
478 } else if (!dlSrc.equals(other.dlSrc)) {
481 if (dynamic != other.dynamic) {
484 if (etherType == null) {
485 if (other.etherType != null) {
488 } else if (!etherType.equals(other.etherType)) {
491 if (ingressPort == null) {
492 if (other.ingressPort != null) {
495 } else if (!ingressPort.equals(other.ingressPort)) {
499 if (other.name != null) {
502 } else if (!name.equals(other.name)) {
506 if (other.nwDst != null) {
509 } else if (!nwDst.equals(other.nwDst)) {
513 if (other.nwSrc != null) {
516 } else if (!nwSrc.equals(other.nwSrc)) {
519 if (portGroup == null) {
520 if (other.portGroup != null) {
523 } else if (!portGroup.equals(other.portGroup)) {
526 if (priority == null) {
527 if (other.priority != null) {
530 } else if (!priority.equals(other.priority)) {
533 if (protocol == null) {
534 if (other.protocol != null) {
537 } else if (!protocol.equals(other.protocol)) {
541 if (other.node != null) {
544 } else if (!node.equals(other.node)) {
547 if (tosBits == null) {
548 if (other.tosBits != null) {
551 } else if (!tosBits.equals(other.tosBits)) {
555 if (other.tpDst != null) {
558 } else if (!tpDst.equals(other.tpDst)) {
562 if (other.tpSrc != null) {
565 } else if (!tpSrc.equals(other.tpSrc)) {
568 if (vlanId == null) {
569 if (other.vlanId != null) {
572 } else if (!vlanId.equals(other.vlanId)) {
575 if (vlanPriority == null) {
576 if (other.vlanPriority != null) {
579 } else if (!vlanPriority.equals(other.vlanPriority)) {
582 if (idleTimeout == null) {
583 if (other.idleTimeout != null) {
586 } else if (!idleTimeout.equals(other.idleTimeout)) {
589 if (hardTimeout == null) {
590 if (other.hardTimeout != null) {
593 } else if (!hardTimeout.equals(other.hardTimeout)) {
599 public boolean isL2AddressValid(String mac) {
604 Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
605 Matcher mm = macPattern.matcher(mac);
607 log.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
613 public boolean isPortValid(Switch sw, Short port) {
615 log.debug("port {} is not valid", port);
620 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
624 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
625 for (NodeConnector nodeConnector : nodeConnectorSet) {
626 if (((Short) nodeConnector.getID()).equals(port)) {
630 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
634 public boolean isVlanIdValid(String vlanId) {
635 int vlan = Integer.decode(vlanId);
636 return ((vlan >= 0) && (vlan < 4096));
639 public boolean isVlanPriorityValid(String vlanPriority) {
640 int pri = Integer.decode(vlanPriority);
641 return ((pri >= 0) && (pri < 8));
644 public boolean isTOSBitsValid(String tosBits) {
645 int tos = Integer.decode(tosBits);
646 return ((tos >= 0) && (tos < 64));
649 public boolean isTpPortValid(String tpPort) {
650 int port = Integer.decode(tpPort);
651 return ((port >= 0) && (port <= 0xffff));
654 public boolean isTimeoutValid(String timeout) {
655 int to = Integer.decode(timeout);
656 return ((to >= 0) && (to <= 0xffff));
659 public boolean isProtocolValid(String protocol) {
660 IPProtocols proto = IPProtocols.fromString(protocol);
661 return (proto != null);
664 private Status conflictWithContainerFlow(IContainer container) {
665 // Return true if it's default container
666 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
667 return new Status(StatusCode.SUCCESS);
670 // No container flow = no conflict
671 List<ContainerFlow> cFlowList = container.getContainerFlows();
672 if (((cFlowList == null)) || cFlowList.isEmpty()) {
673 return new Status(StatusCode.SUCCESS);
676 // Check against each container's flow
677 Flow flow = this.getFlow();
679 // Configuration is rejected if it conflicts with _all_ the container
681 for (ContainerFlow cFlow : cFlowList) {
682 if (cFlow.allowsFlow(flow)) {
683 log.trace("Config is congruent with at least one container flow");
684 return new Status(StatusCode.SUCCESS);
687 String msg = "Flow Config conflicts with all existing container flows";
690 return new Status(StatusCode.BADREQUEST, msg);
693 public Status validate(IContainer container) {
694 EtherIPType etype = EtherIPType.ANY;
695 EtherIPType ipsrctype = EtherIPType.ANY;
696 EtherIPType ipdsttype = EtherIPType.ANY;
698 String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
699 ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
704 if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
705 return new Status(StatusCode.BADREQUEST, "Invalid name");
709 return new Status(StatusCode.BADREQUEST, "Node is null");
712 if (switchManager != null) {
713 for (Switch device : switchManager.getNetworkDevices()) {
714 if (device.getNode().equals(node)) {
720 return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
723 log.debug("switchmanager is not set yet");
726 if (priority != null) {
727 if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
728 return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
733 // make sure it's a valid number
734 if (cookie != null) {
738 if (ingressPort != null) {
739 Short port = Short.decode(ingressPort);
740 if (isPortValid(sw, port) == false) {
741 String msg = String.format("Ingress port %d is not valid for the Switch", port);
742 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
743 msg += " in Container " + containerName;
745 return new Status(StatusCode.BADREQUEST, msg);
749 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
750 return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095",
754 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
755 return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7",
758 if (etherType != null) {
759 int type = Integer.decode(etherType);
760 if ((type < 0) || (type > 0xffff)) {
761 return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType));
764 etype = EtherIPType.V4;
765 } else if (type == 0x86dd) {
766 etype = EtherIPType.V6;
771 if ((protocol != null) && !isProtocolValid(protocol)) {
772 return new Status(StatusCode.BADREQUEST, String.format("Protocol %s is not valid", protocol));
775 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
776 return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
780 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
781 return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc));
784 if ((tpDst != null) && !isTpPortValid(tpDst)) {
785 return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid",
789 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
790 return new Status(StatusCode.BADREQUEST, String.format(
791 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc));
794 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
795 return new Status(StatusCode.BADREQUEST, String.format(
796 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst));
800 if (NetUtils.isIPv4AddressValid(nwSrc)) {
801 ipsrctype = EtherIPType.V4;
802 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
803 ipsrctype = EtherIPType.V6;
805 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc));
810 if (NetUtils.isIPv4AddressValid(nwDst)) {
811 ipdsttype = EtherIPType.V4;
812 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
813 ipdsttype = EtherIPType.V6;
815 return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid",
820 if (etype != EtherIPType.ANY) {
821 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
822 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP"));
824 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
825 return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP"));
828 if (ipsrctype != ipdsttype) {
829 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
830 return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch"));
834 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
835 return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid",
839 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
840 return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid",
845 if (actions == null || actions.isEmpty()) {
846 return new Status(StatusCode.BADREQUEST, "Actions value is null or empty");
848 for (String actiongrp : actions) {
849 // check output ports
850 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
851 if (sstr.matches()) {
852 for (String t : sstr.group(1).split(",")) {
853 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
855 if (n.group(1) != null) {
856 Short port = Short.parseShort(n.group(1));
857 if (isPortValid(sw, port) == false) {
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);
870 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
871 if (sstr.matches()) {
872 if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
873 return new Status(StatusCode.BADREQUEST, String.format(
874 "flood is not allowed in container %s", containerName));
879 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
880 if (sstr.matches()) {
881 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
882 return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid",
888 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
889 if (sstr.matches()) {
890 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
891 return new Status(StatusCode.BADREQUEST, String.format(
892 "IP destination address %s is not valid", sstr.group(1)));
897 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
898 if (sstr.matches()) {
899 if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) {
900 return new Status(StatusCode.BADREQUEST, String.format(
901 "Vlan ID %s is not in the range 0 - 4095", sstr.group(1)));
906 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
907 if (sstr.matches()) {
908 if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
909 return new Status(StatusCode.BADREQUEST, String.format(
910 "Vlan priority %s is not in the range 0 - 7", sstr.group(1)));
915 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
916 if (sstr.matches()) {
917 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
918 return new Status(StatusCode.BADREQUEST, String.format(
919 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
924 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
925 if (sstr.matches()) {
926 if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) {
927 return new Status(StatusCode.BADREQUEST, String.format(
928 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
934 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
935 if (sstr.matches()) {
936 if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) {
937 return new Status(StatusCode.BADREQUEST, String.format(
938 "IP ToS bits %s is not in the range 0 - 63", sstr.group(1)));
943 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
944 if (sstr.matches()) {
945 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
946 return new Status(StatusCode.BADREQUEST, String.format(
947 "Transport source port %s is not valid", sstr.group(1)));
952 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
953 if (sstr.matches()) {
954 if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) {
955 return new Status(StatusCode.BADREQUEST, String.format(
956 "Transport destination port %s is not valid", sstr.group(1)));
960 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
961 if (sstr.matches()) {
962 if (!NetUtils.isIPAddressValid(sstr.group(1))) {
963 return new Status(StatusCode.BADREQUEST, String.format(
964 "IP destination address %s is not valid", sstr.group(1)));
969 // Check against the container flow
971 if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
974 } catch (NumberFormatException e) {
975 return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
978 return new Status(StatusCode.SUCCESS);
981 public FlowEntry getFlowEntry() {
982 String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
983 return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
986 public Flow getFlow() {
987 Match match = new Match();
989 if (this.ingressPort != null) {
990 match.setField(MatchType.IN_PORT,
991 NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode()));
993 if (this.dlSrc != null) {
994 match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
996 if (this.dlDst != null) {
997 match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst));
999 if (this.etherType != null) {
1000 match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue());
1002 if (this.vlanId != null) {
1003 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1005 if (this.vlanPriority != null) {
1006 match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority));
1008 if (this.nwSrc != null) {
1009 String parts[] = this.nwSrc.split("/");
1010 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1011 InetAddress mask = null;
1013 if (parts.length > 1) {
1014 maskLen = Integer.parseInt(parts[1]);
1016 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1018 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1019 match.setField(MatchType.NW_SRC, ip, mask);
1021 if (this.nwDst != null) {
1022 String parts[] = this.nwDst.split("/");
1023 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1024 InetAddress mask = null;
1026 if (parts.length > 1) {
1027 maskLen = Integer.parseInt(parts[1]);
1029 maskLen = (ip instanceof Inet6Address) ? 128 : 32;
1031 mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
1032 match.setField(MatchType.NW_DST, ip, mask);
1034 if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
1035 match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
1037 if (this.tosBits != null) {
1038 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1040 if (this.tpSrc != null) {
1041 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue());
1043 if (this.tpDst != null) {
1044 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue());
1047 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());
1063 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1064 return (this.name.equals(that.name) && this.node.equals(that.node));
1067 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1068 return (this.name.equals(name) && this.node.equals(node));
1071 public boolean onNode(Node node) {
1072 return this.node.equals(node);
1075 public void toggleInstallation() {
1076 installInHw = (installInHw == null) ? Boolean.toString(false) : Boolean.toString(!Boolean.valueOf(installInHw));
1080 * Parses the actions string and return the List of SAL Action No syntax
1081 * check run, as this function will be called when the config validation
1082 * check has already been performed
1084 private List<Action> getActionList() {
1085 List<Action> actionList = new ArrayList<Action>();
1087 if (actions != null) {
1089 for (String actiongrp : actions) {
1090 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
1091 if (sstr.matches()) {
1092 for (String t : sstr.group(1).split(",")) {
1093 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1095 if (n.group(1) != null) {
1096 short ofPort = Short.parseShort(n.group(1));
1097 actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort,
1105 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
1106 if (sstr.matches()) {
1107 actionList.add(new Drop());
1111 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
1112 if (sstr.matches()) {
1113 actionList.add(new Loopback());
1117 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
1118 if (sstr.matches()) {
1119 actionList.add(new Flood());
1123 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
1124 if (sstr.matches()) {
1125 actionList.add(new SwPath());
1129 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
1130 if (sstr.matches()) {
1131 actionList.add(new HwPath());
1135 sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
1136 if (sstr.matches()) {
1137 actionList.add(new Controller());
1141 sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp);
1142 if (sstr.matches()) {
1143 actionList.add(new SetVlanId(Short.parseShort(sstr.group(1))));
1147 sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
1148 if (sstr.matches()) {
1149 actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1153 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
1154 if (sstr.matches()) {
1155 actionList.add(new PopVlan());
1159 sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp);
1160 if (sstr.matches()) {
1161 actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1))));
1165 sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp);
1166 if (sstr.matches()) {
1167 actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1))));
1170 sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
1171 if (sstr.matches()) {
1172 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1))));
1175 sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp);
1176 if (sstr.matches()) {
1177 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1))));
1181 sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp);
1182 if (sstr.matches()) {
1183 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1187 sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp);
1188 if (sstr.matches()) {
1189 actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1193 sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp);
1194 if (sstr.matches()) {
1195 actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1199 sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
1200 if (sstr.matches()) {
1201 actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1))));