blob: ac10021e95c053c9e89a576a76c38c14ec4e671b [file] [log] [blame]
alshabibf1216ed2014-09-03 11:53:54 -07001package org.onlab.onos.of.controller.impl;
alshabib54ebd9c2014-08-27 18:38:41 -07002
3import java.util.ArrayList;
4import java.util.concurrent.ConcurrentHashMap;
5import java.util.concurrent.locks.Lock;
6import java.util.concurrent.locks.ReentrantLock;
7
8import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
11import org.apache.felix.scr.annotations.Service;
12import org.onlab.onos.of.controller.Dpid;
13import org.onlab.onos.of.controller.OpenFlowController;
14import org.onlab.onos.of.controller.OpenFlowSwitch;
15import org.onlab.onos.of.controller.OpenFlowSwitchListener;
16import org.onlab.onos.of.controller.PacketListener;
17import org.onlab.onos.of.controller.RoleState;
alshabib6171f182014-09-02 19:00:32 -070018import org.onlab.onos.of.controller.driver.OpenFlowAgent;
alshabib54ebd9c2014-08-27 18:38:41 -070019import org.projectfloodlight.openflow.protocol.OFMessage;
alshabib54ebd9c2014-08-27 18:38:41 -070020import org.slf4j.Logger;
21import org.slf4j.LoggerFactory;
22
23@Component(immediate = true)
24@Service
25public class OpenFlowControllerImpl implements OpenFlowController {
26
alshabibd777b202014-08-28 17:52:55 -070027 private static final Logger log =
28 LoggerFactory.getLogger(OpenFlowControllerImpl.class);
29
alshabib6171f182014-09-02 19:00:32 -070030 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> connectedSwitches =
31 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
32 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeMasterSwitches =
33 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
34 protected ConcurrentHashMap<Dpid, OpenFlowSwitch> activeEqualSwitches =
35 new ConcurrentHashMap<Dpid, OpenFlowSwitch>();
alshabib54ebd9c2014-08-27 18:38:41 -070036
37 protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
alshabibd777b202014-08-28 17:52:55 -070038 protected ArrayList<OpenFlowSwitchListener> ofEventListener =
39 new ArrayList<OpenFlowSwitchListener>();
alshabib54ebd9c2014-08-27 18:38:41 -070040
41 private final Controller ctrl = new Controller();
42
43 @Activate
44 public void activate() {
45 ctrl.start(agent);
46 }
47
48 @Deactivate
49 public void deactivate() {
50 ctrl.stop();
51 }
52
53 @Override
54 public Iterable<OpenFlowSwitch> getSwitches() {
55 return connectedSwitches.values();
56 }
57
58 @Override
59 public Iterable<OpenFlowSwitch> getMasterSwitches() {
60 return activeMasterSwitches.values();
61 }
62
63 @Override
64 public Iterable<OpenFlowSwitch> getEqualSwitches() {
65 return activeEqualSwitches.values();
66 }
67
68 @Override
69 public OpenFlowSwitch getSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070070 return connectedSwitches.get(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -070071 }
72
73 @Override
74 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070075 return activeMasterSwitches.get(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -070076 }
77
78 @Override
79 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
alshabibf1216ed2014-09-03 11:53:54 -070080 return activeEqualSwitches.get(dpid);
81 }
alshabib54ebd9c2014-08-27 18:38:41 -070082
83 @Override
84 public void addListener(OpenFlowSwitchListener listener) {
85 if (!ofEventListener.contains(listener)) {
86 this.ofEventListener.add(listener);
87 }
88 }
89
90 @Override
91 public void removeListener(OpenFlowSwitchListener listener) {
92 this.ofEventListener.remove(listener);
93 }
94
95 @Override
96 public void addPacketListener(int priority, PacketListener listener) {
97 // TODO Auto-generated method stub
98
99 }
100
101 @Override
102 public void removePacketListener(PacketListener listener) {
103 // TODO Auto-generated method stub
104
105 }
106
107 @Override
108 public void write(Dpid dpid, OFMessage msg) {
alshabibd777b202014-08-28 17:52:55 -0700109 this.getSwitch(dpid).sendMsg(msg);
alshabib54ebd9c2014-08-27 18:38:41 -0700110 }
111
112 @Override
113 public void processPacket(OFMessage msg) {
alshabibd777b202014-08-28 17:52:55 -0700114 log.info("Got message {}", msg);
alshabib54ebd9c2014-08-27 18:38:41 -0700115 }
116
117 @Override
118 public void setRole(Dpid dpid, RoleState role) {
alshabibf1216ed2014-09-03 11:53:54 -0700119 getSwitch(dpid).setRole(role);
alshabib54ebd9c2014-08-27 18:38:41 -0700120 }
121
alshabibf1216ed2014-09-03 11:53:54 -0700122 /**
123 * Implementation of an OpenFlow Agent which is responsible for
124 * keeping track of connected switches and the state in which
125 * they are.
126 *
127 */
alshabib6171f182014-09-02 19:00:32 -0700128 public class OpenFlowSwitchAgent implements OpenFlowAgent {
alshabib54ebd9c2014-08-27 18:38:41 -0700129
130 private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
alshabib6171f182014-09-02 19:00:32 -0700131 private final Lock switchLock = new ReentrantLock();
alshabib54ebd9c2014-08-27 18:38:41 -0700132
alshabib6171f182014-09-02 19:00:32 -0700133 @Override
134 public boolean addConnectedSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700135 if (connectedSwitches.get(dpid) != null) {
136 log.error("Trying to add connectedSwitch but found a previous "
137 + "value for dpid: {}", dpid);
138 return false;
139 } else {
140 log.error("Added switch {}", dpid);
141 connectedSwitches.put(dpid, sw);
142 for (OpenFlowSwitchListener l : ofEventListener) {
alshabib6171f182014-09-02 19:00:32 -0700143 l.switchAdded(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700144 }
145 return true;
146 }
147 }
148
alshabib6171f182014-09-02 19:00:32 -0700149 @Override
150 public boolean validActivation(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700151 if (connectedSwitches.get(dpid) == null) {
152 log.error("Trying to activate switch but is not in "
153 + "connected switches: dpid {}. Aborting ..",
alshabib6171f182014-09-02 19:00:32 -0700154 dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700155 return false;
156 }
157 if (activeMasterSwitches.get(dpid) != null ||
158 activeEqualSwitches.get(dpid) != null) {
159 log.error("Trying to activate switch but it is already "
160 + "activated: dpid {}. Found in activeMaster: {} "
161 + "Found in activeEqual: {}. Aborting ..", new Object[] {
alshabib6171f182014-09-02 19:00:32 -0700162 dpid,
alshabib54ebd9c2014-08-27 18:38:41 -0700163 (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
alshabib6171f182014-09-02 19:00:32 -0700164 (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
alshabib54ebd9c2014-08-27 18:38:41 -0700165 return false;
166 }
167 return true;
168 }
169
alshabib6171f182014-09-02 19:00:32 -0700170
171 @Override
172 public boolean addActivatedMasterSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700173 switchLock.lock();
174 try {
175 if (!validActivation(dpid)) {
176 return false;
177 }
178 activeMasterSwitches.put(dpid, sw);
179 return true;
180 } finally {
181 switchLock.unlock();
182 }
alshabib6171f182014-09-02 19:00:32 -0700183 }
alshabib54ebd9c2014-08-27 18:38:41 -0700184
alshabib6171f182014-09-02 19:00:32 -0700185 @Override
186 public boolean addActivatedEqualSwitch(Dpid dpid, OpenFlowSwitch sw) {
alshabib54ebd9c2014-08-27 18:38:41 -0700187 switchLock.lock();
188 try {
alshabib6171f182014-09-02 19:00:32 -0700189 if (!validActivation(dpid)) {
190 return false;
191 }
192 activeEqualSwitches.put(dpid, sw);
193 log.info("Added Activated EQUAL Switch {}", dpid);
194 return true;
alshabib54ebd9c2014-08-27 18:38:41 -0700195 } finally {
196 switchLock.unlock();
197 }
198 }
199
alshabib6171f182014-09-02 19:00:32 -0700200 @Override
201 public void transitionToMasterSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700202 switchLock.lock();
203 try {
alshabibd777b202014-08-28 17:52:55 -0700204 if (activeMasterSwitches.containsKey(dpid)) {
205 return;
206 }
alshabib54ebd9c2014-08-27 18:38:41 -0700207 OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
208 if (sw == null) {
209 log.error("Transition to master called on sw {}, but switch "
210 + "was not found in controller-cache", dpid);
211 return;
212 }
alshabibf1216ed2014-09-03 11:53:54 -0700213 log.info("Transitioned switch {} to MASTER", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700214 activeMasterSwitches.put(dpid, sw);
215 } finally {
216 switchLock.unlock();
217 }
218 }
219
220
alshabib6171f182014-09-02 19:00:32 -0700221 @Override
222 public void transitionToEqualSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700223 switchLock.lock();
224 try {
alshabibd777b202014-08-28 17:52:55 -0700225 if (activeEqualSwitches.containsKey(dpid)) {
226 return;
227 }
alshabib54ebd9c2014-08-27 18:38:41 -0700228 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
229 if (sw == null) {
230 log.error("Transition to equal called on sw {}, but switch "
231 + "was not found in controller-cache", dpid);
232 return;
233 }
alshabibf1216ed2014-09-03 11:53:54 -0700234 log.info("Transitioned switch {} to EQUAL", dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700235 activeEqualSwitches.put(dpid, sw);
236 } finally {
237 switchLock.unlock();
238 }
239
240 }
241
alshabib6171f182014-09-02 19:00:32 -0700242 @Override
243 public void removeConnectedSwitch(Dpid dpid) {
alshabib54ebd9c2014-08-27 18:38:41 -0700244 connectedSwitches.remove(dpid);
245 OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
246 if (sw == null) {
247 sw = activeEqualSwitches.remove(dpid);
248 }
249 for (OpenFlowSwitchListener l : ofEventListener) {
alshabib6171f182014-09-02 19:00:32 -0700250 l.switchRemoved(dpid);
alshabib54ebd9c2014-08-27 18:38:41 -0700251 }
252 }
253
alshabib6171f182014-09-02 19:00:32 -0700254 @Override
alshabib54ebd9c2014-08-27 18:38:41 -0700255 public void processMessage(OFMessage m) {
256 processPacket(m);
257 }
258 }
259
260
261
262}