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 = {} Type = {}", address,
611 setNHType.toString());
612 if (setNHType == SetNextHopType.RESOLVE_L2RW) {
614 return InetAddress.getByName(address);
615 } catch (Exception e) {
617 "Exception during nextHopAddress resolution : ",
627 public String getNextHopL2RWUsageError() {
628 return "Could not resolve NextHop IP Address for the selected Switch.<br>"
629 + "Please Check the following configurations.<br>"
630 + "1. Is the NextHop IP address directly connected to the Selected Switch<br>"
631 + "2. If appropriate Subnet Configurations are done in the Switch Manager<br>"
632 + "3. If the Nexthop IP-Address is Correct";
635 public boolean isL2AddressValid(String mac) {
640 Pattern macPattern = Pattern
641 .compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
642 Matcher mm = macPattern.matcher(mac);
645 "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f",
652 public boolean isPortValid(Switch sw, Short port) {
654 log.debug("port {} is not valid", port);
659 log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
663 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
664 for (NodeConnector nodeConnector : nodeConnectorSet) {
665 if (((Short) nodeConnector.getID()).equals(port)) {
669 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
673 public boolean isVlanIdValid(String vlanId) {
674 int vlan = Integer.decode(vlanId);
675 return ((vlan >= 0) && (vlan < 4096));
678 public boolean isVlanPriorityValid(String vlanPriority) {
679 int pri = Integer.decode(vlanPriority);
680 return ((pri >= 0) && (pri < 8));
683 public boolean isTOSBitsValid(String tosBits) {
684 int tos = Integer.decode(tosBits);
685 return ((tos >= 0) && (tos < 64));
688 public boolean isTpPortValid(String tpPort) {
689 int port = Integer.decode(tpPort);
690 return ((port > 0) && (port <= 0xffff));
693 public boolean isTimeoutValid(String timeout) {
694 int to = Integer.decode(timeout);
695 return ((to >= 0) && (to <= 0xffff));
698 private boolean conflictWithContainerFlow(IContainer container,
699 StringBuffer resultStr) {
700 // Return true if it's default container
701 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
705 // No container flow = no conflict
706 List<ContainerFlow> cFlowList = container.getContainerFlows();
707 if (((cFlowList == null)) || cFlowList.isEmpty()) {
711 // Check against each container's flow
712 Flow flow = this.getFlow();
714 // Configuration is rejected if it conflicts with _all_ the container
716 for (ContainerFlow cFlow : cFlowList) {
717 if (cFlow.allowsFlow(flow)) {
718 log.trace("Config is congruent with at least one container flow");
722 String msg = "Flow Config conflicts with all existing container flows";
723 resultStr.append(msg);
729 public boolean isValid(IContainer container, StringBuffer resultStr) {
730 EtherIPType etype = EtherIPType.ANY;
731 EtherIPType ipsrctype = EtherIPType.ANY;
732 EtherIPType ipdsttype = EtherIPType.ANY;
734 String containerName = (container == null) ? GlobalConstants.DEFAULT
735 .toString() : container.getName();
736 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
737 .getInstance(ISwitchManager.class, containerName, this);
742 resultStr.append(String.format("Name is null"));
746 resultStr.append(String.format("Node is null"));
749 if (switchManager != null) {
750 for (Switch device : switchManager.getNetworkDevices()) {
751 if (device.getNode().equals(node)) {
757 resultStr.append(String.format("Node %s not found", node));
761 log.debug("switchmanager is not set yet");
764 if (priority != null) {
765 if (Integer.decode(priority) < 0
766 || (Integer.decode(priority) > 65535)) {
767 resultStr.append(String.format(
768 "priority %s is not in the range 0 - 65535",
774 // make sure it's a valid number
778 if (ingressPort != null) {
779 Short port = Short.decode(ingressPort);
780 if (isPortValid(sw, port) == false) {
783 .format("Ingress port %d is not valid for the Switch",
785 if ((container != null)
786 && !container.getName().equals(
787 GlobalConstants.DEFAULT.toString())) {
789 .append(" in Container " + container.getName());
795 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
796 resultStr.append(String.format(
797 "Vlan ID %s is not in the range 0 - 4095", vlanId));
801 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
802 resultStr.append(String.format(
803 "Vlan priority %s is not in the range 0 - 7",
808 if (etherType != null) {
809 int type = Integer.decode(etherType);
810 if ((type < 0) || (type > 0xffff)) {
811 resultStr.append(String.format(
812 "Ethernet type %s is not valid", etherType));
816 etype = EtherIPType.V4;
817 else if (type == 0x86dd)
818 etype = EtherIPType.V6;
822 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
823 resultStr.append(String.format(
824 "IP ToS bits %s is not in the range 0 - 63", tosBits));
828 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
829 resultStr.append(String.format(
830 "Transport source port %s is not valid", tpSrc));
833 if ((tpDst != null) && !isTpPortValid(tpDst)) {
834 resultStr.append(String.format(
835 "Transport destination port %s is not valid", tpDst));
839 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
842 .format("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
847 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
850 .format("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
856 if (NetUtils.isIPv4AddressValid(nwSrc)) {
857 ipsrctype = EtherIPType.V4;
858 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
859 ipsrctype = EtherIPType.V6;
861 resultStr.append(String.format(
862 "IP source address %s is not valid", nwSrc));
868 if (NetUtils.isIPv4AddressValid(nwDst)) {
869 ipdsttype = EtherIPType.V4;
870 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
871 ipdsttype = EtherIPType.V6;
873 resultStr.append(String.format(
874 "IP destination address %s is not valid", nwDst));
879 if (etype != EtherIPType.ANY) {
880 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
881 resultStr.append(String
882 .format("Type mismatch between Ethernet & Src IP"));
885 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
886 resultStr.append(String
887 .format("Type mismatch between Ethernet & Dst IP"));
891 if (ipsrctype != ipdsttype) {
892 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
894 .append(String.format("IP Src Dest Type mismatch"));
899 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
900 resultStr.append(String.format(
901 "Idle Timeout value %s is not valid", idleTimeout));
905 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
906 resultStr.append(String.format(
907 "Hard Timeout value %s is not valid", hardTimeout));
912 if (actions != null && !actions.isEmpty()) {
913 for (String actiongrp : actions) {
914 // check output ports
915 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
916 if (sstr.matches()) {
917 for (String t : sstr.group(1).split(",")) {
918 Matcher n = Pattern.compile("(?:(\\d+))")
921 if (n.group(1) != null) {
922 Short port = Short.parseShort(n.group(1));
923 if (isPortValid(sw, port) == false) {
926 .format("Output port %d is not valid for this switch",
928 if ((container != null)
929 && !container.getName().equals(
930 GlobalConstants.DEFAULT
932 resultStr.append(" in Container "
933 + container.getName());
943 sstr = Pattern.compile(ActionType.FLOOD.toString())
945 if (sstr.matches()) {
946 if (container != null) {
947 resultStr.append(String.format(
948 "flood is not allowed in container %s",
949 container.getName()));
955 sstr = Pattern.compile(
956 ActionType.SET_NW_SRC.toString() + "=(.*)")
958 if (sstr.matches()) {
959 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
960 resultStr.append(String.format(
961 "IP source address %s is not valid",
968 sstr = Pattern.compile(
969 ActionType.SET_NW_DST.toString() + "=(.*)")
971 if (sstr.matches()) {
972 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
973 resultStr.append(String.format(
974 "IP destination address %s is not valid",
981 sstr = Pattern.compile(
982 ActionType.SET_VLAN_ID.toString() + "=(.*)")
984 if (sstr.matches()) {
985 if ((sstr.group(1) != null)
986 && !isVlanIdValid(sstr.group(1))) {
987 resultStr.append(String.format(
988 "Vlan ID %s is not in the range 0 - 4095",
995 sstr = Pattern.compile(
996 ActionType.SET_VLAN_PCP.toString() + "=(.*)")
998 if (sstr.matches()) {
999 if ((sstr.group(1) != null)
1000 && !isVlanPriorityValid(sstr.group(1))) {
1003 .format("Vlan priority %s is not in the range 0 - 7",
1010 sstr = Pattern.compile(
1011 ActionType.SET_DL_SRC.toString() + "=(.*)")
1012 .matcher(actiongrp);
1013 if (sstr.matches()) {
1014 if ((sstr.group(1) != null)
1015 && !isL2AddressValid(sstr.group(1))) {
1018 .format("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
1025 sstr = Pattern.compile(
1026 ActionType.SET_DL_DST.toString() + "=(.*)")
1027 .matcher(actiongrp);
1028 if (sstr.matches()) {
1029 if ((sstr.group(1) != null)
1030 && !isL2AddressValid(sstr.group(1))) {
1033 .format("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
1040 sstr = Pattern.compile(
1041 ActionType.SET_NW_TOS.toString() + "=(.*)")
1042 .matcher(actiongrp);
1043 if (sstr.matches()) {
1044 if ((sstr.group(1) != null)
1045 && !isTOSBitsValid(sstr.group(1))) {
1048 .format("IP ToS bits %s is not in the range 0 - 63",
1055 sstr = Pattern.compile(
1056 ActionType.SET_TP_SRC.toString() + "=(.*)")
1057 .matcher(actiongrp);
1058 if (sstr.matches()) {
1059 if ((sstr.group(1) != null)
1060 && !isTpPortValid(sstr.group(1))) {
1061 resultStr.append(String.format(
1062 "Transport source port %s is not valid",
1069 sstr = Pattern.compile(
1070 ActionType.SET_TP_DST.toString() + "=(.*)")
1071 .matcher(actiongrp);
1072 if (sstr.matches()) {
1073 if ((sstr.group(1) != null)
1074 && !isTpPortValid(sstr.group(1))) {
1077 .format("Transport destination port %s is not valid",
1083 sstr = Pattern.compile(
1084 ActionType.SET_NEXT_HOP.toString() + "=(.*)")
1085 .matcher(actiongrp);
1086 if (sstr.matches()) {
1087 String nextHopInfo = sstr.group(1);
1088 String values[] = nextHopInfo.split("//");
1089 String address = values[0].trim();
1091 if ((address == null) || !isOutputNextHopValid(address)) {
1092 resultStr.append(String.format(
1093 "next hop %s is not valid", sstr.group(1)));
1100 // Check against the container flow
1101 if ((container != null)
1102 && conflictWithContainerFlow(container, resultStr)) {
1105 } catch (NumberFormatException e) {
1106 resultStr.append(String.format("Invalid number format %s",
1114 public FlowEntry getFlowEntry() {
1115 return new FlowEntry(FlowConfig.staticFlowsGroup, this.name,
1116 this.getFlow(), this.getNode());
1119 public Flow getFlow() {
1120 Match match = new Match();
1122 if (this.ingressPort != null) {
1125 NodeConnectorCreator.createOFNodeConnector(
1126 Short.parseShort(ingressPort), getNode()));
1128 if (this.dlSrc != null) {
1129 match.setField(MatchType.DL_SRC,
1130 HexEncode.bytesFromHexString(this.dlSrc));
1132 if (this.dlDst != null) {
1133 match.setField(MatchType.DL_DST,
1134 HexEncode.bytesFromHexString(this.dlDst));
1136 if (this.etherType != null) {
1137 match.setField(MatchType.DL_TYPE, Integer.decode(etherType)
1140 if (this.vlanId != null) {
1141 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1143 if (this.vlanPriority != null) {
1144 match.setField(MatchType.DL_VLAN_PR,
1145 Byte.parseByte(this.vlanPriority));
1147 if (this.nwSrc != null) {
1148 String parts[] = this.nwSrc.split("/");
1149 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1150 InetAddress mask = null;
1151 if (parts.length > 1) {
1152 int maskLen = Integer.parseInt(parts[1]);
1153 mask = NetUtils.getInetNetworkMask(maskLen,
1154 ip instanceof Inet6Address);
1156 match.setField(MatchType.NW_SRC, ip, mask);
1158 if (this.nwDst != null) {
1159 String parts[] = this.nwDst.split("/");
1160 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1161 InetAddress mask = null;
1162 if (parts.length > 1) {
1163 int maskLen = Integer.parseInt(parts[1]);
1164 mask = NetUtils.getInetNetworkMask(maskLen,
1165 ip instanceof Inet6Address);
1167 match.setField(MatchType.NW_DST, ip, mask);
1169 if (this.protocol != null) {
1170 match.setField(MatchType.NW_PROTO,
1171 IPProtocols.getProtocolNumberByte(this.protocol));
1173 if (this.tosBits != null) {
1174 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1176 if (this.tpSrc != null) {
1177 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc)
1180 if (this.tpDst != null) {
1181 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst)
1185 Flow flow = new Flow(match, getActionList());
1186 if (this.cookie != null) {
1187 flow.setId(Long.parseLong(cookie));
1189 if (this.hardTimeout != null) {
1190 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1192 if (this.idleTimeout != null) {
1193 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1195 if (this.priority != null) {
1196 flow.setPriority(Integer.decode(this.priority).shortValue());
1201 public boolean isOutputNextHopValid(String onh) {
1206 * For now, only takes IPv4 or IPv6 address
1208 return (NetUtils.isIPv4AddressValid(onh) || NetUtils
1209 .isIPv6AddressValid(onh));
1212 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1213 return (this.name.equals(that.name) && this.node.equals(that.node));
1216 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1217 return (this.name.equals(name) && this.node.equals(node));
1220 public boolean onNode(Node node) {
1221 return this.node.equals(node);
1224 public static List<String> getSupportedNextHopTypes() {
1225 List<String> s = new ArrayList<String>();
1226 for (SetNextHopType nh : SetNextHopType.values()) {
1227 s.add(nh.toString());
1232 public void toggleStatus() {
1233 installInHw = (installInHw == null) ? "true" : (installInHw
1234 .equals("true")) ? "false" : "true";
1238 * Parses the actions string and return the List of SAL Action No syntax
1239 * check run, as this function will be called when the config validation
1240 * check has already been performed
1242 private List<Action> getActionList() {
1243 List<Action> actionList = new ArrayList<Action>();
1245 if (actions != null) {
1247 for (String actiongrp : actions) {
1248 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(
1250 if (sstr.matches()) {
1251 for (String t : sstr.group(1).split(",")) {
1252 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1254 if (n.group(1) != null) {
1255 short ofPort = Short.parseShort(n.group(1));
1256 actionList.add(new Output(NodeConnectorCreator
1257 .createOFNodeConnector(ofPort,
1265 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(
1267 if (sstr.matches()) {
1268 actionList.add(new Drop());
1272 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(
1274 if (sstr.matches()) {
1275 actionList.add(new Loopback());
1279 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(
1281 if (sstr.matches()) {
1282 actionList.add(new Flood());
1286 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(
1288 if (sstr.matches()) {
1289 actionList.add(new SwPath());
1293 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(
1295 if (sstr.matches()) {
1296 actionList.add(new HwPath());
1300 sstr = Pattern.compile(ActionType.CONTROLLER.toString())
1301 .matcher(actiongrp);
1302 if (sstr.matches()) {
1303 actionList.add(new Controller());
1307 sstr = Pattern.compile(
1308 ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(
1310 if (sstr.matches()) {
1311 actionList.add(new SetVlanId(
1312 Short.parseShort(sstr.group(1))));
1316 sstr = Pattern.compile(
1317 ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(
1319 if (sstr.matches()) {
1321 .add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1325 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(
1327 if (sstr.matches()) {
1328 actionList.add(new PopVlan());
1332 sstr = Pattern.compile(
1333 ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(
1335 if (sstr.matches()) {
1336 actionList.add(new SetDlSrc(HexEncode
1337 .bytesFromHexString(sstr.group(1))));
1341 sstr = Pattern.compile(
1342 ActionType.SET_DL_DST.toString() + "=(.*)").matcher(
1344 if (sstr.matches()) {
1345 actionList.add(new SetDlDst(HexEncode
1346 .bytesFromHexString(sstr.group(1))));
1349 sstr = Pattern.compile(
1350 ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(
1352 if (sstr.matches()) {
1353 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr
1357 sstr = Pattern.compile(
1358 ActionType.SET_NW_DST.toString() + "=(.*)").matcher(
1360 if (sstr.matches()) {
1361 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr
1366 sstr = Pattern.compile(
1367 ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(
1369 if (sstr.matches()) {
1370 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1374 sstr = Pattern.compile(
1375 ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(
1377 if (sstr.matches()) {
1379 .add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1383 sstr = Pattern.compile(
1384 ActionType.SET_TP_DST.toString() + "=(.*)").matcher(
1386 if (sstr.matches()) {
1388 .add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1392 sstr = Pattern.compile(
1393 ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(
1395 if (sstr.matches()) {
1396 log.warn("We do not handle next hop action yet....");