Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 1 | package net.onrc.onos.ofcontroller.flowmanager; |
| 2 | |
| 3 | import java.util.Collection; |
| 4 | import java.util.LinkedList; |
| 5 | import java.util.List; |
| 6 | |
| 7 | import java.util.concurrent.BlockingQueue; |
| 8 | import java.util.concurrent.LinkedBlockingQueue; |
| 9 | |
| 10 | import net.onrc.onos.datagrid.IDatagridService; |
Pavlin Radoslavov | a23e541 | 2013-10-27 19:56:40 -0700 | [diff] [blame^] | 11 | import net.onrc.onos.ofcontroller.topology.Topology; |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 12 | import net.onrc.onos.ofcontroller.topology.TopologyElement; |
| 13 | import net.onrc.onos.ofcontroller.util.EventEntry; |
| 14 | import net.onrc.onos.ofcontroller.util.FlowPath; |
| 15 | |
| 16 | import org.slf4j.Logger; |
| 17 | import org.slf4j.LoggerFactory; |
| 18 | |
| 19 | /** |
| 20 | * Class for implementing the Path Computation and Path Maintenance. |
| 21 | */ |
| 22 | class PathComputation extends Thread implements IPathComputationService { |
| 23 | /** The logger. */ |
| 24 | private final static Logger log = LoggerFactory.getLogger(PathComputation.class); |
| 25 | |
| 26 | private FlowManager flowManager; // The Flow Manager to use |
| 27 | private IDatagridService datagridService; // The Datagrid Service to use |
Pavlin Radoslavov | a23e541 | 2013-10-27 19:56:40 -0700 | [diff] [blame^] | 28 | private Topology topology; // The network topology |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 29 | |
| 30 | // The queue with Flow Path and Topology Element updates |
| 31 | private BlockingQueue<EventEntry<?>> networkEvents = |
| 32 | new LinkedBlockingQueue<EventEntry<?>>(); |
| 33 | |
| 34 | // The pending Topology and Flow Path events |
| 35 | private List<EventEntry<TopologyElement>> topologyEvents = |
| 36 | new LinkedList<EventEntry<TopologyElement>>(); |
| 37 | private List<EventEntry<FlowPath>> flowPathEvents = |
| 38 | new LinkedList<EventEntry<FlowPath>>(); |
| 39 | |
| 40 | /** |
| 41 | * Constructor for a given Flow Manager and Datagrid Service. |
| 42 | * |
| 43 | * @param flowManager the Flow Manager to use. |
| 44 | * @param datagridService the Datagrid Service to use. |
| 45 | */ |
| 46 | PathComputation(FlowManager flowManager, |
| 47 | IDatagridService datagridService) { |
| 48 | this.flowManager = flowManager; |
| 49 | this.datagridService = datagridService; |
Pavlin Radoslavov | a23e541 | 2013-10-27 19:56:40 -0700 | [diff] [blame^] | 50 | this.topology = new Topology(); |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | /** |
| 54 | * Run the thread. |
| 55 | */ |
| 56 | @Override |
| 57 | public void run() { |
| 58 | // |
| 59 | // Obtain the initial Topology state |
| 60 | // |
| 61 | Collection<TopologyElement> topologyElements = |
| 62 | datagridService.getAllTopologyElements(); |
| 63 | for (TopologyElement topologyElement : topologyElements) { |
| 64 | EventEntry<TopologyElement> eventEntry = |
| 65 | new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement); |
| 66 | topologyEvents.add(eventEntry); |
| 67 | } |
| 68 | // |
| 69 | // Obtain the initial Flow Path state |
| 70 | // |
| 71 | Collection<FlowPath> flowPaths = datagridService.getAllFlows(); |
| 72 | for (FlowPath flowPath : flowPaths) { |
| 73 | EventEntry<FlowPath> eventEntry = |
| 74 | new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath); |
| 75 | flowPathEvents.add(eventEntry); |
| 76 | } |
| 77 | // Process the events (if any) |
| 78 | processEvents(); |
| 79 | |
| 80 | // |
| 81 | // The main loop |
| 82 | // |
| 83 | Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>(); |
| 84 | try { |
| 85 | while (true) { |
| 86 | EventEntry<?> eventEntry = networkEvents.take(); |
| 87 | collection.add(eventEntry); |
| 88 | networkEvents.drainTo(collection); |
| 89 | |
Pavlin Radoslavov | ed4c7a9 | 2013-10-26 21:36:21 -0700 | [diff] [blame] | 90 | // |
| 91 | // Demultiplex all events: |
| 92 | // - EventEntry<TopologyElement> |
| 93 | // - EventEntry<FlowPath> |
| 94 | // |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 95 | for (EventEntry<?> event : collection) { |
| 96 | if (event.eventData() instanceof TopologyElement) { |
| 97 | EventEntry<TopologyElement> topologyEventEntry = |
| 98 | (EventEntry<TopologyElement>)event; |
| 99 | topologyEvents.add(topologyEventEntry); |
| 100 | } else if (event.eventData() instanceof FlowPath) { |
| 101 | EventEntry<FlowPath> flowPathEventEntry = |
| 102 | (EventEntry<FlowPath>)event; |
| 103 | flowPathEvents.add(flowPathEventEntry); |
| 104 | } |
| 105 | } |
| 106 | collection.clear(); |
Pavlin Radoslavov | ed4c7a9 | 2013-10-26 21:36:21 -0700 | [diff] [blame] | 107 | |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 108 | // Process the events (if any) |
| 109 | processEvents(); |
| 110 | } |
| 111 | } catch (Exception exception) { |
| 112 | log.debug("Exception processing Network Events: ", exception); |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Process the events (if any) |
| 118 | */ |
| 119 | private void processEvents() { |
| 120 | if (topologyEvents.isEmpty() && flowPathEvents.isEmpty()) |
| 121 | return; // Nothing to do |
| 122 | |
Pavlin Radoslavov | a23e541 | 2013-10-27 19:56:40 -0700 | [diff] [blame^] | 123 | // |
| 124 | // Add the topology events |
| 125 | // |
| 126 | boolean isTopologyModified = false; |
| 127 | for (EventEntry<TopologyElement> eventEntry : topologyEvents) { |
| 128 | TopologyElement topologyElement = eventEntry.eventData(); |
| 129 | switch (eventEntry.eventType()) { |
| 130 | case ENTRY_ADD: |
| 131 | isTopologyModified = topology.addTopologyElement(topologyElement); |
| 132 | break; |
| 133 | case ENTRY_REMOVE: |
| 134 | isTopologyModified = topology.removeTopologyElement(topologyElement); |
| 135 | break; |
| 136 | } |
| 137 | } |
| 138 | |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 139 | // TODO: Implement it! |
| 140 | |
Pavlin Radoslavov | ed4c7a9 | 2013-10-26 21:36:21 -0700 | [diff] [blame] | 141 | // Cleanup |
Pavlin Radoslavov | 6b79f2b | 2013-10-26 21:31:10 -0700 | [diff] [blame] | 142 | topologyEvents.clear(); |
| 143 | flowPathEvents.clear(); |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Receive a notification that a Flow is added. |
| 148 | * |
| 149 | * @param flowPath the flow that is added. |
| 150 | */ |
| 151 | @Override |
| 152 | public void notificationRecvFlowAdded(FlowPath flowPath) { |
| 153 | EventEntry<FlowPath> eventEntry = |
| 154 | new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath); |
| 155 | networkEvents.add(eventEntry); |
| 156 | } |
| 157 | |
| 158 | /** |
| 159 | * Receive a notification that a Flow is removed. |
| 160 | * |
| 161 | * @param flowPath the flow that is removed. |
| 162 | */ |
| 163 | @Override |
| 164 | public void notificationRecvFlowRemoved(FlowPath flowPath) { |
| 165 | EventEntry<FlowPath> eventEntry = |
| 166 | new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath); |
| 167 | networkEvents.add(eventEntry); |
| 168 | } |
| 169 | |
| 170 | /** |
| 171 | * Receive a notification that a Flow is updated. |
| 172 | * |
| 173 | * @param flowPath the flow that is updated. |
| 174 | */ |
| 175 | @Override |
| 176 | public void notificationRecvFlowUpdated(FlowPath flowPath) { |
| 177 | // NOTE: The ADD and UPDATE events are processed in same way |
| 178 | EventEntry<FlowPath> eventEntry = |
| 179 | new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath); |
| 180 | networkEvents.add(eventEntry); |
| 181 | } |
| 182 | |
| 183 | /** |
| 184 | * Receive a notification that a Topology Element is added. |
| 185 | * |
| 186 | * @param topologyElement the Topology Element that is added. |
| 187 | */ |
| 188 | @Override |
| 189 | public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) { |
| 190 | EventEntry<TopologyElement> eventEntry = |
| 191 | new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement); |
| 192 | networkEvents.add(eventEntry); |
| 193 | } |
| 194 | |
| 195 | /** |
| 196 | * Receive a notification that a Topology Element is removed. |
| 197 | * |
| 198 | * @param topologyElement the Topology Element that is removed. |
| 199 | */ |
| 200 | @Override |
| 201 | public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) { |
| 202 | EventEntry<TopologyElement> eventEntry = |
| 203 | new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement); |
| 204 | networkEvents.add(eventEntry); |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Receive a notification that a Topology Element is updated. |
| 209 | * |
| 210 | * @param topologyElement the Topology Element that is updated. |
| 211 | */ |
| 212 | @Override |
| 213 | public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) { |
| 214 | // NOTE: The ADD and UPDATE events are processed in same way |
| 215 | EventEntry<TopologyElement> eventEntry = |
| 216 | new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement); |
| 217 | networkEvents.add(eventEntry); |
| 218 | } |
| 219 | } |