blob: 61d82771dfdc4a50dfc8e68b5467158f873b5eaf [file] [log] [blame]
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07003import java.io.IOException;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07004import java.util.HashMap;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07005import java.util.Map;
6import java.util.Queue;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07007
8import org.openflow.protocol.OFMessage;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07009
10import net.floodlightcontroller.core.FloodlightContext;
11import net.floodlightcontroller.core.IOFSwitch;
Naoki Shiota2ca26f32013-10-31 17:14:13 -070012import net.onrc.onos.ofcontroller.flowmanager.FlowQueueTable.QueueState;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070013
14/**
15 * FlowPusher intermediates flow_mod sent from FlowManager/FlowSync to switches.
16 * FlowPusher controls the rate of sending flow_mods so that connection doesn't overflow.
17 * @author Naoki Shiota
18 *
19 */
20public class FlowPusher {
21 private FloodlightContext context;
Naoki Shiotac2a699a2013-10-31 15:36:01 -070022 private FlowQueueTable flowQueueTable = null;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070023 private Thread thread;
24
Naoki Shiotacf1acca2013-10-31 11:40:32 -070025 /**
26 * Represents state of queue.
27 * This is used for calculation of rate.
28 * @author Naoki Shiota
29 *
30 */
Naoki Shiotac2a699a2013-10-31 15:36:01 -070031 private static class RateInfo {
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070032 long last_sent_time = 0;
33 long last_sent_size = 0;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070034 }
Naoki Shiotacf1acca2013-10-31 11:40:32 -070035
Naoki Shiotac2a699a2013-10-31 15:36:01 -070036 private Map<Long, RateInfo> queue_rateinfos =
37 new HashMap<Long, RateInfo>();
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070038
39 private class FlowPusherProcess implements Runnable {
40 @Override
41 public void run() {
Naoki Shiotac2a699a2013-10-31 15:36:01 -070042 if (flowQueueTable == null) {
43 return;
44 }
45
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070046 while (true) {
Naoki Shiotac2a699a2013-10-31 15:36:01 -070047 for (IOFSwitch sw : flowQueueTable.getSwitches()) {
48 // Skip if queue is suspended
Naoki Shiota2ca26f32013-10-31 17:14:13 -070049 if (flowQueueTable.getQueueState(sw) != QueueState.READY) {
Naoki Shiotac2a699a2013-10-31 15:36:01 -070050 continue;
51 }
52
53 // Skip if queue is locked
54 if (! flowQueueTable.lockQueueIfAvailable(sw)) {
55 continue;
56 }
57
58 long dpid = sw.getId();
59 Queue<OFMessage> queue = flowQueueTable.getQueue(sw);
60
61 if (queue == null) {
62 flowQueueTable.unlockQueue(sw);
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070063 continue;
64 }
65
66 OFMessage msg = queue.poll();
67 if (msg == null) {
Naoki Shiotac2a699a2013-10-31 15:36:01 -070068 flowQueueTable.unlockQueue(sw);
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070069 continue;
70 }
71
Naoki Shiotac2a699a2013-10-31 15:36:01 -070072 RateInfo state = queue_rateinfos.get(dpid);
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070073 if (state == null) {
Naoki Shiotac2a699a2013-10-31 15:36:01 -070074 queue_rateinfos.put(dpid, new RateInfo());
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070075 }
76
77 // check sending rate and determine it to be sent or not
78 long current_time = System.nanoTime();
79 long rate = state.last_sent_size / (current_time - state.last_sent_time);
80
81 // if need to send, call IOFSwitch#write()
Naoki Shiotac2a699a2013-10-31 15:36:01 -070082 if (rate < flowQueueTable.getQueueRate(sw)) {
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070083 try {
84 sw.write(msg, context);
85 state.last_sent_time = current_time;
86 state.last_sent_size = msg.getLengthU();
87 } catch (IOException e) {
88 // TODO Auto-generated catch block
89 e.printStackTrace();
90 }
91 }
Naoki Shiotac2a699a2013-10-31 15:36:01 -070092
93 flowQueueTable.unlockQueue(sw);
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070094 }
95
96 // sleep while all queues are empty
97 boolean sleep = true;
98 do {
Naoki Shiotacf1acca2013-10-31 11:40:32 -070099 // TODO check if queues are empty
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700100 } while (sleep);
101 }
102 }
103 }
104
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700105 public FlowPusher(FlowQueueTable table, FloodlightContext context) {
106 flowQueueTable = table;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700107 this.context = context;
108 }
109
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700110 public void startProcess() {
111 thread = new Thread(new FlowPusherProcess());
112 thread.start();
113 }
114
115 public void stopProcess() {
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700116 if (thread != null && thread.isAlive()) {
117 // TODO tell thread to halt
118 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700119 }
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700120
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700121}