blob: e3dcad0e3316f0530a9c84777e06b04b3696e2bc [file] [log] [blame]
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
Nick Karanatsios758df8d2014-01-14 22:16:32 -08003import com.tinkerpop.blueprints.Direction;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07004import java.io.PrintWriter;
5import java.io.StringWriter;
6import java.util.ArrayList;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07007import java.util.LinkedList;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -08008import java.util.Map;
9
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070010import net.floodlightcontroller.util.MACAddress;
yoshitomob292c622013-11-23 14:35:58 -080011import net.onrc.onos.graph.DBOperation;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -080012import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IBaseObject;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070013import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
14import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
15import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
16import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
17import net.onrc.onos.ofcontroller.util.*;
18
19import org.slf4j.Logger;
20import org.slf4j.LoggerFactory;
21
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080022import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -080023import com.tinkerpop.blueprints.impls.ramcloud.RamCloudVertex;
Yuta HIGUCHIdad0a2d2014-01-06 15:52:52 -080024
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070025/**
26 * Class for performing Flow-related operations on the Database.
27 */
Pavlin Radoslavov6bfaea62013-12-03 14:55:57 -080028public class FlowDatabaseOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070029 private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -080030 private static final boolean measureONOSFlowTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlow", "0")) != 0;
31 private static final boolean measureONOSFlowEntryTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlowEntry", "0")) != 0;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070032
33 /**
Nick Karanatsios1e802382014-01-23 11:12:16 -080034 * Add a flow by batching all flow path properties and flow entries together.
35 * This is done for performance reasons.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070036 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070037 * @param dbHandler the Graph Database handler to use.
38 * @param flowPath the Flow Path to install.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070039 * @return true on success, otherwise false.
40 */
Toshio Koidec71b7122014-01-13 15:16:53 -080041 static boolean addFlowFast(DBOperation dbHandler, FlowPath flowPath) {
Nick Karanatsios1e802382014-01-23 11:12:16 -080042 IFlowPath flowPathObj;
Toshio Koidec71b7122014-01-13 15:16:53 -080043 FlowPathProperty flowProp = new FlowPathProperty();
Nick Karanatsios758df8d2014-01-14 22:16:32 -080044 FlowEntity flowPathEntity = new FlowEntity();
45 boolean flowPathUpdate = false;
Toshio Koidec71b7122014-01-13 15:16:53 -080046
Nick Karanatsios1e802382014-01-23 11:12:16 -080047 flowPathObj = dbHandler.searchFlowPath(flowPath.flowId()); // getVertices("flow_id")
Toshio Koidec71b7122014-01-13 15:16:53 -080048 if (flowPathObj == null) {
49 try {
Nick Karanatsios758df8d2014-01-14 22:16:32 -080050 flowPathEntity.operationBegin(DBOperationType.ADD.toString());
Nick Karanatsios1e802382014-01-23 11:12:16 -080051 flowPathObj = dbHandler.newFlowPath();
Toshio Koidec71b7122014-01-13 15:16:53 -080052 } catch (Exception e) {
53 flowPathObj = null;
54 StringWriter sw = new StringWriter();
55 e.printStackTrace(new PrintWriter(sw));
56 log.error(":addFlow FlowId:{} failed: {}", flowPath.flowId(), sw.toString());
57 }
Nick Karanatsios758df8d2014-01-14 22:16:32 -080058 flowPathEntity.setProperty("user_state", "FP_USER_ADD");
Toshio Koidec71b7122014-01-13 15:16:53 -080059 flowProp.setFlowPathUserState("FP_USER_ADD");
60 } else {
Nick Karanatsios758df8d2014-01-14 22:16:32 -080061 flowPathUpdate = true;
Toshio Koidec71b7122014-01-13 15:16:53 -080062 // Remove the old Flow Entries (this is special for RAMCloud)
Nick Karanatsios1e802382014-01-23 11:12:16 -080063 for (IFlowEntry flowEntryObj : flowPathObj.getFlowEntries()) { // get.@Adjacency("flow", IN)
Nick Karanatsios758df8d2014-01-14 22:16:32 -080064 flowPathEntity.operationBegin(DBOperationType.REMOVE.toString());
Nick Karanatsios1e802382014-01-23 11:12:16 -080065 dbHandler.removeFlowEntry(flowEntryObj); // removeVertex()
Nick Karanatsios758df8d2014-01-14 22:16:32 -080066 flowPathEntity.operationEnd(DBOperationType.REMOVE.toString());
Toshio Koidec71b7122014-01-13 15:16:53 -080067 }
Nick Karanatsios758df8d2014-01-14 22:16:32 -080068 flowPathEntity.operationBegin(DBOperationType.UPDATE.toString());
69 flowPathEntity.setProperty("user_state", "FP_USER_ADD");
Toshio Koidec71b7122014-01-13 15:16:53 -080070 flowProp.setFlowPathUserState("FP_USER_MODIFY");
71 }
72 if (flowPathObj == null) {
73 log.error(":addFlow FlowId:{} failed: Flow object not created", flowPath.flowId());
74 dbHandler.rollback();
Toshio Koidec71b7122014-01-13 15:16:53 -080075 return false;
76 }
77
Nick Karanatsios758df8d2014-01-14 22:16:32 -080078 flowPathEntity.setProperty("flow_id", flowPath.flowId().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -080079 // Set the Flow key
80 flowProp.setFlowId(flowPath.flowId().toString());
81
82 // Set the Flow attributes
Nick Karanatsios758df8d2014-01-14 22:16:32 -080083 flowPathEntity.setProperty("installer_id", flowPath.installerId().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -080084 flowProp.setInstallerId(flowPath.installerId().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -080085
86 flowPathEntity.setProperty("flow_path_type", flowPath.flowPathType().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -080087 flowProp.setFlowPathType(flowPath.flowPathType().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -080088
89 flowPathEntity.setProperty("user_state", flowPath.flowPathUserState().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -080090 flowProp.setFlowPathUserState(flowPath.flowPathUserState().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -080091
92
93 flowPathEntity.setProperty("flow_path_flags", flowPath.flowPathFlags().flags());
Toshio Koidec71b7122014-01-13 15:16:53 -080094 flowProp.setFlowPathFlags(flowPath.flowPathFlags().flags());
Nick Karanatsios758df8d2014-01-14 22:16:32 -080095
96 flowPathEntity.setProperty("idle_timeout", flowPath.idleTimeout());
Toshio Koidec71b7122014-01-13 15:16:53 -080097 flowProp.setIdleTimeout(flowPath.idleTimeout());
Nick Karanatsios758df8d2014-01-14 22:16:32 -080098
99 flowPathEntity.setProperty("hard_timeout", flowPath.hardTimeout());
Toshio Koidec71b7122014-01-13 15:16:53 -0800100 flowProp.setHardTimeout(flowPath.hardTimeout());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800101
102 flowPathEntity.setProperty("src_switch", flowPath.dataPath().srcPort().dpid().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800103 flowProp.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800104
105 flowPathEntity.setProperty("src_port", flowPath.dataPath().srcPort().port().value());
Toshio Koidec71b7122014-01-13 15:16:53 -0800106 flowProp.setSrcPort(flowPath.dataPath().srcPort().port().value());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800107
108 flowPathEntity.setProperty("dst_switch", flowPath.dataPath().dstPort().dpid().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800109 flowProp.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800110
111 flowPathEntity.setProperty("dst_port", flowPath.dataPath().dstPort().port().value());
Toshio Koidec71b7122014-01-13 15:16:53 -0800112 flowProp.setDstPort(flowPath.dataPath().dstPort().port().value());
113
114 if (flowPath.flowEntryMatch().matchSrcMac()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800115 flowPathEntity.setProperty("matchSrcMac",flowPath.flowEntryMatch().srcMac().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800116 flowProp.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
117 }
118 if (flowPath.flowEntryMatch().matchDstMac()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800119 flowPathEntity.setProperty("matchDstMac", flowPath.flowEntryMatch().dstMac().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800120 flowProp.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
121 }
122 if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800123 flowPathEntity.setProperty("matchEthernetFrameType", flowPath.flowEntryMatch().ethernetFrameType());
Toshio Koidec71b7122014-01-13 15:16:53 -0800124 flowProp.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
125 }
126 if (flowPath.flowEntryMatch().matchVlanId()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800127 flowPathEntity.setProperty("matchVlanId", flowPath.flowEntryMatch().vlanId());
Toshio Koidec71b7122014-01-13 15:16:53 -0800128 flowProp.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
129 }
130 if (flowPath.flowEntryMatch().matchVlanPriority()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800131 flowPathEntity.setProperty("matchVlanPriority", flowPath.flowEntryMatch().vlanPriority());
Toshio Koidec71b7122014-01-13 15:16:53 -0800132 flowProp.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
133 }
134 if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800135 flowPathEntity.setProperty("matchSrcIPv4Net", flowPath.flowEntryMatch().srcIPv4Net().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800136 flowProp.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
137 }
138 if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800139 flowPathEntity.setProperty("matchDstIPv4Net", flowPath.flowEntryMatch().dstIPv4Net().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800140 flowProp.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
141 }
142 if (flowPath.flowEntryMatch().matchIpProto()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800143 flowPathEntity.setProperty("matchIpProto", flowPath.flowEntryMatch().ipProto());
Toshio Koidec71b7122014-01-13 15:16:53 -0800144 flowProp.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
145 }
146 if (flowPath.flowEntryMatch().matchIpToS()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800147 flowPathEntity.setProperty("matchIpToS", flowPath.flowEntryMatch().ipToS());
Toshio Koidec71b7122014-01-13 15:16:53 -0800148 flowProp.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
149 }
150 if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800151 flowPathEntity.setProperty("matchSrcTcpUdpPort", flowPath.flowEntryMatch().srcTcpUdpPort());
Toshio Koidec71b7122014-01-13 15:16:53 -0800152 flowProp.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
153 }
154 if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800155 flowPathEntity.setProperty("matchDstTcpUdpPort", flowPath.flowEntryMatch().dstTcpUdpPort());
Toshio Koidec71b7122014-01-13 15:16:53 -0800156 flowProp.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
157 }
158 if (! flowPath.flowEntryActions().actions().isEmpty()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800159 flowPathEntity.setProperty("actions", flowPath.flowEntryActions().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800160 flowProp.setActions(flowPath.flowEntryActions().toString());
161 }
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800162 flowPathEntity.setProperty("data_path_summary", flowPath.dataPath().dataPathSummary());
Toshio Koidec71b7122014-01-13 15:16:53 -0800163 flowProp.setDataPathSummary(flowPath.dataPath().dataPathSummary());
164
Nick Karanatsios1e802382014-01-23 11:12:16 -0800165 flowProp.commitProperties(dbHandler, flowPathObj);
Toshio Koidec71b7122014-01-13 15:16:53 -0800166
167 //
168 // Flow Entries:
169 // flowPath.dataPath().flowEntries()
170 //
171 for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
172 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
173 continue; // Skip: all Flow Entries were deleted earlier
174
Nick Karanatsios1e802382014-01-23 11:12:16 -0800175 IFlowEntry iFlowEntry;
Toshio Koidec71b7122014-01-13 15:16:53 -0800176 FlowEntryProperty flowEntryProp = new FlowEntryProperty();
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800177 FlowEntity flowEntryEntity = new FlowEntity();
178 boolean updateFlowEntry = false;
Toshio Koidec71b7122014-01-13 15:16:53 -0800179
180 try {
Nick Karanatsios1e802382014-01-23 11:12:16 -0800181 iFlowEntry = dbHandler.searchFlowEntry(flowEntry.flowEntryId()); // getVertices()
Toshio Koidec71b7122014-01-13 15:16:53 -0800182 if (iFlowEntry != null) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800183 updateFlowEntry = true;
184 flowEntryEntity.operationBegin(DBOperationType.UPDATE.toString());
185 flowEntryEntity.setProperty("user_state", "FE_USER_MODIFY");
Toshio Koidec71b7122014-01-13 15:16:53 -0800186 flowEntryProp.setUserState("FE_USER_MODIFY");
187 } else {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800188 flowEntryEntity.operationBegin(DBOperationType.ADD.toString());
189 flowEntryEntity.setProperty("user_state", "FE_USER_ADD");
Toshio Koidec71b7122014-01-13 15:16:53 -0800190 flowEntryProp.setUserState("FE_USER_ADD");
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800191 flowEntryEntity.addEdge(flowPathObj, Direction.OUT, "flow");
Toshio Koidec71b7122014-01-13 15:16:53 -0800192 }
193 } catch (Exception e) {
Nick Karanatsios1e802382014-01-23 11:12:16 -0800194 // TODO do we really need to catch this exception.
Toshio Koidec71b7122014-01-13 15:16:53 -0800195 }
Toshio Koidec71b7122014-01-13 15:16:53 -0800196
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800197 flowEntryEntity.setProperty("flow_id", flowEntry.flowEntryId().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800198 // Set the Flow Entry key
Nick Karanatsios1e802382014-01-23 11:12:16 -0800199 flowEntryEntity.setProperty("flow_entry_id", flowEntry.flowEntryId().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800200
201 flowEntryEntity.setProperty("type", "flow_entry");
Toshio Koidec71b7122014-01-13 15:16:53 -0800202
203 // Set the Flow Entry Edges
204 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString()); // toshi memo: getVertices()
205
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800206 flowEntryEntity.setProperty("idle_timeout", flowEntry.idleTimeout());
Toshio Koidec71b7122014-01-13 15:16:53 -0800207
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800208 flowEntryEntity.setProperty("hard_timeout", flowEntry.hardTimeout());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800209
210 flowEntryEntity.setProperty("switch_dpid", flowEntry.dpid().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800211
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800212 flowEntryEntity.addEdge(sw, Direction.OUT, "switch");
Toshio Koidec71b7122014-01-13 15:16:53 -0800213 if (flowEntry.flowEntryMatch().matchInPort()) {
214 IPortObject inport = dbHandler.searchPort(flowEntry.dpid().toString(), flowEntry.flowEntryMatch().inPort().value()); // toshi memo: getVertices()
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800215
216 flowEntryEntity.setProperty("matchInPort", flowEntry.flowEntryMatch().inPort().value());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800217 flowEntryEntity.addEdge(inport, Direction.OUT, "inport");
Toshio Koidec71b7122014-01-13 15:16:53 -0800218 }
219
220 // Set the Flow Entry attributes
221 if (flowEntry.flowEntryMatch().matchSrcMac()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800222 flowEntryEntity.setProperty("matchSrcMac", flowEntry.flowEntryMatch().srcMac().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800223 }
224 if (flowEntry.flowEntryMatch().matchDstMac()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800225 flowEntryEntity.setProperty("matchDstMac", flowEntry.flowEntryMatch().dstMac().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800226 }
227 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800228 flowEntryEntity.setProperty("matchEthernetFrameType", flowEntry.flowEntryMatch().ethernetFrameType());
Toshio Koidec71b7122014-01-13 15:16:53 -0800229 }
230 if (flowEntry.flowEntryMatch().matchVlanId()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800231 flowEntryEntity.setProperty("matchVlanId", flowEntry.flowEntryMatch().vlanId());
Toshio Koidec71b7122014-01-13 15:16:53 -0800232 }
233 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800234 flowEntryEntity.setProperty("matchVlanPriority", flowEntry.flowEntryMatch().vlanPriority());
Toshio Koidec71b7122014-01-13 15:16:53 -0800235 }
236 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800237 flowEntryEntity.setProperty("matchSrcIPv4Net", flowEntry.flowEntryMatch().srcIPv4Net().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800238 }
239 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800240 flowEntryEntity.setProperty("matchDstIPv4Net", flowEntry.flowEntryMatch().dstIPv4Net().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800241 }
242 if (flowEntry.flowEntryMatch().matchIpProto()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800243 flowEntryEntity.setProperty("matchIpProto", flowEntry.flowEntryMatch().ipProto());
Toshio Koidec71b7122014-01-13 15:16:53 -0800244 }
245 if (flowEntry.flowEntryMatch().matchIpToS()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800246 flowEntryEntity.setProperty("matchIpToS", flowEntry.flowEntryMatch().ipToS());
Toshio Koidec71b7122014-01-13 15:16:53 -0800247 }
248 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800249 flowEntryEntity.setProperty("matchSrcTcpUdpPort", flowEntry.flowEntryMatch().srcTcpUdpPort());
Toshio Koidec71b7122014-01-13 15:16:53 -0800250 }
251 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800252 flowEntryEntity.setProperty("matchDstTcpUdpPort", flowEntry.flowEntryMatch().dstTcpUdpPort());
Toshio Koidec71b7122014-01-13 15:16:53 -0800253 }
254
255 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
256 if (fa.actionOutput() != null) {
257 IPortObject outport = dbHandler.searchPort(flowEntry.dpid().toString(), fa.actionOutput().port().value()); // toshi memo: getVertices()
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800258 flowEntryEntity.setProperty("actionOutputPort", fa.actionOutput().port().value());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800259 flowEntryEntity.addEdge(outport, Direction.OUT, "outport");
Toshio Koidec71b7122014-01-13 15:16:53 -0800260 }
261 }
262 if (! flowEntry.flowEntryActions().isEmpty()) {
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800263 flowEntryEntity.setProperty("actions", flowEntry.flowEntryActions().toString());
Toshio Koidec71b7122014-01-13 15:16:53 -0800264 }
265
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800266 flowEntryEntity.setProperty("switch_state", flowEntry.flowEntrySwitchState().toString());
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800267 if (updateFlowEntry) {
268 flowEntryEntity.operationEnd(DBOperationType.UPDATE.toString());
269 } else {
270 flowEntryEntity.operationEnd(DBOperationType.ADD.toString());
271 }
272 flowPathEntity.append(flowEntryEntity);
Toshio Koidec71b7122014-01-13 15:16:53 -0800273 }
274
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800275 if (flowPathUpdate) {
276 flowPathEntity.operationEnd(DBOperationType.UPDATE.toString());
277 } else {
278 flowPathEntity.operationEnd(DBOperationType.ADD.toString());
279 }
280 flowPathEntity.persist(dbHandler);
Toshio Koidec71b7122014-01-13 15:16:53 -0800281 return true;
282 }
283
284 /**
285 * Add a flow.
286 *
287 * @param dbHandler the Graph Database handler to use.
288 * @param flowPath the Flow Path to install.
289 * @return true on success, otherwise false.
290 */
onlab-qa38805cd2013-12-06 20:08:54 -0800291 static boolean addFlow(DBOperation dbHandler, FlowPath flowPath) {
Nick Karanatsios1e802382014-01-23 11:12:16 -0800292 PerfMon pm = PerfMon.getInstance();
293 pm.addflowpath_start();
294 boolean retValue = addFlowFast(dbHandler, flowPath);
295 pm.addflowpath_end();
296 return retValue;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700297 }
298
299 /**
300 * Add a flow entry to the Network MAP.
301 *
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700302 * @param dbHandler the Graph Database handler to use.
303 * @param flowObj the corresponding Flow Path object for the Flow Entry.
304 * @param flowEntry the Flow Entry to install.
305 * @return the added Flow Entry object on success, otherwise null.
306 */
onlab-qa38805cd2013-12-06 20:08:54 -0800307 static IFlowEntry addFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700308 IFlowPath flowObj,
309 FlowEntry flowEntry) {
310 // Flow edges
311 // HeadFE (TODO)
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800312 long startAddFlowEntry = 0;
313 long endAddFlowEntry = 0;
314
315 long endSearchFlowEntry = 0;
316
317 long startCreateNewFlowEntry = 0;
318 long endCreateNewFlowEntry = 0;
319
320 long startSetProperties = 0;
321 long endSetProperties = 0;
322 int numProperties = 0;
323
324 long startSearchSwitch = 0;
325 long endSearchSwitch = 0;
326
327 long startAddEdgeToSwitch =0;
328 long endAddEdgeToSwitch =0;
329
330 long startSearchInPort = 0;
331 long endSearchInPort = 0;
332
333 long startAddEdgeToInPort =0;
334 long endAddEdgeToInPort =0;
335
336 long startSearchOutPort = 0;
337 long endSearchOutPort = 0;
338
339 long startAddEdgeToOutPort =0;
340 long endAddEdgeToOutPort =0;
341
342 long startAddEdgeBetweenFlowPath = 0;
343 long endAddEdgeBetweenFlowPath = 0;
344
345 if (measureONOSFlowEntryTimeProp) {
346 startAddFlowEntry = System.nanoTime();
347 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700348
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700349 IFlowEntry flowEntryObj = null;
350 boolean found = false;
351 try {
Yuta HIGUCHIc27a6c92014-01-07 11:51:11 -0800352 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
353 if (measureONOSFlowEntryTimeProp) {
354 endSearchFlowEntry = System.nanoTime();
355 }
356 if (flowEntryObj != null) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700357 found = true;
358 } else {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800359 if (measureONOSFlowEntryTimeProp) {
360 startCreateNewFlowEntry = System.nanoTime();
361 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700362 flowEntryObj = dbHandler.newFlowEntry();
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800363 if (measureONOSFlowEntryTimeProp) {
364 endCreateNewFlowEntry = System.nanoTime();
365 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700366 }
367 } catch (Exception e) {
368 log.error(":addFlow FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800369 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700370 return null;
371 }
372 if (flowEntryObj == null) {
373 log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800374 flowEntry.flowEntryId());
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700375 return null;
376 }
377
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800378 if (measureONOSFlowEntryTimeProp) {
379 startSetProperties = System.nanoTime();
380 }
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800381
Toshio Koidec71b7122014-01-13 15:16:53 -0800382 FlowEntryProperty flowProp = new FlowEntryProperty();
Yuta HIGUCHI8685f9c2014-01-07 15:53:28 -0800383
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700384 //
385 // Set the Flow Entry key:
386 // - flowEntry.flowEntryId()
387 //
Toshio Koide3f233542014-01-07 14:19:09 -0800388 flowProp.setFlowEntryId(flowEntry.flowEntryId().toString());
389 flowProp.setType("flow_entry");
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800390 if (measureONOSFlowEntryTimeProp) {
391 numProperties += 2;
392 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700393
Yuta HIGUCHI37c55472014-01-03 11:42:27 -0800394 //
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700395 // Set the Flow Entry Edges and attributes:
396 // - Switch edge
397 // - InPort edge
398 // - OutPort edge
399 //
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800400 // - flowEntry.idleTimeout()
401 // - flowEntry.hardTimeout()
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700402 // - flowEntry.dpid()
403 // - flowEntry.flowEntryUserState()
404 // - flowEntry.flowEntrySwitchState()
405 // - flowEntry.flowEntryErrorState()
406 // - flowEntry.matchInPort()
407 // - flowEntry.matchSrcMac()
408 // - flowEntry.matchDstMac()
409 // - flowEntry.matchEthernetFrameType()
410 // - flowEntry.matchVlanId()
411 // - flowEntry.matchVlanPriority()
412 // - flowEntry.matchSrcIPv4Net()
413 // - flowEntry.matchDstIPv4Net()
414 // - flowEntry.matchIpProto()
415 // - flowEntry.matchIpToS()
416 // - flowEntry.matchSrcTcpUdpPort()
417 // - flowEntry.matchDstTcpUdpPort()
418 // - flowEntry.actionOutputPort()
419 // - flowEntry.actions()
420 //
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800421 if (measureONOSFlowEntryTimeProp) {
422 startSearchSwitch = System.nanoTime();
423 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700424 ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800425 if (measureONOSFlowEntryTimeProp) {
426 endSearchSwitch = System.nanoTime();
427 }
428
Toshio Koide3f233542014-01-07 14:19:09 -0800429 flowProp.setIdleTimeout(flowEntry.idleTimeout());
430 flowProp.setHardTimeout(flowEntry.hardTimeout());
431 flowProp.setSwitchDpid(flowEntry.dpid().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800432 if (measureONOSFlowEntryTimeProp) {
433 numProperties += 3;
434 }
435
436 if (measureONOSFlowEntryTimeProp) {
437 startAddEdgeToSwitch = System.nanoTime();
438 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700439 flowEntryObj.setSwitch(sw);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800440 if (measureONOSFlowEntryTimeProp) {
441 endAddEdgeToSwitch = System.nanoTime();
442 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700443 if (flowEntry.flowEntryMatch().matchInPort()) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800444 if (measureONOSFlowEntryTimeProp) {
445 startSearchInPort = System.nanoTime();
446 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700447 IPortObject inport =
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800448 dbHandler.searchPort(flowEntry.dpid().toString(),
449 flowEntry.flowEntryMatch().inPort().value());
450 if (measureONOSFlowEntryTimeProp) {
451 endSearchInPort = System.nanoTime();
452 }
453
Toshio Koide3f233542014-01-07 14:19:09 -0800454 flowProp.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800455 if (measureONOSFlowEntryTimeProp) {
456 ++numProperties;
457 }
458
459 if (measureONOSFlowEntryTimeProp) {
460 startAddEdgeToInPort = System.nanoTime();
461 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700462 flowEntryObj.setInPort(inport);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800463 if (measureONOSFlowEntryTimeProp) {
464 endAddEdgeToInPort = System.nanoTime();
465 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700466 }
467 if (flowEntry.flowEntryMatch().matchSrcMac()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800468 flowProp.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800469 if (measureONOSFlowEntryTimeProp) {
470 ++numProperties;
471 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700472 }
473 if (flowEntry.flowEntryMatch().matchDstMac()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800474 flowProp.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800475 if (measureONOSFlowEntryTimeProp) {
476 ++numProperties;
477 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700478 }
479 if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800480 flowProp.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800481 if (measureONOSFlowEntryTimeProp) {
482 ++numProperties;
483 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700484 }
485 if (flowEntry.flowEntryMatch().matchVlanId()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800486 flowProp.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800487 if (measureONOSFlowEntryTimeProp) {
488 ++numProperties;
489 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700490 }
491 if (flowEntry.flowEntryMatch().matchVlanPriority()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800492 flowProp.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800493 if (measureONOSFlowEntryTimeProp) {
494 ++numProperties;
495 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700496 }
497 if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800498 flowProp.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800499 if (measureONOSFlowEntryTimeProp) {
500 ++numProperties;
501 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700502 }
503 if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800504 flowProp.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800505 if (measureONOSFlowEntryTimeProp) {
506 ++numProperties;
507 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700508 }
509 if (flowEntry.flowEntryMatch().matchIpProto()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800510 flowProp.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800511 if (measureONOSFlowEntryTimeProp) {
512 ++numProperties;
513 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700514 }
515 if (flowEntry.flowEntryMatch().matchIpToS()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800516 flowProp.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800517 if (measureONOSFlowEntryTimeProp) {
518 ++numProperties;
519 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700520 }
521 if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800522 flowProp.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800523 if (measureONOSFlowEntryTimeProp) {
524 ++numProperties;
525 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700526 }
527 if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800528 flowProp.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800529 if (measureONOSFlowEntryTimeProp) {
530 ++numProperties;
531 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700532 }
533
534 for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
535 if (fa.actionOutput() != null) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800536 if (measureONOSFlowEntryTimeProp) {
537 if ( startSearchOutPort != 0 ) log.error("Performance addFlowEntry(_,{},{}) -- Multiple output port action unexpected.", flowEntry.flowId(), flowEntry.flowEntryId());
538 startSearchOutPort = System.nanoTime();
539 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700540 IPortObject outport =
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800541 dbHandler.searchPort(flowEntry.dpid().toString(),
542 fa.actionOutput().port().value());
543 if (measureONOSFlowEntryTimeProp) {
544 endSearchOutPort = System.nanoTime();
545 }
546
Toshio Koide3f233542014-01-07 14:19:09 -0800547 flowProp.setActionOutputPort(fa.actionOutput().port().value());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800548 if (measureONOSFlowEntryTimeProp) {
549 ++numProperties;
550 }
551
552 if (measureONOSFlowEntryTimeProp) {
553 startAddEdgeToOutPort = System.nanoTime();
554 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700555 flowEntryObj.setOutPort(outport);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800556 if (measureONOSFlowEntryTimeProp) {
557 endAddEdgeToOutPort = System.nanoTime();
558 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700559 }
560 }
561 if (! flowEntry.flowEntryActions().isEmpty()) {
Toshio Koide3f233542014-01-07 14:19:09 -0800562 flowProp.setActions(flowEntry.flowEntryActions().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800563 if (measureONOSFlowEntryTimeProp) {
564 ++numProperties;
565 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700566 }
567
568 // TODO: Hacks with hard-coded state names!
569 if (found)
Toshio Koide3f233542014-01-07 14:19:09 -0800570 flowProp.setUserState("FE_USER_MODIFY");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700571 else
Toshio Koide3f233542014-01-07 14:19:09 -0800572 flowProp.setUserState("FE_USER_ADD");
573 flowProp.setSwitchState(flowEntry.flowEntrySwitchState().toString());
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800574 if (measureONOSFlowEntryTimeProp) {
575 numProperties += 2;
576 }
Toshio Koidec71b7122014-01-13 15:16:53 -0800577 flowProp.commitProperties(dbHandler, flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700578 //
579 // TODO: Take care of the FlowEntryErrorState.
580 //
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800581 if (measureONOSFlowEntryTimeProp) {
582 endSetProperties = System.nanoTime();
583 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700584
585 // Flow Entries edges:
586 // Flow
587 // NextFE (TODO)
588 if (! found) {
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800589 if (measureONOSFlowEntryTimeProp) {
590 startAddEdgeBetweenFlowPath = System.nanoTime();
591 }
Toshio Koidec71b7122014-01-13 15:16:53 -0800592 //flowObj.addFlowEntry(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700593 flowEntryObj.setFlow(flowObj);
Yuta HIGUCHIf9ce1c12014-01-04 23:21:58 -0800594 if (measureONOSFlowEntryTimeProp) {
595 endAddEdgeBetweenFlowPath = System.nanoTime();
596 }
597 }
598 if (measureONOSFlowEntryTimeProp) {
599 endAddFlowEntry = System.nanoTime();
600
601 log.error("Performance addFlowEntry(_,{},{}) -- "
602 + "GrandTotal: {} "
603 + "SearchExistingFE: {} "
604 + "CreateNewFE: {} "
605 + "SetProp+Edge: {} #Props: {} "
606 + "SearchSwitch: {} "
607 + "AddEdgeToSwitch: {} "
608 + "SearchInPort: {} "
609 + "AddEdgeToInPort: {} "
610 + "SearchOutPort: {} "
611 + "AddEdgeToOutPort: {} "
612 + "AddEdgeBetweenFlowPath: {} "
613 , flowEntry.flowId(), flowEntry.flowEntryId()
614 , endAddFlowEntry - startAddFlowEntry
615 , endSearchFlowEntry - startAddFlowEntry
616 , endCreateNewFlowEntry - startCreateNewFlowEntry
617 , endSetProperties - startSetProperties, numProperties
618 , endSearchSwitch - startSearchSwitch
619 , endAddEdgeToSwitch - startAddEdgeToSwitch
620 , endSearchInPort - startSearchInPort
621 , endAddEdgeToInPort - startAddEdgeToInPort
622 , endSearchOutPort - startSearchOutPort
623 , endAddEdgeToOutPort - startAddEdgeToOutPort
624 , endAddEdgeBetweenFlowPath - startAddEdgeBetweenFlowPath
625 );
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700626 }
627
628 return flowEntryObj;
629 }
630
631 /**
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700632 * Delete a flow entry from the Network MAP.
633 *
634 * @param dbHandler the Graph Database handler to use.
635 * @param flowObj the corresponding Flow Path object for the Flow Entry.
636 * @param flowEntry the Flow Entry to delete.
637 * @return true on success, otherwise false.
638 */
yoshitomob292c622013-11-23 14:35:58 -0800639 static boolean deleteFlowEntry(DBOperation dbHandler,
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700640 IFlowPath flowObj,
641 FlowEntry flowEntry) {
642 IFlowEntry flowEntryObj = null;
643 try {
644 flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
645 } catch (Exception e) {
646 log.error(":deleteFlowEntry FlowEntryId:{} failed",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800647 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700648 return false;
649 }
650 //
651 // TODO: Don't print an error for now, because multiple controller
652 // instances might be deleting the same flow entry.
653 //
654 /*
655 if (flowEntryObj == null) {
656 log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800657 flowEntry.flowEntryId());
Pavlin Radoslavov7407ab52013-11-01 22:19:00 -0700658 return false;
659 }
660 */
661 if (flowEntryObj == null)
662 return true;
663
664 flowObj.removeFlowEntry(flowEntryObj);
665 dbHandler.removeFlowEntry(flowEntryObj);
666 return true;
667 }
668
669 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700670 * Delete all previously added flows.
671 *
672 * @param dbHandler the Graph Database handler to use.
673 * @return true on success, otherwise false.
674 */
yoshitomob292c622013-11-23 14:35:58 -0800675 static boolean deleteAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700676 Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
677 for (IFlowPath flowPathObj : allFlowPaths) {
678 if (flowPathObj == null)
679 continue;
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700680
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800681 deleteIFlowPath(dbHandler, flowPathObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700682 }
Yuta HIGUCHIeab1c8b2014-01-15 19:13:28 -0800683 dbHandler.commit();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700684
685 return true;
686 }
687
688 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800689 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700690 *
691 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800692 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700693 * @return true on success, otherwise false.
694 */
yoshitomob292c622013-11-23 14:35:58 -0800695 static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700696 IFlowPath flowObj = null;
697 try {
698 flowObj = dbHandler.searchFlowPath(flowId);
699 } catch (Exception e) {
700 // TODO: handle exceptions
701 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800702 log.error(":deleteFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700703 return false;
704 }
705 if (flowObj == null) {
706 dbHandler.commit();
707 return true; // OK: No such flow
708 }
709
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800710 deleteIFlowPath(dbHandler, flowObj);
Yuta HIGUCHIeab1c8b2014-01-15 19:13:28 -0800711 dbHandler.commit();
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800712 return true;
713 }
714
Yuta HIGUCHIeab1c8b2014-01-15 19:13:28 -0800715 /**
716 * Delete a previously added flow.
717 * @note You need to call commit after calling this method.
718 * @param dbHandler the Graph Database handler to use.
719 * @param flowObj IFlowPath object to delete.
720 */
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800721 private static void deleteIFlowPath(DBOperation dbHandler, IFlowPath flowObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700722 //
723 // Remove all Flow Entries
724 //
725 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
726 for (IFlowEntry flowEntryObj : flowEntries) {
727 flowObj.removeFlowEntry(flowEntryObj);
728 dbHandler.removeFlowEntry(flowEntryObj);
729 }
730 // Remove the Flow itself
731 dbHandler.removeFlowPath(flowObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700732 }
733
734 /**
735 * Get a previously added flow.
736 *
737 * @param dbHandler the Graph Database handler to use.
738 * @param flowId the Flow ID of the flow to get.
739 * @return the Flow Path if found, otherwise null.
740 */
yoshitomob292c622013-11-23 14:35:58 -0800741 static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700742 IFlowPath flowObj = null;
743 try {
744 flowObj = dbHandler.searchFlowPath(flowId);
745 } catch (Exception e) {
746 // TODO: handle exceptions
747 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800748 log.error(":getFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700749 return null;
750 }
751 if (flowObj == null) {
752 dbHandler.commit();
753 return null; // Flow not found
754 }
755
756 //
757 // Extract the Flow state
758 //
759 FlowPath flowPath = extractFlowPath(flowObj);
760 dbHandler.commit();
761
762 return flowPath;
763 }
764
765 /**
766 * Get all installed flows by all installers.
767 *
768 * @param dbHandler the Graph Database handler to use.
769 * @return the Flow Paths if found, otherwise null.
770 */
yoshitomob292c622013-11-23 14:35:58 -0800771 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700772 Iterable<IFlowPath> flowPathsObj = null;
773 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
774
775 try {
776 flowPathsObj = dbHandler.getAllFlowPaths();
777 } catch (Exception e) {
778 // TODO: handle exceptions
779 dbHandler.rollback();
780 log.error(":getAllFlowPaths failed");
781 return flowPaths;
782 }
783 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
784 dbHandler.commit();
785 return flowPaths; // No Flows found
786 }
787
788 for (IFlowPath flowObj : flowPathsObj) {
789 //
790 // Extract the Flow state
791 //
792 FlowPath flowPath = extractFlowPath(flowObj);
793 if (flowPath != null)
794 flowPaths.add(flowPath);
795 }
796
797 dbHandler.commit();
798
799 return flowPaths;
800 }
801
802 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700803 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
804 *
805 * @param flowObj the object to extract the Flow Path State from.
806 * @return the extracted Flow Path State.
807 */
808 private static FlowPath extractFlowPath(IFlowPath flowObj) {
809 //
810 // Extract the Flow state
811 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800812 log.info("extractFlowPath: start");
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800813 String flowIdStr;
814 String installerIdStr;
815 String flowPathType;
816 String flowPathUserState;
817 Long flowPathFlags;
818 Integer idleTimeout;
819 Integer hardTimeout;
820 String srcSwitchStr;
821 Short srcPortShort;
822 String dstSwitchStr;
823 Short dstPortShort;
824
825 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
826 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
827 Map<String,Object> propMap = v.getProperties();
828
829 flowIdStr = (String) propMap.get("flow_id");
830 installerIdStr = (String) propMap.get("installer_id");
831 flowPathType = (String) propMap.get("flow_path_type");
832 flowPathUserState = (String) propMap.get("user_state");
833 flowPathFlags = (Long)propMap.get("flow_path_flags");
834 idleTimeout = (Integer) propMap.get("idle_timeout");
835 hardTimeout = (Integer) propMap.get("hard_timeout");
836 srcSwitchStr = (String) propMap.get("src_switch");
837 srcPortShort = (Short)propMap.get("src_port");
838 dstSwitchStr = (String) propMap.get("dst_switch");
839 dstPortShort = (Short)propMap.get("dst_port");
840 } else {
841 flowIdStr = flowObj.getFlowId();
842 installerIdStr = flowObj.getInstallerId();
843 flowPathType = flowObj.getFlowPathType();
844 flowPathUserState = flowObj.getFlowPathUserState();
845 flowPathFlags = flowObj.getFlowPathFlags();
846 idleTimeout = flowObj.getIdleTimeout();
847 hardTimeout = flowObj.getHardTimeout();
848 srcSwitchStr = flowObj.getSrcSwitch();
849 srcPortShort = flowObj.getSrcPort();
850 dstSwitchStr = flowObj.getDstSwitch();
851 dstPortShort = flowObj.getDstPort();
852 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700853
854 if ((flowIdStr == null) ||
855 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700856 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700857 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700858 (flowPathFlags == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800859 (idleTimeout == null) ||
860 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700861 (srcSwitchStr == null) ||
862 (srcPortShort == null) ||
863 (dstSwitchStr == null) ||
864 (dstPortShort == null)) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800865 // TODO: A work-around, because of some bogus database objects
866 log.error("extractFlowPath: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700867 return null;
868 }
869
870 FlowPath flowPath = new FlowPath();
871 flowPath.setFlowId(new FlowId(flowIdStr));
872 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700873 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700874 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700875 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800876 flowPath.setIdleTimeout(idleTimeout);
877 flowPath.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700878 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
879 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
880 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
881 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
882 //
883 // Extract the match conditions common for all Flow Entries
884 //
885 {
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800886 FlowEntryMatch match = extractMatch(flowObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700887
888 flowPath.setFlowEntryMatch(match);
889 }
890 //
891 // Extract the actions for the first Flow Entry
892 //
893 {
894 String actionsStr = flowObj.getActions();
895 if (actionsStr != null) {
896 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
897 flowPath.setFlowEntryActions(flowEntryActions);
898 }
899 }
900
901 //
902 // Extract all Flow Entries
903 //
904 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
905 for (IFlowEntry flowEntryObj : flowEntries) {
906 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
907 if (flowEntry == null)
908 continue;
909 flowPath.dataPath().flowEntries().add(flowEntry);
910 }
911
Toshio Koidea9b25142014-01-10 01:15:57 -0800912 log.info("extractFlowPath: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700913 return flowPath;
914 }
915
916 /**
917 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
918 *
919 * @param flowEntryObj the object to extract the Flow Entry State from.
920 * @return the extracted Flow Entry State.
921 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700922 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800923 log.info("extractFlowEntry: start");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800924 IFlowPath flowObj = flowEntryObj.getFlow();
Toshio Koidea9b25142014-01-10 01:15:57 -0800925 if (flowObj == null) {
926 log.error("extractFlowEntry: no flowPath exists");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800927 return null;
Toshio Koidea9b25142014-01-10 01:15:57 -0800928 }
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800929
930 String flowIdStr = flowObj.getFlowId();
931 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800932 String flowEntryIdStr;
933 Integer idleTimeout;
934 Integer hardTimeout;
935 String switchDpidStr;
936 String userState;
937 String switchState;
938 if ( flowEntryObj.asVertex() instanceof RamCloudVertex ) {
939 RamCloudVertex v = (RamCloudVertex)flowEntryObj.asVertex();
940 Map<String,Object> propMap = v.getProperties();
941
942 flowEntryIdStr = (String) propMap.get("flow_entry_id");
943 idleTimeout = (Integer) propMap.get("idle_timeout");
944 hardTimeout = (Integer) propMap.get("hard_timeout");
945 switchDpidStr = (String) propMap.get("switch_dpid");
946 userState = (String) propMap.get("user_state");
947 switchState = (String) propMap.get("switch_state");
948 } else {
949 flowEntryIdStr = flowEntryObj.getFlowEntryId();
950 idleTimeout = flowEntryObj.getIdleTimeout();
951 hardTimeout = flowEntryObj.getHardTimeout();
952 switchDpidStr = flowEntryObj.getSwitchDpid();
953 userState = flowEntryObj.getUserState();
954 switchState = flowEntryObj.getSwitchState();
955 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700956
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800957 if ((flowIdStr == null) ||
958 (flowEntryIdStr == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800959 (idleTimeout == null) ||
960 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700961 (switchDpidStr == null) ||
962 (userState == null) ||
963 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -0700964 // TODO: A work-around, because of some bogus database objects
Toshio Koidea9b25142014-01-10 01:15:57 -0800965 log.error("extractFlowEntry: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700966 return null;
967 }
968
969 FlowEntry flowEntry = new FlowEntry();
970 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800971 flowEntry.setFlowId(new FlowId(flowIdStr));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700972 flowEntry.setDpid(new Dpid(switchDpidStr));
yoshia97632b2013-12-17 15:46:08 -0800973 flowEntry.setIdleTimeout(idleTimeout);
974 flowEntry.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700975
976 //
977 // Extract the match conditions
978 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800979 FlowEntryMatch match = extractMatch(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700980 flowEntry.setFlowEntryMatch(match);
981
982 //
983 // Extract the actions
984 //
985 FlowEntryActions actions = new FlowEntryActions();
986 String actionsStr = flowEntryObj.getActions();
987 if (actionsStr != null)
988 actions = new FlowEntryActions(actionsStr);
989 flowEntry.setFlowEntryActions(actions);
990 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
991 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
992 //
993 // TODO: Take care of FlowEntryErrorState.
994 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800995 log.info("extractFlowEntry: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700996 return flowEntry;
997 }
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800998
999 /**
1000 * Extract FlowEntryMatch from IFlowPath or IFlowEntry
1001 * @param flowObj : either IFlowPath or IFlowEntry
1002 * @return extracted Match info
1003 */
1004 private static FlowEntryMatch extractMatch(IBaseObject flowObj) {
1005 FlowEntryMatch match = new FlowEntryMatch();
1006
1007 Short matchInPort = null; // Only for IFlowEntry
1008 String matchSrcMac = null;
1009 String matchDstMac = null;
1010 Short matchEthernetFrameType = null;
1011 Short matchVlanId = null;
1012 Byte matchVlanPriority = null;
1013 String matchSrcIPv4Net = null;
1014 String matchDstIPv4Net = null;
1015 Byte matchIpProto = null;
1016 Byte matchIpToS = null;
1017 Short matchSrcTcpUdpPort = null;
1018 Short matchDstTcpUdpPort = null;
1019
1020 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
1021 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
1022 Map<String,Object> propMap = v.getProperties();
1023 matchInPort = (Short) propMap.get("matchInPort");
1024 matchSrcMac = (String) propMap.get("matchSrcMac");
1025 matchDstMac = (String) propMap.get("matchDstMac");
1026 matchEthernetFrameType = (Short) propMap.get("matchEthernetFrameType");
1027 matchVlanId = (Short) propMap.get("matchVlanId");
1028 matchVlanPriority = (Byte) propMap.get("matchVlanPriority");
1029 matchSrcIPv4Net = (String) propMap.get("matchSrcIPv4Net");
1030 matchDstIPv4Net = (String) propMap.get("matchDstIPv4Net");
1031 matchIpProto = (Byte) propMap.get("matchIpProto");
1032 matchIpToS = (Byte) propMap.get("matchIpToS");
1033 matchSrcTcpUdpPort = (Short) propMap.get("matchSrcTcpUdpPort");
1034 matchDstTcpUdpPort = (Short) propMap.get("matchDstTcpUdpPort");
1035 } else {
1036 if (flowObj instanceof IFlowEntry ){
1037 IFlowEntry flowEntry = (IFlowEntry) flowObj;
1038 matchInPort = flowEntry.getMatchInPort();
1039 matchSrcMac = flowEntry.getMatchSrcMac();
1040 matchDstMac = flowEntry.getMatchDstMac();
1041 matchEthernetFrameType = flowEntry.getMatchEthernetFrameType();
1042 matchVlanId = flowEntry.getMatchVlanId();
1043 matchVlanPriority = flowEntry.getMatchVlanPriority();
1044 matchSrcIPv4Net = flowEntry.getMatchSrcIPv4Net();
1045 matchDstIPv4Net = flowEntry.getMatchDstIPv4Net();
1046 matchIpProto = flowEntry.getMatchIpProto();
1047 matchIpToS = flowEntry.getMatchIpToS();
1048 matchSrcTcpUdpPort = flowEntry.getMatchSrcTcpUdpPort();
1049 matchDstTcpUdpPort = flowEntry.getMatchDstTcpUdpPort();
1050 } else if(flowObj instanceof IFlowPath) {
1051 IFlowPath flowPath = (IFlowPath) flowObj;
1052 matchSrcMac = flowPath.getMatchSrcMac();
1053 matchDstMac = flowPath.getMatchDstMac();
1054 matchEthernetFrameType = flowPath.getMatchEthernetFrameType();
1055 matchVlanId = flowPath.getMatchVlanId();
1056 matchVlanPriority = flowPath.getMatchVlanPriority();
1057 matchSrcIPv4Net = flowPath.getMatchSrcIPv4Net();
1058 matchDstIPv4Net = flowPath.getMatchDstIPv4Net();
1059 matchIpProto = flowPath.getMatchIpProto();
1060 matchIpToS = flowPath.getMatchIpToS();
1061 matchSrcTcpUdpPort = flowPath.getMatchSrcTcpUdpPort();
1062 matchDstTcpUdpPort = flowPath.getMatchDstTcpUdpPort();
1063 }
1064 }
1065
1066 if (matchInPort != null)
1067 match.enableInPort(new Port(matchInPort));
1068 if (matchSrcMac != null)
1069 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
1070 if (matchDstMac != null)
1071 match.enableDstMac(MACAddress.valueOf(matchDstMac));
1072 if (matchEthernetFrameType != null)
1073 match.enableEthernetFrameType(matchEthernetFrameType);
1074 if (matchVlanId != null)
1075 match.enableVlanId(matchVlanId);
1076 if (matchVlanPriority != null)
1077 match.enableVlanPriority(matchVlanPriority);
1078 if (matchSrcIPv4Net != null)
1079 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
1080 if (matchDstIPv4Net != null)
1081 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
1082 if (matchIpProto != null)
1083 match.enableIpProto(matchIpProto);
1084 if (matchIpToS != null)
1085 match.enableIpToS(matchIpToS);
1086 if (matchSrcTcpUdpPort != null)
1087 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
1088 if (matchDstTcpUdpPort != null)
1089 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
1090 return match;
1091 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001092}