Jonathan Hart | 23701d1 | 2014-04-03 10:45:48 -0700 | [diff] [blame] | 1 | package net.onrc.onos.core.util; |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 2 | |
| 3 | import java.util.ArrayList; |
| 4 | |
Pavlin Radoslavov | ad008e0 | 2013-02-21 18:42:42 -0800 | [diff] [blame] | 5 | import org.codehaus.jackson.annotate.JsonProperty; |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 6 | |
| 7 | /** |
Pavlin Radoslavov | d5b21db | 2013-07-29 17:09:53 -0700 | [diff] [blame] | 8 | * The data forwarding path state from a source to a destination. |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 9 | */ |
| 10 | public class DataPath { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 11 | private SwitchPort srcPort; // The source port |
| 12 | private SwitchPort dstPort; // The destination port |
| 13 | private ArrayList<FlowEntry> flowEntries; // The Flow Entries |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 14 | |
| 15 | /** |
| 16 | * Default constructor. |
| 17 | */ |
| 18 | public DataPath() { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 19 | srcPort = new SwitchPort(); |
| 20 | dstPort = new SwitchPort(); |
| 21 | flowEntries = new ArrayList<FlowEntry>(); |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 22 | } |
| 23 | |
| 24 | /** |
| 25 | * Get the data path source port. |
| 26 | * |
| 27 | * @return the data path source port. |
| 28 | */ |
Pavlin Radoslavov | 2013cbb | 2013-02-26 10:15:18 -0800 | [diff] [blame] | 29 | @JsonProperty("srcPort") |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 30 | public SwitchPort srcPort() { |
| 31 | return srcPort; |
| 32 | } |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 33 | |
| 34 | /** |
| 35 | * Set the data path source port. |
| 36 | * |
| 37 | * @param srcPort the data path source port to set. |
| 38 | */ |
Pavlin Radoslavov | 2013cbb | 2013-02-26 10:15:18 -0800 | [diff] [blame] | 39 | @JsonProperty("srcPort") |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 40 | public void setSrcPort(SwitchPort srcPort) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 41 | this.srcPort = srcPort; |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 42 | } |
| 43 | |
| 44 | /** |
| 45 | * Get the data path destination port. |
| 46 | * |
| 47 | * @return the data path destination port. |
| 48 | */ |
Pavlin Radoslavov | 2013cbb | 2013-02-26 10:15:18 -0800 | [diff] [blame] | 49 | @JsonProperty("dstPort") |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 50 | public SwitchPort dstPort() { |
| 51 | return dstPort; |
| 52 | } |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 53 | |
| 54 | /** |
| 55 | * Set the data path destination port. |
| 56 | * |
| 57 | * @param dstPort the data path destination port to set. |
| 58 | */ |
Pavlin Radoslavov | 2013cbb | 2013-02-26 10:15:18 -0800 | [diff] [blame] | 59 | @JsonProperty("dstPort") |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 60 | public void setDstPort(SwitchPort dstPort) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 61 | this.dstPort = dstPort; |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 62 | } |
| 63 | |
| 64 | /** |
| 65 | * Get the data path flow entries. |
| 66 | * |
| 67 | * @return the data path flow entries. |
| 68 | */ |
Pavlin Radoslavov | 2013cbb | 2013-02-26 10:15:18 -0800 | [diff] [blame] | 69 | @JsonProperty("flowEntries") |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 70 | public ArrayList<FlowEntry> flowEntries() { |
| 71 | return flowEntries; |
| 72 | } |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 73 | |
| 74 | /** |
| 75 | * Set the data path flow entries. |
| 76 | * |
| 77 | * @param flowEntries the data path flow entries to set. |
| 78 | */ |
Pavlin Radoslavov | 2013cbb | 2013-02-26 10:15:18 -0800 | [diff] [blame] | 79 | @JsonProperty("flowEntries") |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 80 | public void setFlowEntries(ArrayList<FlowEntry> flowEntries) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 81 | this.flowEntries = flowEntries; |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | /** |
Pavlin Radoslavov | 204b286 | 2013-07-12 14:15:36 -0700 | [diff] [blame] | 85 | * Apply Flow Path Flags to the pre-computed Data Path. |
| 86 | * |
| 87 | * @param flowPathFlags the Flow Path Flags to apply. |
| 88 | */ |
| 89 | public void applyFlowPathFlags(FlowPathFlags flowPathFlags) { |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 90 | if (flowPathFlags == null) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 91 | return; // Nothing to do |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 92 | } |
Pavlin Radoslavov | 204b286 | 2013-07-12 14:15:36 -0700 | [diff] [blame] | 93 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 94 | // Discard the first Flow Entry |
| 95 | if (flowPathFlags.isDiscardFirstHopEntry()) { |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 96 | if (flowEntries.size() > 0) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 97 | flowEntries.remove(0); |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 98 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 99 | } |
Pavlin Radoslavov | 204b286 | 2013-07-12 14:15:36 -0700 | [diff] [blame] | 100 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 101 | // Keep only the first Flow Entry |
| 102 | if (flowPathFlags.isKeepOnlyFirstHopEntry()) { |
| 103 | if (flowEntries.size() > 1) { |
| 104 | FlowEntry flowEntry = flowEntries.get(0); |
| 105 | flowEntries.clear(); |
| 106 | flowEntries.add(flowEntry); |
| 107 | } |
| 108 | } |
Pavlin Radoslavov | 204b286 | 2013-07-12 14:15:36 -0700 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | /** |
Pavlin Radoslavov | 31a15c3 | 2013-11-06 17:51:12 -0800 | [diff] [blame] | 112 | * Remove Flow Entries that were deleted. |
| 113 | */ |
| 114 | public void removeDeletedFlowEntries() { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 115 | // |
| 116 | // NOTE: We create a new ArrayList, and add only the Flow Entries |
| 117 | // that are NOT FE_USER_DELETE. |
| 118 | // This is sub-optimal: if it adds notable processing cost, |
| 119 | // the Flow Entries container should be changed to LinkedList |
| 120 | // or some other container that has O(1) cost of removing an entry. |
| 121 | // |
Pavlin Radoslavov | 31a15c3 | 2013-11-06 17:51:12 -0800 | [diff] [blame] | 122 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 123 | // Test first whether any Flow Entry was deleted |
| 124 | boolean foundDeletedFlowEntry = false; |
| 125 | for (FlowEntry flowEntry : this.flowEntries) { |
| 126 | if (flowEntry.flowEntryUserState() == |
| 127 | FlowEntryUserState.FE_USER_DELETE) { |
| 128 | foundDeletedFlowEntry = true; |
| 129 | break; |
| 130 | } |
| 131 | } |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 132 | if (!foundDeletedFlowEntry) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 133 | return; // Nothing to do |
Ray Milkey | b29e626 | 2014-04-09 16:02:14 -0700 | [diff] [blame] | 134 | } |
Pavlin Radoslavov | 31a15c3 | 2013-11-06 17:51:12 -0800 | [diff] [blame] | 135 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 136 | // Create a new collection and exclude the deleted flow entries |
| 137 | ArrayList<FlowEntry> newFlowEntries = new ArrayList<FlowEntry>(); |
| 138 | for (FlowEntry flowEntry : this.flowEntries()) { |
| 139 | if (flowEntry.flowEntryUserState() != |
| 140 | FlowEntryUserState.FE_USER_DELETE) { |
| 141 | newFlowEntries.add(flowEntry); |
| 142 | } |
| 143 | } |
| 144 | setFlowEntries(newFlowEntries); |
Pavlin Radoslavov | 31a15c3 | 2013-11-06 17:51:12 -0800 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | /** |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 148 | * Convert the data path to a string. |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 149 | * <p/> |
Pavlin Radoslavov | ad008e0 | 2013-02-21 18:42:42 -0800 | [diff] [blame] | 150 | * The string has the following form: |
Pavlin Radoslavov | a10a9a8 | 2013-02-22 11:47:54 -0800 | [diff] [blame] | 151 | * [src=01:01:01:01:01:01:01:01/1111 flowEntry=<entry1> flowEntry=<entry2> flowEntry=<entry3> dst=02:02:02:02:02:02:02:02/2222] |
Pavlin Radoslavov | ad008e0 | 2013-02-21 18:42:42 -0800 | [diff] [blame] | 152 | * |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 153 | * @return the data path as a string. |
| 154 | */ |
| 155 | @Override |
| 156 | public String toString() { |
Pavlin Radoslavov | 424150c | 2014-04-09 12:12:36 -0700 | [diff] [blame] | 157 | StringBuilder ret = new StringBuilder(); |
| 158 | |
| 159 | ret.append("[src=" + this.srcPort.toString()); |
Pavlin Radoslavov | ad008e0 | 2013-02-21 18:42:42 -0800 | [diff] [blame] | 160 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 161 | for (FlowEntry fe : flowEntries) { |
Pavlin Radoslavov | 424150c | 2014-04-09 12:12:36 -0700 | [diff] [blame] | 162 | ret.append(" flowEntry=" + fe.toString()); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 163 | } |
Pavlin Radoslavov | 424150c | 2014-04-09 12:12:36 -0700 | [diff] [blame] | 164 | ret.append(" dst=" + this.dstPort.toString() + "]"); |
Pavlin Radoslavov | ad008e0 | 2013-02-21 18:42:42 -0800 | [diff] [blame] | 165 | |
Pavlin Radoslavov | 424150c | 2014-04-09 12:12:36 -0700 | [diff] [blame] | 166 | return ret.toString(); |
Pavlin Radoslavov | 5363c2a | 2013-02-18 09:55:42 -0800 | [diff] [blame] | 167 | } |
| 168 | } |