3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.controller.forwardingrulesmanager;
12 import java.io.Serializable;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.util.ArrayList;
16 import java.util.List;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
21 import javax.xml.bind.annotation.XmlAccessType;
22 import javax.xml.bind.annotation.XmlAccessorType;
23 import javax.xml.bind.annotation.XmlElement;
24 import javax.xml.bind.annotation.XmlRootElement;
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.SetNwDst;
38 import org.opendaylight.controller.sal.action.SetNwSrc;
39 import org.opendaylight.controller.sal.action.SetNwTos;
40 import org.opendaylight.controller.sal.action.SetTpDst;
41 import org.opendaylight.controller.sal.action.SetTpSrc;
42 import org.opendaylight.controller.sal.action.SetVlanId;
43 import org.opendaylight.controller.sal.action.SetVlanPcp;
44 import org.opendaylight.controller.sal.action.SwPath;
45 import org.opendaylight.controller.sal.core.ContainerFlow;
46 import org.opendaylight.controller.sal.core.IContainer;
47 import org.opendaylight.controller.sal.core.Node;
48 import org.opendaylight.controller.sal.core.NodeConnector;
49 import org.opendaylight.controller.sal.flowprogrammer.Flow;
50 import org.opendaylight.controller.sal.match.Match;
51 import org.opendaylight.controller.sal.match.MatchType;
52 import org.opendaylight.controller.sal.utils.GlobalConstants;
53 import org.opendaylight.controller.sal.utils.HexEncode;
54 import org.opendaylight.controller.sal.utils.IPProtocols;
55 import org.opendaylight.controller.sal.utils.NetUtils;
56 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
57 import org.opendaylight.controller.sal.utils.ServiceHelper;
58 import org.opendaylight.controller.sal.utils.StatusCode;
59 import org.opendaylight.controller.switchmanager.ISwitchManager;
60 import org.opendaylight.controller.switchmanager.Switch;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
65 * Configuration Java Object which represents a flow configuration information
66 * for Forwarding Rules Manager.
70 @XmlAccessorType(XmlAccessType.NONE)
71 public class FlowConfig implements Serializable {
72 private static final long serialVersionUID = 1L;
73 private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
74 private static final String staticFlowsGroup = "**StaticFlows";
75 private boolean dynamic;
76 private String status;
79 * The order of the object data defined below is used directly in the UI built using JSP.
80 * Hence try to keep the order in a more logical way.
83 private String installInHw;
89 private String ingressPort;
90 private String portGroup;
92 private String priority;
94 private String etherType;
96 private String vlanId;
98 private String vlanPriority;
100 private String dlSrc;
102 private String dlDst;
104 private String nwSrc;
106 private String nwDst;
108 private String protocol;
110 private String tosBits;
112 private String tpSrc;
114 private String tpDst;
116 private String cookie;
118 private String idleTimeout;
120 private String hardTimeout;
122 private List<String> actions;
124 private enum EtherIPType {
128 private enum SetNextHopType {
129 CISCO_EXTENSION("Cisco NextHop Extension"), RESOLVE_L2RW(
130 "Resolve L2 Rewrite");
132 private SetNextHopType(String name) {
138 public String toString() {
142 public boolean equals(String type) {
143 if (type.trim().equalsIgnoreCase(name))
149 public FlowConfig() {
152 public FlowConfig(String installInHw, String name, Node node,
153 String priority, String cookie, String ingressPort,
154 String portGroup, String vlanId, String vlanPriority,
155 String etherType, String srcMac, String dstMac, String protocol,
156 String tosBits, String srcIP, String dstIP, String tpSrc,
157 String tpDst, String idleTimeout, String hardTimeout,
158 List<String> actions) {
160 this.installInHw = installInHw;
163 this.priority = priority;
164 this.cookie = cookie;
165 this.ingressPort = ingressPort;
166 this.portGroup = portGroup;
167 this.vlanId = vlanId;
168 this.vlanPriority = vlanPriority;
169 this.etherType = etherType;
172 this.protocol = protocol;
173 this.tosBits = tosBits;
178 this.idleTimeout = idleTimeout;
179 this.hardTimeout = hardTimeout;
180 this.actions = actions;
181 this.status = StatusCode.SUCCESS.toString();
184 public FlowConfig(FlowConfig from) {
185 this.installInHw = from.installInHw;
186 this.name = from.name;
187 this.node = from.node;
188 this.priority = from.priority;
189 this.cookie = from.cookie;
190 this.ingressPort = from.ingressPort;
191 this.portGroup = from.portGroup;
192 this.vlanId = from.vlanId;
193 this.vlanPriority = from.vlanPriority;
194 this.etherType = from.etherType;
195 this.dlSrc = from.dlSrc;
196 this.dlDst = from.dlDst;
197 this.protocol = from.protocol;
198 this.tosBits = from.tosBits;
199 this.nwSrc = from.nwSrc;
200 this.nwDst = from.nwDst;
201 this.tpSrc = from.tpSrc;
202 this.tpDst = from.tpDst;
203 this.idleTimeout = from.idleTimeout;
204 this.hardTimeout = from.hardTimeout;
205 this.actions = new ArrayList<String>(from.actions);
208 public boolean installInHw() {
209 if (installInHw == null) {
210 // backward compatibility
211 installInHw = "true";
213 return installInHw.equals("true");
216 public void setInstallInHw(boolean inHw) {
217 installInHw = inHw ? "true" : "false";
220 public String getInstallInHw() {
224 public boolean isInternalFlow() {
225 // Controller generated static flows have name starting with "**"
226 return (this.name != null && this.name.startsWith("**"));
229 public String getName() {
233 public void setName(String name) {
240 public Node getNode() {
244 public void setNode(Node node) {
248 public String getPriority() {
252 public void setPriority(String priority) {
253 this.priority = priority;
256 public String getCookie() {
260 public void setCookie(String cookie) {
261 this.cookie = cookie;
264 public String getIngressPort() {
268 public void setIngressPort(String ingressPort) {
269 this.ingressPort = ingressPort;
272 public String getPortGroup() {
277 public String toString() {
278 return "FlowConfig [dynamic=" + dynamic + ", status=" + status
279 + ", installInHw=" + installInHw + ", name=" + name
280 + ", switchId=" + node + ", ingressPort=" + ingressPort
281 + ", portGroup=" + portGroup + ", etherType=" + etherType
282 + ", priority=" + priority + ", vlanId=" + vlanId
283 + ", vlanPriority=" + vlanPriority + ", dlSrc=" + dlSrc
284 + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
285 + ", protocol=" + protocol + ", tosBits=" + tosBits
286 + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst + ", cookie="
287 + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout="
288 + hardTimeout + ", actions=" + actions + "]";
291 public void setPortGroup(String portGroup) {
292 this.portGroup = portGroup;
295 public String getVlanId() {
299 public void setVlanId(String vlanId) {
300 this.vlanId = vlanId;
303 public String getVlanPriority() {
307 public void setVlanPriority(String vlanPriority) {
308 this.vlanPriority = vlanPriority;
311 public String getEtherType() {
315 public void setEtherType(String etherType) {
316 this.etherType = etherType;
319 public String getSrcMac() {
323 public void setSrcMac(String srcMac) {
327 public String getDstMac() {
331 public void setDstMac(String dstMac) {
335 public String getProtocol() {
339 public void setProtocol(String protocol) {
340 this.protocol = protocol;
343 public String getTosBits() {
347 public void setTosBits(String tos_bits) {
348 this.tosBits = tos_bits;
351 public String getSrcIp() {
355 public void setSrcIp(String src_ip) {
359 public String getDstIp() {
363 public void setDstIp(String dst_ip) {
367 public String getSrcPort() {
371 public void setSrcPort(String src_port) {
372 this.tpSrc = src_port;
375 public String getDstPort() {
379 public void setDstPort(String dst_port) {
380 this.tpDst = dst_port;
383 public String getIdleTimeout() {
387 public void setIdleTimeout(String idleTimeout) {
388 this.idleTimeout = idleTimeout;
391 public String getHardTimeout() {
395 public void setHardTimeout(String hardTimeout) {
396 this.hardTimeout = hardTimeout;
399 public boolean isIPv6() {
400 if (NetUtils.isIPv6AddressValid(this.getSrcIp())
401 || NetUtils.isIPv6AddressValid(this.getDstIp())) {
407 public List<String> getActions() {
411 public void setActions(List<String> actions) {
412 this.actions = actions;
415 public boolean isPortGroupEnabled() {
416 return (portGroup != null);
419 public boolean isDynamic() {
423 public void setDynamic(boolean dynamic) {
424 this.dynamic = dynamic;
427 public String getStatus() {
431 public void setStatus(String status) {
432 this.status = status;
435 public boolean isStatusSuccessful() {
436 return status.equals(StatusCode.SUCCESS.toString());
440 public int hashCode() {
441 final int prime = 31;
443 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
444 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
445 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
446 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
447 result = prime * result + (dynamic ? 1231 : 1237);
448 result = prime * result
449 + ((etherType == null) ? 0 : etherType.hashCode());
450 result = prime * result
451 + ((ingressPort == null) ? 0 : ingressPort.hashCode());
452 result = prime * result + ((name == null) ? 0 : name.hashCode());
453 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
454 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
455 result = prime * result
456 + ((portGroup == null) ? 0 : portGroup.hashCode());
457 result = prime * result
458 + ((priority == null) ? 0 : priority.hashCode());
459 result = prime * result
460 + ((protocol == null) ? 0 : protocol.hashCode());
461 result = prime * result + ((node == null) ? 0 : node.hashCode());
462 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
463 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
464 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
465 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
466 result = prime * result
467 + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
468 result = prime * result
469 + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
470 result = prime * result
471 + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
476 public boolean equals(Object obj) {
481 if (getClass() != obj.getClass())
483 FlowConfig other = (FlowConfig) obj;
484 if (actions == null) {
485 if (other.actions != null)
487 } else if (!actions.equals(other.actions))
489 if (cookie == null) {
490 if (other.cookie != null)
492 } else if (!cookie.equals(other.cookie))
495 if (other.dlDst != null)
497 } else if (!dlDst.equals(other.dlDst))
500 if (other.dlSrc != null)
502 } else if (!dlSrc.equals(other.dlSrc))
504 if (dynamic != other.dynamic)
506 if (etherType == null) {
507 if (other.etherType != null)
509 } else if (!etherType.equals(other.etherType))
511 if (ingressPort == null) {
512 if (other.ingressPort != null)
514 } else if (!ingressPort.equals(other.ingressPort))
517 if (other.name != null)
519 } else if (!name.equals(other.name))
522 if (other.nwDst != null)
524 } else if (!nwDst.equals(other.nwDst))
527 if (other.nwSrc != null)
529 } else if (!nwSrc.equals(other.nwSrc))
531 if (portGroup == null) {
532 if (other.portGroup != null)
534 } else if (!portGroup.equals(other.portGroup))
536 if (priority == null) {
537 if (other.priority != null)
539 } else if (!priority.equals(other.priority))
541 if (protocol == null) {
542 if (other.protocol != null)
544 } else if (!protocol.equals(other.protocol))
547 if (other.node != null)
549 } else if (!node.equals(other.node))
551 if (tosBits == null) {
552 if (other.tosBits != null)
554 } else if (!tosBits.equals(other.tosBits))
557 if (other.tpDst != null)
559 } else if (!tpDst.equals(other.tpDst))
562 if (other.tpSrc != null)
564 } else if (!tpSrc.equals(other.tpSrc))
566 if (vlanId == null) {
567 if (other.vlanId != null)
569 } else if (!vlanId.equals(other.vlanId))
571 if (vlanPriority == null) {
572 if (other.vlanPriority != null)
574 } else if (!vlanPriority.equals(other.vlanPriority))
576 if (idleTimeout == null) {
577 if (other.idleTimeout != null)
579 } else if (!idleTimeout.equals(other.idleTimeout))
581 if (hardTimeout == null) {
582 if (other.hardTimeout != null)
584 } else if (!hardTimeout.equals(other.hardTimeout))
589 public InetAddress getNextHopAddressForL2RWAction() {
590 if (actions != null) {
592 for (String actiongrp : actions) {
593 sstr = Pattern.compile("SET_NEXT_HOP=(.*)").matcher(actiongrp);
594 if (sstr.matches()) {
595 SetNextHopType setNHType = SetNextHopType.CISCO_EXTENSION;
596 String nextHopInfo = sstr.group(1);
597 String values[] = nextHopInfo.split("//");
598 String address = values[0].trim();
600 if (values.length > 1) {
601 type = values[1].trim();
605 for (SetNextHopType nh : SetNextHopType.values()) {
611 log.debug("Get Nexthop address = " + address + " Type = "
612 + setNHType.toString());
613 if (setNHType == SetNextHopType.RESOLVE_L2RW) {
615 return InetAddress.getByName(address);
616 } catch (Exception e) {
618 .debug("Exception during nextHopAddress resolution : "
628 public String getNextHopL2RWUsageError() {
629 return "Could not resolve NextHop IP Address for the selected Switch.<br>"
630 + "Please Check the following configurations.<br>"
631 + "1. Is the NextHop IP address directly connected to the Selected Switch<br>"
632 + "2. If appropriate Subnet Configurations are done in the Switch Manager<br>"
633 + "3. If the Nexthop IP-Address is Correct";
636 public boolean isL2AddressValid(String mac) {
641 Pattern macPattern = Pattern
642 .compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
643 Matcher mm = macPattern.matcher(mac);
647 "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f",
654 public boolean isPortValid(Switch sw, Short port) {
656 log.debug("port {} is not valid", port);
662 .debug("switch info is not available. Skip checking if port is part of a switch or not.");
666 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
667 for (NodeConnector nodeConnector : nodeConnectorSet) {
668 if (((Short) nodeConnector.getID()).equals(port)) {
672 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
676 public boolean isVlanIdValid(String vlanId) {
677 int vlan = Integer.decode(vlanId);
678 return ((vlan >= 0) && (vlan < 4096));
681 public boolean isVlanPriorityValid(String vlanPriority) {
682 int pri = Integer.decode(vlanPriority);
683 return ((pri >= 0) && (pri < 8));
686 public boolean isTOSBitsValid(String tosBits) {
687 int tos = Integer.decode(tosBits);
688 return ((tos >= 0) && (tos < 64));
691 public boolean isTpPortValid(String tpPort) {
692 int port = Integer.decode(tpPort);
693 return ((port > 0) && (port <= 0xffff));
696 public boolean isTimeoutValid(String timeout) {
697 int to = Integer.decode(timeout);
698 return ((to >= 0) && (to <= 0xffff));
701 private boolean conflictWithContainerFlow(IContainer container,
702 StringBuffer resultStr) {
703 // Return true if it's default container
704 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
708 // No container flow = no conflict
709 List<ContainerFlow> cFlowList = container.getContainerFlows();
710 if (((cFlowList == null)) || cFlowList.isEmpty()) {
714 // Check against each container's flow
715 Flow flow = this.getFlow();
717 // Configuration is rejected if it conflicts with _all_ the container flows
718 for (ContainerFlow cFlow : cFlowList) {
719 if (cFlow.allowsFlow(flow)) {
721 .trace("Config is congruent with at least one container flow");
725 String msg = "Flow Config conflicts with all existing container flows";
726 resultStr.append(msg);
732 public boolean isValid(IContainer container, StringBuffer resultStr) {
733 EtherIPType etype = EtherIPType.ANY;
734 EtherIPType ipsrctype = EtherIPType.ANY;
735 EtherIPType ipdsttype = EtherIPType.ANY;
737 String containerName = (container == null) ? GlobalConstants.DEFAULT
738 .toString() : container.getName();
739 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
740 .getInstance(ISwitchManager.class, containerName, this);
745 resultStr.append(String.format("Name is null"));
749 resultStr.append(String.format("Node is null"));
752 if (switchManager != null) {
753 for (Switch device : switchManager.getNetworkDevices()) {
754 if (device.getNode().equals(node)) {
761 .append(String.format("Node %s not found", node));
765 log.debug("switchmanager is not set yet");
768 if (priority != null) {
769 if (Integer.decode(priority) < 0
770 || (Integer.decode(priority) > 65535)) {
771 resultStr.append(String.format(
772 "priority %s is not in the range 0 - 65535",
778 // make sure it's a valid number
782 if (ingressPort != null) {
783 Short port = Short.decode(ingressPort);
784 if (isPortValid(sw, port) == false) {
788 "Ingress port %d is not valid for the Switch",
790 if ((container != null)
791 && !container.getName().equals(
792 GlobalConstants.DEFAULT.toString())) {
794 .append(" in Container " + container.getName());
800 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
801 resultStr.append(String.format(
802 "Vlan ID %s is not in the range 0 - 4095", vlanId));
806 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
807 resultStr.append(String.format(
808 "Vlan priority %s is not in the range 0 - 7",
813 if (etherType != null) {
814 int type = Integer.decode(etherType);
815 if ((type < 0) || (type > 0xffff)) {
816 resultStr.append(String.format(
817 "Ethernet type %s is not valid", etherType));
821 etype = EtherIPType.V4;
822 else if (type == 0x86dd)
823 etype = EtherIPType.V6;
827 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
828 resultStr.append(String.format(
829 "IP ToS bits %s is not in the range 0 - 63", tosBits));
833 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
834 resultStr.append(String.format(
835 "Transport source port %s is not valid", tpSrc));
838 if ((tpDst != null) && !isTpPortValid(tpDst)) {
839 resultStr.append(String.format(
840 "Transport destination port %s is not valid", tpDst));
844 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
848 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
853 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
857 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
863 if (NetUtils.isIPv4AddressValid(nwSrc)) {
864 ipsrctype = EtherIPType.V4;
865 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
866 ipsrctype = EtherIPType.V6;
868 resultStr.append(String.format(
869 "IP source address %s is not valid", nwSrc));
875 if (NetUtils.isIPv4AddressValid(nwDst)) {
876 ipdsttype = EtherIPType.V4;
877 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
878 ipdsttype = EtherIPType.V6;
880 resultStr.append(String.format(
881 "IP destination address %s is not valid", nwDst));
886 if (etype != EtherIPType.ANY) {
887 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
888 resultStr.append(String
889 .format("Type mismatch between Ethernet & Src IP"));
892 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
893 resultStr.append(String
894 .format("Type mismatch between Ethernet & Dst IP"));
898 if (ipsrctype != ipdsttype) {
899 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
901 .append(String.format("IP Src Dest Type mismatch"));
906 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
907 resultStr.append(String.format(
908 "Idle Timeout value %s is not valid", idleTimeout));
912 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
913 resultStr.append(String.format(
914 "Hard Timeout value %s is not valid", hardTimeout));
919 if (actions != null && !actions.isEmpty()) {
920 for (String actiongrp : actions) {
921 // check output ports
922 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
923 if (sstr.matches()) {
924 for (String t : sstr.group(1).split(",")) {
925 Matcher n = Pattern.compile("(?:(\\d+))")
928 if (n.group(1) != null) {
929 Short port = Short.parseShort(n.group(1));
930 if (isPortValid(sw, port) == false) {
934 "Output port %d is not valid for this switch",
936 if ((container != null)
937 && !container.getName().equals(
938 GlobalConstants.DEFAULT
940 resultStr.append(" in Container "
941 + container.getName());
951 sstr = Pattern.compile(ActionType.FLOOD.toString())
953 if (sstr.matches()) {
954 if (container != null) {
955 resultStr.append(String.format(
956 "flood is not allowed in container %s",
957 container.getName()));
963 sstr = Pattern.compile(
964 ActionType.SET_NW_SRC.toString() + "=(.*)")
966 if (sstr.matches()) {
967 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
968 resultStr.append(String.format(
969 "IP source address %s is not valid", sstr
976 sstr = Pattern.compile(
977 ActionType.SET_NW_DST.toString() + "=(.*)")
979 if (sstr.matches()) {
980 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
981 resultStr.append(String.format(
982 "IP destination address %s is not valid",
989 sstr = Pattern.compile(
990 ActionType.SET_VLAN_ID.toString() + "=(.*)")
992 if (sstr.matches()) {
993 if ((sstr.group(1) != null)
994 && !isVlanIdValid(sstr.group(1))) {
995 resultStr.append(String.format(
996 "Vlan ID %s is not in the range 0 - 4095",
1003 sstr = Pattern.compile(
1004 ActionType.SET_VLAN_PCP.toString() + "=(.*)")
1005 .matcher(actiongrp);
1006 if (sstr.matches()) {
1007 if ((sstr.group(1) != null)
1008 && !isVlanPriorityValid(sstr.group(1))) {
1012 "Vlan priority %s is not in the range 0 - 7",
1019 sstr = Pattern.compile(
1020 ActionType.SET_DL_SRC.toString() + "=(.*)")
1021 .matcher(actiongrp);
1022 if (sstr.matches()) {
1023 if ((sstr.group(1) != null)
1024 && !isL2AddressValid(sstr.group(1))) {
1028 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
1035 sstr = Pattern.compile(
1036 ActionType.SET_DL_DST.toString() + "=(.*)")
1037 .matcher(actiongrp);
1038 if (sstr.matches()) {
1039 if ((sstr.group(1) != null)
1040 && !isL2AddressValid(sstr.group(1))) {
1044 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
1051 sstr = Pattern.compile(
1052 ActionType.SET_NW_TOS.toString() + "=(.*)")
1053 .matcher(actiongrp);
1054 if (sstr.matches()) {
1055 if ((sstr.group(1) != null)
1056 && !isTOSBitsValid(sstr.group(1))) {
1060 "IP ToS bits %s is not in the range 0 - 63",
1067 sstr = Pattern.compile(
1068 ActionType.SET_TP_SRC.toString() + "=(.*)")
1069 .matcher(actiongrp);
1070 if (sstr.matches()) {
1071 if ((sstr.group(1) != null)
1072 && !isTpPortValid(sstr.group(1))) {
1073 resultStr.append(String.format(
1074 "Transport source port %s is not valid",
1081 sstr = Pattern.compile(
1082 ActionType.SET_TP_DST.toString() + "=(.*)")
1083 .matcher(actiongrp);
1084 if (sstr.matches()) {
1085 if ((sstr.group(1) != null)
1086 && !isTpPortValid(sstr.group(1))) {
1090 "Transport destination port %s is not valid",
1096 sstr = Pattern.compile(
1097 ActionType.SET_NEXT_HOP.toString() + "=(.*)")
1098 .matcher(actiongrp);
1099 if (sstr.matches()) {
1100 String nextHopInfo = sstr.group(1);
1101 String values[] = nextHopInfo.split("//");
1102 String address = values[0].trim();
1104 if ((address == null) || !isOutputNextHopValid(address)) {
1105 resultStr.append(String.format(
1106 "next hop %s is not valid", sstr.group(1)));
1113 // Check against the container flow
1114 if ((container != null)
1115 && conflictWithContainerFlow(container, resultStr)) {
1118 } catch (NumberFormatException e) {
1119 resultStr.append(String.format("Invalid number format %s", e
1127 public FlowEntry getFlowEntry() {
1128 return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this
1129 .getFlow(), this.getNode());
1132 public Flow getFlow() {
1133 Match match = new Match();
1135 if (this.ingressPort != null) {
1136 match.setField(MatchType.IN_PORT, NodeConnectorCreator
1137 .createOFNodeConnector(Short.parseShort(ingressPort),
1140 if (this.dlSrc != null) {
1141 match.setField(MatchType.DL_SRC, HexEncode
1142 .bytesFromHexString(this.dlSrc));
1144 if (this.dlDst != null) {
1145 match.setField(MatchType.DL_DST, HexEncode
1146 .bytesFromHexString(this.dlDst));
1148 if (this.etherType != null) {
1149 match.setField(MatchType.DL_TYPE, Integer.decode(etherType)
1152 if (this.vlanId != null) {
1153 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1155 if (this.vlanPriority != null) {
1156 match.setField(MatchType.DL_VLAN_PR, Byte
1157 .parseByte(this.vlanPriority));
1159 if (this.nwSrc != null) {
1160 String parts[] = this.nwSrc.split("/");
1161 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1162 InetAddress mask = null;
1163 if (parts.length > 1) {
1164 int maskLen = Integer.parseInt(parts[1]);
1165 mask = NetUtils.getInetNetworkMask(maskLen,
1166 ip instanceof Inet6Address);
1168 match.setField(MatchType.NW_SRC, ip, mask);
1170 if (this.nwDst != null) {
1171 String parts[] = this.nwDst.split("/");
1172 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1173 InetAddress mask = null;
1174 if (parts.length > 1) {
1175 int maskLen = Integer.parseInt(parts[1]);
1176 mask = NetUtils.getInetNetworkMask(maskLen,
1177 ip instanceof Inet6Address);
1179 match.setField(MatchType.NW_DST, ip, mask);
1181 if (this.protocol != null) {
1182 match.setField(MatchType.NW_PROTO, IPProtocols
1183 .getProtocolNumberByte(this.protocol));
1185 if (this.tosBits != null) {
1186 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1188 if (this.tpSrc != null) {
1189 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc)
1192 if (this.tpDst != null) {
1193 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst)
1197 Flow flow = new Flow(match, getActionList());
1198 if (this.cookie != null) {
1199 flow.setId(Long.parseLong(cookie));
1201 if (this.hardTimeout != null) {
1202 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1204 if (this.idleTimeout != null) {
1205 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1207 if (this.priority != null) {
1208 flow.setPriority(Integer.decode(this.priority).shortValue());
1213 public boolean isOutputNextHopValid(String onh) {
1218 * For now, only takes IPv4 or IPv6 address
1220 return (NetUtils.isIPv4AddressValid(onh) || NetUtils
1221 .isIPv6AddressValid(onh));
1224 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1225 return (this.name.equals(that.name) && this.node.equals(that.node));
1228 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1229 return (this.name.equals(name) && this.node.equals(node));
1232 public boolean onNode(Node node) {
1233 return this.node.equals(node);
1236 public static List<String> getSupportedNextHopTypes() {
1237 List<String> s = new ArrayList<String>();
1238 for (SetNextHopType nh : SetNextHopType.values()) {
1239 s.add(nh.toString());
1244 public void toggleStatus() {
1245 installInHw = (installInHw == null) ? "true" : (installInHw
1246 .equals("true")) ? "false" : "true";
1250 * Parses the actions string and return the List of SAL Action
1251 * No syntax check run, as this function will be called when the
1252 * config validation check has already been performed
1254 private List<Action> getActionList() {
1255 List<Action> actionList = new ArrayList<Action>();
1257 if (actions != null) {
1259 for (String actiongrp : actions) {
1260 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(
1262 if (sstr.matches()) {
1263 for (String t : sstr.group(1).split(",")) {
1264 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1266 if (n.group(1) != null) {
1267 short ofPort = Short.parseShort(n.group(1));
1268 actionList.add(new Output(NodeConnectorCreator
1269 .createOFNodeConnector(ofPort, this
1277 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(
1279 if (sstr.matches()) {
1280 actionList.add(new Drop());
1284 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(
1286 if (sstr.matches()) {
1287 actionList.add(new Loopback());
1291 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(
1293 if (sstr.matches()) {
1294 actionList.add(new Flood());
1298 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(
1300 if (sstr.matches()) {
1301 actionList.add(new SwPath());
1305 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(
1307 if (sstr.matches()) {
1308 actionList.add(new HwPath());
1312 sstr = Pattern.compile(ActionType.CONTROLLER.toString())
1313 .matcher(actiongrp);
1314 if (sstr.matches()) {
1315 actionList.add(new Controller());
1319 sstr = Pattern.compile(
1320 ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(
1322 if (sstr.matches()) {
1323 actionList.add(new SetVlanId(Short
1324 .parseShort(sstr.group(1))));
1328 sstr = Pattern.compile(
1329 ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(
1331 if (sstr.matches()) {
1333 .add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1337 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(
1339 if (sstr.matches()) {
1340 actionList.add(new PopVlan());
1344 sstr = Pattern.compile(
1345 ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(
1347 if (sstr.matches()) {
1348 actionList.add(new SetDlSrc(HexEncode
1349 .bytesFromHexString(sstr.group(1))));
1353 sstr = Pattern.compile(
1354 ActionType.SET_DL_DST.toString() + "=(.*)").matcher(
1356 if (sstr.matches()) {
1357 actionList.add(new SetDlDst(HexEncode
1358 .bytesFromHexString(sstr.group(1))));
1361 sstr = Pattern.compile(
1362 ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(
1364 if (sstr.matches()) {
1365 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr
1369 sstr = Pattern.compile(
1370 ActionType.SET_NW_DST.toString() + "=(.*)").matcher(
1372 if (sstr.matches()) {
1373 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr
1378 sstr = Pattern.compile(
1379 ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(
1381 if (sstr.matches()) {
1382 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1386 sstr = Pattern.compile(
1387 ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(
1389 if (sstr.matches()) {
1391 .add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1395 sstr = Pattern.compile(
1396 ActionType.SET_TP_DST.toString() + "=(.*)").matcher(
1398 if (sstr.matches()) {
1400 .add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1404 sstr = Pattern.compile(
1405 ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(
1407 if (sstr.matches()) {
1408 log.warn("We do not handle next hop action yet....");