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 = {} Type = {}", address, setNHType.toString());
612 if (setNHType == SetNextHopType.RESOLVE_L2RW) {
614 return InetAddress.getByName(address);
615 } catch (Exception e) {
617 .debug("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);
646 "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f",
653 public boolean isPortValid(Switch sw, Short port) {
655 log.debug("port {} is not valid", port);
661 .debug("switch info is not available. Skip checking if port is part of a switch or not.");
665 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
666 for (NodeConnector nodeConnector : nodeConnectorSet) {
667 if (((Short) nodeConnector.getID()).equals(port)) {
671 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
675 public boolean isVlanIdValid(String vlanId) {
676 int vlan = Integer.decode(vlanId);
677 return ((vlan >= 0) && (vlan < 4096));
680 public boolean isVlanPriorityValid(String vlanPriority) {
681 int pri = Integer.decode(vlanPriority);
682 return ((pri >= 0) && (pri < 8));
685 public boolean isTOSBitsValid(String tosBits) {
686 int tos = Integer.decode(tosBits);
687 return ((tos >= 0) && (tos < 64));
690 public boolean isTpPortValid(String tpPort) {
691 int port = Integer.decode(tpPort);
692 return ((port > 0) && (port <= 0xffff));
695 public boolean isTimeoutValid(String timeout) {
696 int to = Integer.decode(timeout);
697 return ((to >= 0) && (to <= 0xffff));
700 private boolean conflictWithContainerFlow(IContainer container,
701 StringBuffer resultStr) {
702 // Return true if it's default container
703 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
707 // No container flow = no conflict
708 List<ContainerFlow> cFlowList = container.getContainerFlows();
709 if (((cFlowList == null)) || cFlowList.isEmpty()) {
713 // Check against each container's flow
714 Flow flow = this.getFlow();
716 // Configuration is rejected if it conflicts with _all_ the container flows
717 for (ContainerFlow cFlow : cFlowList) {
718 if (cFlow.allowsFlow(flow)) {
720 .trace("Config is congruent with at least one container flow");
724 String msg = "Flow Config conflicts with all existing container flows";
725 resultStr.append(msg);
731 public boolean isValid(IContainer container, StringBuffer resultStr) {
732 EtherIPType etype = EtherIPType.ANY;
733 EtherIPType ipsrctype = EtherIPType.ANY;
734 EtherIPType ipdsttype = EtherIPType.ANY;
736 String containerName = (container == null) ? GlobalConstants.DEFAULT
737 .toString() : container.getName();
738 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
739 .getInstance(ISwitchManager.class, containerName, this);
744 resultStr.append(String.format("Name is null"));
748 resultStr.append(String.format("Node is null"));
751 if (switchManager != null) {
752 for (Switch device : switchManager.getNetworkDevices()) {
753 if (device.getNode().equals(node)) {
760 .append(String.format("Node %s not found", node));
764 log.debug("switchmanager is not set yet");
767 if (priority != null) {
768 if (Integer.decode(priority) < 0
769 || (Integer.decode(priority) > 65535)) {
770 resultStr.append(String.format(
771 "priority %s is not in the range 0 - 65535",
777 // make sure it's a valid number
781 if (ingressPort != null) {
782 Short port = Short.decode(ingressPort);
783 if (isPortValid(sw, port) == false) {
787 "Ingress port %d is not valid for the Switch",
789 if ((container != null)
790 && !container.getName().equals(
791 GlobalConstants.DEFAULT.toString())) {
793 .append(" in Container " + container.getName());
799 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
800 resultStr.append(String.format(
801 "Vlan ID %s is not in the range 0 - 4095", vlanId));
805 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
806 resultStr.append(String.format(
807 "Vlan priority %s is not in the range 0 - 7",
812 if (etherType != null) {
813 int type = Integer.decode(etherType);
814 if ((type < 0) || (type > 0xffff)) {
815 resultStr.append(String.format(
816 "Ethernet type %s is not valid", etherType));
820 etype = EtherIPType.V4;
821 else if (type == 0x86dd)
822 etype = EtherIPType.V6;
826 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
827 resultStr.append(String.format(
828 "IP ToS bits %s is not in the range 0 - 63", tosBits));
832 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
833 resultStr.append(String.format(
834 "Transport source port %s is not valid", tpSrc));
837 if ((tpDst != null) && !isTpPortValid(tpDst)) {
838 resultStr.append(String.format(
839 "Transport destination port %s is not valid", tpDst));
843 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
847 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
852 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
856 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
862 if (NetUtils.isIPv4AddressValid(nwSrc)) {
863 ipsrctype = EtherIPType.V4;
864 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
865 ipsrctype = EtherIPType.V6;
867 resultStr.append(String.format(
868 "IP source address %s is not valid", nwSrc));
874 if (NetUtils.isIPv4AddressValid(nwDst)) {
875 ipdsttype = EtherIPType.V4;
876 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
877 ipdsttype = EtherIPType.V6;
879 resultStr.append(String.format(
880 "IP destination address %s is not valid", nwDst));
885 if (etype != EtherIPType.ANY) {
886 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
887 resultStr.append(String
888 .format("Type mismatch between Ethernet & Src IP"));
891 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
892 resultStr.append(String
893 .format("Type mismatch between Ethernet & Dst IP"));
897 if (ipsrctype != ipdsttype) {
898 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
900 .append(String.format("IP Src Dest Type mismatch"));
905 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
906 resultStr.append(String.format(
907 "Idle Timeout value %s is not valid", idleTimeout));
911 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
912 resultStr.append(String.format(
913 "Hard Timeout value %s is not valid", hardTimeout));
918 if (actions != null && !actions.isEmpty()) {
919 for (String actiongrp : actions) {
920 // check output ports
921 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
922 if (sstr.matches()) {
923 for (String t : sstr.group(1).split(",")) {
924 Matcher n = Pattern.compile("(?:(\\d+))")
927 if (n.group(1) != null) {
928 Short port = Short.parseShort(n.group(1));
929 if (isPortValid(sw, port) == false) {
933 "Output port %d is not valid for this switch",
935 if ((container != null)
936 && !container.getName().equals(
937 GlobalConstants.DEFAULT
939 resultStr.append(" in Container "
940 + container.getName());
950 sstr = Pattern.compile(ActionType.FLOOD.toString())
952 if (sstr.matches()) {
953 if (container != null) {
954 resultStr.append(String.format(
955 "flood is not allowed in container %s",
956 container.getName()));
962 sstr = Pattern.compile(
963 ActionType.SET_NW_SRC.toString() + "=(.*)")
965 if (sstr.matches()) {
966 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
967 resultStr.append(String.format(
968 "IP source address %s is not valid", sstr
975 sstr = Pattern.compile(
976 ActionType.SET_NW_DST.toString() + "=(.*)")
978 if (sstr.matches()) {
979 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
980 resultStr.append(String.format(
981 "IP destination address %s is not valid",
988 sstr = Pattern.compile(
989 ActionType.SET_VLAN_ID.toString() + "=(.*)")
991 if (sstr.matches()) {
992 if ((sstr.group(1) != null)
993 && !isVlanIdValid(sstr.group(1))) {
994 resultStr.append(String.format(
995 "Vlan ID %s is not in the range 0 - 4095",
1002 sstr = Pattern.compile(
1003 ActionType.SET_VLAN_PCP.toString() + "=(.*)")
1004 .matcher(actiongrp);
1005 if (sstr.matches()) {
1006 if ((sstr.group(1) != null)
1007 && !isVlanPriorityValid(sstr.group(1))) {
1011 "Vlan priority %s is not in the range 0 - 7",
1018 sstr = Pattern.compile(
1019 ActionType.SET_DL_SRC.toString() + "=(.*)")
1020 .matcher(actiongrp);
1021 if (sstr.matches()) {
1022 if ((sstr.group(1) != null)
1023 && !isL2AddressValid(sstr.group(1))) {
1027 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
1034 sstr = Pattern.compile(
1035 ActionType.SET_DL_DST.toString() + "=(.*)")
1036 .matcher(actiongrp);
1037 if (sstr.matches()) {
1038 if ((sstr.group(1) != null)
1039 && !isL2AddressValid(sstr.group(1))) {
1043 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
1050 sstr = Pattern.compile(
1051 ActionType.SET_NW_TOS.toString() + "=(.*)")
1052 .matcher(actiongrp);
1053 if (sstr.matches()) {
1054 if ((sstr.group(1) != null)
1055 && !isTOSBitsValid(sstr.group(1))) {
1059 "IP ToS bits %s is not in the range 0 - 63",
1066 sstr = Pattern.compile(
1067 ActionType.SET_TP_SRC.toString() + "=(.*)")
1068 .matcher(actiongrp);
1069 if (sstr.matches()) {
1070 if ((sstr.group(1) != null)
1071 && !isTpPortValid(sstr.group(1))) {
1072 resultStr.append(String.format(
1073 "Transport source port %s is not valid",
1080 sstr = Pattern.compile(
1081 ActionType.SET_TP_DST.toString() + "=(.*)")
1082 .matcher(actiongrp);
1083 if (sstr.matches()) {
1084 if ((sstr.group(1) != null)
1085 && !isTpPortValid(sstr.group(1))) {
1089 "Transport destination port %s is not valid",
1095 sstr = Pattern.compile(
1096 ActionType.SET_NEXT_HOP.toString() + "=(.*)")
1097 .matcher(actiongrp);
1098 if (sstr.matches()) {
1099 String nextHopInfo = sstr.group(1);
1100 String values[] = nextHopInfo.split("//");
1101 String address = values[0].trim();
1103 if ((address == null) || !isOutputNextHopValid(address)) {
1104 resultStr.append(String.format(
1105 "next hop %s is not valid", sstr.group(1)));
1112 // Check against the container flow
1113 if ((container != null)
1114 && conflictWithContainerFlow(container, resultStr)) {
1117 } catch (NumberFormatException e) {
1118 resultStr.append(String.format("Invalid number format %s", e
1126 public FlowEntry getFlowEntry() {
1127 return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this
1128 .getFlow(), this.getNode());
1131 public Flow getFlow() {
1132 Match match = new Match();
1134 if (this.ingressPort != null) {
1135 match.setField(MatchType.IN_PORT, NodeConnectorCreator
1136 .createOFNodeConnector(Short.parseShort(ingressPort),
1139 if (this.dlSrc != null) {
1140 match.setField(MatchType.DL_SRC, HexEncode
1141 .bytesFromHexString(this.dlSrc));
1143 if (this.dlDst != null) {
1144 match.setField(MatchType.DL_DST, HexEncode
1145 .bytesFromHexString(this.dlDst));
1147 if (this.etherType != null) {
1148 match.setField(MatchType.DL_TYPE, Integer.decode(etherType)
1151 if (this.vlanId != null) {
1152 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1154 if (this.vlanPriority != null) {
1155 match.setField(MatchType.DL_VLAN_PR, Byte
1156 .parseByte(this.vlanPriority));
1158 if (this.nwSrc != null) {
1159 String parts[] = this.nwSrc.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_SRC, ip, mask);
1169 if (this.nwDst != null) {
1170 String parts[] = this.nwDst.split("/");
1171 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1172 InetAddress mask = null;
1173 if (parts.length > 1) {
1174 int maskLen = Integer.parseInt(parts[1]);
1175 mask = NetUtils.getInetNetworkMask(maskLen,
1176 ip instanceof Inet6Address);
1178 match.setField(MatchType.NW_DST, ip, mask);
1180 if (this.protocol != null) {
1181 match.setField(MatchType.NW_PROTO, IPProtocols
1182 .getProtocolNumberByte(this.protocol));
1184 if (this.tosBits != null) {
1185 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1187 if (this.tpSrc != null) {
1188 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc)
1191 if (this.tpDst != null) {
1192 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst)
1196 Flow flow = new Flow(match, getActionList());
1197 if (this.cookie != null) {
1198 flow.setId(Long.parseLong(cookie));
1200 if (this.hardTimeout != null) {
1201 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1203 if (this.idleTimeout != null) {
1204 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1206 if (this.priority != null) {
1207 flow.setPriority(Integer.decode(this.priority).shortValue());
1212 public boolean isOutputNextHopValid(String onh) {
1217 * For now, only takes IPv4 or IPv6 address
1219 return (NetUtils.isIPv4AddressValid(onh) || NetUtils
1220 .isIPv6AddressValid(onh));
1223 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1224 return (this.name.equals(that.name) && this.node.equals(that.node));
1227 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1228 return (this.name.equals(name) && this.node.equals(node));
1231 public boolean onNode(Node node) {
1232 return this.node.equals(node);
1235 public static List<String> getSupportedNextHopTypes() {
1236 List<String> s = new ArrayList<String>();
1237 for (SetNextHopType nh : SetNextHopType.values()) {
1238 s.add(nh.toString());
1243 public void toggleStatus() {
1244 installInHw = (installInHw == null) ? "true" : (installInHw
1245 .equals("true")) ? "false" : "true";
1249 * Parses the actions string and return the List of SAL Action
1250 * No syntax check run, as this function will be called when the
1251 * config validation check has already been performed
1253 private List<Action> getActionList() {
1254 List<Action> actionList = new ArrayList<Action>();
1256 if (actions != null) {
1258 for (String actiongrp : actions) {
1259 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(
1261 if (sstr.matches()) {
1262 for (String t : sstr.group(1).split(",")) {
1263 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1265 if (n.group(1) != null) {
1266 short ofPort = Short.parseShort(n.group(1));
1267 actionList.add(new Output(NodeConnectorCreator
1268 .createOFNodeConnector(ofPort, this
1276 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(
1278 if (sstr.matches()) {
1279 actionList.add(new Drop());
1283 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(
1285 if (sstr.matches()) {
1286 actionList.add(new Loopback());
1290 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(
1292 if (sstr.matches()) {
1293 actionList.add(new Flood());
1297 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(
1299 if (sstr.matches()) {
1300 actionList.add(new SwPath());
1304 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(
1306 if (sstr.matches()) {
1307 actionList.add(new HwPath());
1311 sstr = Pattern.compile(ActionType.CONTROLLER.toString())
1312 .matcher(actiongrp);
1313 if (sstr.matches()) {
1314 actionList.add(new Controller());
1318 sstr = Pattern.compile(
1319 ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(
1321 if (sstr.matches()) {
1322 actionList.add(new SetVlanId(Short
1323 .parseShort(sstr.group(1))));
1327 sstr = Pattern.compile(
1328 ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(
1330 if (sstr.matches()) {
1332 .add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1336 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(
1338 if (sstr.matches()) {
1339 actionList.add(new PopVlan());
1343 sstr = Pattern.compile(
1344 ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(
1346 if (sstr.matches()) {
1347 actionList.add(new SetDlSrc(HexEncode
1348 .bytesFromHexString(sstr.group(1))));
1352 sstr = Pattern.compile(
1353 ActionType.SET_DL_DST.toString() + "=(.*)").matcher(
1355 if (sstr.matches()) {
1356 actionList.add(new SetDlDst(HexEncode
1357 .bytesFromHexString(sstr.group(1))));
1360 sstr = Pattern.compile(
1361 ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(
1363 if (sstr.matches()) {
1364 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr
1368 sstr = Pattern.compile(
1369 ActionType.SET_NW_DST.toString() + "=(.*)").matcher(
1371 if (sstr.matches()) {
1372 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr
1377 sstr = Pattern.compile(
1378 ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(
1380 if (sstr.matches()) {
1381 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1385 sstr = Pattern.compile(
1386 ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(
1388 if (sstr.matches()) {
1390 .add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1394 sstr = Pattern.compile(
1395 ActionType.SET_TP_DST.toString() + "=(.*)").matcher(
1397 if (sstr.matches()) {
1399 .add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1403 sstr = Pattern.compile(
1404 ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(
1406 if (sstr.matches()) {
1407 log.warn("We do not handle next hop action yet....");