2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.forwardingrulesmanager;
11 import java.io.Serializable;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import javax.xml.bind.annotation.XmlAccessType;
21 import javax.xml.bind.annotation.XmlAccessorType;
22 import javax.xml.bind.annotation.XmlElement;
23 import javax.xml.bind.annotation.XmlRootElement;
25 import org.opendaylight.controller.sal.action.Action;
26 import org.opendaylight.controller.sal.action.ActionType;
27 import org.opendaylight.controller.sal.action.Controller;
28 import org.opendaylight.controller.sal.action.Drop;
29 import org.opendaylight.controller.sal.action.Flood;
30 import org.opendaylight.controller.sal.action.HwPath;
31 import org.opendaylight.controller.sal.action.Loopback;
32 import org.opendaylight.controller.sal.action.Output;
33 import org.opendaylight.controller.sal.action.PopVlan;
34 import org.opendaylight.controller.sal.action.SetDlDst;
35 import org.opendaylight.controller.sal.action.SetDlSrc;
36 import org.opendaylight.controller.sal.action.SetNwDst;
37 import org.opendaylight.controller.sal.action.SetNwSrc;
38 import org.opendaylight.controller.sal.action.SetNwTos;
39 import org.opendaylight.controller.sal.action.SetTpDst;
40 import org.opendaylight.controller.sal.action.SetTpSrc;
41 import org.opendaylight.controller.sal.action.SetVlanId;
42 import org.opendaylight.controller.sal.action.SetVlanPcp;
43 import org.opendaylight.controller.sal.action.SwPath;
44 import org.opendaylight.controller.sal.core.ContainerFlow;
45 import org.opendaylight.controller.sal.core.IContainer;
46 import org.opendaylight.controller.sal.core.Node;
47 import org.opendaylight.controller.sal.core.NodeConnector;
48 import org.opendaylight.controller.sal.flowprogrammer.Flow;
49 import org.opendaylight.controller.sal.match.Match;
50 import org.opendaylight.controller.sal.match.MatchType;
51 import org.opendaylight.controller.sal.utils.GlobalConstants;
52 import org.opendaylight.controller.sal.utils.HexEncode;
53 import org.opendaylight.controller.sal.utils.IPProtocols;
54 import org.opendaylight.controller.sal.utils.NetUtils;
55 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
56 import org.opendaylight.controller.sal.utils.ServiceHelper;
57 import org.opendaylight.controller.sal.utils.StatusCode;
58 import org.opendaylight.controller.switchmanager.ISwitchManager;
59 import org.opendaylight.controller.switchmanager.Switch;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
64 * Configuration Java Object which represents a flow configuration information
65 * 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 staticFlowsGroup = "**StaticFlows";
74 private boolean dynamic;
75 private String status;
78 * The order of the object data defined below is used directly in the UI
79 * built using JSP. Hence try to keep the order in a more logical way.
82 private String installInHw;
88 private String ingressPort;
89 private String portGroup;
91 private String priority;
93 private String etherType;
95 private String vlanId;
97 private String vlanPriority;
101 private String dlDst;
103 private String nwSrc;
105 private String nwDst;
107 private String protocol;
109 private String tosBits;
111 private String tpSrc;
113 private String tpDst;
115 private String cookie;
117 private String idleTimeout;
119 private String hardTimeout;
121 private List<String> actions;
123 private enum EtherIPType {
127 private enum SetNextHopType {
128 CISCO_EXTENSION("Cisco NextHop Extension"), RESOLVE_L2RW(
129 "Resolve L2 Rewrite");
131 private SetNextHopType(String name) {
137 public String toString() {
141 public boolean equals(String type) {
142 if (type.trim().equalsIgnoreCase(name))
148 public FlowConfig() {
151 public FlowConfig(String installInHw, String name, Node node,
152 String priority, String cookie, String ingressPort,
153 String portGroup, String vlanId, String vlanPriority,
154 String etherType, String srcMac, String dstMac, String protocol,
155 String tosBits, String srcIP, String dstIP, String tpSrc,
156 String tpDst, String idleTimeout, String hardTimeout,
157 List<String> actions) {
159 this.installInHw = installInHw;
162 this.priority = priority;
163 this.cookie = cookie;
164 this.ingressPort = ingressPort;
165 this.portGroup = portGroup;
166 this.vlanId = vlanId;
167 this.vlanPriority = vlanPriority;
168 this.etherType = etherType;
171 this.protocol = protocol;
172 this.tosBits = tosBits;
177 this.idleTimeout = idleTimeout;
178 this.hardTimeout = hardTimeout;
179 this.actions = actions;
180 this.status = StatusCode.SUCCESS.toString();
183 public FlowConfig(FlowConfig from) {
184 this.installInHw = from.installInHw;
185 this.name = from.name;
186 this.node = from.node;
187 this.priority = from.priority;
188 this.cookie = from.cookie;
189 this.ingressPort = from.ingressPort;
190 this.portGroup = from.portGroup;
191 this.vlanId = from.vlanId;
192 this.vlanPriority = from.vlanPriority;
193 this.etherType = from.etherType;
194 this.dlSrc = from.dlSrc;
195 this.dlDst = from.dlDst;
196 this.protocol = from.protocol;
197 this.tosBits = from.tosBits;
198 this.nwSrc = from.nwSrc;
199 this.nwDst = from.nwDst;
200 this.tpSrc = from.tpSrc;
201 this.tpDst = from.tpDst;
202 this.idleTimeout = from.idleTimeout;
203 this.hardTimeout = from.hardTimeout;
204 this.actions = new ArrayList<String>(from.actions);
207 public boolean installInHw() {
208 if (installInHw == null) {
209 // backward compatibility
210 installInHw = "true";
212 return installInHw.equals("true");
215 public void setInstallInHw(boolean inHw) {
216 installInHw = inHw ? "true" : "false";
219 public String getInstallInHw() {
223 public boolean isInternalFlow() {
224 // Controller generated static flows have name starting with "**"
225 return (this.name != null && this.name.startsWith("**"));
228 public String getName() {
232 public void setName(String name) {
239 public Node getNode() {
243 public void setNode(Node node) {
247 public String getPriority() {
251 public void setPriority(String priority) {
252 this.priority = priority;
255 public String getCookie() {
259 public void setCookie(String cookie) {
260 this.cookie = cookie;
263 public String getIngressPort() {
267 public void setIngressPort(String ingressPort) {
268 this.ingressPort = ingressPort;
271 public String getPortGroup() {
276 public String toString() {
277 return "FlowConfig [dynamic=" + dynamic + ", status=" + status
278 + ", installInHw=" + installInHw + ", name=" + name
279 + ", switchId=" + node + ", ingressPort=" + ingressPort
280 + ", portGroup=" + portGroup + ", etherType=" + etherType
281 + ", priority=" + priority + ", vlanId=" + vlanId
282 + ", vlanPriority=" + vlanPriority + ", dlSrc=" + dlSrc
283 + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
284 + ", protocol=" + protocol + ", tosBits=" + tosBits
285 + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst + ", cookie="
286 + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout="
287 + hardTimeout + ", actions=" + actions + "]";
290 public void setPortGroup(String portGroup) {
291 this.portGroup = portGroup;
294 public String getVlanId() {
298 public void setVlanId(String vlanId) {
299 this.vlanId = vlanId;
302 public String getVlanPriority() {
306 public void setVlanPriority(String vlanPriority) {
307 this.vlanPriority = vlanPriority;
310 public String getEtherType() {
314 public void setEtherType(String etherType) {
315 this.etherType = etherType;
318 public String getSrcMac() {
322 public void setSrcMac(String srcMac) {
326 public String getDstMac() {
330 public void setDstMac(String dstMac) {
334 public String getProtocol() {
338 public void setProtocol(String protocol) {
339 this.protocol = protocol;
342 public String getTosBits() {
346 public void setTosBits(String tos_bits) {
347 this.tosBits = tos_bits;
350 public String getSrcIp() {
354 public void setSrcIp(String src_ip) {
358 public String getDstIp() {
362 public void setDstIp(String dst_ip) {
366 public String getSrcPort() {
370 public void setSrcPort(String src_port) {
371 this.tpSrc = src_port;
374 public String getDstPort() {
378 public void setDstPort(String dst_port) {
379 this.tpDst = dst_port;
382 public String getIdleTimeout() {
386 public void setIdleTimeout(String idleTimeout) {
387 this.idleTimeout = idleTimeout;
390 public String getHardTimeout() {
394 public void setHardTimeout(String hardTimeout) {
395 this.hardTimeout = hardTimeout;
398 public boolean isIPv6() {
399 if (NetUtils.isIPv6AddressValid(this.getSrcIp())
400 || NetUtils.isIPv6AddressValid(this.getDstIp())) {
406 public List<String> getActions() {
410 public void setActions(List<String> actions) {
411 this.actions = actions;
414 public boolean isPortGroupEnabled() {
415 return (portGroup != null);
418 public boolean isDynamic() {
422 public void setDynamic(boolean dynamic) {
423 this.dynamic = dynamic;
426 public String getStatus() {
430 public void setStatus(String status) {
431 this.status = status;
434 public boolean isStatusSuccessful() {
435 return status.equals(StatusCode.SUCCESS.toString());
439 public int hashCode() {
440 final int prime = 31;
442 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
443 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
444 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
445 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
446 result = prime * result + (dynamic ? 1231 : 1237);
447 result = prime * result
448 + ((etherType == null) ? 0 : etherType.hashCode());
449 result = prime * result
450 + ((ingressPort == null) ? 0 : ingressPort.hashCode());
451 result = prime * result + ((name == null) ? 0 : name.hashCode());
452 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
453 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
454 result = prime * result
455 + ((portGroup == null) ? 0 : portGroup.hashCode());
456 result = prime * result
457 + ((priority == null) ? 0 : priority.hashCode());
458 result = prime * result
459 + ((protocol == null) ? 0 : protocol.hashCode());
460 result = prime * result + ((node == null) ? 0 : node.hashCode());
461 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
462 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
463 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
464 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
465 result = prime * result
466 + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
467 result = prime * result
468 + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
469 result = prime * result
470 + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
475 public boolean equals(Object obj) {
480 if (getClass() != obj.getClass())
482 FlowConfig other = (FlowConfig) obj;
483 if (actions == null) {
484 if (other.actions != null)
486 } else if (!actions.equals(other.actions))
488 if (cookie == null) {
489 if (other.cookie != null)
491 } else if (!cookie.equals(other.cookie))
494 if (other.dlDst != null)
496 } else if (!dlDst.equals(other.dlDst))
499 if (other.dlSrc != null)
501 } else if (!dlSrc.equals(other.dlSrc))
503 if (dynamic != other.dynamic)
505 if (etherType == null) {
506 if (other.etherType != null)
508 } else if (!etherType.equals(other.etherType))
510 if (ingressPort == null) {
511 if (other.ingressPort != null)
513 } else if (!ingressPort.equals(other.ingressPort))
516 if (other.name != null)
518 } else if (!name.equals(other.name))
521 if (other.nwDst != null)
523 } else if (!nwDst.equals(other.nwDst))
526 if (other.nwSrc != null)
528 } else if (!nwSrc.equals(other.nwSrc))
530 if (portGroup == null) {
531 if (other.portGroup != null)
533 } else if (!portGroup.equals(other.portGroup))
535 if (priority == null) {
536 if (other.priority != null)
538 } else if (!priority.equals(other.priority))
540 if (protocol == null) {
541 if (other.protocol != null)
543 } else if (!protocol.equals(other.protocol))
546 if (other.node != null)
548 } else if (!node.equals(other.node))
550 if (tosBits == null) {
551 if (other.tosBits != null)
553 } else if (!tosBits.equals(other.tosBits))
556 if (other.tpDst != null)
558 } else if (!tpDst.equals(other.tpDst))
561 if (other.tpSrc != null)
563 } else if (!tpSrc.equals(other.tpSrc))
565 if (vlanId == null) {
566 if (other.vlanId != null)
568 } else if (!vlanId.equals(other.vlanId))
570 if (vlanPriority == null) {
571 if (other.vlanPriority != null)
573 } else if (!vlanPriority.equals(other.vlanPriority))
575 if (idleTimeout == null) {
576 if (other.idleTimeout != null)
578 } else if (!idleTimeout.equals(other.idleTimeout))
580 if (hardTimeout == null) {
581 if (other.hardTimeout != null)
583 } else if (!hardTimeout.equals(other.hardTimeout))
588 public InetAddress getNextHopAddressForL2RWAction() {
589 if (actions != null) {
591 for (String actiongrp : actions) {
592 sstr = Pattern.compile("SET_NEXT_HOP=(.*)").matcher(actiongrp);
593 if (sstr.matches()) {
594 SetNextHopType setNHType = SetNextHopType.CISCO_EXTENSION;
595 String nextHopInfo = sstr.group(1);
596 String values[] = nextHopInfo.split("//");
597 String address = values[0].trim();
599 if (values.length > 1) {
600 type = values[1].trim();
604 for (SetNextHopType nh : SetNextHopType.values()) {
610 log.debug("Get Nexthop address = " + address + " Type = "
611 + setNHType.toString());
612 if (setNHType == SetNextHopType.RESOLVE_L2RW) {
614 return InetAddress.getByName(address);
615 } catch (Exception e) {
616 log.debug("Exception during nextHopAddress resolution : "
626 public String getNextHopL2RWUsageError() {
627 return "Could not resolve NextHop IP Address for the selected Switch.<br>"
628 + "Please Check the following configurations.<br>"
629 + "1. Is the NextHop IP address directly connected to the Selected Switch<br>"
630 + "2. If appropriate Subnet Configurations are done in the Switch Manager<br>"
631 + "3. If the Nexthop IP-Address is Correct";
634 public boolean isL2AddressValid(String mac) {
639 Pattern macPattern = Pattern
640 .compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
641 Matcher mm = macPattern.matcher(mac);
644 "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f",
651 public boolean isPortValid(Switch sw, Short port) {
653 log.debug("port {} is not valid", port);
658 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
662 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
663 for (NodeConnector nodeConnector : nodeConnectorSet) {
664 if (((Short) nodeConnector.getID()).equals(port)) {
668 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
672 public boolean isVlanIdValid(String vlanId) {
673 int vlan = Integer.decode(vlanId);
674 return ((vlan >= 0) && (vlan < 4096));
677 public boolean isVlanPriorityValid(String vlanPriority) {
678 int pri = Integer.decode(vlanPriority);
679 return ((pri >= 0) && (pri < 8));
682 public boolean isTOSBitsValid(String tosBits) {
683 int tos = Integer.decode(tosBits);
684 return ((tos >= 0) && (tos < 64));
687 public boolean isTpPortValid(String tpPort) {
688 int port = Integer.decode(tpPort);
689 return ((port > 0) && (port <= 0xffff));
692 public boolean isTimeoutValid(String timeout) {
693 int to = Integer.decode(timeout);
694 return ((to >= 0) && (to <= 0xffff));
697 private boolean conflictWithContainerFlow(IContainer container,
698 StringBuffer resultStr) {
699 // Return true if it's default container
700 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
704 // No container flow = no conflict
705 List<ContainerFlow> cFlowList = container.getContainerFlows();
706 if (((cFlowList == null)) || cFlowList.isEmpty()) {
710 // Check against each container's flow
711 Flow flow = this.getFlow();
713 // Configuration is rejected if it conflicts with _all_ the container
715 for (ContainerFlow cFlow : cFlowList) {
716 if (cFlow.allowsFlow(flow)) {
717 log.trace("Config is congruent with at least one container flow");
721 String msg = "Flow Config conflicts with all existing container flows";
722 resultStr.append(msg);
728 public boolean isValid(IContainer container, StringBuffer resultStr) {
729 EtherIPType etype = EtherIPType.ANY;
730 EtherIPType ipsrctype = EtherIPType.ANY;
731 EtherIPType ipdsttype = EtherIPType.ANY;
733 String containerName = (container == null) ? GlobalConstants.DEFAULT
734 .toString() : container.getName();
735 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
736 .getInstance(ISwitchManager.class, containerName, this);
741 resultStr.append(String.format("Name is null"));
745 resultStr.append(String.format("Node is null"));
748 if (switchManager != null) {
749 for (Switch device : switchManager.getNetworkDevices()) {
750 if (device.getNode().equals(node)) {
756 resultStr.append(String.format("Node %s not found", node));
760 log.debug("switchmanager is not set yet");
763 if (priority != null) {
764 if (Integer.decode(priority) < 0
765 || (Integer.decode(priority) > 65535)) {
766 resultStr.append(String.format(
767 "priority %s is not in the range 0 - 65535",
773 // make sure it's a valid number
777 if (ingressPort != null) {
778 Short port = Short.decode(ingressPort);
779 if (isPortValid(sw, port) == false) {
782 .format("Ingress port %d is not valid for the Switch",
784 if ((container != null)
785 && !container.getName().equals(
786 GlobalConstants.DEFAULT.toString())) {
788 .append(" in Container " + container.getName());
794 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
795 resultStr.append(String.format(
796 "Vlan ID %s is not in the range 0 - 4095", vlanId));
800 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
801 resultStr.append(String.format(
802 "Vlan priority %s is not in the range 0 - 7",
807 if (etherType != null) {
808 int type = Integer.decode(etherType);
809 if ((type < 0) || (type > 0xffff)) {
810 resultStr.append(String.format(
811 "Ethernet type %s is not valid", etherType));
815 etype = EtherIPType.V4;
816 else if (type == 0x86dd)
817 etype = EtherIPType.V6;
821 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
822 resultStr.append(String.format(
823 "IP ToS bits %s is not in the range 0 - 63", tosBits));
827 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
828 resultStr.append(String.format(
829 "Transport source port %s is not valid", tpSrc));
832 if ((tpDst != null) && !isTpPortValid(tpDst)) {
833 resultStr.append(String.format(
834 "Transport destination port %s is not valid", tpDst));
838 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
841 .format("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
846 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
849 .format("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
855 if (NetUtils.isIPv4AddressValid(nwSrc)) {
856 ipsrctype = EtherIPType.V4;
857 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
858 ipsrctype = EtherIPType.V6;
860 resultStr.append(String.format(
861 "IP source address %s is not valid", nwSrc));
867 if (NetUtils.isIPv4AddressValid(nwDst)) {
868 ipdsttype = EtherIPType.V4;
869 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
870 ipdsttype = EtherIPType.V6;
872 resultStr.append(String.format(
873 "IP destination address %s is not valid", nwDst));
878 if (etype != EtherIPType.ANY) {
879 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
880 resultStr.append(String
881 .format("Type mismatch between Ethernet & Src IP"));
884 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
885 resultStr.append(String
886 .format("Type mismatch between Ethernet & Dst IP"));
890 if (ipsrctype != ipdsttype) {
891 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
893 .append(String.format("IP Src Dest Type mismatch"));
898 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
899 resultStr.append(String.format(
900 "Idle Timeout value %s is not valid", idleTimeout));
904 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
905 resultStr.append(String.format(
906 "Hard Timeout value %s is not valid", hardTimeout));
911 if (actions != null && !actions.isEmpty()) {
912 for (String actiongrp : actions) {
913 // check output ports
914 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
915 if (sstr.matches()) {
916 for (String t : sstr.group(1).split(",")) {
917 Matcher n = Pattern.compile("(?:(\\d+))")
920 if (n.group(1) != null) {
921 Short port = Short.parseShort(n.group(1));
922 if (isPortValid(sw, port) == false) {
925 .format("Output port %d is not valid for this switch",
927 if ((container != null)
928 && !container.getName().equals(
929 GlobalConstants.DEFAULT
931 resultStr.append(" in Container "
932 + container.getName());
942 sstr = Pattern.compile(ActionType.FLOOD.toString())
944 if (sstr.matches()) {
945 if (container != null) {
946 resultStr.append(String.format(
947 "flood is not allowed in container %s",
948 container.getName()));
954 sstr = Pattern.compile(
955 ActionType.SET_NW_SRC.toString() + "=(.*)")
957 if (sstr.matches()) {
958 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
959 resultStr.append(String.format(
960 "IP source address %s is not valid",
967 sstr = Pattern.compile(
968 ActionType.SET_NW_DST.toString() + "=(.*)")
970 if (sstr.matches()) {
971 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
972 resultStr.append(String.format(
973 "IP destination address %s is not valid",
980 sstr = Pattern.compile(
981 ActionType.SET_VLAN_ID.toString() + "=(.*)")
983 if (sstr.matches()) {
984 if ((sstr.group(1) != null)
985 && !isVlanIdValid(sstr.group(1))) {
986 resultStr.append(String.format(
987 "Vlan ID %s is not in the range 0 - 4095",
994 sstr = Pattern.compile(
995 ActionType.SET_VLAN_PCP.toString() + "=(.*)")
997 if (sstr.matches()) {
998 if ((sstr.group(1) != null)
999 && !isVlanPriorityValid(sstr.group(1))) {
1002 .format("Vlan priority %s is not in the range 0 - 7",
1009 sstr = Pattern.compile(
1010 ActionType.SET_DL_SRC.toString() + "=(.*)")
1011 .matcher(actiongrp);
1012 if (sstr.matches()) {
1013 if ((sstr.group(1) != null)
1014 && !isL2AddressValid(sstr.group(1))) {
1017 .format("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
1024 sstr = Pattern.compile(
1025 ActionType.SET_DL_DST.toString() + "=(.*)")
1026 .matcher(actiongrp);
1027 if (sstr.matches()) {
1028 if ((sstr.group(1) != null)
1029 && !isL2AddressValid(sstr.group(1))) {
1032 .format("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
1039 sstr = Pattern.compile(
1040 ActionType.SET_NW_TOS.toString() + "=(.*)")
1041 .matcher(actiongrp);
1042 if (sstr.matches()) {
1043 if ((sstr.group(1) != null)
1044 && !isTOSBitsValid(sstr.group(1))) {
1047 .format("IP ToS bits %s is not in the range 0 - 63",
1054 sstr = Pattern.compile(
1055 ActionType.SET_TP_SRC.toString() + "=(.*)")
1056 .matcher(actiongrp);
1057 if (sstr.matches()) {
1058 if ((sstr.group(1) != null)
1059 && !isTpPortValid(sstr.group(1))) {
1060 resultStr.append(String.format(
1061 "Transport source port %s is not valid",
1068 sstr = Pattern.compile(
1069 ActionType.SET_TP_DST.toString() + "=(.*)")
1070 .matcher(actiongrp);
1071 if (sstr.matches()) {
1072 if ((sstr.group(1) != null)
1073 && !isTpPortValid(sstr.group(1))) {
1076 .format("Transport destination port %s is not valid",
1082 sstr = Pattern.compile(
1083 ActionType.SET_NEXT_HOP.toString() + "=(.*)")
1084 .matcher(actiongrp);
1085 if (sstr.matches()) {
1086 String nextHopInfo = sstr.group(1);
1087 String values[] = nextHopInfo.split("//");
1088 String address = values[0].trim();
1090 if ((address == null) || !isOutputNextHopValid(address)) {
1091 resultStr.append(String.format(
1092 "next hop %s is not valid", sstr.group(1)));
1099 // Check against the container flow
1100 if ((container != null)
1101 && conflictWithContainerFlow(container, resultStr)) {
1104 } catch (NumberFormatException e) {
1105 resultStr.append(String.format("Invalid number format %s",
1113 public FlowEntry getFlowEntry() {
1114 return new FlowEntry(FlowConfig.staticFlowsGroup, this.name,
1115 this.getFlow(), this.getNode());
1118 public Flow getFlow() {
1119 Match match = new Match();
1121 if (this.ingressPort != null) {
1124 NodeConnectorCreator.createOFNodeConnector(
1125 Short.parseShort(ingressPort), getNode()));
1127 if (this.dlSrc != null) {
1128 match.setField(MatchType.DL_SRC,
1129 HexEncode.bytesFromHexString(this.dlSrc));
1131 if (this.dlDst != null) {
1132 match.setField(MatchType.DL_DST,
1133 HexEncode.bytesFromHexString(this.dlDst));
1135 if (this.etherType != null) {
1136 match.setField(MatchType.DL_TYPE, Integer.decode(etherType)
1139 if (this.vlanId != null) {
1140 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1142 if (this.vlanPriority != null) {
1143 match.setField(MatchType.DL_VLAN_PR,
1144 Byte.parseByte(this.vlanPriority));
1146 if (this.nwSrc != null) {
1147 String parts[] = this.nwSrc.split("/");
1148 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1149 InetAddress mask = null;
1150 if (parts.length > 1) {
1151 int maskLen = Integer.parseInt(parts[1]);
1152 mask = NetUtils.getInetNetworkMask(maskLen,
1153 ip instanceof Inet6Address);
1155 match.setField(MatchType.NW_SRC, ip, mask);
1157 if (this.nwDst != null) {
1158 String parts[] = this.nwDst.split("/");
1159 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1160 InetAddress mask = null;
1161 if (parts.length > 1) {
1162 int maskLen = Integer.parseInt(parts[1]);
1163 mask = NetUtils.getInetNetworkMask(maskLen,
1164 ip instanceof Inet6Address);
1166 match.setField(MatchType.NW_DST, ip, mask);
1168 if (this.protocol != null) {
1169 match.setField(MatchType.NW_PROTO,
1170 IPProtocols.getProtocolNumberByte(this.protocol));
1172 if (this.tosBits != null) {
1173 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1175 if (this.tpSrc != null) {
1176 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc)
1179 if (this.tpDst != null) {
1180 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst)
1184 Flow flow = new Flow(match, getActionList());
1185 if (this.cookie != null) {
1186 flow.setId(Long.parseLong(cookie));
1188 if (this.hardTimeout != null) {
1189 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1191 if (this.idleTimeout != null) {
1192 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1194 if (this.priority != null) {
1195 flow.setPriority(Integer.decode(this.priority).shortValue());
1200 public boolean isOutputNextHopValid(String onh) {
1205 * For now, only takes IPv4 or IPv6 address
1207 return (NetUtils.isIPv4AddressValid(onh) || NetUtils
1208 .isIPv6AddressValid(onh));
1211 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1212 return (this.name.equals(that.name) && this.node.equals(that.node));
1215 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1216 return (this.name.equals(name) && this.node.equals(node));
1219 public boolean onNode(Node node) {
1220 return this.node.equals(node);
1223 public static List<String> getSupportedNextHopTypes() {
1224 List<String> s = new ArrayList<String>();
1225 for (SetNextHopType nh : SetNextHopType.values()) {
1226 s.add(nh.toString());
1231 public void toggleStatus() {
1232 installInHw = (installInHw == null) ? "true" : (installInHw
1233 .equals("true")) ? "false" : "true";
1237 * Parses the actions string and return the List of SAL Action No syntax
1238 * check run, as this function will be called when the config validation
1239 * check has already been performed
1241 private List<Action> getActionList() {
1242 List<Action> actionList = new ArrayList<Action>();
1244 if (actions != null) {
1246 for (String actiongrp : actions) {
1247 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(
1249 if (sstr.matches()) {
1250 for (String t : sstr.group(1).split(",")) {
1251 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1253 if (n.group(1) != null) {
1254 short ofPort = Short.parseShort(n.group(1));
1255 actionList.add(new Output(NodeConnectorCreator
1256 .createOFNodeConnector(ofPort,
1264 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(
1266 if (sstr.matches()) {
1267 actionList.add(new Drop());
1271 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(
1273 if (sstr.matches()) {
1274 actionList.add(new Loopback());
1278 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(
1280 if (sstr.matches()) {
1281 actionList.add(new Flood());
1285 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(
1287 if (sstr.matches()) {
1288 actionList.add(new SwPath());
1292 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(
1294 if (sstr.matches()) {
1295 actionList.add(new HwPath());
1299 sstr = Pattern.compile(ActionType.CONTROLLER.toString())
1300 .matcher(actiongrp);
1301 if (sstr.matches()) {
1302 actionList.add(new Controller());
1306 sstr = Pattern.compile(
1307 ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(
1309 if (sstr.matches()) {
1310 actionList.add(new SetVlanId(
1311 Short.parseShort(sstr.group(1))));
1315 sstr = Pattern.compile(
1316 ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(
1318 if (sstr.matches()) {
1320 .add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1324 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(
1326 if (sstr.matches()) {
1327 actionList.add(new PopVlan());
1331 sstr = Pattern.compile(
1332 ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(
1334 if (sstr.matches()) {
1335 actionList.add(new SetDlSrc(HexEncode
1336 .bytesFromHexString(sstr.group(1))));
1340 sstr = Pattern.compile(
1341 ActionType.SET_DL_DST.toString() + "=(.*)").matcher(
1343 if (sstr.matches()) {
1344 actionList.add(new SetDlDst(HexEncode
1345 .bytesFromHexString(sstr.group(1))));
1348 sstr = Pattern.compile(
1349 ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(
1351 if (sstr.matches()) {
1352 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr
1356 sstr = Pattern.compile(
1357 ActionType.SET_NW_DST.toString() + "=(.*)").matcher(
1359 if (sstr.matches()) {
1360 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr
1365 sstr = Pattern.compile(
1366 ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(
1368 if (sstr.matches()) {
1369 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1373 sstr = Pattern.compile(
1374 ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(
1376 if (sstr.matches()) {
1378 .add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1382 sstr = Pattern.compile(
1383 ActionType.SET_TP_DST.toString() + "=(.*)").matcher(
1385 if (sstr.matches()) {
1387 .add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1391 sstr = Pattern.compile(
1392 ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(
1394 if (sstr.matches()) {
1395 log.warn("We do not handle next hop action yet....");