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.lang.reflect.Field;
14 import java.net.Inet6Address;
15 import java.net.InetAddress;
16 import java.util.ArrayList;
17 import java.util.List;
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
22 import javax.xml.bind.annotation.XmlAccessType;
23 import javax.xml.bind.annotation.XmlAccessorType;
24 import javax.xml.bind.annotation.XmlElement;
25 import javax.xml.bind.annotation.XmlRootElement;
27 import org.opendaylight.controller.sal.action.Action;
28 import org.opendaylight.controller.sal.action.ActionType;
29 import org.opendaylight.controller.sal.action.Controller;
30 import org.opendaylight.controller.sal.action.Drop;
31 import org.opendaylight.controller.sal.action.Flood;
32 import org.opendaylight.controller.sal.action.HwPath;
33 import org.opendaylight.controller.sal.action.Loopback;
34 import org.opendaylight.controller.sal.action.Output;
35 import org.opendaylight.controller.sal.action.PopVlan;
36 import org.opendaylight.controller.sal.action.SetDlDst;
37 import org.opendaylight.controller.sal.action.SetDlSrc;
38 import org.opendaylight.controller.sal.action.SetNwDst;
39 import org.opendaylight.controller.sal.action.SetNwSrc;
40 import org.opendaylight.controller.sal.action.SetNwTos;
41 import org.opendaylight.controller.sal.action.SetTpDst;
42 import org.opendaylight.controller.sal.action.SetTpSrc;
43 import org.opendaylight.controller.sal.action.SetVlanId;
44 import org.opendaylight.controller.sal.action.SetVlanPcp;
45 import org.opendaylight.controller.sal.action.SwPath;
46 import org.opendaylight.controller.sal.core.ContainerFlow;
47 import org.opendaylight.controller.sal.core.IContainer;
48 import org.opendaylight.controller.sal.core.Node;
49 import org.opendaylight.controller.sal.core.NodeConnector;
50 import org.opendaylight.controller.sal.flowprogrammer.Flow;
51 import org.opendaylight.controller.sal.match.Match;
52 import org.opendaylight.controller.sal.match.MatchType;
53 import org.opendaylight.controller.sal.utils.GlobalConstants;
54 import org.opendaylight.controller.sal.utils.HexEncode;
55 import org.opendaylight.controller.sal.utils.IPProtocols;
56 import org.opendaylight.controller.sal.utils.NetUtils;
57 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
58 import org.opendaylight.controller.sal.utils.ServiceHelper;
59 import org.opendaylight.controller.sal.utils.StatusCode;
60 import org.opendaylight.controller.switchmanager.ISwitchManager;
61 import org.opendaylight.controller.switchmanager.Switch;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
66 * Configuration Java Object which represents a flow configuration information
67 * for Forwarding Rrules Manager.
71 @XmlAccessorType(XmlAccessType.NONE)
72 public class FlowConfig implements Serializable {
73 private static final long serialVersionUID = 1L;
74 private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
75 private static final String staticFlowsGroup = "**StaticFlows";
76 private boolean dynamic;
77 private String status;
80 * The order of the object data defined below is used directly in the UI built using JSP.
81 * Hence try to keep the order in a more logical way.
84 private String installInHw;
90 private String ingressPort;
91 private String portGroup;
93 private String priority;
95 private String etherType;
97 private String vlanId;
99 private String vlanPriority;
101 private String dlSrc;
103 private String dlDst;
105 private String nwSrc;
107 private String nwDst;
109 private String protocol;
111 private String tosBits;
113 private String tpSrc;
115 private String tpDst;
117 private String cookie;
119 private String idleTimeout;
121 private String hardTimeout;
123 private List<String> actions;
125 private enum EtherIPType {
129 private enum SetNextHopType {
130 CISCO_EXTENSION("Cisco NextHop Extension"), RESOLVE_L2RW(
131 "Resolve L2 Rewrite");
133 private SetNextHopType(String name) {
139 public String toString() {
143 public boolean equals(String type) {
144 if (type.trim().equalsIgnoreCase(name))
150 public FlowConfig() {
153 public FlowConfig(String installInHw, String name, Node node,
154 String priority, String cookie, String ingressPort,
155 String portGroup, String vlanId, String vlanPriority,
156 String etherType, String srcMac, String dstMac, String protocol,
157 String tosBits, String srcIP, String dstIP, String tpSrc,
158 String tpDst, String idleTimeout, String hardTimeout,
159 List<String> actions) {
161 this.installInHw = installInHw;
164 this.priority = priority;
165 this.cookie = cookie;
166 this.ingressPort = ingressPort;
167 this.portGroup = portGroup;
168 this.vlanId = vlanId;
169 this.vlanPriority = vlanPriority;
170 this.etherType = etherType;
173 this.protocol = protocol;
174 this.tosBits = tosBits;
179 this.idleTimeout = idleTimeout;
180 this.hardTimeout = hardTimeout;
181 this.actions = actions;
182 this.status = StatusCode.SUCCESS.toString();
185 public FlowConfig(FlowConfig from) {
186 this.installInHw = from.installInHw;
187 this.name = from.name;
188 this.node = from.node;
189 this.priority = from.priority;
190 this.cookie = from.cookie;
191 this.ingressPort = from.ingressPort;
192 this.portGroup = from.portGroup;
193 this.vlanId = from.vlanId;
194 this.vlanPriority = from.vlanPriority;
195 this.etherType = from.etherType;
196 this.dlSrc = from.dlSrc;
197 this.dlDst = from.dlDst;
198 this.protocol = from.protocol;
199 this.tosBits = from.tosBits;
200 this.nwSrc = from.nwSrc;
201 this.nwDst = from.nwDst;
202 this.tpSrc = from.tpSrc;
203 this.tpDst = from.tpDst;
204 this.idleTimeout = from.idleTimeout;
205 this.hardTimeout = from.hardTimeout;
206 this.actions = new ArrayList<String>(from.actions);
209 public boolean installInHw() {
210 if (installInHw == null) {
211 // backward compatibility
212 installInHw = "true";
214 return installInHw.equals("true");
217 public void setInstallInHw(boolean inHw) {
218 installInHw = inHw ? "true" : "false";
221 public String getInstallInHw() {
225 public boolean isInternalFlow() {
226 // Controller generated static flows have name starting with "**"
227 if (this.name == null)
229 return this.name.startsWith("**");
232 public String getName() {
236 public void setName(String name) {
243 public Node getNode() {
247 public void setNode(Node node) {
251 public String getPriority() {
255 public void setPriority(String priority) {
256 this.priority = priority;
259 public String getCookie() {
263 public void setCookie(String cookie) {
264 this.cookie = cookie;
267 public String getIngressPort() {
271 public void setIngressPort(String ingressPort) {
272 this.ingressPort = ingressPort;
275 public String getPortGroup() {
280 public String toString() {
281 return "FlowConfig [dynamic=" + dynamic + ", status=" + status
282 + ", installInHw=" + installInHw + ", name=" + name
283 + ", switchId=" + node + ", ingressPort=" + ingressPort
284 + ", portGroup=" + portGroup + ", etherType=" + etherType
285 + ", priority=" + priority + ", vlanId=" + vlanId
286 + ", vlanPriority=" + vlanPriority + ", dlSrc=" + dlSrc
287 + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
288 + ", protocol=" + protocol + ", tosBits=" + tosBits
289 + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst + ", cookie="
290 + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout="
291 + hardTimeout + ", actions=" + actions + "]";
294 public void setPortGroup(String portGroup) {
295 this.portGroup = portGroup;
298 public String getVlanId() {
302 public void setVlanId(String vlanId) {
303 this.vlanId = vlanId;
306 public String getVlanPriority() {
310 public void setVlanPriority(String vlanPriority) {
311 this.vlanPriority = vlanPriority;
314 public String getEtherType() {
318 public void setEtherType(String etherType) {
319 this.etherType = etherType;
322 public String getSrcMac() {
326 public void setSrcMac(String srcMac) {
330 public String getDstMac() {
334 public void setDstMac(String dstMac) {
338 public String getProtocol() {
342 public void setProtocol(String protocol) {
343 this.protocol = protocol;
346 public String getTosBits() {
350 public void setTosBits(String tos_bits) {
351 this.tosBits = tos_bits;
354 public String getSrcIp() {
358 public void setSrcIp(String src_ip) {
362 public String getDstIp() {
366 public void setDstIp(String dst_ip) {
370 public String getSrcPort() {
374 public void setSrcPort(String src_port) {
375 this.tpSrc = src_port;
378 public String getDstPort() {
382 public void setDstPort(String dst_port) {
383 this.tpDst = dst_port;
386 public String getIdleTimeout() {
390 public void setIdleTimeout(String idleTimeout) {
391 this.idleTimeout = idleTimeout;
394 public String getHardTimeout() {
398 public void setHardTimeout(String hardTimeout) {
399 this.hardTimeout = hardTimeout;
402 public boolean isIPv6() {
403 if (NetUtils.isIPv6AddressValid(this.getSrcIp())
404 || NetUtils.isIPv6AddressValid(this.getDstIp())) {
410 public List<String> getActions() {
414 public void setActions(List<String> actions) {
415 this.actions = actions;
418 public static List<String> getFieldsNames() {
419 List<String> fieldList = new ArrayList<String>();
420 for (Field fld : FlowConfig.class.getDeclaredFields()) {
421 fieldList.add(fld.getName());
423 // Remove 4 static fields + 2 internal field
424 for (int i = 0; i < 6; i++)
430 public boolean isPortGroupEnabled() {
431 return (portGroup != null);
434 public boolean isDynamic() {
438 public void setDynamic(boolean dynamic) {
439 this.dynamic = dynamic;
442 public String getStatus() {
446 public void setStatus(String status) {
447 this.status = status;
450 public boolean isStatusSuccessful() {
451 return status.equals(StatusCode.SUCCESS.toString());
455 public int hashCode() {
456 final int prime = 31;
458 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
459 result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
460 result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
461 result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
462 result = prime * result + (dynamic ? 1231 : 1237);
463 result = prime * result
464 + ((etherType == null) ? 0 : etherType.hashCode());
465 result = prime * result
466 + ((ingressPort == null) ? 0 : ingressPort.hashCode());
467 result = prime * result + ((name == null) ? 0 : name.hashCode());
468 result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
469 result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
470 result = prime * result
471 + ((portGroup == null) ? 0 : portGroup.hashCode());
472 result = prime * result
473 + ((priority == null) ? 0 : priority.hashCode());
474 result = prime * result
475 + ((protocol == null) ? 0 : protocol.hashCode());
476 result = prime * result + ((node == null) ? 0 : node.hashCode());
477 result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
478 result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
479 result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
480 result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
481 result = prime * result
482 + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
483 result = prime * result
484 + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
485 result = prime * result
486 + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
491 public boolean equals(Object obj) {
496 if (getClass() != obj.getClass())
498 FlowConfig other = (FlowConfig) obj;
499 if (actions == null) {
500 if (other.actions != null)
502 } else if (!actions.equals(other.actions))
504 if (cookie == null) {
505 if (other.cookie != null)
507 } else if (!cookie.equals(other.cookie))
510 if (other.dlDst != null)
512 } else if (!dlDst.equals(other.dlDst))
515 if (other.dlSrc != null)
517 } else if (!dlSrc.equals(other.dlSrc))
519 if (dynamic != other.dynamic)
521 if (etherType == null) {
522 if (other.etherType != null)
524 } else if (!etherType.equals(other.etherType))
526 if (ingressPort == null) {
527 if (other.ingressPort != null)
529 } else if (!ingressPort.equals(other.ingressPort))
532 if (other.name != null)
534 } else if (!name.equals(other.name))
537 if (other.nwDst != null)
539 } else if (!nwDst.equals(other.nwDst))
542 if (other.nwSrc != null)
544 } else if (!nwSrc.equals(other.nwSrc))
546 if (portGroup == null) {
547 if (other.portGroup != null)
549 } else if (!portGroup.equals(other.portGroup))
551 if (priority == null) {
552 if (other.priority != null)
554 } else if (!priority.equals(other.priority))
556 if (protocol == null) {
557 if (other.protocol != null)
559 } else if (!protocol.equals(other.protocol))
562 if (other.node != null)
564 } else if (!node.equals(other.node))
566 if (tosBits == null) {
567 if (other.tosBits != null)
569 } else if (!tosBits.equals(other.tosBits))
572 if (other.tpDst != null)
574 } else if (!tpDst.equals(other.tpDst))
577 if (other.tpSrc != null)
579 } else if (!tpSrc.equals(other.tpSrc))
581 if (vlanId == null) {
582 if (other.vlanId != null)
584 } else if (!vlanId.equals(other.vlanId))
586 if (vlanPriority == null) {
587 if (other.vlanPriority != null)
589 } else if (!vlanPriority.equals(other.vlanPriority))
591 if (idleTimeout == null) {
592 if (other.idleTimeout != null)
594 } else if (!idleTimeout.equals(other.idleTimeout))
596 if (hardTimeout == null) {
597 if (other.hardTimeout != null)
599 } else if (!hardTimeout.equals(other.hardTimeout))
604 public InetAddress getNextHopAddressForL2RWAction() {
605 if (actions != null) {
607 for (String actiongrp : actions) {
608 sstr = Pattern.compile("SET_NEXT_HOP=(.*)").matcher(actiongrp);
609 if (sstr.matches()) {
610 SetNextHopType setNHType = SetNextHopType.CISCO_EXTENSION;
611 String nextHopInfo = sstr.group(1);
612 String values[] = nextHopInfo.split("//");
613 String address = values[0].trim();
615 if (values.length > 1) {
616 type = values[1].trim();
620 for (SetNextHopType nh : SetNextHopType.values()) {
626 log.debug("Get Nexthop address = " + address + " Type = "
627 + setNHType.toString());
628 if (setNHType == SetNextHopType.RESOLVE_L2RW) {
630 return InetAddress.getByName(address);
631 } catch (Exception e) {
633 .debug("Exception during nextHopAddress resolution : "
643 public String getNextHopL2RWUsageError() {
644 return "Could not resolve NextHop IP Address for the selected Switch.<br>"
645 + "Please Check the following configurations.<br>"
646 + "1. Is the NextHop IP address directly connected to the Selected Switch<br>"
647 + "2. If appropriate Subnet Configurations are done in the Switch Manager<br>"
648 + "3. If the Nexthop IP-Address is Correct";
651 public boolean isL2AddressValid(String mac) {
656 Pattern macPattern = Pattern
657 .compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
658 Matcher mm = macPattern.matcher(mac);
662 "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f",
669 public boolean isPortValid(Switch sw, Short port) {
671 log.debug("port {} is not valid", port);
677 .debug("switch info is not available. Skip checking if port is part of a switch or not.");
681 Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
682 for (NodeConnector nodeConnector : nodeConnectorSet) {
683 if (((Short) nodeConnector.getID()).equals(port)) {
687 log.debug("port {} is not a valid port of node {}", port, sw.getNode());
691 public boolean isVlanIdValid(String vlanId) {
692 int vlan = Integer.decode(vlanId);
693 return ((vlan >= 0) && (vlan < 4096));
696 public boolean isVlanPriorityValid(String vlanPriority) {
697 int pri = Integer.decode(vlanPriority);
698 return ((pri >= 0) && (pri < 8));
701 public boolean isTOSBitsValid(String tosBits) {
702 int tos = Integer.decode(tosBits);
703 return ((tos >= 0) && (tos < 64));
706 public boolean isTpPortValid(String tpPort) {
707 int port = Integer.decode(tpPort);
708 return ((port > 0) && (port <= 0xffff));
711 public boolean isTimeoutValid(String timeout) {
712 int to = Integer.decode(timeout);
713 return ((to >= 0) && (to <= 0xffff));
716 private boolean conflictWithContainerFlow(IContainer container,
717 StringBuffer resultStr) {
718 // Return true if it's default container
719 if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
723 // No container flow = no conflict
724 List<ContainerFlow> cFlowList = container.getContainerFlows();
725 if (((cFlowList == null)) || cFlowList.isEmpty()) {
729 // Check against each container's flow
730 Flow flow = this.getFlow();
732 // Configuration is rejected if it conflicts with _all_ the container flows
733 for (ContainerFlow cFlow : cFlowList) {
734 if (cFlow.allowsFlow(flow)) {
736 .trace("Config is congruent with at least one container flow");
740 String msg = "Flow Config conflicts with all existing container flows";
741 resultStr.append(msg);
747 public boolean isValid(IContainer container, StringBuffer resultStr) {
748 EtherIPType etype = EtherIPType.ANY;
749 EtherIPType ipsrctype = EtherIPType.ANY;
750 EtherIPType ipdsttype = EtherIPType.ANY;
752 String containerName = (container == null) ? GlobalConstants.DEFAULT
753 .toString() : container.getName();
754 ISwitchManager switchManager = (ISwitchManager) ServiceHelper
755 .getInstance(ISwitchManager.class, containerName, this);
760 resultStr.append(String.format("Name is null"));
764 resultStr.append(String.format("Node is null"));
767 if (switchManager != null) {
768 for (Switch device : switchManager.getNetworkDevices()) {
769 if (device.getNode().equals(node)) {
776 .append(String.format("Node %s not found", node));
780 log.debug("switchmanager is not set yet");
783 if (priority != null) {
784 if (Integer.decode(priority) < 0
785 || (Integer.decode(priority) > 65535)) {
786 resultStr.append(String.format(
787 "priority %s is not in the range 0 - 65535",
793 // make sure it's a valid number
797 if (ingressPort != null) {
798 Short port = Short.decode(ingressPort);
799 if (isPortValid(sw, port) == false) {
803 "Ingress port %d is not valid for the Switch",
805 if ((container != null)
806 && !container.getName().equals(
807 GlobalConstants.DEFAULT.toString())) {
809 .append(" in Container " + container.getName());
815 if ((vlanId != null) && !isVlanIdValid(vlanId)) {
816 resultStr.append(String.format(
817 "Vlan ID %s is not in the range 0 - 4095", vlanId));
821 if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
822 resultStr.append(String.format(
823 "Vlan priority %s is not in the range 0 - 7",
828 if (etherType != null) {
829 int type = Integer.decode(etherType);
830 if ((type < 0) || (type > 0xffff)) {
831 resultStr.append(String.format(
832 "Ethernet type %s is not valid", etherType));
836 etype = EtherIPType.V4;
837 else if (type == 0x86dd)
838 etype = EtherIPType.V6;
842 if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
843 resultStr.append(String.format(
844 "IP ToS bits %s is not in the range 0 - 63", tosBits));
848 if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
849 resultStr.append(String.format(
850 "Transport source port %s is not valid", tpSrc));
853 if ((tpDst != null) && !isTpPortValid(tpDst)) {
854 resultStr.append(String.format(
855 "Transport destination port %s is not valid", tpDst));
859 if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
863 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
868 if ((dlDst != null) && !isL2AddressValid(dlDst)) {
872 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
878 if (NetUtils.isIPv4AddressValid(nwSrc)) {
879 ipsrctype = EtherIPType.V4;
880 } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
881 ipsrctype = EtherIPType.V6;
883 resultStr.append(String.format(
884 "IP source address %s is not valid", nwSrc));
890 if (NetUtils.isIPv4AddressValid(nwDst)) {
891 ipdsttype = EtherIPType.V4;
892 } else if (NetUtils.isIPv6AddressValid(nwDst)) {
893 ipdsttype = EtherIPType.V6;
895 resultStr.append(String.format(
896 "IP destination address %s is not valid", nwDst));
901 if (etype != EtherIPType.ANY) {
902 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
903 resultStr.append(String
904 .format("Type mismatch between Ethernet & Src IP"));
907 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
908 resultStr.append(String
909 .format("Type mismatch between Ethernet & Dst IP"));
913 if (ipsrctype != ipdsttype) {
914 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
916 .append(String.format("IP Src Dest Type mismatch"));
921 if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
922 resultStr.append(String.format(
923 "Idle Timeout value %s is not valid", idleTimeout));
927 if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
928 resultStr.append(String.format(
929 "Hard Timeout value %s is not valid", hardTimeout));
934 if (actions != null && !actions.isEmpty()) {
935 for (String actiongrp : actions) {
936 // check output ports
937 sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
938 if (sstr.matches()) {
939 for (String t : sstr.group(1).split(",")) {
940 Matcher n = Pattern.compile("(?:(\\d+))")
943 if (n.group(1) != null) {
944 Short port = Short.parseShort(n.group(1));
945 if (isPortValid(sw, port) == false) {
949 "Output port %d is not valid for this switch",
951 if ((container != null)
952 && !container.getName().equals(
953 GlobalConstants.DEFAULT
955 resultStr.append(" in Container "
956 + container.getName());
966 sstr = Pattern.compile(ActionType.FLOOD.toString())
968 if (sstr.matches()) {
969 if (container != null) {
970 resultStr.append(String.format(
971 "flood is not allowed in container %s",
972 container.getName()));
978 sstr = Pattern.compile(
979 ActionType.SET_NW_SRC.toString() + "=(.*)")
981 if (sstr.matches()) {
982 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
983 resultStr.append(String.format(
984 "IP source address %s is not valid", sstr
991 sstr = Pattern.compile(
992 ActionType.SET_NW_DST.toString() + "=(.*)")
994 if (sstr.matches()) {
995 if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
996 resultStr.append(String.format(
997 "IP destination address %s is not valid",
1004 sstr = Pattern.compile(
1005 ActionType.SET_VLAN_ID.toString() + "=(.*)")
1006 .matcher(actiongrp);
1007 if (sstr.matches()) {
1008 if ((sstr.group(1) != null)
1009 && !isVlanIdValid(sstr.group(1))) {
1010 resultStr.append(String.format(
1011 "Vlan ID %s is not in the range 0 - 4095",
1018 sstr = Pattern.compile(
1019 ActionType.SET_VLAN_PCP.toString() + "=(.*)")
1020 .matcher(actiongrp);
1021 if (sstr.matches()) {
1022 if ((sstr.group(1) != null)
1023 && !isVlanPriorityValid(sstr.group(1))) {
1027 "Vlan priority %s is not in the range 0 - 7",
1034 sstr = Pattern.compile(
1035 ActionType.SET_DL_SRC.toString() + "=(.*)")
1036 .matcher(actiongrp);
1037 if (sstr.matches()) {
1038 if ((sstr.group(1) != null)
1039 && !isL2AddressValid(sstr.group(1))) {
1043 "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
1050 sstr = Pattern.compile(
1051 ActionType.SET_DL_DST.toString() + "=(.*)")
1052 .matcher(actiongrp);
1053 if (sstr.matches()) {
1054 if ((sstr.group(1) != null)
1055 && !isL2AddressValid(sstr.group(1))) {
1059 "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
1066 sstr = Pattern.compile(
1067 ActionType.SET_NW_TOS.toString() + "=(.*)")
1068 .matcher(actiongrp);
1069 if (sstr.matches()) {
1070 if ((sstr.group(1) != null)
1071 && !isTOSBitsValid(sstr.group(1))) {
1075 "IP ToS bits %s is not in the range 0 - 63",
1082 sstr = Pattern.compile(
1083 ActionType.SET_TP_SRC.toString() + "=(.*)")
1084 .matcher(actiongrp);
1085 if (sstr.matches()) {
1086 if ((sstr.group(1) != null)
1087 && !isTpPortValid(sstr.group(1))) {
1088 resultStr.append(String.format(
1089 "Transport source port %s is not valid",
1096 sstr = Pattern.compile(
1097 ActionType.SET_TP_DST.toString() + "=(.*)")
1098 .matcher(actiongrp);
1099 if (sstr.matches()) {
1100 if ((sstr.group(1) != null)
1101 && !isTpPortValid(sstr.group(1))) {
1105 "Transport destination port %s is not valid",
1111 sstr = Pattern.compile(
1112 ActionType.SET_NEXT_HOP.toString() + "=(.*)")
1113 .matcher(actiongrp);
1114 if (sstr.matches()) {
1115 String nextHopInfo = sstr.group(1);
1116 String values[] = nextHopInfo.split("//");
1117 String address = values[0].trim();
1119 if ((address == null) || !isOutputNextHopValid(address)) {
1120 resultStr.append(String.format(
1121 "next hop %s is not valid", sstr.group(1)));
1128 // Check against the container flow
1129 if ((container != null)
1130 && conflictWithContainerFlow(container, resultStr)) {
1133 } catch (NumberFormatException e) {
1134 resultStr.append(String.format("Invalid number format %s", e
1142 public FlowEntry getFlowEntry() {
1143 return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this
1144 .getFlow(), this.getNode());
1147 public Flow getFlow() {
1148 Match match = new Match();
1150 if (this.ingressPort != null) {
1151 match.setField(MatchType.IN_PORT, NodeConnectorCreator
1152 .createOFNodeConnector(Short.parseShort(ingressPort),
1155 if (this.dlSrc != null) {
1156 match.setField(MatchType.DL_SRC, HexEncode
1157 .bytesFromHexString(this.dlSrc));
1159 if (this.dlDst != null) {
1160 match.setField(MatchType.DL_DST, HexEncode
1161 .bytesFromHexString(this.dlDst));
1163 if (this.etherType != null) {
1164 match.setField(MatchType.DL_TYPE, Integer.decode(etherType)
1167 if (this.vlanId != null) {
1168 match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
1170 if (this.vlanPriority != null) {
1171 match.setField(MatchType.DL_VLAN_PR, Byte
1172 .parseByte(this.vlanPriority));
1174 if (this.nwSrc != null) {
1175 String parts[] = this.nwSrc.split("/");
1176 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1177 InetAddress mask = null;
1178 if (parts.length > 1) {
1179 int maskLen = Integer.parseInt(parts[1]);
1180 mask = NetUtils.getInetNetworkMask(maskLen,
1181 ip instanceof Inet6Address);
1183 match.setField(MatchType.NW_SRC, ip, mask);
1185 if (this.nwDst != null) {
1186 String parts[] = this.nwDst.split("/");
1187 InetAddress ip = NetUtils.parseInetAddress(parts[0]);
1188 InetAddress mask = null;
1189 if (parts.length > 1) {
1190 int maskLen = Integer.parseInt(parts[1]);
1191 mask = NetUtils.getInetNetworkMask(maskLen,
1192 ip instanceof Inet6Address);
1194 match.setField(MatchType.NW_DST, ip, mask);
1196 if (this.protocol != null) {
1197 match.setField(MatchType.NW_PROTO, IPProtocols
1198 .getProtocolNumberByte(this.protocol));
1200 if (this.tosBits != null) {
1201 match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
1203 if (this.tpSrc != null) {
1204 match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc)
1207 if (this.tpDst != null) {
1208 match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst)
1212 Flow flow = new Flow(match, getActionList());
1213 if (this.cookie != null) {
1214 flow.setId(Long.parseLong(cookie));
1216 if (this.hardTimeout != null) {
1217 flow.setHardTimeout(Short.parseShort(this.hardTimeout));
1219 if (this.idleTimeout != null) {
1220 flow.setIdleTimeout(Short.parseShort(idleTimeout));
1222 if (this.priority != null) {
1223 flow.setPriority(Integer.decode(this.priority).shortValue());
1228 public boolean isOutputNextHopValid(String onh) {
1233 * For now, only takes IPv4 or IPv6 address
1235 return (NetUtils.isIPv4AddressValid(onh) || NetUtils
1236 .isIPv6AddressValid(onh));
1239 public boolean isByNameAndNodeIdEqual(FlowConfig that) {
1240 return (this.name.equals(that.name) && this.node.equals(that.node));
1243 public boolean isByNameAndNodeIdEqual(String name, Node node) {
1244 return (this.name.equals(name) && this.node.equals(node));
1247 public boolean onNode(Node node) {
1248 return this.node.equals(node);
1251 public static List<String> getSupportedNextHopTypes() {
1252 List<String> s = new ArrayList<String>();
1253 for (SetNextHopType nh : SetNextHopType.values()) {
1254 s.add(nh.toString());
1259 public void toggleStatus() {
1260 installInHw = (installInHw == null) ? "true" : (installInHw
1261 .equals("true")) ? "false" : "true";
1265 * Parses the actions string and return the List of SAL Action
1266 * No syntax check run, as this function will be called when the
1267 * config validation check has already been performed
1269 private List<Action> getActionList() {
1270 List<Action> actionList = new ArrayList<Action>();
1272 if (actions != null) {
1274 for (String actiongrp : actions) {
1275 sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(
1277 if (sstr.matches()) {
1278 for (String t : sstr.group(1).split(",")) {
1279 Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
1281 if (n.group(1) != null) {
1282 short ofPort = Short.parseShort(n.group(1));
1283 actionList.add(new Output(NodeConnectorCreator
1284 .createOFNodeConnector(ofPort, this
1292 sstr = Pattern.compile(ActionType.DROP.toString()).matcher(
1294 if (sstr.matches()) {
1295 actionList.add(new Drop());
1299 sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(
1301 if (sstr.matches()) {
1302 actionList.add(new Loopback());
1306 sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(
1308 if (sstr.matches()) {
1309 actionList.add(new Flood());
1313 sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(
1315 if (sstr.matches()) {
1316 actionList.add(new SwPath());
1320 sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(
1322 if (sstr.matches()) {
1323 actionList.add(new HwPath());
1327 sstr = Pattern.compile(ActionType.CONTROLLER.toString())
1328 .matcher(actiongrp);
1329 if (sstr.matches()) {
1330 actionList.add(new Controller());
1334 sstr = Pattern.compile(
1335 ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(
1337 if (sstr.matches()) {
1338 actionList.add(new SetVlanId(Short
1339 .parseShort(sstr.group(1))));
1343 sstr = Pattern.compile(
1344 ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(
1346 if (sstr.matches()) {
1348 .add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
1352 sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(
1354 if (sstr.matches()) {
1355 actionList.add(new PopVlan());
1359 sstr = Pattern.compile(
1360 ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(
1362 if (sstr.matches()) {
1363 actionList.add(new SetDlSrc(HexEncode
1364 .bytesFromHexString(sstr.group(1))));
1368 sstr = Pattern.compile(
1369 ActionType.SET_DL_DST.toString() + "=(.*)").matcher(
1371 if (sstr.matches()) {
1372 actionList.add(new SetDlDst(HexEncode
1373 .bytesFromHexString(sstr.group(1))));
1376 sstr = Pattern.compile(
1377 ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(
1379 if (sstr.matches()) {
1380 actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr
1384 sstr = Pattern.compile(
1385 ActionType.SET_NW_DST.toString() + "=(.*)").matcher(
1387 if (sstr.matches()) {
1388 actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr
1393 sstr = Pattern.compile(
1394 ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(
1396 if (sstr.matches()) {
1397 actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
1401 sstr = Pattern.compile(
1402 ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(
1404 if (sstr.matches()) {
1406 .add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
1410 sstr = Pattern.compile(
1411 ActionType.SET_TP_DST.toString() + "=(.*)").matcher(
1413 if (sstr.matches()) {
1415 .add(new SetTpDst(Integer.valueOf(sstr.group(1))));
1419 sstr = Pattern.compile(
1420 ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(
1422 if (sstr.matches()) {
1423 log.warn("We do not handle next hop action yet....");