blob: 343b5325c26423c4cd9a63dc316c84623ded0585 [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;
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800680 deleteIFlowPath(dbHandler, flowPathObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700681 }
682
683 return true;
684 }
685
686 /**
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800687 * Delete a previously added flow.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700688 *
689 * @param dbHandler the Graph Database handler to use.
Pavlin Radoslavovf2a52652013-11-22 12:35:42 -0800690 * @param flowId the Flow ID of the flow to delete.
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700691 * @return true on success, otherwise false.
692 */
yoshitomob292c622013-11-23 14:35:58 -0800693 static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700694 IFlowPath flowObj = null;
695 try {
696 flowObj = dbHandler.searchFlowPath(flowId);
697 } catch (Exception e) {
698 // TODO: handle exceptions
699 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800700 log.error(":deleteFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700701 return false;
702 }
703 if (flowObj == null) {
704 dbHandler.commit();
705 return true; // OK: No such flow
706 }
707
Yuta HIGUCHI53794052014-01-10 16:49:41 -0800708 deleteIFlowPath(dbHandler, flowObj);
709
710 return true;
711 }
712
713 private static void deleteIFlowPath(DBOperation dbHandler, IFlowPath flowObj) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700714 //
715 // Remove all Flow Entries
716 //
717 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
718 for (IFlowEntry flowEntryObj : flowEntries) {
719 flowObj.removeFlowEntry(flowEntryObj);
720 dbHandler.removeFlowEntry(flowEntryObj);
721 }
722 // Remove the Flow itself
723 dbHandler.removeFlowPath(flowObj);
Nick Karanatsios758df8d2014-01-14 22:16:32 -0800724 dbHandler.commit();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700725 }
726
727 /**
728 * Get a previously added flow.
729 *
730 * @param dbHandler the Graph Database handler to use.
731 * @param flowId the Flow ID of the flow to get.
732 * @return the Flow Path if found, otherwise null.
733 */
yoshitomob292c622013-11-23 14:35:58 -0800734 static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700735 IFlowPath flowObj = null;
736 try {
737 flowObj = dbHandler.searchFlowPath(flowId);
738 } catch (Exception e) {
739 // TODO: handle exceptions
740 dbHandler.rollback();
Yuta HIGUCHI5302ddf2014-01-06 12:53:35 -0800741 log.error(":getFlow FlowId:{} failed", flowId);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700742 return null;
743 }
744 if (flowObj == null) {
745 dbHandler.commit();
746 return null; // Flow not found
747 }
748
749 //
750 // Extract the Flow state
751 //
752 FlowPath flowPath = extractFlowPath(flowObj);
753 dbHandler.commit();
754
755 return flowPath;
756 }
757
758 /**
759 * Get all installed flows by all installers.
760 *
761 * @param dbHandler the Graph Database handler to use.
762 * @return the Flow Paths if found, otherwise null.
763 */
yoshitomob292c622013-11-23 14:35:58 -0800764 static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700765 Iterable<IFlowPath> flowPathsObj = null;
766 ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
767
768 try {
769 flowPathsObj = dbHandler.getAllFlowPaths();
770 } catch (Exception e) {
771 // TODO: handle exceptions
772 dbHandler.rollback();
773 log.error(":getAllFlowPaths failed");
774 return flowPaths;
775 }
776 if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
777 dbHandler.commit();
778 return flowPaths; // No Flows found
779 }
780
781 for (IFlowPath flowObj : flowPathsObj) {
782 //
783 // Extract the Flow state
784 //
785 FlowPath flowPath = extractFlowPath(flowObj);
786 if (flowPath != null)
787 flowPaths.add(flowPath);
788 }
789
790 dbHandler.commit();
791
792 return flowPaths;
793 }
794
795 /**
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700796 * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
797 *
798 * @param flowObj the object to extract the Flow Path State from.
799 * @return the extracted Flow Path State.
800 */
801 private static FlowPath extractFlowPath(IFlowPath flowObj) {
802 //
803 // Extract the Flow state
804 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800805 log.info("extractFlowPath: start");
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800806 String flowIdStr;
807 String installerIdStr;
808 String flowPathType;
809 String flowPathUserState;
810 Long flowPathFlags;
811 Integer idleTimeout;
812 Integer hardTimeout;
813 String srcSwitchStr;
814 Short srcPortShort;
815 String dstSwitchStr;
816 Short dstPortShort;
817
818 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
819 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
820 Map<String,Object> propMap = v.getProperties();
821
822 flowIdStr = (String) propMap.get("flow_id");
823 installerIdStr = (String) propMap.get("installer_id");
824 flowPathType = (String) propMap.get("flow_path_type");
825 flowPathUserState = (String) propMap.get("user_state");
826 flowPathFlags = (Long)propMap.get("flow_path_flags");
827 idleTimeout = (Integer) propMap.get("idle_timeout");
828 hardTimeout = (Integer) propMap.get("hard_timeout");
829 srcSwitchStr = (String) propMap.get("src_switch");
830 srcPortShort = (Short)propMap.get("src_port");
831 dstSwitchStr = (String) propMap.get("dst_switch");
832 dstPortShort = (Short)propMap.get("dst_port");
833 } else {
834 flowIdStr = flowObj.getFlowId();
835 installerIdStr = flowObj.getInstallerId();
836 flowPathType = flowObj.getFlowPathType();
837 flowPathUserState = flowObj.getFlowPathUserState();
838 flowPathFlags = flowObj.getFlowPathFlags();
839 idleTimeout = flowObj.getIdleTimeout();
840 hardTimeout = flowObj.getHardTimeout();
841 srcSwitchStr = flowObj.getSrcSwitch();
842 srcPortShort = flowObj.getSrcPort();
843 dstSwitchStr = flowObj.getDstSwitch();
844 dstPortShort = flowObj.getDstPort();
845 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700846
847 if ((flowIdStr == null) ||
848 (installerIdStr == null) ||
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700849 (flowPathType == null) ||
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700850 (flowPathUserState == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700851 (flowPathFlags == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800852 (idleTimeout == null) ||
853 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700854 (srcSwitchStr == null) ||
855 (srcPortShort == null) ||
856 (dstSwitchStr == null) ||
857 (dstPortShort == null)) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800858 // TODO: A work-around, because of some bogus database objects
859 log.error("extractFlowPath: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700860 return null;
861 }
862
863 FlowPath flowPath = new FlowPath();
864 flowPath.setFlowId(new FlowId(flowIdStr));
865 flowPath.setInstallerId(new CallerId(installerIdStr));
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700866 flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700867 flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700868 flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800869 flowPath.setIdleTimeout(idleTimeout);
870 flowPath.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700871 flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
872 flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
873 flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
874 flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
875 //
876 // Extract the match conditions common for all Flow Entries
877 //
878 {
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800879 FlowEntryMatch match = extractMatch(flowObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700880
881 flowPath.setFlowEntryMatch(match);
882 }
883 //
884 // Extract the actions for the first Flow Entry
885 //
886 {
887 String actionsStr = flowObj.getActions();
888 if (actionsStr != null) {
889 FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
890 flowPath.setFlowEntryActions(flowEntryActions);
891 }
892 }
893
894 //
895 // Extract all Flow Entries
896 //
897 Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
898 for (IFlowEntry flowEntryObj : flowEntries) {
899 FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
900 if (flowEntry == null)
901 continue;
902 flowPath.dataPath().flowEntries().add(flowEntry);
903 }
904
Toshio Koidea9b25142014-01-10 01:15:57 -0800905 log.info("extractFlowPath: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700906 return flowPath;
907 }
908
909 /**
910 * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
911 *
912 * @param flowEntryObj the object to extract the Flow Entry State from.
913 * @return the extracted Flow Entry State.
914 */
Brian O'Connora8e49802013-10-30 20:49:59 -0700915 public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
Toshio Koidea9b25142014-01-10 01:15:57 -0800916 log.info("extractFlowEntry: start");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800917 IFlowPath flowObj = flowEntryObj.getFlow();
Toshio Koidea9b25142014-01-10 01:15:57 -0800918 if (flowObj == null) {
919 log.error("extractFlowEntry: no flowPath exists");
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800920 return null;
Toshio Koidea9b25142014-01-10 01:15:57 -0800921 }
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800922
923 String flowIdStr = flowObj.getFlowId();
924 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800925 String flowEntryIdStr;
926 Integer idleTimeout;
927 Integer hardTimeout;
928 String switchDpidStr;
929 String userState;
930 String switchState;
931 if ( flowEntryObj.asVertex() instanceof RamCloudVertex ) {
932 RamCloudVertex v = (RamCloudVertex)flowEntryObj.asVertex();
933 Map<String,Object> propMap = v.getProperties();
934
935 flowEntryIdStr = (String) propMap.get("flow_entry_id");
936 idleTimeout = (Integer) propMap.get("idle_timeout");
937 hardTimeout = (Integer) propMap.get("hard_timeout");
938 switchDpidStr = (String) propMap.get("switch_dpid");
939 userState = (String) propMap.get("user_state");
940 switchState = (String) propMap.get("switch_state");
941 } else {
942 flowEntryIdStr = flowEntryObj.getFlowEntryId();
943 idleTimeout = flowEntryObj.getIdleTimeout();
944 hardTimeout = flowEntryObj.getHardTimeout();
945 switchDpidStr = flowEntryObj.getSwitchDpid();
946 userState = flowEntryObj.getUserState();
947 switchState = flowEntryObj.getSwitchState();
948 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700949
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800950 if ((flowIdStr == null) ||
951 (flowEntryIdStr == null) ||
Pavlin Radoslavov5139c0b2013-12-09 18:04:53 -0800952 (idleTimeout == null) ||
953 (hardTimeout == null) ||
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700954 (switchDpidStr == null) ||
955 (userState == null) ||
956 (switchState == null)) {
Brian O'Connora8e49802013-10-30 20:49:59 -0700957 // TODO: A work-around, because of some bogus database objects
Toshio Koidea9b25142014-01-10 01:15:57 -0800958 log.error("extractFlowEntry: wrong properties");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700959 return null;
960 }
961
962 FlowEntry flowEntry = new FlowEntry();
963 flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
Pavlin Radoslavovcf87e532013-12-13 18:17:00 -0800964 flowEntry.setFlowId(new FlowId(flowIdStr));
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700965 flowEntry.setDpid(new Dpid(switchDpidStr));
yoshia97632b2013-12-17 15:46:08 -0800966 flowEntry.setIdleTimeout(idleTimeout);
967 flowEntry.setHardTimeout(hardTimeout);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700968
969 //
970 // Extract the match conditions
971 //
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800972 FlowEntryMatch match = extractMatch(flowEntryObj);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700973 flowEntry.setFlowEntryMatch(match);
974
975 //
976 // Extract the actions
977 //
978 FlowEntryActions actions = new FlowEntryActions();
979 String actionsStr = flowEntryObj.getActions();
980 if (actionsStr != null)
981 actions = new FlowEntryActions(actionsStr);
982 flowEntry.setFlowEntryActions(actions);
983 flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
984 flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
985 //
986 // TODO: Take care of FlowEntryErrorState.
987 //
Toshio Koidea9b25142014-01-10 01:15:57 -0800988 log.info("extractFlowEntry: end");
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700989 return flowEntry;
990 }
Yuta HIGUCHIcb32b2a2014-01-10 18:07:33 -0800991
992 /**
993 * Extract FlowEntryMatch from IFlowPath or IFlowEntry
994 * @param flowObj : either IFlowPath or IFlowEntry
995 * @return extracted Match info
996 */
997 private static FlowEntryMatch extractMatch(IBaseObject flowObj) {
998 FlowEntryMatch match = new FlowEntryMatch();
999
1000 Short matchInPort = null; // Only for IFlowEntry
1001 String matchSrcMac = null;
1002 String matchDstMac = null;
1003 Short matchEthernetFrameType = null;
1004 Short matchVlanId = null;
1005 Byte matchVlanPriority = null;
1006 String matchSrcIPv4Net = null;
1007 String matchDstIPv4Net = null;
1008 Byte matchIpProto = null;
1009 Byte matchIpToS = null;
1010 Short matchSrcTcpUdpPort = null;
1011 Short matchDstTcpUdpPort = null;
1012
1013 if ( flowObj.asVertex() instanceof RamCloudVertex ) {
1014 RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
1015 Map<String,Object> propMap = v.getProperties();
1016 matchInPort = (Short) propMap.get("matchInPort");
1017 matchSrcMac = (String) propMap.get("matchSrcMac");
1018 matchDstMac = (String) propMap.get("matchDstMac");
1019 matchEthernetFrameType = (Short) propMap.get("matchEthernetFrameType");
1020 matchVlanId = (Short) propMap.get("matchVlanId");
1021 matchVlanPriority = (Byte) propMap.get("matchVlanPriority");
1022 matchSrcIPv4Net = (String) propMap.get("matchSrcIPv4Net");
1023 matchDstIPv4Net = (String) propMap.get("matchDstIPv4Net");
1024 matchIpProto = (Byte) propMap.get("matchIpProto");
1025 matchIpToS = (Byte) propMap.get("matchIpToS");
1026 matchSrcTcpUdpPort = (Short) propMap.get("matchSrcTcpUdpPort");
1027 matchDstTcpUdpPort = (Short) propMap.get("matchDstTcpUdpPort");
1028 } else {
1029 if (flowObj instanceof IFlowEntry ){
1030 IFlowEntry flowEntry = (IFlowEntry) flowObj;
1031 matchInPort = flowEntry.getMatchInPort();
1032 matchSrcMac = flowEntry.getMatchSrcMac();
1033 matchDstMac = flowEntry.getMatchDstMac();
1034 matchEthernetFrameType = flowEntry.getMatchEthernetFrameType();
1035 matchVlanId = flowEntry.getMatchVlanId();
1036 matchVlanPriority = flowEntry.getMatchVlanPriority();
1037 matchSrcIPv4Net = flowEntry.getMatchSrcIPv4Net();
1038 matchDstIPv4Net = flowEntry.getMatchDstIPv4Net();
1039 matchIpProto = flowEntry.getMatchIpProto();
1040 matchIpToS = flowEntry.getMatchIpToS();
1041 matchSrcTcpUdpPort = flowEntry.getMatchSrcTcpUdpPort();
1042 matchDstTcpUdpPort = flowEntry.getMatchDstTcpUdpPort();
1043 } else if(flowObj instanceof IFlowPath) {
1044 IFlowPath flowPath = (IFlowPath) flowObj;
1045 matchSrcMac = flowPath.getMatchSrcMac();
1046 matchDstMac = flowPath.getMatchDstMac();
1047 matchEthernetFrameType = flowPath.getMatchEthernetFrameType();
1048 matchVlanId = flowPath.getMatchVlanId();
1049 matchVlanPriority = flowPath.getMatchVlanPriority();
1050 matchSrcIPv4Net = flowPath.getMatchSrcIPv4Net();
1051 matchDstIPv4Net = flowPath.getMatchDstIPv4Net();
1052 matchIpProto = flowPath.getMatchIpProto();
1053 matchIpToS = flowPath.getMatchIpToS();
1054 matchSrcTcpUdpPort = flowPath.getMatchSrcTcpUdpPort();
1055 matchDstTcpUdpPort = flowPath.getMatchDstTcpUdpPort();
1056 }
1057 }
1058
1059 if (matchInPort != null)
1060 match.enableInPort(new Port(matchInPort));
1061 if (matchSrcMac != null)
1062 match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
1063 if (matchDstMac != null)
1064 match.enableDstMac(MACAddress.valueOf(matchDstMac));
1065 if (matchEthernetFrameType != null)
1066 match.enableEthernetFrameType(matchEthernetFrameType);
1067 if (matchVlanId != null)
1068 match.enableVlanId(matchVlanId);
1069 if (matchVlanPriority != null)
1070 match.enableVlanPriority(matchVlanPriority);
1071 if (matchSrcIPv4Net != null)
1072 match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
1073 if (matchDstIPv4Net != null)
1074 match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
1075 if (matchIpProto != null)
1076 match.enableIpProto(matchIpProto);
1077 if (matchIpToS != null)
1078 match.enableIpToS(matchIpToS);
1079 if (matchSrcTcpUdpPort != null)
1080 match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
1081 if (matchDstTcpUdpPort != null)
1082 match.enableDstTcpUdpPort(matchDstTcpUdpPort);
1083 return match;
1084 }
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001085}